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.
So I am new to all of this - self taught mostly - and am having trouble figuring out how in the world to do a multi-byte read without using the ISR (it just seems simpler to me that way and power time doesn't matter much in this case). My trouble is that I don't know how to know when the rx buffer is ready to read, and thus how to trigger another read.
I know that if you issue a stop before the last byte sends then you just wait until the stop sends and then rxbuff will be ready, but for the other bytes I'm not sure... Also, I am only getting zeros from the accelerometer when I'm pretty sure a multi-byte read should auto increment the read register. (datasheet is here) Since I am new, I would really appreciate any advice you may have. Here's my code (I am also attaching a readout of the bus read):
// SDA: 1.7 // SCL: 1.6 #include <msp430.h> #include "gy-80_config.h" int RXByteCtr, RPT_Flag = 0; // enables repeated start when 1 volatile unsigned char RxBuffer[128]; // Allocate 128 byte of RAM unsigned char TxData; // TX data unsigned char *PRxData; // Pointer to RX data unsigned char TXByteCtr, RX = 0; int i,j,k; int byte_rdy =0; int i2c_mode = I2C_DISABLE; // This is to help the interrupt routing // 0 = disabled, 1 = acc, 2 = gyro, 3 = compass; 4 = barometer int acc_sample_indx = 0; volatile char acc_samples[32][6]; // 32 samples in buffer - 3 axis with 2 chars data unsigned char acc_si; // Sample index void Setup_TX(unsigned char ); void Setup_RX(unsigned char ); void I2C_Init(); void I2C_Reset(); void Sample_Init(); void Acce_Data(); int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer I2C_Init(); Sample_Init(); while(1){ Acce_Data(); } } #pragma vector = USCIAB0TX_VECTOR __interrupt void USCIAB0TX_ISR(void) { byte_rdy = 1; } void I2C_Init(){ byte_rdy = 0; I2C_Reset(); P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0 P1SEL2|= BIT6 + BIT7; // 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; UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation } void I2C_Reset() { P1DIR |= BIT5; // This controls bus power (connected to bus ground) P1OUT |= BIT5; // bus off for (i = 0; i< 100; i++){} // Wait a second P1OUT &= ~BIT5; // Power bus on for (i = 0; i< 100; i++){} // Wait a second (so that it can get ready) } void Sample_Init() { acc_si = 0; } void Acce_Data() { Setup_TX(ACCE_ADDR); UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition UCB0TXBUF = ACCE_STT; // Multi-byte read address while (UCB0CTL1 & UCTXSTT); // Wait for start condition and data to send UCB0CTL1 |= UCTXSTP; // I2C stop condition while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent Setup_RX(ACCE_ADDR); UCB0CTL1 |= UCTXSTT; // I2C start condition while (UCB0CTL1 & UCTXSTT); // Wait for start condition for (i = 0; i< 6; i++) { if (i == 5) { UCB0CTL1 |= UCTXSTP; // I2C stop condition } acc_samples[acc_si][i] = UCB0RXBUF; // Load RXBuffer, start getting next one. } acc_si++; } void Setup_TX(unsigned char slAddress){ UCB0I2CSA = slAddress; // Slave Address RX = 0; // TX IE2 &= ~UCB0RXIE; // Disable RX interrupt IE2 |= UCB0TXIE; // Enable TX interrupt } void Setup_RX(unsigned char slAddress){ _DINT(); RX = 1; 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 UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz UCB0BR1 = 0; UCB0I2CSA = slAddress; // Slave Address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation IE2 |= UCB0RXIE; // Enable RX interrupt }
So simple.. I just needed to wait until the rxbuffer was ready by adding "while (!(IFG2 & UCB0RXIFG));" before reading the buffer. Still trying to figure out how to do sequential read on my accelerometer though...
**Attention** This is a public forum