手把手教你用STM32F103的SPI驱动ADXL362加速度计(附完整代码与调试心得)
从零玩转STM32F103与ADXL362SPI驱动全攻略与实战避坑指南当你第一次拿到ADXL362这款超低功耗三轴加速度计时可能会被它精致的封装和丰富的功能所吸引。但真正要让它跑起来特别是通过STM32F103的SPI接口进行通信时各种细节问题往往会让人措手不及。本文将带你完整走通从硬件连接到数据采集的全流程分享那些手册上不会告诉你的实战经验。1. 硬件连接别让接线成为第一道坎ADXL362与STM32F103的SPI接口连接看似简单但魔鬼藏在细节里。我们先来看标准接线方案ADXL362引脚STM32F103引脚备注VDD3.3V绝对不要接5VGNDGND共地至关重要CSPB12软件控制片选SCLKPB13SPI2时钟线MOSIPB15主出从入MISOPB14主入从出常见硬件坑点供电电压混淆ADXL362最大耐受3.6V直接接5V会永久损坏未启用上拉电阻CS线建议接10kΩ上拉避免初始状态不稳定线缆过长超过10cm建议使用屏蔽线防止SPI时钟干扰提示在面包板上搭建电路时务必先断电测量VDD与GND之间电阻防止短路烧毁传感器。2. SPI初始化参数配置的玄机SPI通信的核心在于时钟极性和相位的正确匹配。ADXL362要求CPOL0且CPHA0这在STM32CubeMX中对应Mode 0配置。以下是经过优化的初始化代码void SPI2_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; SPI_InitTypeDef SPI_InitStruct {0}; // 启用GPIOB和SPI2时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // 配置SPI引脚为复用推挽输出 GPIO_InitStruct.GPIO_Pin GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStruct); // SPI主模式配置 SPI_InitStruct.SPI_Direction SPI_Direction_2Lines_FullDuplex; SPI_InitStruct.SPI_Mode SPI_Mode_Master; SPI_InitStruct.SPI_DataSize SPI_DataSize_8b; SPI_InitStruct.SPI_CPOL SPI_CPOL_Low; // CPOL0 SPI_InitStruct.SPI_CPHA SPI_CPHA_1Edge; // CPHA0 SPI_InitStruct.SPI_NSS SPI_NSS_Soft; SPI_InitStruct.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_32; SPI_InitStruct.SPI_FirstBit SPI_FirstBit_MSB; SPI_Init(SPI2, SPI_InitStruct); SPI_Cmd(SPI2, ENABLE); // 发送dummy字节启动传输 SPI2_ReadWriteByte(0xFF); }关键参数解析BaudRatePrescaler系统时钟72MHz时分频32得到2.25MHz时钟符合ADXL362的1-5MHz要求SPI_NSS_Soft软件控制片选更灵活避免硬件NSS的时序问题dummy字节首次启动时需要发送无效数据激活SPI时钟3. 寄存器操作读写背后的时序奥秘ADXL362的所有功能配置都通过寄存器完成理解其读写时序是成功的关键。先看基础读写函数// 读寄存器函数 uint8_t ADXL362_ReadReg(uint8_t addr) { uint8_t txBuf[3] {0x0B, addr, 0x00}; // 读命令地址dummy uint8_t rxData; CS_LOW(); // 拉低片选 SPI2_ReadWriteByte(txBuf[0]); // 发送读命令 SPI2_ReadWriteByte(txBuf[1]); // 发送地址 rxData SPI2_ReadWriteByte(txBuf[2]); // 获取数据 CS_HIGH(); // 释放片选 return rxData; } // 写寄存器函数 void ADXL362_WriteReg(uint8_t addr, uint8_t value) { uint8_t txBuf[3] {0x0A, addr, value}; // 写命令地址数据 CS_LOW(); SPI2_ReadWriteByte(txBuf[0]); SPI2_ReadWriteByte(txBuf[1]); SPI2_ReadWriteByte(txBuf[2]); CS_HIGH(); }时序要点解析片选信号(CS)必须在整个传输期间保持低电平读操作需要发送3个字节命令(0x0B)、地址、dummy写操作需要发送3个字节命令(0x0A)、地址、数据每个字节传输后都要检查SPI标志位但为简洁省略了错误处理4. 功能配置从基础测量到高级应用4.1 基础加速度测量要让ADXL362输出加速度数据需要配置以下关键寄存器// 进入测量模式 ADXL362_WriteReg(0x2D, 0x02); // POWER_CTL: 测量模式 // 设置量程和输出速率 ADXL362_WriteReg(0x2C, 0x03); // 2g量程100Hz输出数据读取技巧X轴数据寄存器0x08~0x09低字节在前Y轴数据寄存器0x0A~0x0BZ轴数据寄存器0x0C~0x0Dint16_t ADXL362_ReadAxis(uint8_t addrLow) { int16_t axisData; uint8_t lowByte ADXL362_ReadReg(addrLow); uint8_t highByte ADXL362_ReadReg(addrLow 1); axisData (highByte 8) | lowByte; return axisData; }4.2 运动检测功能实现ADXL362的运动/静止检测功能非常适合低功耗应用// 配置运动检测 void ADXL362_ConfigMotionDetection(void) { // 设置运动阈值(200mg) ADXL362_WriteReg(0x20, 0x14); // THRESH_ACT_L ADXL362_WriteReg(0x21, 0x00); // THRESH_ACT_H // 设置运动检测时间(500ms) ADXL362_WriteReg(0x22, 0x32); // TIME_ACT // 启用运动检测 ADXL362_WriteReg(0x27, 0x01); // ACT_INACT_CTL }实际调试中发现运动中断信号有约50ms延迟不适合实时性要求高的场景多次快速运动可能被合并为一个事件需要软件去抖5. 典型问题排查指南问题1读取的数据全是0xFF或0x00检查硬件连接特别是MISO线是否接反用逻辑分析仪抓取SPI波形确认时钟极性和相位测量VDD电压确保在2.0-3.6V范围内问题2数据跳动剧烈检查电源滤波建议在VDD附近加0.1μF陶瓷电容降低SPI时钟频率到1MHz以下测试确保传感器固定牢固避免机械振动影响问题3无法唤醒MCU确认中断引脚配置正确上拉/下拉检查STATUS寄存器(0x0B)的值确认中断源在中断服务程序中及时读取数据寄存器清除中断在最近的一个穿戴设备项目中我们发现当SPI时钟超过3MHz时数据错误率显著上升。最终将时钟降至1.5MHz并缩短走线长度后问题得到解决。这提醒我们手册给出的最大5MHz时钟在实际PCB布局中可能难以达到。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2586679.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!