BMI088 板技术手册#
备注
本手册为最早 V1.0 协议产品,与当前上位机不兼容。
渲染#
实物#
BMI088 板开源地址#
协议#
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);
}