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.
I'm using I2C to communicate with an I2C slave. The code first tells the slave which register it wants to read, then reads from that address using a repeat start. Now this code was working, but now has stopped working partly because I removed breakpoints from the code. It is stopping at next to last line below, checking to make sure Start was sent.
I have read that it could be a CCS issue, so I have re-installed (CCSv6.1.1) but no change in behavior.
void Read_ID(void)
{
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
WriteByte(ID_ADDR);
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
__no_operation(); // Remain in LPM0 until all data are sent
UCB0CTL1 ^= UCTR; // Switch to receive.
UCB0CTL1 |= UCTXSTT; // Send Repeat START
while(UCB0CTL1 & UCTXSTT); // Start condition sent?
UCB0CTL1 |= UCTXSTP; // I2C stop condition
}
Hi,
There was an issue with START condition checking in the default driverlib library I2C repeated start. Refer to the attached I2C code as it fixes the issue. In the meantime, I will try to find out why the breakpoint will make the code work as intended.
Sincerely,
Sean
Hi Sean,
I should have been more detailed in my original post and mentioned the specific MSP430 I am using, and so may have misled you when I mentioned driver code.
I am using a MSP430F55xx and the specific TI I2C driver file I am referring to is "MSP430F55xx_uscib0_i2c_04.c." The file is also attached. In this file, you will see the check for Repeat START sent, followed by the STOP command.
Thanks.
/* --COPYRIGHT--,BSD_EX * Copyright (c) 2012, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************* * * MSP430 CODE EXAMPLE DISCLAIMER * * MSP430 code examples are self-contained low-level programs that typically * demonstrate a single peripheral function or device feature in a highly * concise manner. For this the code may rely on the device's power-on default * register values and settings such as the clock configuration and care must * be taken when combining code from several examples to avoid potential side * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware * for an API functional library-approach to peripheral configuration. * * --/COPYRIGHT--*/ //****************************************************************************** // MSP430F552x Demo - USCI_B0 I2C Master RX single bytes from MSP430 Slave // // Description: This demo connects two MSP430's via the I2C bus. The master // reads from the slave. This is the MASTER CODE. The data from the slave // transmitter begins at 0 and increments with each transfer. The received // data is in R5 and is checked for validity. If the received data is // incorrect, the CPU is trapped and the P1.0 LED will stay on. The USCI_B0 // RX interrupt is used to know when new data has been received. // ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz // // ***to be used with "MSP430F55xx_uscib0_i2c_05.c" *** // // /|\ /|\ // MSP430F5529 10k 10k MSP430F5529 // slave | | master // ----------------- | | ----------------- // -|XIN P3.0/UCB0SDA|<-|----+->|P3.0/UCB0SDA XIN|- // | | | | | 32kHz // -|XOUT | | | XOUT|- // | P3.1/UCB0SCL|<-+------>|P3.1/UCB0SCL | // | | | P1.0|--> LED // // Bhargavi Nisarga // Texas Instruments Inc. // April 2009 // Built with CCSv4 and IAR Embedded Workbench Version: 4.21 //****************************************************************************** #include <msp430.h> unsigned char RXData; unsigned char RXCompare; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1OUT &= ~0x01; // P1.0 = 0 P1DIR |= 0x01; // P1.0 output 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; UCB0I2CSA = 0x48; // Slave Address is 048h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB0IE |= UCRXIE; // Enable RX interrupt RXCompare = 0x0; // Used to check incoming data while (1) { while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent UCB0CTL1 |= UCTXSTT; // I2C start condition while(UCB0CTL1 & UCTXSTT); // Start condition sent? UCB0CTL1 |= UCTXSTP; // I2C stop condition __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts __no_operation(); // For debugger if (RXData != RXCompare) // Trap CPU if wrong { P1OUT |= 0x01; // P1.0 = 1 while(1); } RXCompare++; // Increment correct RX value } } // USCI_B0 Data ISR #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) #else #error Compiler not supported! #endif { 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 RXData = UCB0RXBUF; // Get RX data __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU break; case 12: break; // Vector 12: TXIFG default: break; } }
Hello,
I've referenced your code and the sample master RX MSPware example and do note the check conditions, I have reached out and asked for working sample code relating to repeat start and will get back to you ASAP.
Sincerely,
Sean
Hi,
I've also asked around for a working example of repeat start, please consult the USCIB0_I2C_RX_MultiByte_Poll function in the attached code.
/*-===========================================================================-- --- MODULE : uscib0_i2c_drv.c --- VERSION : 2.20 ---===========================================================================--- --- Environment : Device : MSP430G2553 --- Compiler/Assembler/IDE : CCS V5.2 ---=========================================================================---*/ #include "msp430g2553.h" #include "application.h" #include "spi_il.h" #include "stdtypes.h" //***** Definitions ***** typedef enum { OK = 0, ERROR }I2C_BusState_T; //***** Function Prototypes ***** #ifndef USING_I2C_INT I2C_BusState_T USCIB0RX_ISR_Poll(void); I2C_BusState_T USCIB0TX_ISR_Poll(void); #endif //***** Global Data ***** u08 locSlaveAddr; u08 TXByteCtr; u08 RXByteCtr; u08 *PTxData; u08 *PRxData; Boolean MultiByteReadFG = FALSE; Boolean WaitforSTPCondition = FALSE; #ifdef USING_I2C_INT Boolean RPTCondition = FALSE; #endif /*********************************************************** Function: USCIB0_I2C_Init */ void USCIB0_I2C_Init(void) { P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0 P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0 IE2 &= ~UCB0RXIE; // Disable RX interrupt IE2 &= ~UCB0TXIE; // Disable TX interrupt UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 0xA0; // fSCL = SMCLK/160 = ~100kHz // UCB0BR0 = 0x28; // fSCL = SMCLK/40 = ~400kHz UCB0BR1 = 0; } /*********************************************************** Function: USCIB0_I2C_Ready */ I2C_BusState_T USCIB0_I2C_Ready(void) { // Configure a 50ms Timeout Timeout(5); while ( ( UCB0STAT & UCBBUSY ) && (Timer_CCR1_Get_Timeout_Counts()) ); if (Timer_CCR1_Get_Timeout_Counts() != 0) { return (OK); } else { Timer_CCR1_Stop_Timeout(); return (ERROR); } } /*********************************************************** Function: USCIB0_I2C_SetSlaveAddress */ u08 USCIB0_I2C_SetSlaveAddress(u08 address) { u08 returnValue = 0; #ifdef USING_I2C_INT u08 ie2_bak; u08 slaveadr_bak; u08 ucb0i2cie; /* Verify that Slave is present */ ucb0i2cie = UCB0I2CIE; // store old UCB0I2CIE ie2_bak = IE2; // store IE2 register slaveadr_bak = UCB0I2CSA; // store old slave address UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0I2CIE &= ~ UCNACKIE; // no NACK interrupt UCB0I2CSA = address; // set slave address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation IE2 &= ~(UCB0TXIE + UCB0RXIE); // no RX or TX interrupts // Configure a 50ms Timeout Timeout(5); UCB0TXBUF = 0xFF; UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP; // I2C TX, start and stop condition while ( (UCB0CTL1 & UCTXSTP) && (Timer_CCR1_Get_Timeout_Counts()) ); // wait for STOP condition if (Timer_CCR1_Get_Timeout_Counts()) { returnValue = !(UCB0STAT & UCNACKIFG); TXByteCtr = 0; RXByteCtr = 0; } else { Timer_CCR1_Stop_Timeout(); } UCB0CTL1 |= UCSWRST; // Enable SW reset IE2 = ie2_bak; // restore IE2 UCB0I2CSA = slaveadr_bak; // restore old slave address UCB0I2CIE = ucb0i2cie; // restore old UCB0CIE #else UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0I2CIE &= ~ UCNACKIE; // no NACK interrupt UCB0I2CSA = address; // set slave address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation // Configure a 50ms Timeout Timeout(5); UCB0TXBUF = 0xFF; UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP; // I2C TX, start and stop condition while ( (UCB0CTL1 & UCTXSTP) && (Timer_CCR1_Get_Timeout_Counts()) ); // wait for STOP condition if (Timer_CCR1_Get_Timeout_Counts()) { returnValue = !(UCB0STAT & UCNACKIFG); TXByteCtr = 0; RXByteCtr = 0; } else { Timer_CCR1_Stop_Timeout(); } UCB0CTL1 |= UCSWRST; // Enable SW reset #endif /* Set the new Slave address*/ locSlaveAddr = address; return (returnValue); // return whether or not a NACK occurred } #ifdef USING_I2C_INT /*********************************************************** Function: USCIB0_I2C_TX_Init */ void USCIB0_I2C_TX_Init(u08 SlaveAddress) { IE2 &= ~UCB0RXIE; UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0I2CSA = SlaveAddress; // Slave Address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation IE2 |= UCB0TXIE; // Enable TX interrupt } /*********************************************************** Function: USCIB0_I2C_RX_Init */ void USCIB0_I2C_RX_Init(u08 SlaveAddress) { IE2 &= ~UCB0TXIE; UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0I2CSA = SlaveAddress; // Slave Address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation IE2 |= UCB0RXIE; // Enable RX interrupt } /*********************************************************** Function: USCIB0_I2C_TX_MultiByte */ u08 USCIB0_I2C_TX_MultiByte(u08 *i2cArray, u08 NumBytes) { I2C_BusState_T locBusState = ERROR; Boolean locRPTCondition = FALSE; u08 ret = 1; // Store a copy of RPTCondition locRPTCondition = RPTCondition; // Configure a 50ms Timeout Timeout(5); // Wait for bus to be free while ( (UCB0CTL1 & UCTXSTP) || ( (UCB0STAT & UCBBUSY) && (Timer_CCR1_Get_Timeout_Counts()) ) ); if (Timer_CCR1_Get_Timeout_Counts()) { USCIB0_I2C_TX_Init(locSlaveAddr); // re-init i2c with new slave address // Wait for bus to be free locBusState = USCIB0_I2C_Ready(); if ( locBusState == OK ) { /* start transmitting */ PTxData = i2cArray; // TX array start address TXByteCtr = NumBytes; // Load TX byte counter UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition // Reset Timeout 50ms Timeout(5); while ( (UCB0CTL1 & UCTXSTT) && (Timer_CCR1_Get_Timeout_Counts()) ); if (Timer_CCR1_Get_Timeout_Counts() != 0) { // Reset Timeout 50ms Timeout(5); // Ensure stop condition got sent while ( (!WaitforSTPCondition) && (Timer_CCR1_Get_Timeout_Counts()) ); if (!locRPTCondition) { // Avoid STOP condition overrun if multiple i2c are sent one after the other (contiguously) while ( (UCB0CTL1 & UCTXSTP) && (Timer_CCR1_Get_Timeout_Counts()) ); // wait for STOP condition } } } } // Check if there was a TimeOut if ( (!Timer_CCR1_Get_Timeout_Counts()) || (locBusState == ERROR) ) { /* Send I2C to bus off */ Send_I2C_to_BusOFF(); ret = 0; } else { Timer_CCR1_Stop_Timeout(); } WaitforSTPCondition = FALSE; return (ret); } /*********************************************************** Function: USCIB0_I2C_RX_MultiByte */ u08 USCIB0_I2C_RX_MultiByte(u08 *i2cArray, u08 RxNumBytes, u08 TxNumBytes) { I2C_BusState_T locBusState = ERROR; u08 ret = 1; // Configure a 50ms Timeout Timeout(5); // Wait for bus to be free while (MultiByteReadFG || (UCB0CTL1 & UCTXSTP) || ( (UCB0STAT & UCBBUSY) && (Timer_CCR1_Get_Timeout_Counts()) )); if (Timer_CCR1_Get_Timeout_Counts()) { MultiByteReadFG = TRUE; // Multi-byte transaction starting // Reset Timeout 50ms Timeout(5); RPTCondition = TRUE; USCIB0_I2C_TX_MultiByte(i2cArray,TxNumBytes); // Write the read register to slave device USCIB0_I2C_RX_Init(locSlaveAddr); // Initialize I2C read operation PRxData = (i2cArray + TxNumBytes); // RX array start address if (RxNumBytes == 1) { RXByteCtr = 0; MultiByteReadFG = FALSE; UCB0CTL1 |= UCTXSTT; // Send I2C start condition while ( (UCB0CTL1 & UCTXSTT) && (Timer_CCR1_Get_Timeout_Counts()) ); if (Timer_CCR1_Get_Timeout_Counts() != 0) { UCB0CTL1 |= UCTXSTP; // I2C stop condition } } else { RXByteCtr = RxNumBytes - 2; // Load RX byte counter UCB0CTL1 |= UCTXSTT; // Send I2C start condition } // Wait until I2C is ready locBusState = USCIB0_I2C_Ready(); } // Check if there was a TimeOut if ( (!Timer_CCR1_Get_Timeout_Counts()) || (locBusState == ERROR) ) { /* Send I2C to bus off */ ret = 0; Send_I2C_to_BusOFF(); } else { Timer_CCR1_Stop_Timeout(); } return (ret); } /*********************************************************** Function: USCIB0_I2C_RX_SingleByte */ u08 USCIB0_I2C_RX_SingleByte(u08 *i2cArray) { I2C_BusState_T locBusState = ERROR; u08 ret = 1; // Wait for bus to be free locBusState = USCIB0_I2C_Ready(); if ( locBusState == OK ) { USCIB0_I2C_RX_Init(locSlaveAddr); // Initialize I2C read operation // Set Rx Buffer PRxData = i2cArray; // Clear Rx Counter RXByteCtr = 0; UCB0CTL1 |= UCTXSTT; // Send I2C start condition // Configure a 50ms Timeout Timeout(5); while ( (UCB0CTL1 & UCTXSTT) && (Timer_CCR1_Get_Timeout_Counts()) ); if (Timer_CCR1_Get_Timeout_Counts() != 0) { UCB0CTL1 |= UCTXSTP; // I2C stop condition // Wait until I2C is ready locBusState = USCIB0_I2C_Ready(); } } // Check if there was a TimeOut if ( (!Timer_CCR1_Get_Timeout_Counts()) || (locBusState == ERROR) ) { /* Send I2C to bus off */ ret = 0; Send_I2C_to_BusOFF(); } else { Timer_CCR1_Stop_Timeout(); } return (ret); } /*********************************************************** Function: USCIB0TX_ISR */ void USCIB0TX_ISR(void) { if (IFG2 & UCB0RXIFG) // RX - if a receive interrupt (byte received in buffer) { if ( RXByteCtr > 0 ) { *PRxData = UCB0RXBUF; // Load RX buffer PRxData++; RXByteCtr--; // Decrement TX byte counter } else if ( (RXByteCtr == 0) && (MultiByteReadFG) ) // Check RX byte counter { *PRxData = UCB0RXBUF; // Load RX buffer PRxData++; UCB0CTL1 |= UCTXSTP; // I2C stop condition MultiByteReadFG = FALSE; // Multi-byte transaction done } else { *PRxData = UCB0RXBUF; // Load RX buffer } } else { if (TXByteCtr) // Check TX byte counter { UCB0TXBUF = *PTxData; // Load TX buffer PTxData++; TXByteCtr--; // Decrement TX byte counter } else if (RPTCondition) { UCB0TXBUF = 0xFF; // Dummy write, it will not go out due to the RPT condition RPTCondition = FALSE; } else { UCB0CTL1 |= UCTXSTP; // I2C stop condition WaitforSTPCondition = TRUE; IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag } } } #else /*********************************************************** Function: USCIB0_I2C_TX_Init_Poll */ void USCIB0_I2C_TX_Init_Poll(u08 SlaveAddress) { IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0I2CSA = SlaveAddress; // Slave Address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation } /*********************************************************** Function: USCIB0_I2C_RX_Init_Poll */ void USCIB0_I2C_RX_Init_Poll(u08 SlaveAddress) { IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 RX int flag UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0I2CSA = SlaveAddress; // Slave Address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation } /*********************************************************** Function: USCIB0_I2C_TX_MultiByte_Poll */ u08 USCIB0_I2C_TX_MultiByte_Poll(u08 *i2cArray, u08 NumBytes) { I2C_BusState_T locBusState = ERROR; u08 ret = 1; USCIB0_I2C_TX_Init_Poll(locSlaveAddr); // re-init i2c with new slave address // Wait for bus to be free locBusState = USCIB0_I2C_Ready(); if ( locBusState == OK ) { /* start transmitting */ PTxData = i2cArray; // TX array start address TXByteCtr = NumBytes; // Load TX byte counter UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition UCB0TXBUF = *PTxData; // Load TX buffer PTxData++; TXByteCtr--; // Decrement TX byte counter // Reset Timeout 50ms Timeout(5); while ( (UCB0CTL1 & UCTXSTT) && (Timer_CCR1_Get_Timeout_Counts()) ); if (TXByteCtr != 0) { // Poll ISR locBusState = USCIB0TX_ISR_Poll(); } else { UCB0CTL1 |= UCTXSTP; // I2C stop condition } if (Timer_CCR1_Get_Timeout_Counts() != 0) { // Reset Timeout 50ms Timeout(5); // Ensure stop condition got sent while ( (UCB0CTL1 & UCTXSTP) && (Timer_CCR1_Get_Timeout_Counts()) ); } } // Check if there was a TimeOut if ( (!Timer_CCR1_Get_Timeout_Counts()) || (locBusState == ERROR) ) { /* Send I2C to bus off */ Send_I2C_to_BusOFF(); ret = 0; } else { Timer_CCR1_Stop_Timeout(); } return (ret); } /*********************************************************** Function: USCIB0_I2C_RX_MultiByte_Poll */ u08 USCIB0_I2C_RX_MultiByte_Poll(u08 *i2cArray, u08 RxNumBytes, u08 TxNumBytes) { I2C_BusState_T locBusState = ERROR; u08 ret = 1; // Configure a 50ms Timeout Timeout(5); // Wait for bus to be free while (MultiByteReadFG || (UCB0CTL1 & UCTXSTP) || ( (UCB0STAT & UCBBUSY) && (Timer_CCR1_Get_Timeout_Counts()) )); if (Timer_CCR1_Get_Timeout_Counts()) { MultiByteReadFG = TRUE; // Multi-byte transaction starting // Reset Timeout 50ms Timeout(5); USCIB0_I2C_TX_MultiByte_Poll(i2cArray,TxNumBytes); // Write the read register to slave device USCIB0_I2C_RX_Init_Poll(locSlaveAddr); // Initialize I2C read operation PRxData = (i2cArray + TxNumBytes); // RX array start address if (RxNumBytes == 1) { RXByteCtr = 0; MultiByteReadFG = FALSE; UCB0CTL1 |= UCTXSTT; // Send I2C start condition while ( (UCB0CTL1 & UCTXSTT) && (Timer_CCR1_Get_Timeout_Counts()) ); UCB0CTL1 |= UCTXSTP; // I2C stop condition // Poll ISR locBusState = USCIB0RX_ISR_Poll(); if (Timer_CCR1_Get_Timeout_Counts() != 0) { // Wait until I2C is ready locBusState = USCIB0_I2C_Ready(); IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 RX int flag } } else { RXByteCtr = RxNumBytes - 2; // Load RX byte counter UCB0CTL1 |= UCTXSTT; // Send I2C start condition while ( (UCB0CTL1 & UCTXSTT) && (Timer_CCR1_Get_Timeout_Counts()) ); // Poll ISR locBusState = USCIB0RX_ISR_Poll(); } // Wait until I2C is ready locBusState = USCIB0_I2C_Ready(); } // Check if there was a TimeOut if ( (!Timer_CCR1_Get_Timeout_Counts()) || (locBusState == ERROR) ) { /* Send I2C to bus off */ ret = 0; Send_I2C_to_BusOFF(); } else { Timer_CCR1_Stop_Timeout(); } return (ret); } /*********************************************************** Function: USCIB0_I2C_RX_SingleByte_Poll */ u08 USCIB0_I2C_RX_SingleByte_Poll(u08 *i2cArray) { I2C_BusState_T locBusState = ERROR; u08 ret = 1; // Wait for bus to be free locBusState = USCIB0_I2C_Ready(); if ( locBusState == OK ) { USCIB0_I2C_RX_Init_Poll(locSlaveAddr); // Initialize I2C read operation // Set Rx Buffer PRxData = i2cArray; // Clear Rx Counter RXByteCtr = 0; UCB0CTL1 |= UCTXSTT; // Send I2C start condition // Configure a 50ms Timeout Timeout(5); while ( (UCB0CTL1 & UCTXSTT) && (Timer_CCR1_Get_Timeout_Counts()) ); // Poll ISR UCB0CTL1 |= UCTXSTP; // I2C stop condition locBusState = USCIB0RX_ISR_Poll(); if (Timer_CCR1_Get_Timeout_Counts() != 0) { // Wait until I2C is ready locBusState = USCIB0_I2C_Ready(); IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 RX int flag } } // Check if there was a TimeOut if ( (!Timer_CCR1_Get_Timeout_Counts()) || (locBusState == ERROR) ) { /* Send I2C to bus off */ ret = 0; Send_I2C_to_BusOFF(); } else { Timer_CCR1_Stop_Timeout(); } return (ret); } /*********************************************************** Function: USCIB0RX_ISR_Poll */ I2C_BusState_T USCIB0RX_ISR_Poll(void) { Boolean Rx_ISR = TRUE; // Reset Timeout 50ms Timeout(5); while (Rx_ISR) { // RX - if a receive interrupt (byte received in buffer) while ( ((IFG2 & UCB0RXIFG) == 0x00 ) && (Timer_CCR1_Get_Timeout_Counts()) ); if (!Timer_CCR1_Get_Timeout_Counts()) { return (ERROR); } IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 RX int flag if ( RXByteCtr > 0 ) { *PRxData = UCB0RXBUF; // Load RX buffer PRxData++; RXByteCtr--; // Decrement TX byte counter } else if ( (RXByteCtr == 0) && (MultiByteReadFG) ) // Check RX byte counter { *PRxData = UCB0RXBUF; // Load RX buffer PRxData++; UCB0CTL1 |= UCTXSTP; // I2C stop condition MultiByteReadFG = FALSE; // Multi-byte transaction done // Rx_ISR = FALSE; } else { *PRxData = UCB0RXBUF; // Load RX buffer Rx_ISR = FALSE; } } return (OK); } /*********************************************************** Function: USCIB0TX_ISR_Poll */ I2C_BusState_T USCIB0TX_ISR_Poll(void) { Boolean Tx_ISR = TRUE; // Reset Timeout 50ms Timeout(5); while (Tx_ISR) { // TX - Wait for the data is transferred from the buffer into the shift register while ( ((IFG2 & UCB0TXIFG) == 0x00 ) && (Timer_CCR1_Get_Timeout_Counts()) ); if (!Timer_CCR1_Get_Timeout_Counts()) { return (ERROR); } IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag if (TXByteCtr > 0) // Check TX byte counter { UCB0TXBUF = *PTxData; // Load TX buffer PTxData++; TXByteCtr--; // Decrement TX byte counter } else { UCB0CTL1 |= UCTXSTP; // I2C stop condition Tx_ISR = FALSE; } } return (OK); } #endif /*-===========================================================================-- --- Version Information --- 1.00 (08/31/2012) - Initial Release --- 1.10 (10/26/2012) - Check for the I2C slave before sending any message in --- USCIB0_I2C_SetSlaveAddress, change it from void to u08 --- 1.20 (11/14/2012) - Added an extra parameter on USCIB0_I2C_RX_MultiByte --- (TxNumBytes), if more than 1 byte is needed before --- the repeated start --- Created USCIB0_I2C_RXByte_Test, for FuelGauge Debug --- 1.30 (11/20/2012) - Removed USCIB0_I2C_RXByte_Test and created --- USCIB0_I2C_RX_SingleByte, used by the FuelGauge --- 1.40 (12/07/2012) - Reduced I2C clock to 100KHz, for testing purposes --- 1.50 (12/14/2012) - Replaced the delays on USCIB0_I2C_RX_MultiByte and --- USCIB0_I2C_RX_SingleByte with USCIB0_I2C_Ready. --- 1.60 (12/21/2012) - Updated the I2C BusOff implementation. --- 1.70 (01/30/2013) - Added Boot Loader support. Relocated interrupt vectors --- to app_vect.c --- 1.80 (02/25/2013) - Changed Shared_Data to AppFlags. --- 1.90 (03/26/2013) - Speed-up that Slave is present check --- 2.00 (04/10/2013) - Changed variable name AppFlags to StatusFlags. --- 2.10 (04/22/2013) - Implemented I2C timeouts, avoid "hanging" condition. --- 2.20 (06/21/2013) - Included PACE updates from SW V4.21. --- ---=========================================================================---*/
Sincerely,
Sean
**Attention** This is a public forum