1. 硬件连接与初始化配置
第一次接触LIS3DHTR加速度传感器时,最让人头疼的就是硬件连接问题。我当年调试时因为引脚接错,整整浪费了一个下午。这里分享下我的经验:STM32F103的IIC接口默认对应PB6(SCL)和PB7(SDA),而LIS3DHTR的引脚排列需要注意VCC和GND不能接反。
具体接线方案如下:
- VCC接3.3V电源(切记不要接5V)
- GND接地
- SCL接PB6
- SDA接PB7
- SDO/SA0引脚根据需求接高或低(影响I2C地址)
- CS引脚必须接高电平(启用I2C模式)
硬件连接完成后,建议先用万用表检查各引脚电压:
- VCC应为3.3V±0.2V
- SDA/SCL空闲时应为高电平
- CS引脚必须确认是高电平
初始化配置有个小技巧:先读取WHO_AM_I寄存器(0x0F),正常应该返回0x33。这个步骤能快速验证硬件连接是否正确。我常用的初始化代码如下:
#define LIS3DH_ADDRESS 0x18 // SA0接地时的地址 void LIS3DH_Init(void) { uint8_t who_am_i = I2C_ReadByte(LIS3DH_ADDRESS, 0x0F); if(who_am_i != 0x33) { printf("LIS3DH检测失败,返回值:0x%02X\r\n", who_am_i); while(1); } // 配置CTRL_REG1:100Hz数据速率,XYZ轴使能 I2C_WriteByte(LIS3DH_ADDRESS, 0x20, 0x57); // 配置CTRL_REG4:±2g量程,高分辨率模式 I2C_WriteByte(LIS3DH_ADDRESS, 0x23, 0x08); }2. IIC通信协议实现细节
很多新手在实现IIC通信时会遇到各种奇怪的问题,我自己就踩过不少坑。这里分享几个关键点:
首先是时序问题,STM32的硬件IIC有个"特性":在标准模式下(100kHz)工作稳定,但在快速模式(400kHz)容易出错。建议先用标准模式调试,稳定后再尝试提速。
IIC读写函数实现要注意以下几点:
- 起始条件后必须检查ACK
- 每次发送完寄存器地址后也要检查ACK
- 读取多个字节时,最后一个字节要发送NACK
这是我优化过的IIC读写函数:
uint8_t I2C_ReadByte(uint8_t devAddr, uint8_t regAddr) { uint8_t data; I2C_Start(); I2C_Send_Byte(devAddr << 1); // 写模式 I2C_Wait_Ack(); I2C_Send_Byte(regAddr); I2C_Wait_Ack(); I2C_Start(); I2C_Send_Byte((devAddr << 1) | 1); // 读模式 I2C_Wait_Ack(); data = I2C_Read_Byte(0); // 发送NACK I2C_Stop(); return data; } void I2C_WriteByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { I2C_Start(); I2C_Send_Byte(devAddr << 1); I2C_Wait_Ack(); I2C_Send_Byte(regAddr); I2C_Wait_Ack(); I2C_Send_Byte(data); I2C_Wait_Ack(); I2C_Stop(); delay_ms(5); // 写入后需要适当延时 }常见问题排查:
- 如果读取总是返回0xFF:检查上拉电阻(4.7kΩ)是否接好
- 如果ACK失败:检查设备地址是否正确(SA0引脚状态)
- 如果数据不稳定:尝试降低IIC时钟频率
3. 数据读取与处理技巧
LIS3DHTR的数据寄存器是6个8位寄存器(OUT_X_L, OUT_X_H, OUT_Y_L, OUT_Y_H, OUT_Z_L, OUT_Z_H),需要组合成16位数据。这里有个细节:数据是补码形式,需要转换为有符号整数。
我推荐使用这个读取函数,它一次性读取所有三个轴的数据:
typedef struct { int16_t x; int16_t y; int16_t z; } LIS3DH_Data; void LIS3DH_ReadAccel(LIS3DH_Data *data) { uint8_t buf[6]; // 使用地址自动递增功能,连续读取6个寄存器 I2C_Start(); I2C_Send_Byte(LIS3DH_ADDRESS << 1); I2C_Wait_Ack(); I2C_Send_Byte(0x28 | 0x80); // 0x80启用地址自动递增 I2C_Wait_Ack(); I2C_Start(); I2C_Send_Byte((LIS3DH_ADDRESS << 1) | 1); I2C_Wait_Ack(); for(int i=0; i<5; i++) { buf[i] = I2C_Read_Byte(1); // 发送ACK } buf[5] = I2C_Read_Byte(0); // 最后一个字节发送NACK I2C_Stop(); // 组合数据并转换为有符号整数 >// 配置Z轴高阈值中断 void LIS3DH_ConfigInterrupt(void) { // 使能AOI1中断 I2C_WriteByte(LIS3DH_ADDRESS, 0x22, 0x40); // 配置Z轴高阈值检测 I2C_WriteByte(LIS3DH_ADDRESS, 0x30, 0x20); // 设置阈值为0.5g (0.5/0.001 = 500) I2C_WriteByte(LIS3DH_ADDRESS, 0x32, 0x05); // 设置持续时间10个采样周期(100Hz时为100ms) I2C_WriteByte(LIS3DH_ADDRESS, 0x33, 0x0A); }FIFO模式配置:
- 配置FIFO_CTRL_REG(0x2E)选择模式
- 通过FIFO_SRC_REG(0x2F)读取状态
- 建议使用流模式(Stream mode)实现连续采样
// 启用FIFO流模式 void LIS3DH_EnableFIFO(void) { // FIFO模式使能,流模式,触发中断1 I2C_WriteByte(LIS3DH_ADDRESS, 0x2E, 0x40); // 设置CTRL_REG5使能FIFO I2C_WriteByte(LIS3DH_ADDRESS, 0x24, 0x40); }调试技巧:
- 使用逻辑分析仪抓取IIC波形
- 读取STATUS_REG(0x27)检查数据就绪标志
- 对于间歇性故障,检查电源稳定性
- 温度变化大时,建议重新校准零点