This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

About some error in MSP430F5529

Other Parts Discussed in Thread: MSP430F5529, MSP430G2553, MSP430WARE

I am new in the world of MSP430. I have got a code of msp430g2553 in the internet.The code is given below:The question is when I tried to use this code after necessary modification for MSP430F5529, The CCS compiler is showing me this error:Can u please explain this.

Error:


#20 identifier "UCB0TXIFG" is undefined main.c /sun18_may line 44 C/C++ Problem
#20 identifier "IE2" is undefined main.c /sun18_may line 58 C/C++ Problem
#20 identifier "UCB0RXIE" is undefined main.c /sun18_may line 58 C/C++ Problem
#20 identifier "IFG2" is undefined main.c /sun18_may line 44 C/C++ Problem
#20 identifier "UCB0TXIE" is undefined main.c /sun18_may line 58 C/C++ Problem

Code:


int TXByteCtr;
unsigned char PRxData;
int Rx = 0;
char WHO_AM_I = 0x00;

char itgAddress = 0x69;

void init_I2C(void);
void Transmit(void);
void Receive(void);


int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
init_I2C();


while(1){
//Transmit process
Rx = 0;
TXByteCtr = 1;
Transmit();
//Receive process
Rx = 1;
Receive();
}
}

//-------------------------------------------------------------------------------
// The USCI_B0 data ISR is used to move received data from the I2C slave
// to the MSP430 memory. It is structured such that it can be used to receive
//-------------------------------------------------------------------------------
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if(Rx == 1){ // Master Recieve?
PRxData = UCB0RXBUF; // Get RX data
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}

else{ // Master Transmit
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = WHO_AM_I; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}

}
void init_I2C(void) {
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = itgAddress; // Slave Address is 069h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0RXIE + UCB0TXIE; //Enable RX and TX interrupt
}

void Transmit(void){
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
}
void Receive(void){
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 &= ~UCTR ; // Clear UCTR
UCB0CTL1 |= UCTXSTT; // I2C start condition
while (UCB0CTL1 & UCTXSTT); // Start condition sent?
UCB0CTL1 |= UCTXSTP; // I2C stop condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
}

  • Hi,

    it seems the header file is not included in the beginning of the file, try to add

    #include "msp430f5529.h"

    at the beginning of your code to include the register declarations.

    EDIT: just saw again that you were porting from MSP430G2553. Although both devices share the same USCI module, I would recommend not to do this. You can refer to the MSP430F5529 example codes - http://www.ti.com/lit/zip/slac300 - or use the driverlib example code from MSP430ware as starting point.

  • Hi,

    Some how your modification went wrond. Its maily because, g series is quite different from  F series.
    Look at the errors you have got, For real they dont exist in F family at all.

    SALEHA KHATUN said:
    #20 identifier "UCB0TXIFG" is undefined main.c /sun18_may line 44 C/C++ Problem
    #20 identifier "IE2" is undefined main.c /sun18_may line 58 C/C++ Problem
    #20 identifier "UCB0RXIE" is undefined main.c /sun18_may line 58 C/C++ Problem
    #20 identifier "IFG2" is undefined main.c /sun18_may line 44 C/C++ Problem
    #20 identifier "UCB0TXIE" is undefined main.c /sun18_may line 58 C/C++ Problem


    UCB0TXIFG ---> UCTXIFG and so on.
    IFG2 --------------> UCB1IFG

    I mean to say, you have to check the relevant registers while porting. here I am giving u a code of mine for I2C communication using F5510 micro of similat family.

    #include "I2CMaster.h"
    //#include <msp430f5510.h>
    
    volatile uint16_t 	I2CNumBytes;
    volatile uint16_t	Ack;
    volatile uint8_t	   *I2CRxBuffer, *I2CTxBuffer;
    
    volatile uint16_t	I2CStop;
    volatile uint16_t	Stop_Ticks = 0, Start_Ticks = 0, I2C_Ticks = 0;
    
    void I2CInit( void )
    {
    	P4SEL  |= BIT2 + BIT1;					// Assign I2C pins to USCI_B1
    
    	P4OUT |= BIT2 + BIT1;					// We can enable internal pull-ups
    	P4REN |= BIT2 + BIT1;
    
    	UCB1CTL1    |= UCSWRST;												// Enable SW reset
    	UCB1CTL0    = UCMST + UCMODE_3 + UCSYNC;		    // 7-bit addressing, single-master environment, I2C Master, synchronous mode
    	UCB1CTL1    = UCSSEL_2 + UCSWRST;							// Use SMCLK, keep SW reset
    	UCB1BR0      = I2C_400KHZ;												// fSCL = SMCLK/UCB0BR0
    	UCB1BR1      = 0;
    	UCB1CTL1 &= ~UCSWRST;												// Clear SW reset, resume operation
    	UCB1IE        |= UCNACKIE + UCTXIE + UCRXIE;    // Enable not-acknowledge interrupt TX&RX interrupts
    }
    
    uint16_t I2CWrite( uint8_t sladdr , uint8_t *data , uint16_t n )
    {
    	Ack = 1;							// Return value
        I2CTxBuffer = data;					// TX array start address
        I2CNumBytes = n;                  	// Update counter
    	UCB1I2CSA = sladdr;  				// Slave address (Right justified, bits6-0)
        //
    	while( (UCB1CTL1 & UCTXSTP));
        UCB1CTL1 |= UCTR + UCTXSTT;			// Send I2C start condition, I2C TX mode
        //
        do{
        	_BIS_SR(LPM0_bits + GIE);
        		_DINT();
          }while( I2CNumBytes && Ack );
         	_EINT();
       	//SetUp WDT with 2ms Interval, don't enable Interrupts, we are monitoring WDTInettupt flag here for condition.
    	SFRIFG1    &= ~WDTIFG;
    	SFRIE1 	   &= ~WDTIE;
    	WDTCTL   = WDT_MDLY_32;
    	while( (UCB1CTL1 & UCTXSTP) && (!(SFRIFG1 & WDTIFG)) );		// I2C stop condition sent?
    	Stop_WDT();
    	UCB1CTL1 &= ~UCTXSTP;
    
    	return Ack;
    }
    
    uint16_t I2CRead( uint8_t sladdr , uint8_t *data , uint16_t n )
    {
    	//
    	Ack = 1;							// Return value
    	// 
        I2CRxBuffer = data;					// Start of RX buffer
        UCB1I2CSA = sladdr;					// Slave address (Right justified, bits6-0)
        //
        UCB1CTL1 &= ~UCTR;					// I2C RX mode
        //
        if( n == 1 )
        {
        	I2CNumBytes = 0;				// Update counter
    
        	_DINT();
        	UCB1CTL1 |= UCTXSTT;			// Send I2C start condition, I2C RX mode
       		while( (UCB1CTL1 & UCTXSTT) );		// I2C start condition sent?
        	UCB1CTL1 |= UCTXSTP;			// Send I2C stop condition
        	I2CStop = 1;					// I2C stop condition sent
        	_BIS_SR(LPM0_bits + GIE);
        }
        else if( n > 1 )
        {
        	I2CStop = 0;					// I2C stop condition not sent yet
        	I2CNumBytes = n - 2;			// Update counter
    		//SetUp WDT with interval of 2ms (default)
    		__disable_interrupt();
        	UCB1CTL1 |= UCTXSTT;			// Send I2C start condition
        	//We are looking for NACK Interrupt. THis interrupt will make ACK = 0 if there is no Acknowledge.
        	do
        	{
        		_BIS_SR(LPM0_bits + GIE);
        		_DINT();
        	}while( I2CNumBytes && Ack );
        	_EINT();
    
        	SFRIFG1  &= ~WDTIFG;
        	SFRIE1 &= ~WDTIE;
        	WDTCTL = WDT_MDLY_32;
        	while( (UCB1CTL1 & UCTXSTP) && (!(SFRIFG1 & WDTIFG) ));		// I2C stop condition sent?
        	Stop_WDT();
       		UCB1CTL1 &= ~UCTXSTP;
        }//else if( n > 1 )
    	return Ack;
    }
    
    #pragma vector = USCI_B1_VECTOR
    __interrupt void USCI_B1_ISR(void)
    {
    	switch(__even_in_range(UCB1IV,0x0C)) {
    		case 0x00: // Vector 0: No interrupts
    						break;
    		case 0x02: // Vector 2: UCALIFG
    						// Arbitration-lost. When UCALIFG is set the UCMST bit is cleared and the I2C
    						// controller becomes a slave. This can only happen in a multimaster environment
    						break;
    		case 0x04: // Vector 4: UCNACKIFG  ---> Not-acknowledge interrupt.
    						// This flag is set when an acknowledge is expected, but is not received.
    						// UCNACKIFG is automatically cleared when a START condition  is received.
    						UCB1CTL1 |= UCTXSTP;			// I2C stop condition
    						Ack = 0;						// Return value
    						UCB1IFG &= ~UCNACKIFG;			// Clear interrupt flag
    						_low_power_mode_off_on_exit( );		// Exit LPM0
    						break;
    		case 0x06:  // Vector 6: UCSTTIFG
    						  // Start condition detected interrupt. UCSTTIFG only used in slave mode.
    					   break;
    		case 0x08:  // Vector 8: UCSTPIFG
    			              // Stop condition detected interrupt. UCSTPIFG only used in slave mode.
    			           break;
    	    //------------------------------------------------------------------------------------------------------------------------------------------------
    		case 0x0a:  // Vector 10: UCRXIFG
    						if( I2CNumBytes == 0 )
    						{
    							// I2CStop is used just to make sure that we leave LPM0 at the right time and not before
    							if( I2CStop )
    							{
    								_low_power_mode_off_on_exit( );		// Exit LPM0
    							}
    							else
    							{
    								UCB1CTL1 |= UCTXSTP;                // I2C stop condition
    								I2CStop = 1;						                // I2C stop condition sent
    							}
    						}
    						else
    						{
    							I2CNumBytes--;							// Decrement counter
    						}
    						*I2CRxBuffer++ = UCB1RXBUF;					// Read RX data. This automatically clears UCB0RXIFG
    						break;
    		//------------------------------------------------------------------------------------------------------------------------------------------------
    		case 0x0c:  // Vector 14: UCTXIFG
    						if( I2CNumBytes )							// Check counter
    						{
    							UCB1TXBUF = *I2CTxBuffer++;         	// Load TX buffer. This automatically clears UCB0TXIFG
    							I2CNumBytes--;							// Decrement counter
    						}
    						else
    						{
    							UCB1CTL1 |= UCTXSTP;                    // I2C stop condition
    							UCB1IFG &= ~UCTXIFG;                     // Clear USCI_B0 TX int flag
    							_low_power_mode_off_on_exit( );			// Exit LPM0
    						}
    						break;
    		//------------------------------------------------------------------------------------------------------------------------------------------------
    		default: break;
    	}
    }
    
    #pragma vector=WDT_VECTOR
     __interrupt void WDT_ISR(void)
    {
        /* clear the interrupt flag for Watchdog timer */
        SFRIFG1 &= ~WDTIFG;
        Ack = 0;
        _low_power_mode_off_on_exit( );			// Exit LPM0
    }
    
    
    #ifdef	I2C_PING
    uint16_t I2CPing( uint8_t sladdr )
    {
    	//
        UCB0I2CSA = sladdr;  					// Slave address (Right justified, bits6-0)
        //
        __disable_interrupt();
        UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP;	// I2C start condition, I2C TX mode, I2C stop condition
        while( UCB0CTL1 & UCTXSTP );			// I2C stop condition sent?
        Ack = !(UCB0STAT & UCNACKIFG);			// I2C start condition akd'd or not?
        __enable_interrupt();
    	//
    	return Ack;
    }
    #endif	/* !I2C_PING */
    

    hope this is useful to you.
    cheers

  • In my previous post, I have included the original source code. But when I am using MSP430F5529, I am using 

    #include "msp430f5529.h". Then should I conclude that those registers which are showing undefined in the compiler are actually not a part of MSP430F5529 but a part of MSP430G2553?

     

    Best,

    Saleha Khatun

     

  • sri-sri,

    Although it might be silly question to ask, I am asking that in your code,I have found that there is no main function.Then how I2CInit( void ),I2CWrite( uint8_t sladdr , uint8_t *data , uint16_t n ),I2CRead( uint8_t sladdr , uint8_t *data , uint16_t n ) is called?

    Best,

    Saleha

  • Well, this I have written as a I2C library.
    I have created a corresponding header file like I2C.h and I have included in my main programme. The beauty of developing libraries is you can just import the file and can run with any code.
    Any way, for you ,
    just cut and pate them in your code or modify your code in accordance with those functions.

  • SALEHA KHATUN said:

    In my previous post, I have included the original source code. But when I am using MSP430F5529, I am using 

    #include "msp430f5529.h". Then should I conclude that those registers which are showing undefined in the compiler are actually not a part of MSP430F5529 but a part of MSP430G2553?

     


    yes absolutely

  • SALEHA KHATUN said:
    Then should I conclude that those registers which are showing undefined in the compiler are actually not a part of MSP430F5529 but a part of MSP430G2553?

    Yes, the USCI module, while present in G2553 as well as the F5529, is implemented slightly different on both. On the G2553 (the whole 2xx family, G and F), it has been implemented to fit into the existing family structure regarding interrupts, while on 5x family, each module handles its interrupt son its own, with own interrupt registers. Also, some bit definitions, while doing the same, have changed the value. Finally, the A and B parts have their own interrupt in 5x family, for both, RX and TX, while on 2x family, they share an interrupt for RX and another for TX.

    Operation itself is almost identical on both families.

  • Hi sri-sri,

    What is the purpose of DINT() and EINT() function in your code?

  • :) well, it may not be necessary for your code, but I have been experiencing some data loss & unwanted halt etc in my I2C application. So I had these two instructions. The Idea here is,

    1. I want the ( Do,while) loop to run uptill all the bytes of data were received or sent. => while(I2Cnum && Ack) 
    2. upon entering the do loop, LPM0 is executed with GIE. Systems sleeps here and the Interrupts enables here, does the task of reading byte in ISR.
    3. Once the byte is read/written, LPM0 exit is executed in ISR. This makes the execution to move furthur from _bis_SR_(LPM0+GIE)  to _DINT();
    4. Remember here, if thre are still more byteswaiting to be read/written, system has to go in to loop to read further bytes. *** There is a possibility that there might be some port interrupt and that might change some registers or variables. I donot want that to happen. SO _DINT() disables all other interrupts and makes the loop run.
    5. Once the complete data is read/writen , _EINT enables all other interrupts.
    Note:  first instruction executed in loop is to enter sleep with GIE so, literally u have interrupts all the time except for the instruction where checking I2CNUM && ACK

  • sri-sri,

    Thank you for your previous reply. Now, I am talking about a given sample code of TI website. It is a master code transmitting data to slave.

    #include <msp430.h>

    unsigned char TXData;
    unsigned char TXByteCtr;

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P3SEL |= 0x03; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x48; // Slave Address is 048h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE; // Enable TX interrupt

    TXData = 0x01; // Holds TX data

    while (1)
    {
    TXByteCtr = 1; // Load TX byte counter

    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

    __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
    __no_operation(); // Remain in LPM0 until all data
    // is TX'd

    TXData++; // Increment data byte
    }
    }

    //------------------------------------------------------------------------------
    // The USCIAB0_ISR is structured such that it can be used to transmit any
    // number of bytes by pre-loading TXByteCtr with the byte count.
    //------------------------------------------------------------------------------
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 0: break; // Vector 0: No interrupts
    case 2: break; // Vector 2: ALIFG
    case 4: break; // Vector 4: NACKIFG
    case 6: break; // Vector 6: STTIFG
    case 8: break; // Vector 8: STPIFG
    case 10: break; // Vector 10: RXIFG
    case 12: // Vector 12: TXIFG
    if (TXByteCtr) // Check TX byte counter
    {
    UCB0TXBUF = TXData; // Load TX buffer
    TXByteCtr--; // Decrement TX byte counter
    }
    else
    {
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
    __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }
    break;
    default: break;
    }
    }

    My question is
    1.exactly when case 12 executes
    2. I am working with a sensor and try to read some data using MSP430F5529. In the sensor datasheet, it is given that the reading protocol is in the attachment.

    Suppose a sensor address is 1D. While reading from that sensor, the protocol says that from the master side, first one has to send the start signal, modified sensor address to write and so on. Now the modified address would be 3A to write. My question is while initializing I2c ,shuld i load the UCB0I2CSA with actual address and in ISR case 12, should I send the modified address?

  • A simple answer would be Modified address.

    But, What is the modified address? 


    I donot know/comprehend the slave u r using but let me brief you this. I have used LIS3DH accelerometer. This is a typical accelerometer. its address being 0x0011000. (Usually I2C devices support either 7/10 bit slave address). Depending on The write or read operation the LSB would become 1/0 this fills the entire 8 bits of a Byte.

    It looks like u were using F series of MSP micro controllers. Which mean u don't need to substitute this read or right bit in the Slave address it self. MSP I2C machine does this for your. 

    SALEHA KHATUN said:
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

    This instruction, makes ur I2C machine know that you want to write. UCTR = 1/0-> write/Read.

    Any way all u need to do is to put right justified address in. 
    Example 
    LIS3DH address in Data sheet ----- 0x0011000   
    Adress I pt in to I2C machine   ----  0x00011000 = 0x19

  • sri-sri,

    Thank you so much for your every previous reply. I have another concern about MSP430. I am giving the link below:

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/342469.aspx

    Can you please look into the issue and can provide any solution?

    Best,

    Saleha

  • sri-sri,

    Another thing is I have written my code to capture data from a sensor using MSP430F5529:

    #include <msp430.h>

    /*
    * main.c
    */
    unsigned char RXData;
    unsigned char tx;
    unsigned char rx;


    int main(void) {
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    P3SEL |= 0x03; // Assign I2C pins to USCI_B0 P3SEL |= 0x03;
    // Assign I2C pins to USCI_B0
    // void init_i2c(void);
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;

    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt

    while (1)
    {
    tx=1;
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    UCB0I2CSA = 0x3A; // Slave Address

    __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
    __no_operation(); // For debugger
    }

    return 0;
    }

    //void init_i2c(void)
    //{
    // UCB0CTL1 |= UCSWRST; // Enable SW reset
    // UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    // UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK
    // UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    // UCB0BR1 = 0;
    // UCB0I2CSA = 0x1D; // Slave Address is 048h
    // UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    // UCB0IE |= UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt
    //}

    // USCI_B0 Data ISR
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 0: break; // Vector 0: No interrupts
    case 2: break; // Vector 2: ALIFG
    case 4: break; // Vector 4: NACKIFG
    case 6: break; // Vector 6: STTIFG
    case 8: break; // Vector 8: STPIFG
    case 10: // Vector 10: RXIFG
    if(rx){
    RXData = UCB0RXBUF; // Get RX data
    __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    rx=0;
    if((UCB0IFG & UCNACKIFG))
    {
    UCB0CTL1 |= UCTXSTP;
    }
    }
    break;
    case 12:
    if(tx){

    if(!(UCB0IFG & UCNACKIFG)) //If slave acknowledge
    {
    UCB0I2CSA = 0x0F;
    }
    if(!(UCB0IFG & UCNACKIFG))
    {
    UCB0CTL1 |= UCTXSTT; // I2C Repeated Start
    UCB0I2CSA = 0x3B;
    }
    tx=0;
    rx=1;
    }

    break; // Vector 12: TXIFG
    default: break;
    }
    }

    But the problem is when I try to debug it in real time, It is not entering into ISR? Could you please explain me the

    matter?

    Again I am telling that to read from the sensor their protocol is like this?

  • try this modified code, you should enter in to ISR now.

    /*
    * main.c
    */
    unsigned char RXData;
    unsigned char tx;
    unsigned char rx;
    
    
    int main(void) {
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
    
    P3SEL    |= BIT2 + BIT1; // Assign I2C pins to USCI_B0 P3SEL |= 0x03;
    
    // MAke sure that you have right clock here I hope u r using around 1.2mHZ clock.
    
    //MAKE sure that you have opull up resistir they r inmportant in I2c
    
    // Assign I2C pins to USCI_B0
    // void init_i2c(void);
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    //for debugging change this line to 
    //---->UCB0IE |= UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt
    UCB0IE |= UCNACKIE + UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt
    
    while (1)
    {
    	tx=1;
    	UCB0I2CSA = 0x3A; // Slave Address
    	while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    	UCB0CTL1 |= UCTR + UCTXSTT; // I2C start condition
    	
    	//UCTR = 1/0 for Write/Read
    
    
    	__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
    	__no_operation(); // For debugger
    }
    
    return 0;
    }
    
    //void init_i2c(void)
    //{
    // UCB0CTL1 |= UCSWRST; // Enable SW reset
    // UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    // UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK
    // UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    // UCB0BR1 = 0;
    // UCB0I2CSA = 0x1D; // Slave Address is 048h
    // UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    // UCB0IE |= UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt
    //}
    
    // USCI_B0 Data ISR
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    	switch(__even_in_range(UCB0IV,12))
    	{
    	case 0: break; // Vector 0: No interrupts
    	case 2: break; // Vector 2: ALIFG
    	case 4: 
    			//if your slave is not acknowledged you will come here
    			UCB1IFG &= ~UCNACKIFG;          // Clear interrupt flag
    			break; // Vector 4: NACKIFG
    	case 6: break; // Vector 6: STTIFG
    	case 8: break; // Vector 8: STPIFG
    	case 10: // Vector 10: RXIFG
    			if(rx){
    				RXData = UCB0RXBUF; // Get RX data
    				__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    				rx=0;
    				if((UCB0IFG & UCNACKIFG))
    						UCB0CTL1 |= UCTXSTP;				
    			}
    			break;
    	case 12://TXIFG
    			if(tx){
    
    			if(!(UCB0IFG & UCNACKIFG)) //If slave acknowledge
    				UCB0I2CSA = 0x0F; ?? i dont understand this but any way I think u will get Interrupts now.
    				
    			if(!(UCB0IFG & UCNACKIFG))
    			{
    				UCB0CTL1 |= UCTXSTT; // I2C Repeated Start
    				UCB0I2CSA = 0x3B;
    			}
    			tx=0;
    			rx=1;
    			}
    			break; // Vector 12: TXIFG
    	default: break;
    	}
    }

  • sri-sri,

    Thank you very much. It is now going into ISR. But it stops at Case4. I mean after entering into case4 , it is not stepping further.Do you have any explanation for that?I also want to add another observation with that: While real time debugging, when it has just stepped into case 4 , the value of UCB0I2CSA is changed automatically to 3B which is the address to read.

    In my case, the slave address is 1D. But they modified it like for reading, it is 3B (In the figure below,it is SAD+R) and for writing , it is 3A (In the figure below,it is SAD+W). Here, 0F is the register address(In the figure below,it is SUB) from where I try to fetch the data. 

    Another thing is pull-up resistor is ensured.

    And I didn't understand what u meant by this line below:

    // MAke sure that you have right clock here I hope u r using around 1.2mHZ clock.?

    Thanks in advance.

  • hi,
    It is clearly the case that your slave address is WRONG.thats y I have modified case 4 in the earlir code and also enabled the UCA0NACK bit.
    :)
    As I said u , in my previous post. All you need to do is to put the slave address. DO not put slave adress for writing and slave address for reading.

    look here your slave address is
    0x1D  = 00011101 .

    you don't have to do this.
    0x3A  = 00111010 you have left shifted and added a 0 in LSb
    0x3B  = 00111011 here added 1 in LSB
    UCTR bit in I2C_write function and read function does this for you.
    understand here.

    	UCB0I2CSA = sladdr;//PUT 0X1D HERE  				// Slave address (Right justified, bits6-0)
        //
        UCB0CTL1 |= UCTR + UCTXSTT;			// Send I2C start condition, I2C TX mode
    
    //HERE YOU CAN CHECK THE I2C REGISTERS IT GETS MODIFIED OX3A.

    -------------------------------------------------------------------------------

        UCB0I2CSA = sladdr;		//0X1D ONLY DO NOT CHANGE			// Slave address (Right justified, bits6-0)
        //
        UCB0CTL1 &= ~UCTR;					// I2C RX mode
    
    // HERE CHCEK THE REGISTER AGAIN IT WILL BE MODIFIED TO 0X3B. IT IS DONE BY UCTR BIT.

    All you need to do is to have a different functions for reading and writing and leave the same slave address (0x1d) in both the functions but change UCTR bit. this will do every thing for you.

    TO make sure that you are using right I2C frequency you need to have proper SMCLK and so I have asked to you to check for the clock.

  • Thanks for your generous reply. If I have not misunderstood, I have written a code in easy format: But the problem is while real time debugging, I didn't see any changes in UCB0I2CSA. All the time, the value showed what I have assigned.

    #include <msp430.h>


    #define add 0x1D;


    int main(void) {

    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    //Initialization I2C

    P3SEL |= 0x03; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;

    UCB0CTL1 &= ~UCSWRST;// Clear SW reset, resume operation
    UCB0IE |= UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt

    while(1){

    int data;
    UCB0I2CSA = add;

    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT;// I2C in TX mode

    if(!(UCB0IFG & UCNACKIFG)) //If slave acknowledge
    {
    UCB0TXBUF=0x0F;

    }


    if(!(UCB0IFG & UCNACKIFG))
    {
    UCB0I2CSA = add;
    UCB0CTL1 |= UCTXSTT; // I2C Repeated Start
    UCB0CTL1 &= ~UCTR;
    }

    if(!(UCB0IFG & UCNACKIFG)){

    data=UCB0RXBUF;
    }

    if((UCB0IFG & UCNACKIFG))
    {
    UCB0CTL1 |= UCTXSTP;
    }


    }


    return 0;
    }

  • Hey,

    why would the address in UCB0I2CSA change?

     

    SALEHA KHATUN said:
    I didn't see any changes in UCB0I2CSA.

    It wont change. If you want to debug in RT and see what's happening.
    See this way. 


    1.set up a break point right after  
                      UCB0CTL1 |=  UCTR + UCTXSTT; 
       in I2C Write function.

    2.set up a brak poit after
                      UCB0CTL &= ~UCTR;
    in I2C read function.

    after the execution halted at either of this this lines. Expand Special function register from registers view and further expand IFG2 register.

    now hit F6, you will see either of UCB0TXIFG or UCB0RXIFG being set. Mean you are transmitting/Receiving.

    point 1. You will see UCB0TXIFG being set for I2c WRITE FUNCTION. Which explains you how I2C machine works without changing / modifying the slave address.

    SALEHA KHATUN said:
    If I have not misunderstood, I have written a code in easy format:

    You are forbidden to write such slave addressing. You should only use right justified slave address.

    Cheers.

  • Ahh sorry yaaar!,


    My apologies for bringing this confusion in to you.

    sri-sri said:
    UCB0I2CSA = sladdr; //0X1D ONLY DO NOT CHANGE // Slave address (Right justified, bits6-0) // UCB0CTL1 &= ~UCTR; // I2C RX mode // HERE CHCEK THE REGISTER AGAIN IT WILL BE MODIFIED TO 0X3B. IT IS DONE BY UCTR BIT.

    I dint really mean that the slave address bits being modified, I mean it serves that task. Apologies for that.I mean to say, that the purpose of reading from OR writing is being served and check the registers.


    Yes the wording says as if the values in slave address being changed.

    I am so sorry for that.

  • Hi,

    just to check the change of the flag of TX and RX, I have written the below code. For my case,see the screenshot of Special function register:

    and the screenshot of the flag register that I have used to check:

    My code to check the flag only:

    #include <msp430.h>

    unsigned char RXData;

    unsigned char add;

    #define add 0x1D;

    i2c_init()
    {
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;

    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    //for debugging change this line to
    UCB0IE |= UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt
    //UCB0IE |= UCNACKIE + UCTXIE+UCRXIE; // Enable Tx and Rx Interrupt
    }

    i2c_tx()
    {
    UCB0I2CSA = add;
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT;// I2C in TX mode
    UCB0TXBUF=0x0F;

    }

    i2c_rx()
    {
    UCB0I2CSA = add;
    UCB0CTL1 |= UCTXSTT; // I2C Repeated Start
    UCB0CTL1 &= ~UCTR;
    RXData=UCB0RXBUF;
    }

    int main(void) {

    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    P3SEL |= BIT2 + BIT1; // Assign I2C pins to USCI_B0 P3SEL |= 0x03;

    i2c_init();

    while (1)
    {

    i2c_tx();
    i2c_rx();

    //__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
    //__no_operation(); // For debugger
    }

    return 0;
    }

    }

    The Result:

    After Tx function:bit changed:

    after rx function: bit not changed:

    Please explain....:)

**Attention** This is a public forum