村田 IMU SCC2000系列芯片驱动
?
一、总体特点
1、本次具体的型号是村田SCC2130系,IMU有1轴(x)陀螺仪、三轴加速度计和温度计,测量范围陀螺仪±125°/s,加速度±6,温度-50到150。
2、高稳定性,广泛的自诊断等安全保护,因此主要应用都是在一些汽车工业级的场景。
3、32位四线SPI,最大8MHZ通信速度,有CRC校验。
4、硬件针脚图如下,实际上硬件IMU比较大针脚太多,成本高。
二、启动时序和逻辑
1、启动时序也就是驱动IMU初始化,主要是根据状态机的图来实现整个IMU的驱动,本次MCU是采用国产芯片
2、硬件上电复位或者软件复位IO引脚上拉后需要等待20ms后在总状态寄存器设置输出滤波,接着根据两种不同的滤波等待不同的时间,然后需要清除所有的状态寄存器状态,读总状态寄存器看RS位返回状态。正常状态后才可以正常读取IMU数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TALJ1CQP-1647160100539)(C:/Users/曾伟荣/AppData/Roaming/Typora/typora-user-images/image-20220313130839320.png)]
3、RS的状态
4、驱动代码
uint16_t HW_MURATA_INIT_TIM_Cnt_u16 = 0;
uint8_t HW_MURATA_INIT_OK_Flag_u8 = 0xEE;
uint8_t HW_MURATA_INIT_TIM_stopFlag_u8 = 0xEE;
void FUN_HW_Murata_IMU_Init()
{
uint8_t S_agspi_rsdata_u8;
if(HW_MURATA_INIT_TIM_stopFlag_u8 == 0xEE)
{
HW_MURATA_INIT_TIM_Cnt_u16 ++;
}
if(HW_MURATA_INIT_TIM_Cnt_u16 < 2)
{
Murata_IMU_SendAndRead(Murata_IMU_HARD_RST);
}
else if(HW_MURATA_INIT_TIM_Cnt_u16 < 5)
{
Murata_IMU_SendAndRead(Murata_IMU_Status_Summary_10HZ);
}
else if(HW_MURATA_INIT_TIM_Cnt_u16 < 10)
{
if(HW_MURATA_INIT_OK_Flag_u8 == 0xEE)
{
Murata_IMU_SendAndRead(Murata_IMU_RATE_STATUS1);
Murata_IMU_SendAndRead(Murata_IMU_RATE_STATUS2);
Murata_IMU_SendAndRead(Murata_IMU_ACC_STATUS);
Murata_IMU_SendAndRead(Murata_IMU_Common_Status);
Murata_IMU_SendAndRead(Murata_IMU_Status_Summary);
StartupOK = TRUE;
Response_StatSum = Murata_IMU_SendAndRead(Murata_IMU_Status_Summary);
S_agspi_rsdata_u8 = (uint8_t)((Response_StatSum & Murata_IMU_STATUS_MASK) >> 24);
if(S_agspi_rsdata_u8 != 1)
{
StartupOK = FALSE;
}
if(!StartupOK)
{
Response_RateState1 =Murata_IMU_SendAndRead(Murata_IMU_RATE_STATUS1);
Response_RateState2 = Murata_IMU_SendAndRead(Murata_IMU_RATE_STATUS2);
Response_AccStat = Murata_IMU_SendAndRead(Murata_IMU_ACC_STATUS);
Response_ComStat1 = Murata_IMU_SendAndRead(Murata_IMU_Common_Status);
}
HW_MURATA_INIT_OK_Flag_u8 = 0xAA;
}
}
else
{
HW_MURATA_INIT_TIM_Cnt_u16 = 0xEEEB;
HW_MURATA_INIT_TIM_stopFlag_u8 = 0xAA;
}
}
三、SPI通信和数据读取
1、32位SPI,还是OUT-OFF模式,下一帧返回上一帧的结果,而我是直接连着发两帧相同的命令这样回传处理就很方便。
2、MOSI的读写命令前8位为寄存器地址中间16位为数据,最后八位为CRC校验。
3、官方手册已经给了具体的相关寄存器读写命令可以直接用
4、读取数据代码,本次MCU是国产的芯片上海芯旺微的KF系列,环境啥都还挺好搭建,上手也挺容易。
uint32_t Murata_IMU_SendAndRead(uint32_t data)
{
uint32_t receive_data;
SPI_I2S_SendData32(SPI0_COM,data);
delay_us(2);
SPI_I2S_SendData32(SPI0_COM,data);
delay_us(2);
receive_data = SPI_I2S_ReceiveData(SPI0_COM);
return receive_data;
}
/*原始数据读取,读取到的数据是补码形式*/
/*x轴角速度*/
x_rate = Murata_IMU_SendAndRead(Murata_IMU_X_RATE);
/*x轴加速度*/
x_acc = Murata_IMU_SendAndRead(Murata_IMU_X_ACC);
/*y轴加速度*/
y_acc = Murata_IMU_SendAndRead(Murata_IMU_Y_ACC);
/*z轴加速度*/
z_acc = Murata_IMU_SendAndRead(Murata_IMU_Z_ACC);
/*温度值*/
temp = Murata_IMU_SendAndRead(Murata_IMU_TEMP);
/*状态读取*/
rate_status1 = Murata_IMU_SendAndRead(Murata_IMU_RATE_STATUS1);
rate_status2 = Murata_IMU_SendAndRead(Murata_IMU_RATE_STATUS2);
acc_status = Murata_IMU_SendAndRead(Murata_IMU_ACC_STATUS);
common_status = Murata_IMU_SendAndRead(Murata_IMU_Common_Status);
summary_status = Murata_IMU_SendAndRead(Murata_IMU_Status_Summary);
四、数据处理
1、SPI读取到的数据是一个二进制补码,需要我们对数据处理转化为原码。手册上也有处理方法。
2、博世SMI810一样也是原始数据转化为原码后除以sensitivity。
3、数据处理代码
x_rate_origin = (int32_t)(Murata_IMU_DataProcess(x_rate,x_rate));
S_SPI_yawrate_s16 =(int32_t)(x_rate_origin*2);
x_acc_origin = (int32_t)(Murata_IMU_DataProcess(x_acc,x_acc));
S_SPI_accx_s16 = (int32_t)(x_acc_origin*100/1962);
y_acc_origin = (int32_t)(Murata_IMU_DataProcess(y_acc,y_acc));
S_SPI_accy_s16 = (int32_t)(y_acc_origin*100/1962);
z_acc_origin = (int32_t)(Murata_IMU_DataProcess(z_acc,z_acc));
S_SPI_accz_s16 = (int32_t)(z_acc_origin*100/1962);
S_SPI_temperture_s16_last =(int32_t)(Murata_IMU_DataProcess(temp,temp));
S_SPI_temperture_s16 = (int32_t)((S_SPI_temperture_s16_last * 10/ 147 + 60));
uint16_t Murata_IMU_DataProcess(uint32_t input_data,uint32_t input_status)
{
uint16_t output_data;
uint16_t output_status;
uint16_t output_first;
output_data = (uint16_t)((input_data & Murata_IMU_DATA_MASK ) >> 8);
output_first = output_data >> 15;
if(output_first == 1)
{
output_data = (~output_data) + 1;
output_data = (int16_t)(output_data & 0xFFFF);
output_data *= -1;
}
else
{
output_data = output_data;
}
output_status = (uint8_t)((input_status & Murata_IMU_STATUS_MASK)>>24);
if (output_status != 1)
{
spi_imu_status_flag = 1;
output_data = 0xFFFF;
}
return output_data;
}
|