10-01-2019 08:12 PM - edited 10-01-2019 08:15 PM
Hi Bosch sesnrtec community
I am using BMI160 IMU (shuttle board) as motion sesnor in my application. The MCU is MSP432P401R.
1- What is the proper wiring configuration for the shuttle board for I2C protocol?
2- I have written the code for I2C read/write functions like below:
/************BMI160 I2C*********/
UCB1CTLW0 |= UCSWRST; // **Initialize USCI state machine**
P6SEL0 |= BIT4 + BIT5;
P6SEL1 &= ~(BIT4 + BIT5); // | P6.3: UCB1SCLK| P6.4: UCB1SIMO | P6.5: UCB1SOMI (Refer to the datasheet, page: 159).
UCB1CTLW0 |= UCCKPH + UCMST + UCMSB + UCSYNC + UCSSEL_2 + UCMODE_3; // 3-pin, 8-bit, SPI master
UCB1BR0 = 12; // fSCL = SMCLK/12 = ~250kHz
UCB1BR1 = 0;
UCB1I2CSA = BMI160_I2C_ADDR; // Set slave address
UCB1CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
/*
* The parameter dev_id can be used as a variable to store the I2C address of the device
*/
UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
UCB1TXBUF = reg_addr; // Write reg_addr byte
UCB1CTLW0 |= UCTXSTP; // I2C stop condition.
UCB1I2CSA |= BMI160_I2C_ADDR; // Set slave address
UCB1CTLW0 &=~UCA10; //10BIT ADDRESS
UCB1CTLW0 &=~UCTR;//CLEAR TRANSMIT MODE
UCB1CTLW0 |= UCTXSTT; // I2C RX, start condition
int i=0;
for (i=0;i<len;i++)
{
reg_data[i]=UCB1RXBUF;
}
UCB1CTLW0 |= UCTXSTP; // I2C stop condition.
return rslt;
}
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
UCB1TXBUF = reg_addr; // Write reg_addr byte
int i=0;
for (i=0;i<len;i++)
{
UCB1TXBUF=reg_data[i];
}
UCB1CTLW0 |= UCTXSTP; // I2C stop condition.
return rslt;
}
Is it the right statement for them?
Thanks
Saber
Solved! Go to Solution.
10-02-2019 02:15 PM
@SaberKazemi1992 wrote:
1- What is the proper wiring configuration for the shuttle board for I2C protocol?
The protocol is automatically elected based on the CSB pin behavior after power-up. By default and if you would like to remain in I2C mode, CSB pin should be directly connected to VDDIO. In I2C mode please be aware of the I2C address selection via the SDO pin behavior. Below is a snippet from BMI160's datasheet showing the recommended connection diagram for the I2C protocol:
The schematic of BMI160's shuttle board can be found here: BMI160 Shuttle Board flyer.
@SaberKazemi1992 wrote:
2- I have written the code for I2C read/write functions like below:
/************BMI160 I2C*********/
UCB1CTLW0 |= UCSWRST; // **Initialize USCI state machine**
P6SEL0 |= BIT4 + BIT5;
P6SEL1 &= ~(BIT4 + BIT5); // | P6.3: UCB1SCLK| P6.4: UCB1SIMO | P6.5: UCB1SOMI (Refer to the datasheet, page: 159).
UCB1CTLW0 |= UCCKPH + UCMST + UCMSB + UCSYNC + UCSSEL_2 + UCMODE_3; // 3-pin, 8-bit, SPI master
UCB1BR0 = 12; // fSCL = SMCLK/12 = ~250kHz
UCB1BR1 = 0;
UCB1I2CSA = BMI160_I2C_ADDR; // Set slave address
UCB1CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure *//*
* The parameter dev_id can be used as a variable to store the I2C address of the device
*/
UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
UCB1TXBUF = reg_addr; // Write reg_addr byte
UCB1CTLW0 |= UCTXSTP; // I2C stop condition.UCB1I2CSA |= BMI160_I2C_ADDR; // Set slave address
UCB1CTLW0 &=~UCA10; //10BIT ADDRESS
UCB1CTLW0 &=~UCTR;//CLEAR TRANSMIT MODE
UCB1CTLW0 |= UCTXSTT; // I2C RX, start condition
int i=0;
for (i=0;i<len;i++)
{
reg_data[i]=UCB1RXBUF;
}
UCB1CTLW0 |= UCTXSTP; // I2C stop condition.return rslt;
}int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
UCB1TXBUF = reg_addr; // Write reg_addr byte
int i=0;
for (i=0;i<len;i++)
{
UCB1TXBUF=reg_data[i];
}
UCB1CTLW0 |= UCTXSTP; // I2C stop condition.return rslt;
}
I am not very familiar with the MSP432P401R in particular, but I do not see the slaved address (UCB1I2CSA?) being used in the write function. Note that when using our official sensor API in I2C mode, the I2C address of BMI160 (defined in 1- above) should be initialized in the id element (e.g. here), and this value will be transmitted to the dev_id argument of your user read/write functions. For reference, the two snippets below (from the datasheet) also show the expected read/write sequences on the bus:
10-02-2019 06:49 PM
Thanks for your reply.
For pin connections, I see in the datasheet, a pin SA0 for I2C protocol, it is connected to GND. Is it correct?
When I connected this pin to the GND, the MCU crashed!
Thanks
Saber
10-02-2019 06:50 PM
And also, one more question:
- What is the difference between VDD and VDDIO? Both goes to 3.3V pin of the MCU?
Thanks
Saber
10-02-2019 07:24 PM
@SaberKazemi1992 wrote:
- What is the difference between VDD and VDDIO? Both goes to 3.3V pin of the MCU?
Both pins must be power, and can be tied together. 3.3V is fine.
@SaberKazemi1992 wrote:
For pin connections, I see in the datasheet, a pin SA0 for I2C protocol, it is connected to GND. Is it correct?
When I connected this pin to the GND, the MCU crashed!
Ouchies 😯 The SDO pin of the BMI160 can act differently depending on the protocol selected. In I2C mode, this pin acts as an I2C address selector. This means connecting SDO pin to GND will results in I2C address 0x68 for the BMI160, but connecting it to VDDIO will results in the alternative I2C address 0x69.
Note that SDO is pin#1 of BMI160's package, but routed to pin#4 (and pin#15) of the shuttle board.