Hey,
I am new to MSP430. I have to write data to an external memory( Non- volatile) chip (DS1682). It supports 2 wire serial interface( I2C). I am using MSP430G2231. And also i have to read the bytes written onto this chip. Does msp430g2231 have any inbuilt library to read and write data onto external memory..i have to write 16 bit data.
Hi Pavan,
the MSP430G2231 has built in an USI module which will support you in hardware. Here is one of the code examples:
//******************************************************************************// MSP430G2x21/G2x31 Demo - I2C Master Receiver, single byte//// Description: I2C Master communicates with I2C Slave using// the USI. Slave data should increment from 0x00 with each transmitted byte// which is verified by the Master.// LED off for address or data Ack; LED on for address or data NAck.// ACLK = n/a, MCLK = SMCLK = Calibrated 1MHz//// ***THIS IS THE MASTER CODE***//// Slave Master// (msp430g2x21_usi_09.c)// MSP430G2x21/G2x31 MSP430G2x21/G2x31// ----------------- -----------------// /|\| XIN|- /|\| XIN|-// | | | | | |// --|RST XOUT|- --|RST XOUT|-// | | | |// LED <-|P1.0 | | |// | | | P1.0|-> LED// | SDA/P1.7|------->|P1.7/SDA |// | SCL/P1.6|<-------|P1.6/SCL |//// Note: internal pull-ups are used in this example for SDA & SCL//// D. Dang// Texas Instruments Inc.// October 2010// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10//******************************************************************************#include <msp430g2221.h>char SLV_data = 0x00; // Variable for received datachar SLV_Addr = 0x91; // Address is 0x48 << 1 bit + 1 for Readint I2C_State = 0; // State variablevoid main(void){ volatile unsigned int i; // Use volatile to prevent removal WDTCTL = WDTPW + WDTHOLD; // Stop watchdog if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF) { while(1); // If calibration constants are erased // do not load, trap CPU!! } BCSCTL1 = CALBC1_1MHZ; // Set DCO DCOCTL = CALDCO_1MHZ; P1OUT = 0xC0; // P1.6 & P1.7 Pullups P1REN |= 0xC0; // P1.6 & P1.7 Pullups P1DIR = 0xFF; // Unused pins as outputs P2OUT = 0; P2DIR = 0xFF; USICTL0 = USIPE6+USIPE7+USIMST+USISWRST;// Port & USI mode setup USICTL1 = USII2C+USIIE; // Enable I2C mode & USI interrupt USICKCTL = USIDIV_3+USISSEL_2+USICKPL;// Setup USI clocks: SCL = SMCLK/8 (~120kHz) USICNT |= USIIFGCC; // Disable automatic clear control USICTL0 &= ~USISWRST; // Enable USI USICTL1 &= ~USIIFG; // Clear pending flag _EINT(); while(1) { USICTL1 |= USIIFG; // Set flag and start communication LPM0; // CPU off, await USI interrupt _NOP(); // Used for IAR for (i = 0; i < 5000; i++); // Dummy delay between communication cycles }}/******************************************************// USI interrupt service routine******************************************************/#pragma vector = USI_VECTOR__interrupt void USI_TXRX (void){ switch(I2C_State) { case 0: // Generate Start Condition & send address to slave P1OUT |= 0x01; // LED on: sequence start USISRL = 0x00; // Generate Start Condition... USICTL0 |= USIGE+USIOE; USICTL0 &= ~USIGE; USISRL = SLV_Addr; // ... and transmit address, R/W = 1 USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address I2C_State = 2; // Go to next state: receive address (N)Ack break; case 2: // Receive Address Ack/Nack bit USICTL0 &= ~USIOE; // SDA = input USICNT |= 0x01; // Bit counter = 1, receive (N)Ack bit I2C_State = 4; // Go to next state: check (N)Ack break; case 4: // Process Address Ack/Nack & handle data RX if (USISRL & 0x01) // If Nack received... { // Prep Stop Condition USICTL0 |= USIOE; USISRL = 0x00; USICNT |= 0x01; // Bit counter = 1, SCL high, SDA low I2C_State = 10; // Go to next state: generate Stop P1OUT |= 0x01; // Turn on LED: error } else // Ack received { // Receive Data from slave USICNT |= 0x08; // Bit counter = 8, RX data I2C_State = 6; // Go to next state: Test data and (N)Ack P1OUT &= ~0x01; // LED off } break; case 6: // Send Data Ack/Nack bit USICTL0 |= USIOE; // SDA = output if (USISRL == SLV_data) // If data valid... { USISRL = 0x00; // Send Ack SLV_data++; // Increment Slave data P1OUT &= ~0x01; // LED off } else { USISRL = 0xFF; // Send NAck P1OUT |= 0x01; // LED on: error } USICNT |= 0x01; // Bit counter = 1, send (N)Ack bit I2C_State = 8; // Go to next state: prep stop break; case 8: // Prep Stop Condition USICTL0 |= USIOE; // SDA = output USISRL = 0x00; USICNT |= 0x01; // Bit counter = 1, SCL high, SDA low I2C_State = 10; // Go to next state: generate Stop break; case 10: // Generate Stop Condition USISRL = 0x0FF; // USISRL = 1 to release SDA USICTL0 |= USIGE; // Transparent latch enabled USICTL0 &= ~(USIGE+USIOE);// Latch/SDA output disabled I2C_State = 0; // Reset state machine for next transmission LPM0_EXIT; // Exit active for next transfer break; } USICTL1 &= ~USIIFG; // Clear pending flag}from: http://www.ti.com/lit/zip/slac463
--Regards,JanOxfam Trailwalker 2012 - Runner
Found any horribly english mistakes? - Drop me a note as private conversation via my profile if you like ;-)
Thanks for the early reply Jan!
But shouldnt I use MSP430G2231 as a master ? I have seen the example code which sends/transmits multiple bytes (usi_12 in the example codes). But I was not able to figure out where to put the data which i want to write!
any help would be greatly appreciated !
PAVAN ANANDBut shouldnt I use MSP430G2231 as a master ?
The differences aren't that big. A different slave address to be sent (LSB clear instead of set), no ACK bit generated but received instead, and write outgoing byte to USISRL before writing the count instead of writing the count, waiting until it reaches zero and reading the incoming byte from USISRL.
_____________________________________Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.
Can i use the program shown below to send multiple bytes to my eeprom chip( example code) ? but i am not able to figure out where to enter the data which i need to send..also my eeprom has 32 bits..and i have to write the first 16 bits with data..how to access the first 16 bits..plz help
//******************************************************************************// MSP430G2x21/G2x31 Demo - I2C Master Transmitter / Reciever, multiple bytes//// Description: I2C Master communicates with I2C Slave using// the USI. Master data should increment from 0x55 with each transmitted byte// and Master determines the number of bytes recieved, set by // the Number_of_Bytes value. LED off for address or data Ack; // LED on for address or data NAck.// ACLK = n/a, MCLK = SMCLK = Calibrated 1MHz////// ***THIS IS THE MASTER CODE***//// Slave Master// (msp430g2x21_usi_15.c)// MSP430G2x21/G2x31 MSP430G2x21/G2x31// ----------------- -----------------// /|\| XIN|- /|\| XIN|-// | | | | | |// --|RST XOUT|- --|RST XOUT|-// | | | |// LED <-|P1.0 | | |// | | | P1.0|-> LED// | SDA/P1.7|------->|P1.6/SDA |// | SCL/P1.6|<-------|P1.7/SCL |//// Note: internal pull-ups are used in this example for SDA & SCL//// D. Dang// Texas Instruments Inc.// October 2010// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10//******************************************************************************#include <msp430g2221.h>#define number_of_bytes 5 // How many bytes?void Master_Transmit(void);void Master_Recieve(void);void Setup_USI_Master_TX(void);void Setup_USI_Master_RX(void);char MST_Data = 0x55; // Variable for transmitted datachar SLV_Addr = 0x90; int I2C_State, Bytecount, Transmit = 0; // State variablevoid Data_TX (void);void Data_RX (void);void main(void){ volatile unsigned int i; // Use volatile to prevent removal WDTCTL = WDTPW + WDTHOLD; // Stop watchdog if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF) { while(1); // If calibration constants erased // do not load, trap CPU!! } BCSCTL1 = CALBC1_1MHZ; // Set DCO DCOCTL = CALDCO_1MHZ; P1OUT = 0xC0; // P1.6 & P1.7 Pullups, others to 0 P1REN |= 0xC0; // P1.6 & P1.7 Pullups P1DIR = 0xFF; // Unused pins as outputs P2OUT = 0; P2DIR = 0xFF; while(1) { Master_Transmit(); _NOP(); // Used for IAR Master_Recieve(); _NOP(); }}/******************************************************// USI interrupt service routine// Data Transmit : state 0 -> 2 -> 4 -> 10 -> 12 -> 14// Data Recieve : state 0 -> 2 -> 4 -> 6 -> 8 -> 14******************************************************/#pragma vector = USI_VECTOR__interrupt void USI_TXRX (void){ switch(__even_in_range(I2C_State,14)) { case 0: // Generate Start Condition & send address to slave P1OUT |= 0x01; // LED on: sequence start Bytecount = 0; USISRL = 0x00; // Generate Start Condition... USICTL0 |= USIGE+USIOE; USICTL0 &= ~USIGE; if (Transmit == 1){ USISRL = 0x90; // Address is 0x48 << 1 bit + 0 (rw) } if (Transmit == 0){ USISRL = 0x91; // 0x91 Address is 0x48 << 1 bit // + 1 for Read } USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address I2C_State = 2; // next state: rcv address (N)Ack break; case 2: // Receive Address Ack/Nack bit USICTL0 &= ~USIOE; // SDA = input USICNT |= 0x01; // Bit counter=1, receive (N)Ack bit I2C_State = 4; // Go to next state: check (N)Ack break; case 4: // Process Address Ack/Nack & handle data TX if(Transmit == 1){ USICTL0 |= USIOE; // SDA = output if (USISRL & 0x01) // If Nack received... { // Send stop... USISRL = 0x00; USICNT |= 0x01; // Bit counter=1, SCL high, SDA low I2C_State = 14; // Go to next state: generate Stop P1OUT |= 0x01; // Turn on LED: error } else { // Ack received, TX data to slave... USISRL = MST_Data++; // Load data byte USICNT |= 0x08; // Bit counter = 8, start TX I2C_State = 10; // next state: receive data (N)Ack Bytecount++; P1OUT &= ~0x01; // Turn off LED break; } } if(Transmit == 0){ if (USISRL & 0x01) // If Nack received { // Prep Stop Condition USICTL0 |= USIOE; USISRL = 0x00; USICNT |= 0x01; // Bit counter= 1, SCL high, SDA low I2C_State = 8; // Go to next state: generate Stop P1OUT |= 0x01; // Turn on LED: error } else{ Data_RX();} // Ack received } break;case 6: // Send Data Ack/Nack bit USICTL0 |= USIOE; // SDA = output if (Bytecount <= number_of_bytes-2) { // If this is not the last byte USISRL = 0x00; // Send Ack P1OUT &= ~0x01; // LED off I2C_State = 4; // Go to next state: data/rcv again Bytecount++; } else //last byte: send NACK { USISRL = 0xFF; // Send NAck P1OUT |= 0x01; // LED on: end of comm I2C_State = 8; // stop condition } USICNT |= 0x01; // Bit counter = 1, send (N)Ack bit break; case 8: // Prep Stop Condition USICTL0 |= USIOE; // SDA = output USISRL = 0x00; USICNT |= 0x01; // Bit counter= 1, SCL high, SDA low I2C_State = 14; // Go to next state: generate Stop break; case 10: // Receive Data Ack/Nack bit USICTL0 &= ~USIOE; // SDA = input USICNT |= 0x01; // Bit counter = 1, receive (N)Ack bit I2C_State = 12; // Go to next state: check (N)Ack break; case 12: // Process Data Ack/Nack & send Stop USICTL0 |= USIOE; if (Bytecount == number_of_bytes){// If last byte USISRL = 0x00; I2C_State = 14; // Go to next state: generate Stop P1OUT |= 0x01; USICNT |= 0x01; } // set count=1 to trigger next state else{ P1OUT &= ~0x01; // Turn off LED Data_TX(); // TX byte } break; case 14:// Generate Stop Condition USISRL = 0x0FF; // USISRL = 1 to release SDA USICTL0 |= USIGE; // Transparent latch enabled USICTL0 &= ~(USIGE+USIOE); // Latch/SDA output disabled I2C_State = 0; // Reset state machine for next xmt LPM0_EXIT; // Exit active for next transfer break; } USICTL1 &= ~USIIFG; // Clear pending flag}void Data_TX (void){ USISRL = MST_Data++; // Load data byte USICNT |= 0x08; // Bit counter = 8, start TX I2C_State = 10; // next state: receive data (N)Ack Bytecount++;}void Data_RX (void){ USICTL0 &= ~USIOE; // SDA = input --> redundant USICNT |= 0x08; // Bit counter = 8, RX data I2C_State = 6; // Next state: Test data and (N)Ack P1OUT &= ~0x01; // LED off }void Setup_USI_Master_TX (void){ _DINT(); Bytecount = 0; Transmit = 1; USICTL0 = USIPE6+USIPE7+USIMST+USISWRST; // Port & USI mode setup USICTL1 = USII2C+USIIE; // Enable I2C mode & USI interrupt USICKCTL = USIDIV_7+USISSEL_2+USICKPL; // USI clk: SCL = SMCLK/128 USICNT |= USIIFGCC; // Disable automatic clear control USICTL0 &= ~USISWRST; // Enable USI USICTL1 &= ~USIIFG; // Clear pending flag _EINT();}void Setup_USI_Master_RX (void){ _DINT(); Bytecount = 0; Transmit = 0; USICTL0 = USIPE6+USIPE7+USIMST+USISWRST; // Port & USI mode setup USICTL1 = USII2C+USIIE; // Enable I2C mode & USI interrupt USICKCTL = USIDIV_7+USISSEL_2+USICKPL; // USI clks: SCL = SMCLK/128 USICNT |= USIIFGCC; // Disable automatic clear control USICTL0 &= ~USISWRST; // Enable USI USICTL1 &= ~USIIFG; // Clear pending flag _EINT();}void Master_Transmit(void){Setup_USI_Master_TX(); USICTL1 |= USIIFG; // Set flag and start communication LPM0; // CPU off, await USI interrupt __delay_cycles(10000); // Delay between comm cycles}void Master_Recieve(void){ Setup_USI_Master_RX(); USICTL1 |= USIIFG; // Set flag and start communication LPM0; // CPU off, await USI interrupt __delay_cycles(10000); // Delay between comm cycles}
PAVAN ANANDi am not able to figure out where to enter the data which i need to send
To send an independent string, you must change the following:
changechar MST_Data = 0x55;tounsigned char * MST_Data = myData;
add your data arrayunsigned char myData[number_of_bytes]="data"; // or "= {0x12, 0x34, 64, 'a', 0};"
and change the lines containingUSISRL=MST_Data++;toUSISRL=*(MST_Data++);
Then it will number_of_bytes bytes from myData to the slave.
Thanks.That helped me a lot.
How do I access these registers? I have the data sheet I have to write bytes to addresses 09 and 0A
I tried the suggestions..plz tell me how to access particular registers on my chip? and to read the data is it enough if i just change the slave address and transmit variable =0?
Hi,
i just finished creating another example with USI in I2C mode, it is available under the following wiki page:
http://processors.wiki.ti.com/index.php/I2C_Communication_with_USI_Module
the library provided in the example code should be more straight forward and easier to be understood.
Comments are highly welcomed.
-Leo-
Regards,
Leo Hendrawan
- Now that my signature has caught your attention, please click the "Verify Answer" button if this post answers your question. Thanks! -
PAVAN ANANDplz tell me how to access particular registers on my chip
PAVAN ANANDand to read the data is it enough if i just change the slave address and transmit variable=0?
In the program I mentioned to write data onto my eeprom chip is it enough if i change the slave address and transmit=1 to send data?
According to the eeprom datasheet (DS1682 ETC) I have to send 1) Slave address first 2) Then the register address 3) Then the actual data
In the program I posted above, I dont see where the registers are addressed. Where do I send register addresses?
I have to send slave address first, then the register byte then the actual data..plz reply!
PAVAN ANANDIn the program I mentioned to write data onto my eeprom chip is it enough if i change the slave address and transmit=1 to send data?
PAVAN ANANDAccording to the eeprom datasheet (DS1682 ETC) I have to send 1) Slave address first 2) Then the register address 3) Then the actual data
PAVAN ANANDIn the program I posted above, I dont see where the registers are addressed. Where do I send register addresses?
Jens-michael Gross ,
The data sheet of DS1682 specifically says that I have to send register address after sending the slave address while writing. N either my program nor your's has this facility. In my program there is facility to send slave address first then the data bytes, but where do I send the register? (I have to send register address right after I send the slave address ).