TI CC265x的IIC通讯读取IMU BMI08x数据

Posted lwlv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TI CC265x的IIC通讯读取IMU BMI08x数据相关的知识,希望对你有一定的参考价值。

SmartLink CC265x是TI公司出的无线MCU平台器件。最近玩了个小项目用TI的CC265x平板IIC接口通讯,获取博世BMI08x陀螺仪、加速度计传感器的数据。本篇博客亦是对博客《树莓派IIC通讯获取BMI08x IMU数据进行姿态解算,并通过UART/TCP在rviz上显示》的一个扩展。

目录

1. CCS(Code Composer Studio)的安装

2. IIC模块的配置与调试


1. CCS(Code Composer Studio)的安装

CCS的针对TI开发板的编程与下载工具,最新软件可在CCSTUDIO IDE、配置、编译器或调试器 | TI.com.cn下载,其使用手册可以在Code Composer Studio User’s Guide — Code Composer Studio 11.0.0 Documentation中查看。

大多数情况下我们是使用安装好之后的官方自带例程,并再其基础上更新。

 比如我们想要了解I2C相关的例程,直接选择后import导入到本地路径。

关于如何从零建立自己的CCS工程,暂时还没研究清楚,有大神清楚还望多多指教,万分感谢。

2. IIC模块的配置与调试

我开发的TI板是CC2652,9,10号引脚为I2C的通讯线。

这些引脚的定义需结合syscfg,比如Display表示可通过开发板的串口将数据打印出来,TI的库已经封装好了这一层。

另外还可以配置一些GPIO用于LED灯的操作。

官方的给的IIC例程写得有点让人难理解,全都封装在I2C_Transaction函数了,在读寄存器处并没有说明要写入寄存器地址。

 *  // Import I2C Driver definitions
 *  #include <ti/drivers/I2C.h>
 *
 *  // Define name for an index of an I2C bus
 *  #define SENSORS 0
 *
 *  // Define the slave address of device on the SENSORS bus
 *  #define OPT_ADDR 0x47
 *
 *  // One-time init of I2C driver
 *  I2C_init();
 *
 *  // initialize optional I2C bus parameters
 *  I2C_Params params;
 *  I2C_Params_init(&params);
 *  params.bitRate = I2C_400kHz;
 *
 *  // Open I2C bus for usage
 *  I2C_Handle i2cHandle = I2C_open(SENSORS, &params);
 *
 *  // Initialize slave address of transaction
 *  I2C_Transaction transaction = 0;
 *  transaction.slaveAddress = OPT_ADDR;
 *
 *  // Read from I2C slave device
 *  transaction.readBuf = data;
 *  transaction.readCount = sizeof(data);
 *  transaction.writeCount = 0;
 *  I2C_transfer(i2cHandle, &transaction);
 *
 *  // Write to I2C slave device
 *  transaction.writeBuf = command;
 *  transaction.writeCount = sizeof(command);
 *  transaction.readCount = 0;
 *  I2C_transferTimeout(i2cHandle, &transaction, 5000);
 *
 *  // Close I2C
 *  I2C_close(i2cHandle);
 *  @endcode
 *
 *  @anchor ti_drivers_I2C_Examples
 *  ## Examples
 *
 *  @li @ref ti_drivers_I2C_Example_open "Getting an I2C bus handle"
 *  @li @ref ti_drivers_I2C_Example_write3bytes "Sending 3 bytes"
 *  @li @ref ti_drivers_I2C_Example_read5bytes "Reading 5 bytes"
 *  @li @ref ti_drivers_I2C_Example_writeread "Writing then reading in a single transaction"
 *  @li @ref ti_drivers_I2C_Example_callback "Using Callback mode"
 *
 *  @anchor ti_drivers_I2C_Example_open
 *  ## Opening the I2C Driver
 *
 *  After calling I2C_init(), the application can open an I2C instance by
 *  calling I2C_open().The following code example opens an I2C instance with
 *  default parameters by passing @p NULL for the #I2C_Params argument.
 *
 *  @code
 *  I2C_Handle i2cHandle;
 *
 *  i2cHandle = I2C_open(0, NULL);
 *
 *  if (i2cHandle == NULL) 
 *      // Error opening I2C
 *      while (1) 
 *  
 *  @endcode
 *
 *  @anchor ti_drivers_I2C_Example_write3bytes
 *  ## Sending three bytes of data.
 *
 *  @code
 *  I2C_Transaction i2cTransaction = 0;
 *  uint8_t writeBuffer[3];
 *
 *  writeBuffer[0] = 0xAB;
 *  writeBuffer[1] = 0xCD;
 *  writeBuffer[2] = 0xEF;
 *
 *  i2cTransaction.slaveAddress = 0x50;
 *  i2cTransaction.writeBuf = writeBuffer;
 *  i2cTransaction.writeCount = 3;
 *  i2cTransaction.readBuf = NULL;
 *  i2cTransaction.readCount = 0;
 *
 *  status = I2C_transfer(i2cHandle, &i2cTransaction);
 *
 *  if (status == false) 
 *      // Unsuccessful I2C transfer
 *      if (i2cTransaction.status == I2C_STATUS_ADDR_NACK) 
 *          // I2C slave address not acknowledged
 *      
 *  
 *  @endcode
 *
 *  @anchor ti_drivers_I2C_Example_read5bytes
 *  ## Reading five bytes of data.
 *
 *  @code
 *  I2C_Transaction i2cTransaction = 0;
 *  uint8_t readBuffer[5];
 *
 *  i2cTransaction.slaveAddress = 0x50;
 *  i2cTransaction.writeBuf = NULL;
 *  i2cTransaction.writeCount = 0;
 *  i2cTransaction.readBuf = readBuffer;
 *  i2cTransaction.readCount = 5;
 *
 *  status = I2C_transfer(i2cHandle, &i2cTransaction);
 *
 *  if (status == false) 
 *      if (i2cTransaction.status == I2C_STATUS_ADDR_NACK) 
 *          // I2C slave address not acknowledged
 *      
 *  
 *  @endcode
 *
 *  @anchor ti_drivers_I2C_Example_writeread
 *  ## Writing two bytes and reading four bytes in a single transaction.
 *
 *  @code
 *  I2C_Transaction i2cTransaction = 0;
 *  uint8_t readBuffer[4];
 *  uint8_t writeBuffer[2];
 *
 *  writeBuffer[0] = 0xAB;
 *  writeBuffer[1] = 0xCD;
 *
 *  i2cTransaction.slaveAddress = 0x50;
 *  i2cTransaction.writeBuf = writeBuffer;
 *  i2cTransaction.writeCount = 2;
 *  i2cTransaction.readBuf = readBuffer;
 *  i2cTransaction.readCount = 4;
 *
 *  status = I2C_transfer(i2cHandle, &i2cTransaction);
 *
 *  if (status == false) 
*       if (i2cTransaction->status == I2C_STATUS_ADDR_NACK) 
*           // slave address not acknowledged
*       
 *  
 *  @endcode

感谢 获夜 的博文《CC2652RB硬件I2C读取FXOS8700CQ加速度传感器》 及其给与的帮助,让我对TI CCS使用IIC库有所理解。这里依旧使用博世官方提供的API  “https://github.com/BoschSensortec/BMI08x-Sensor-API”,对common函数的读写操作进行了改进(而不是使用博世提供的COINES平台)。

更改为TI获取IIC的读写寄存器操作如下:

/*!
 * I2C read function map to SimpleLink launchpad
 */
int8_t bmi08x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)

    uint8_t dev_addr = *(uint8_t*)intf_ptr;

    /* Common I2C transaction setup */
    i2cTransaction.slaveAddress = dev_addr;
    i2cTransaction.writeBuf   = &reg_addr;
    i2cTransaction.writeCount = 1;
    i2cTransaction.readBuf    = reg_data;
    i2cTransaction.readCount  = len;

    uint8_t cnt = 0;
    if (I2C_transfer(i2c_handle, &i2cTransaction)) 
        for(cnt = 0; cnt < len; cnt++)
            Display_printf(display, 0, 0, "Device 0x%x read register 0x%x value = 0x%x", dev_addr, reg_addr+cnt, reg_data[cnt]);
    
    else 
        i2cErrorHandler(&i2cTransaction, display);
        return -2;
    

    return 0;


/*!
 * I2C write function map to SimpleLink launchpad
 */
int8_t bmi08x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)

    uint8_t dev_addr = *(uint8_t*)intf_ptr;
    i2cTransaction.slaveAddress = dev_addr;

    uint8_t cnt = 0;
    for(cnt = 0; cnt < len; cnt++)
    
        uint8_t writeBuf[2] = 0;
        writeBuf[0] = reg_addr+cnt;
        writeBuf[1] = reg_data[cnt];
        /* Common I2C transaction setup */
        i2cTransaction.writeBuf   = writeBuf;
        i2cTransaction.writeCount = 2;
        i2cTransaction.readBuf    = NULL;
        i2cTransaction.readCount  = 0;
        if (I2C_transfer(i2c_handle, &i2cTransaction)) 
            Display_printf(display, 0, 0, "Device 0x%x write register 0x%x value = 0x%x", dev_addr, reg_addr + cnt, reg_data[cnt]);
        
        else 
            i2cErrorHandler(&i2cTransaction, display);
            return -2;
        
    

    return 0;


/*
 *  ======== i2cErrorHandler ========
 */
void i2cErrorHandler(I2C_Transaction *transaction, Display_Handle display)

    switch (transaction->status) 
    case I2C_STATUS_TIMEOUT:
        Display_printf(display, 0, 0, "I2C transaction timed out!");
        break;
    case I2C_STATUS_CLOCK_TIMEOUT:
        Display_printf(display, 0, 0, "I2C serial clock line timed out!");
        break;
    case I2C_STATUS_ADDR_NACK:
        Display_printf(display, 0, 0, "I2C slave address 0x%x not"
            " acknowledged!", transaction->slaveAddress);
        break;
    case I2C_STATUS_DATA_NACK:
        Display_printf(display, 0, 0, "I2C data byte not acknowledged!");
        break;
    case I2C_STATUS_ARB_LOST:
        Display_printf(display, 0, 0, "I2C arbitration to another master!");
        break;
    case I2C_STATUS_INCOMPLETE:
        Display_printf(display, 0, 0, "I2C transaction returned before completion!");
        break;
    case I2C_STATUS_BUS_BUSY:
        Display_printf(display, 0, 0, "I2C bus is already in use!");
        break;
    case I2C_STATUS_CANCEL:
        Display_printf(display, 0, 0, "I2C transaction cancelled!");
        break;
    case I2C_STATUS_INVALID_TRANS:
        Display_printf(display, 0, 0, "I2C transaction invalid!");
        break;
    case I2C_STATUS_ERROR:
        Display_printf(display, 0, 0, "I2C generic error!");
        break;
    default:
        Display_printf(display, 0, 0, "I2C undefined error case!");
        break;
    

而这两个读写IIC寄存器恰好是获取IMU数据的关键。在IIC线程获取到数据后我们可以通过Display_printf函数将其打印出来。这样通过串口助手便将数据显示出来了,如下。

 

Enjoy!

以上是关于TI CC265x的IIC通讯读取IMU BMI08x数据的主要内容,如果未能解决你的问题,请参考以下文章

TI CC265x的IIC通讯读取IMU BMI08x数据

树莓派IIC通讯获取BMI08x IMU数据进行姿态解算,并通过UART/TCP在rviz上显示

树莓派IIC通讯获取BMI08x IMU数据进行姿态解算,并通过UART/TCP在rviz上显示

树莓派IIC通讯获取BMI08x IMU数据进行姿态解算,并通过UART/TCP在rviz上显示

树莓派IIC通讯获取BMI08x IMU数据进行姿态解算,并通过UART/TCP在rviz上显示

TI CC2541的通讯抓包.