All pastes #2106979 Raw Edit

MSP430 Hardware I2C Problem

public c v1 · immutable
#2106979 ·published 2012-01-28 07:13 UTC
rendered paste body
/* I2C Module */#define I2C_FLAG_TX_DONE           0x1#define I2C_FLAG_RX_DONE           0x2#define I2C_FLAG_ERROR             0x80//#define I2C_LOG                    1#ifdef I2C_LOG#define i2c_log(x) log(x, 0);#else#define i2c_log(x)#endif#define I2C_PROTOCOL_STATE           1#ifdef I2C_PROTOCOL_STATE#define I2C_STATE_S_TX         0x01#define I2C_STATE_TX_D1        0x02#define I2C_STATE_TX_DX        0x04#define I2C_STATE_S_RX         0x08#define I2C_STATE_RX_D1        0x10#define I2C_STATE_RX_DX        0x20#define I2C_STATE_P            0x40volatile uint8_t i2c_state = 0;#define i2c_resetState (i2c_state=0)#define i2c_state(x) (i2c_state|=(x))#else#define i2c_resetState(x)#define i2c_state(x)#endifvolatile uint8_t i2c_flags = 0;volatile const uint8_t* i2c_txBuffer;volatile uint8_t* i2c_rxBuffer;volatile uint8_t i2c_inBufferIndex = 0;volatile uint8_t i2c_txLength = 0;volatile uint8_t i2c_rxLength = 0;int i2c_TXRX(const uint8_t* txData, uint8_t txDataLength, uint8_t* rxData, uint8_t rxDataLength) {    i2c_log("I2C TXRX\r\n");    i2c_txBuffer = txData;    i2c_rxBuffer = rxData;    i2c_txLength = txDataLength;    i2c_rxLength = rxDataLength;    i2c_inBufferIndex = 0;    i2c_flags = 0;    i2c_resetState;    i2c_log(" I2C <-TX START-\r\n");    UCB0CTL1 |= UCTR; // Transmitter mode    trigger();    while( UCB0STAT & UCBBUSY)        ;    i2c_state(I2C_STATE_S_TX);    UCB0CTL1 |= UCTXSTT; // START condition    while( 1 )        if( i2c_flags & I2C_FLAG_ERROR )            return 0;        else if( i2c_flags & I2C_FLAG_RX_DONE )            return 1;}void i2cTransmitInterrupt() {    IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX interrupt flag    i2c_log("\r\n >> I2C TX IR\r\n");    if( !(i2c_flags & I2C_FLAG_ERROR) && !(i2c_flags & I2C_FLAG_TX_DONE) ) {        if( !(i2c_flags & I2C_FLAG_TX_DONE) && i2c_txLength > 0 ) { // TX            if( i2c_inBufferIndex < i2c_txLength ) {                uint16_t data = i2c_txBuffer[i2c_inBufferIndex++];                //while( !(UCB0STAT & UCSCLLOW) ) // Wait for SCL _held_ low                 //   ;                //__delay_cycles(140); <- DOESN"T WORK WITHOUT THOSE                UCB0TXBUF = data;                //__delay_cycles(140); <- DOESN"T WORK WITHOUT THOSE                i2c_state(i2c_inBufferIndex == 1 ? I2C_STATE_TX_D1 : I2C_STATE_TX_DX);#ifdef I2C_LOG                char text[32];                sprintf(text, "  I2C <-%d/0x%x-\r\n", data, data);                log(text, 1);#endif            }            if( i2c_inBufferIndex == i2c_txLength ) { // Last TX byte                i2c_flags |= I2C_FLAG_TX_DONE;                if( i2c_rxLength < 1 ) {                    i2c_log("  I2C <-TX STOP-\r\n");                    UCB0CTL1 &= UCTXSTP; // STOP condition                    i2c_state(i2c_inBufferIndex == 1 ? I2C_STATE_TX_D1 : I2C_STATE_TX_DX);                }            }        }        if( !(UCB0CTL1 & UCTXSTT) && i2c_rxLength > 0 && (i2c_flags & I2C_FLAG_TX_DONE) ) {            i2c_inBufferIndex = 0;            i2c_log("  I2C <-RX START-\r\n");            UCB0CTL1 &= ~UCTR; // Receiver mode            while( UCB0STAT & UCBBUSY)                ;            UCB0CTL1 |= UCTXSTT; // START condition            IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX interrupt flag            i2c_state(I2C_STATE_P);            if( i2c_rxLength == 1 ) { // Special case: send stop during RX                while( UCB0CTL1 & UCTXSTT )                    // Wait until RX starts                    ;                i2c_log("  I2C <-RX STOP-\r\n");                UCB0CTL1 |= UCTXSTP; // STOP condition                i2c_state(I2C_STATE_P);            }        }    }    i2c_log(" << I2C TX IR\r\n");}void i2cReceiveInterrupt() {    IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 RX interrupt flag    i2c_log("\r\n >> I2C RX IR\r\n");    if( !(i2c_flags & I2C_FLAG_ERROR) ) {        if( i2c_inBufferIndex >= i2c_rxLength ) { // Unexpected RX byte            i2c_flags |= I2C_FLAG_ERROR;            i2c_log(" I2C ERROR: extra RX byte\r\n");        } else {            uint16_t data = UCB0RXBUF;            i2c_state(i2c_inBufferIndex < 1 ? I2C_STATE_RX_D1 : I2C_STATE_RX_DX);            i2c_rxBuffer[i2c_inBufferIndex++] = data;#ifdef I2C_LOG            char text[32];            sprintf(text, "  I2C -%d/0x%x-> \r\n", data, data);            log(text, 1);#endif            if( i2c_inBufferIndex == i2c_rxLength - 1 ) { // Last RX set up                if( i2c_rxLength != 1 ) { // If 1 then this was already handled by i2cTransmitInterrupt()                    i2c_log("  I2C <-RX STOP-\r\n");                    UCB0CTL1 |= UCTXSTP; // STOP condition                    i2c_state(I2C_STATE_P);                }            } else if( i2c_inBufferIndex == i2c_rxLength ) // Last RX byte received                i2c_flags |= I2C_FLAG_RX_DONE;        }    }    i2c_log(" << I2C RX IR\r\n");}void i2cNotAckInterrupt() {    i2c_flags |= I2C_FLAG_ERROR;    i2c_log("I2C ERROR: NACK\r\n");    UCB0STAT &= ~UCNACKIFG;}void i2cArbitrationLostInterrupt() {    i2c_flags |= I2C_FLAG_ERROR;    i2c_log("I2C ERROR: ARB LOST\r\n");    UCB0STAT &= ~UCALIFG;}/* End I2C Module */