BMI088 板技术手册#

备注

本手册为最早 V1.0 协议产品,与当前上位机不兼容。

渲染#

bmi088_v2.png

实物#

bmi088_v2.png

BMI088 板开源地址#

bmi088-board

协议#

BMI088 模块 16 位寄存器#

  • 上电复位状态bit2=1,bit3=1,其余位位0,即使能所有输出

  • 同时向模块发送CAN或USART数据,CAN数据具有更高优先级

  • CAN 发送 0X8004:关闭串口输出,CAN 持续输出姿态。

  • USART 发送 0X4008:在 CAN 未发送(bit15=0)时关闭 CAN 输出,USART 持续输出;发送数据需按协议打包。

UART 通信#

通信要求#

波特率 115200,8 数据位,1 停止位,无流控、无校验,发送频率 100Hz。

接口协议说明#

Seasky 通信协议详见 Sailor 通信协议

BMI088 端发送(float 长度 10)#

发送函数(模块内调用)#

void imu_usart_send(void)
{
    static uint8_t send_data[60];//保证大于发送的数据
    uint16_t tx_flag=0,send_data_len=0;

    /*发送寄存器赋值*/
    tx_flag |= imu_ctr_t.ctr.res&0x01;
    tx_flag |= (imu_ctr_t.ctr.cmd<<1)&0x01;

    /*发送的数据赋值*/
    imu_ctr_t.ctr.float_data[0] = imu_ctr_t.imu_t->accel.x;
    imu_ctr_t.ctr.float_data[1] = imu_ctr_t.imu_t->accel.y;
    imu_ctr_t.ctr.float_data[2] = imu_ctr_t.imu_t->accel.z;

    imu_ctr_t.ctr.float_data[3] = imu_ctr_t.imu_t->angle_rate.x;
    imu_ctr_t.ctr.float_data[4] = imu_ctr_t.imu_t->angle_rate.y;
    imu_ctr_t.ctr.float_data[5] = imu_ctr_t.imu_t->angle_rate.z;

    imu_ctr_t.ctr.float_data[6] = imu_ctr_t.imu_t->gyro.yaw;
    imu_ctr_t.ctr.float_data[7] = imu_ctr_t.imu_t->continuous_gyro.yaw;

    imu_ctr_t.ctr.float_data[8] = imu_ctr_t.imu_t->gyro.pitch;
    imu_ctr_t.ctr.float_data[9] = imu_ctr_t.imu_t->gyro.roll;

    get_protocol_send_data(IMU_USART_TX_ID,tx_flag,&imu_ctr_t.ctr.float_data[0],
                          10,send_data,&send_data_len);

    usart_send(send_data,send_data_len);
}

BMI088 控制数据(float 长度 0)#

使用端向 BMI088 发送数据详见协议文档。

寄存器数据打包#

get_protocol_send_data
(0X0201,//信号id
  flag,//16位寄存器
  NULL,//待发送的float数据
  0,//float的数据长度
  usart6_tx_buf,//待发送的数据帧
  &usart6_tx_length);//待发送的数据帧长度

CAN 通信#

  • CAN波特率1MHZ、发送频率100Hz

  • 协议部分

  • 定义共用体变量

typedef union
{
  float data_f;
  uint8_t data_u8[4];
}data_f_u8;

协议说明(单次发送、单 ID):信号数据

控制数据(CAN 帧 8 字节,此处仅用 2 字节)

ID

union

u8

0X306

flag

使用 CAN 向 BMI088 发送控制数据:

/*设定BMI088*/
void set_can_tx_bmi088(uint16_t flag)
{
    CanTxMsg TxMessage;
    TxMessage.StdId= CAN_TX_BMI088_CMD;
    TxMessage.IDE = 0;
    TxMessage.RTR = 0;
    TxMessage.DLC = 8;
    TxMessage.Data[0] = flag >> 8;
    TxMessage.Data[1] = flag;
    TxMessage.Data[2] = 0 >> 8;
    TxMessage.Data[3] = 0;
    TxMessage.Data[4] = 0 >> 8;
    TxMessage.Data[5] = 0;
    TxMessage.Data[6] = 0 >> 8;
    TxMessage.Data[7] = 0;
    CAN_Transmit(CAN2,&TxMessage);
  }

BMI088 模块端发送#

void CAN_Send_Msg(uint32_t Send_StdId,float data1,float data2)
{

    static CAN_TxHeaderTypeDef  Tx_Message;
    static uint8_t              Tx_Buf[8];
    uint32_t send_mail_box;
    data_f_u8 Tx_data[2];

    Tx_Message.StdId = Send_StdId;//设置id
    Tx_Message.IDE = CAN_ID_STD;
    Tx_Message.RTR = CAN_RTR_DATA;
    Tx_Message.DLC = 0x08;

    Tx_data[0].data_f=data1;
    Tx_data[1].data_f=data2;

    for(int i=0; i<8; i++)
        {
            Tx_Buf[i]=Tx_data[i/4].data_u8[i%4];
        }
    while(HAL_CAN_AddTxMessage(&hcan1, &Tx_Message,Tx_Buf, &send_mail_box));
}

BMI088 模块端发送调用示例#

CAN_Send_Msg(0x301, imu_ctr_t.imu_t->accel.x, imu_ctr_t.imu_t->angle_rate.x);
CAN_Send_Msg(0x302,imu_ctr_t.imu_t->accel.y,imu_ctr_t.imu_t->angle_rate.y);
CAN_Send_Msg(0x303,imu_ctr_t.imu_t->accel.z,imu_ctr_t.imu_t->angle_rate.z);
CAN_Send_Msg(0x304,imu_ctr_t.imu_t->gyro.yaw,imu_ctr_t.imu_t->continuous_gyro.yaw);
CAN_Send_Msg(0x305,imu_ctr_t.imu_t->gyro.pitch,imu_ctr_t.imu_t->gyro.roll);

使用端接收示例#

枚举定义示例:

CAN_RX_BMI088_X = 0X301,
CAN_RX_BMI088_Y = 0X302,
CAN_RX_BMI088_Z = 0X303,
CAN_RX_BMI088_YAW = 0X304,
CAN_RX_BMI088_GYRO = 0X305,
CAN_TX_BMI088_CMD = 0X306

结构体#

typedef union
{
    float data_f;
    uint8_t data_u8[4];
} data_f_u8;
typedef  struct
{
    struct
    {
        uint8_t res:1;//<<0
        uint8_t cmd:1;//<<1
        uint8_t can_out_cmd:1;//<<2
        uint8_t usart_out_cmd:1;//<<3
        uint16_t flag;
    } imu_ctr;
    struct
    {
        float x;
        float y;
        float z;
    } acc;
    struct
    {
        float x;
        float y;
        float z;
    } rate;
    struct
    {
        float yaw;
        float pitch;
        float roll;
        float yaw_c;
    } angle;
} seasky_bmi088;

数据解读#

void get_bmi088(float *imu_1, float *imu_2, uint8_t *data)
{
    data_f_u8 rx_buf[2];
    for (int i = 0; i < 8; i++)
        rx_buf[i/4].data_u8[i%4] = data[i];
    *imu_1 = rx_buf[0].data_f;
    *imu_2 = rx_buf[1].data_f;
}

CAN 接收中断调用示例#

void get_moto_info2(void)
{
    CanRxMsg RxMessage;
    CAN_Receive(CAN2, CAN_FIFO0, &RxMessage);
    switch (RxMessage.StdId) {
    case CAN_RX_BMI088_X:
        get_bmi088x(RxMessage.Data);
        break;
    case CAN_RX_BMI088_Y:
        get_bmi088y(RxMessage.Data);
        break;
    case CAN_RX_BMI088_Z:
        get_bmi088z(RxMessage.Data);
        break;
    case CAN_RX_BMI088_YAW:
        get_bmi088_yaw(RxMessage.Data);
        break;
    case CAN_RX_BMI088_GYRO:
        get_bmi088_angle(RxMessage.Data);
        break;
    default:
        break;
    }
}

解析函数封装示例#

void get_bmi088x(uint8_t *data)
{
    get_bmi088(&imu_rm.acc.x, &imu_rm.rate.x, data);
}
void get_bmi088y(uint8_t *data)
{
    get_bmi088(&imu_rm.acc.y, &imu_rm.rate.y, data);
}
void get_bmi088z(uint8_t *data)
{
    get_bmi088(&imu_rm.acc.z, &imu_rm.rate.z, data);
}
void get_bmi088_yaw(uint8_t *data)
{
    get_bmi088(&imu_rm.angle.yaw, &imu_rm.angle.yaw_c, data);
}
void get_bmi088_angle(uint8_t *data)
{
    get_bmi088(&imu_rm.angle.pitch, &imu_rm.angle.roll, data);
}

接收端发送控制数据(寄存器赋值)#

void imu_set(void)
{
    imu_rm.imu_ctr.flag |= imu_rm.imu_ctr.res & 0x01;
    imu_rm.imu_ctr.flag |= (imu_rm.imu_ctr.cmd << 1) & 0x01;
    set_can_tx_bmi088(imu_rm.imu_ctr.flag);
}