Quantcast
Channel: Forums - Recent Threads
Viewing all articles
Browse latest Browse all 262198

MSP430BT5190 I2C code problem

$
0
0

Hi,

I'm trying to use I2C on an MSP430BT5190 (master) to read a MLX90620 IR sensor (slave) and I'm having trouble.  I'm following the "MSP430F541xA, MSP430F543xA Code Examples" but they seem to be incomplete for what I want to do.  All I2C commands follow the specification, and consist of master transmission of 1 or more bytes, followed by either a stop or a repeated start receive of 2 or more bytes (up to 256).  My EEPROM read works find but some of the read commands don't produce the expected data (verified using I2C from an arduino).  I didn't particularly want to use mspware because my EEPROM read command blew up to over 40 lines (if I ignore the ISR code) - is that normal? Below I've listed my code, MLX90620_read_EEPROM() gives the expected values from the receive command, but the MLX90620_read_TA() command does not.  I suspect there is a problem with the I2C receive code because I've used my arduino to slowly build up the I2C o-scope like view and its hard to tell but it looks like the 8th bit of each receieve byte comes only after an STT is set, and I get an extra byte at the end of my receive on the read_TA command.  Is there any I2C code examples explicitly for the MSP430F5xx series that encompasses a transmit X bytes+receive X bytes without a stop condition in between them?  Thanks, I'm pretty sure I'm not the only person looking for more complete code examples specific to this proc.  There was the previous bluetooth lib (mindtree's ethermind) released with the ez430-rf256x that used I2C to comm with the accelerometer for this chip, but they yanked the library and I can't find it anywhere despite having bought one.

Erik

//code functions:

static unsigned char IR_EEPROM_DATA[256];
static unsigned int IR_RAW_TA;
static unsigned char i2c_buffer[IR_ARRAY_LEN_2X];
signed char byteCtr;
unsigned char I2C_byteCtr;
unsigned char *TI_receive_field;
unsigned char *TI_transmit_field;
unsigned char i2c_txrx = 0;

void MLX90620_read_EEPROM(void)
{
    while ( TI_USCI_I2C_notready() );         // wait for bus to be free
    TI_USCI_I2C_transmitinit(EEPROM_Addr,I2C_PRESCALER);
    i2c_buffer[0]=0x0;
    i2c_txrx=1; // don't send stop after transmit, turn into a receiver like repeated start
    TI_USCI_I2C_transmit(1, i2c_buffer);
    TI_USCI_I2C_receive(256,IR_EEPROM_DATA);
}

signed int MLX90620_read_TA(void)
{
    i2c_buffer[0]=0x02;
    i2c_buffer[1]=0x90; // set addr of subsequent read
    i2c_buffer[2]=0x00; // addr step = 0
    i2c_buffer[3]=0x01; // number of reads = 1
    i2c_txrx=1;
    while ( TI_USCI_I2C_notready() );         // wait for bus to be free
    TI_USCI_I2C_transmitinit(ARRAY_Addr,I2C_PRESCALER);
    TI_USCI_I2C_transmit(4, i2c_buffer);
    TI_USCI_I2C_receive(2,i2c_buffer);
    signed int ta_data = (256*i2c_buffer[1]) + i2c_buffer[0];
    return ta_data;
}

void TI_USCI_I2C_receiveinit(unsigned char slave_address, unsigned char prescale){
  if (i2c_txrx)
    return;
  P3SEL |= SDA_PIN + SCL_PIN;                 // 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 = prescale;                         // set prescaler
  UCB0BR1 = 0;
  UCB0I2CSA = slave_address;                  // set slave address
  UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
  UCB0IE |= UCRXIE + UCNACKIE;                // Enable RX interrupt
}

void TI_USCI_I2C_transmitinit(unsigned char slave_address,
                          unsigned char prescale){
  P3SEL |= SDA_PIN + SCL_PIN;                 // 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 = prescale;                         // set prescaler
  UCB0BR1 = 0;
  UCB0I2CSA = slave_address;                  // Set slave address
  UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
  UCB0IE |= UCTXIE + UCNACKIE;                // Enable TX interrupt, EBB
}

void TI_USCI_I2C_receive(unsigned int byteCount, unsigned char *field){
  TI_receive_field = field;
  if ( byteCount == 1 ){
    I2C_byteCtr = 1 ;
    __disable_interrupt();
    UCB0CTL1 |= UCTXSTT;                      // I2C start condition
    __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
  } else if ( byteCount > 1 ) {
    I2C_byteCtr = byteCount;
    UCB0CTL1 |= UCTXSTT;                      // I2C start condition  // TODO10 in read_PTAT, this causes the device to send back two bytes, but now SCL low
    __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
  }
}

void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field){
  TI_transmit_field = field;
  I2C_byteCtr = byteCount;
  UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition (UCTR = Tx/Rx flag, UCTXSTT=start), address byte sent at this point in time.
  __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
  if (i2c_txrx==0)
  {
      while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
  }
  else
  {
      while (i2c_txrx);        // this gets cleared by my ISR when done transmitting
  }
}

#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  USCI_I2C_UCALIFG: break;            // Vector  2: ALIFG
  case  USCI_I2C_UCNACKIFG:                 // Vector  4: NACKIFG
      // error handling, set flags
    break;
  case  USCI_I2C_UCSTTIFG:                    // Vector 6: USCI_I2C_UCSTTIFG start int flag, used in slave mode only
    break;                                   // end Vector  6: STTIFG
  case  USCI_I2C_UCSTPIFG:                    // Vector  8: STPIFG stop int flag, used in slave mode only
      break;                                 // end Vector  8: STPIFG stop int flag
  case  USCI_I2C_UCRXIFG:                   // Vector 10: RXIFG, set when receive buffer is filled with a char
    I2C_byteCtr--;                          // Decrement RX byte counter
    if (I2C_byteCtr>2)
    {
      *TI_receive_field++ = UCB0RXBUF;               // Move RX data to address TI_receive_field
    }
    else
    {
      *TI_receive_field = UCB0RXBUF;                 // Move final RX data to TI_receive_field
      //UCB0CTL1 |= UCTXNACK;                  // first send a NACK before the STOP in master rx mode (pg 972 of MSP4305xx family guide)
      UCB0CTL1 |= UCTXSTP;                    // for MLX90620, no NACK is necessary, just ACK when rxing two bytes from PTAT or otherwise
      __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    }
    break;
  case USCI_I2C_UCTXIFG:                      // Vector 12: TXIFG, set when TX buffer is empty
    if (I2C_byteCtr)                          // Check TX byte counter
    {
      UCB0TXBUF = *TI_transmit_field++;               // Load TX buffer: sends 8+ACK clock.
      I2C_byteCtr--;                          // Decrement TX byte counter
    }
    else
    {
        if (i2c_txrx)                        // use this flag for reading immed after writing, so we only send stop if not about to do a read
        {
            i2c_txrx=0;
            // turn it into receiver, but otherwise don't do much else
            UCB0CTL1 &= ~UCTR;
            UCB0IE |= UCRXIE + UCNACKIE;
        }
        else
        {
            UCB0CTL1 |= UCTXSTP;                  // I2C stop condition
        }
        UCB0IFG &= ~UCTXIFG;                  // Clear USCI_B0 TX int flag
        //UCB0TXBUF = *TI_transmit_field++;
        __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }
  default: break;
  }
}


Viewing all articles
Browse latest Browse all 262198

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>