一:ISM330DHCX知识分享:
带可选满量程的3D加速度计:+2/+4/+8/+16g
带扩展可选满量程的3D陀螺仪:+125/±250/±500/±1000/±2000/±4000 dps
扩展温度范围从-40到+105°C嵌入式补偿,确保温度变化下的高稳定性
SPI/I2C串行接口
辅助SPI串行接口,用于陀螺仪和加速度计的数据输出(OIS及其他稳定应用)
六通道同步输出
传感器集线器功能,可高效从额外外部传感器收集数据;
嵌入式智能FIFO,最大支持9千字节
可编程有限状态机,用于处理加速度计、陀螺仪和外部传感器的数据
机器学习核心智能嵌入式功能与中断:倾斜检测、自由落体、唤醒、6D/4D方向、单击与双击
嵌入式计步器、步数检测器和计数器,用于医疗保健应用
模拟供电电压:1.71V至3.6V
嵌入式温度传感器陀螺仪和加速度计均内置自检功能高抗冲击性
符合ECOPACK、RoHS和“绿色”标准
二:STM32cube MX配置
2.1 安装 X-CUBE-MEMS1 扩展包
1.打开 STM32CubeMX
2.进入 "Software Packs" 选项卡
3.点击 "Select Components" 或 "Manage Software Packs"
4.搜索 "X-CUBE-MEMS1"
5.点击安装最新版本(如 v6.2.0 或更高版本)
2.2 芯片的原理图:

2.3 添加传感器组件
1.在 "Pinout & Configuration" 视图的左侧,找到 "Software Packs" 部分
2.展开 "X-CUBE-MEMS1"
3.找到并勾选 "Sensor" 组件
4.点击确认添加
2.4 配置 ISM330DHCX 传感器
在添加传感器组件后,会出现配置界面:
1.在 "Middleware" 部分找到 "X-CUBE-MEMS1"
2.点击进入配置页面
3.在 "Sensor" 列表中,找到 "ISM330DHCX"
4.配置参数:

三:软件代码:
3.1 SPI 通讯底层函数
// SPI写寄存器
static uint8_t ism330dhcx_spi_write(SPI_HandleTypeDef *hspi, uint16_t cs_pin,
uint8_t reg_addr, uint8_t *data, uint16_t len)
{
uint8_t tx_buffer[256];
uint8_t rx_buffer[256];
uint8_t ret = 0;
// CS片选拉低
HAL_GPIO_WritePin(CS_GPIO_Port, cs_pin, GPIO_PIN_RESET);
// 发送寄存器地址(写操作,bit7=0)
tx_buffer[0] = reg_addr & 0x7F;
for(uint16_t i = 0; i < len; i++) {
tx_buffer[i+1] = data[i];
}
// SPI收发数据
HAL_SPI_TransmitReceive(hspi, tx_buffer, rx_buffer, len+1, HAL_MAX_DELAY);
// CS片选拉高
HAL_GPIO_WritePin(CS_GPIO_Port, cs_pin, GPIO_PIN_SET);
return ret;
}
// SPI读寄存器
static uint8_t ism330dhcx_spi_read(SPI_HandleTypeDef *hspi, uint16_t cs_pin,
uint8_t reg_addr, uint8_t *data, uint16_t len)
{
uint8_t tx_buffer[256];
uint8_t rx_buffer[256];
// CS片选拉低
HAL_GPIO_WritePin(CS_GPIO_Port, cs_pin, GPIO_PIN_RESET);
// 发送寄存器地址(读操作,bit7=1)
tx_buffer[0] = reg_addr | 0x80;
for(uint16_t i = 0; i < len; i++) {
tx_buffer[i+1] = 0xFF; // 发送dummy数据以产生时钟
}
// SPI收发数据
HAL_SPI_TransmitReceive(hspi, tx_buffer, rx_buffer, len+1, HAL_MAX_DELAY);
// 复制接收到的数据
for(uint16_t i = 0; i < len; i++) {
data[i] = rx_buffer[i+1];
}
// CS片选拉高
HAL_GPIO_WritePin(CS_GPIO_Port, cs_pin, GPIO_PIN_SET);
return 0;
}数据处理函数:
/**
* @brief 批量读取加速度计和陀螺仪数据(6轴同步)
* @param hspi SPI句柄
* @param cs_pin CS引脚
* @param acc_data 加速度数据结构体(输出)
* @param gyro_data 陀螺仪数据结构体(输出)
* @return HAL状态
*/
HAL_StatusTypeDef ISM330DHCX_ReadAllAxes(SPI_HandleTypeDef *hspi,
uint16_t cs_pin,
ISM330DHCX_Axes_t *acc_data,
ISM330DHCX_Axes_t *gyro_data)
{
uint8_t tx_buffer[15] = {0};
uint8_t rx_buffer[15] = {0};
int16_t raw_acc[3], raw_gyro[3];
// CS片选拉低
HAL_GPIO_WritePin(CS_GPIO_Port, cs_pin, GPIO_PIN_RESET);
// 从OUTX_L_G开始连续读取14字节(陀螺仪+加速度计)
// 读操作:最高位为1,自动地址递增
tx_buffer[0] = ISM330DHCX_OUTX_L_G | 0x80 | 0x40; // 0x80=读操作, 0x40=自动递增
for(int i = 1; i < 15; i++) {
tx_buffer[i] = 0xFF; // 发送dummy数据产生时钟
}
// SPI收发
HAL_SPI_TransmitReceive(hspi, tx_buffer, rx_buffer, 15, HAL_MAX_DELAY);
// CS片选拉高
HAL_GPIO_WritePin(CS_GPIO_Port, cs_pin, GPIO_PIN_SET);
// 解析陀螺仪原始数据(小端格式)
raw_gyro[0] = (int16_t)((rx_buffer[2] << 8) | rx_buffer[1]); // OUTX_L_G, OUTX_H_G
raw_gyro[1] = (int16_t)((rx_buffer[4] << 8) | rx_buffer[3]); // OUTY_L_G, OUTY_H_G
raw_gyro[2] = (int16_t)((rx_buffer[6] << 8) | rx_buffer[5]); // OUTZ_L_G, OUTZ_H_G
// 解析加速度计原始数据
raw_acc[0] = (int16_t)((rx_buffer[8] << 8) | rx_buffer[7]); // OUTX_L_A, OUTX_H_A
raw_acc[1] = (int16_t)((rx_buffer[10] << 8) | rx_buffer[9]); // OUTY_L_A, OUTY_H_A
raw_acc[2] = (int16_t)((rx_buffer[12] << 8) | rx_buffer[11]); // OUTZ_L_A, OUTZ_H_A
// 应用灵敏度转换为物理单位
acc_data->x = (int32_t)((float)raw_acc[0] * acc_sensitivity);
acc_data->y = (int32_t)((float)raw_acc[1] * acc_sensitivity);
acc_data->z = (int32_t)((float)raw_acc[2] * acc_sensitivity);
gyro_data->x = (int32_t)((float)raw_gyro[0] * gyro_sensitivity);
gyro_data->y = (int32_t)((float)raw_gyro[1] * gyro_sensitivity);
gyro_data->z = (int32_t)((float)raw_gyro[2] * gyro_sensitivity);
return HAL_OK;
}使用注意事项:
数据格式:传感器输出16位有符号整数(int16_t),小端格式
灵敏度计算:转换系数取决于量程设置,需在初始化时配置
零偏校准:静止状态检测是实现零偏校准的前提
滤波器选择:MCU资源受限时用互补滤波,资源充足可用卡尔曼滤波
四:串口数据如下所示:

五:调试过程中遇到问题:1:SPI 通信无响应
原因:
CS 引脚配置错误
SPI 时钟频率过高(超过 10MHz)
SA0 引脚未悬空(仍处于 I2C 模式)
解决方法:
使用示波器或逻辑分析仪检查 SPI 波形
降低 SPI 分频值,确保 SCLK < 10MHz
2:读取数据全为 0 或 0xFF
可能原因:
SPI 读写函数中的命令格式错误
片选时序不正确
解决方法:
确认读命令的最高位为 1(例如:reg | 0x80)
确认写命令的最高位为 0(例如:reg & 0x7F)
确保在每次 SPI 传输前后正确控制 CS 引脚。
我要赚赏金
