4、传感器接口与通信:I2C/SPI协议基础、GD32与加速度传感器的硬件连接、寄存器读写操作
加速度传感器与MCU之间的数据交换,本质上是在物理层通过特定电气接口、在逻辑层通过通信协议完成的。GD32微控制器与加速度传感器(如ADXL345、LIS3DH、MMA8452Q)之间最常用的两种通信方式是I2C(Inter-Integrated Circuit)和SPI(Serial Peripheral Interface)。本章将深入剖析这两种协议的工作原理、GD32与传感器的硬件连接方法、寄存器读写操作流程,并结合实际项目中的常见问题给出排障思路。
4.1 I2C与SPI协议核心原理
I2C和SPI是嵌入式系统中最常用的板级通信协议,两者在引脚占用、传输速率、时序复杂度上各有取舍。理解它们的本质差异,是正确设计传感器接口的第一步。
4.1.1 I2C协议:两线制多设备总线
I2C由Philips(现NXP)发明,仅需两根信号线:SCL(串行时钟线)和SDA(串行数据线)。所有设备通过开漏输出连接到这两根线上,并外接上拉电阻(典型值4.7kΩ)。I2C采用7位或10位设备地址寻址,理论上一条总线上可挂载多达128个设备。其通信速率分为标准模式(100kbit/s)、快速模式(400kbit/s)和高速模式(3.4Mbit/s)。
I2C的时序核心在于起始条件(SCL高电平时SDA下降沿)、停止条件(SCL高电平时SDA上升沿)以及应答位(ACK)机制。每次传输以起始条件开始,发送设备地址+读写标志位,从设备在地址匹配后拉低SDA作为应答。随后传输寄存器地址和数据字节,每字节后都需要应答确认。
4.1.2 SPI协议:四线制高速全双工
SPI采用主从架构,需要至少四根线:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)和CS(片选,低电平有效)。SPI没有设备地址概念,每个从设备独占一根CS线,因此挂载设备越多,占用的GPIO也越多。SPI的传输速率远高于I2C,典型可达10Mbit/s以上,且支持全双工通信。
SPI的时序由时钟极性(CPOL)和时钟相位(CPHA)决定。CPOL决定空闲时SCLK的电平(0或1),CPHA决定数据在时钟的哪个边沿采样(第一个或第二个边沿)。GD32的SPI外设支持四种组合模式,与传感器通信时需查阅数据手册确认其要求的模式(ADXL345支持SPI模式0和模式3)。
| 对比维度 | I2C | SPI |
|---|---|---|
| 信号线数量 | 2根(SCL+SDA) | 4根(SCLK+MOSI+MISO+CS) |
| 设备寻址 | 7位/10位地址,软件可配置 | 片选线CS,硬件选择 |
| 传输速率 | 100k~3.4Mbit/s | 可达10Mbit/s以上 |
| 通信模式 | 半双工(分时读写) | 全双工(同时收发) |
| 多设备支持 | 一条总线多设备,地址区分 | 每个设备独立CS,占用GPIO |
| 硬件复杂度 | 需上拉电阻,开漏输出 | 推挽输出,无需上拉 |
| 典型应用 | 低速传感器、EEPROM、RTC | 高速传感器、Flash、显示屏 |
4.2 GD32与加速度传感器的硬件连接设计
硬件连接是传感器正常工作的物理基础。以GD32F303系列MCU和ADXL345加速度传感器为例,我们需要从电源、通信接口、中断引脚三个维度进行设计。
4.2.1 电源与去耦设计
ADXL345的工作电压范围为2.0V~3.6V,GD32F303的I/O口兼容3.3V逻辑,因此两者可直接共用一个3.3V电源轨。但需要注意:传感器电源必须加去耦电容,通常在VDD引脚附近放置0.1µF陶瓷电容和10µF钽电容,以滤除高频噪声和电源纹波。若系统中有电机、继电器等大功率负载,建议使用磁珠或LC滤波器将传感器电源与数字电源隔离。
4.2.2 I2C接口连接
当选择I2C模式时,ADXL345的SDO/ADDR引脚接地(7位地址为0x53)或接VDD(地址为0x1D)。GD32的I2C外设引脚(如PB6/PB7)需配置为开漏输出,并外接4.7kΩ上拉电阻至3.3V。连接关系如下:
GD32F303 ADXL345
PB6 (I2C0_SCL) ──→ SCL
PB7 (I2C0_SDA) ──→ SDA
3.3V ──┬── 4.7kΩ ──→ SCL
└── 4.7kΩ ──→ SDA
GND ──────────────→ GND
PB0 (EXTI0) ──────→ INT1
4.2.3 SPI接口连接
若选择SPI模式,ADXL345的CS引脚必须接高电平(选择I2C模式)或由MCU的GPIO控制(选择SPI模式)。SPI连接时,GD32的SPI0引脚映射为:PA5(SCK)、PA6(MISO)、PA7(MOSI)、PA4(CS)。注意ADXL345的SDO引脚在SPI模式下作为MISO使用,SDI/SDA引脚作为MOSI使用。
4.3 寄存器读写操作与驱动实现
加速度传感器的功能配置和数据读取,本质上都是对内部寄存器的读写操作。以ADXL345为例,其寄存器空间为0x00~0x3D,其中0x00~0x1E为只读数据寄存器,0x1D~0x38为读写配置寄存器。
4.3.1 寄存器写操作流程
写操作通常用于配置传感器的量程、采样率、中断使能等参数。以设置ADXL345为±4g量程、100Hz输出速率为例:
// 伪代码:通过I2C写寄存器
uint8_t write_reg(uint8_t reg_addr, uint8_t data) {
i2c_start();
i2c_send_byte(0x53 << 1 | 0); // 设备地址+写标志
i2c_send_byte(reg_addr); // 寄存器地址
i2c_send_byte(data); // 写入数据
i2c_stop();
}
// 配置数据格式寄存器(0x31)为±4g
write_reg(0x31, 0x01);
// 配置带宽速率寄存器(0x2C)为100Hz
write_reg(0x2C, 0x0A);
// 进入测量模式(0x2D)
write_reg(0x2D, 0x08);
4.3.2 寄存器读操作流程
读操作需要先发送寄存器地址,然后重新发送设备地址+读标志,再连续读取数据。ADXL345支持多字节连续读取,读取0x32~0x37即可获得X、Y、Z三轴的16位数据:
// 伪代码:通过I2C读多字节
void read_regs(uint8_t reg_addr, uint8_t *buf, uint8_t len) {
i2c_start();
i2c_send_byte(0x53 << 1 | 0); // 设备地址+写
i2c_send_byte(reg_addr); // 寄存器起始地址
i2c_restart();
i2c_send_byte(0x53 << 1 | 1); // 设备地址+读
for (int i = 0; i < len; i++) {
buf[i] = i2c_read_byte(i == len-1 ? NACK : ACK);
}
i2c_stop();
}
// 读取三轴加速度数据
uint8_t acc_data[6];
read_regs(0x32, acc_data, 6);
int16_t x = (acc_data[1] << 8) | acc_data[0];
int16_t y = (acc_data[3] << 8) | acc_data[2];
int16_t z = (acc_data[5] << 8) | acc_data[4];
4.3.3 中断寄存器配置
为了实现运动检测和低功耗唤醒,需要配置ADXL345的中断功能。典型配置包括:使能数据就绪中断(DATA_READY)、活动/静止检测中断(ACTIVITY/INACTIVITY)。配置流程为:设置阈值寄存器(0x24~0x27)、设置持续时间寄存器(0x28~0x2B)、使能中断映射(0x2E)、使能中断源(0x2F)。
4.4 常见通信故障与调试方法
传感器通信故障是嵌入式开发中最常见的问题之一。掌握系统的排障方法,可以大幅缩短开发周期。
4.4.1 通信故障现象与原因对照
| 故障现象 | 可能原因 | 排查方法 |
|---|---|---|
| I2C无应答(ACK失败) | 设备地址错误、上拉电阻缺失、传感器未上电 | 用示波器测量SCL/SDA波形,检查地址位 |
| SPI读回全0xFF | CS电平错误、SPI模式不匹配、MISO接线错误 | 检查CS是否拉低,确认CPOL/CPHA配置 |
| 数据跳变不稳定 | 电源纹波过大、I2C速率过高、线缆过长 | 增加去耦电容,降低通信速率,缩短连线 |
| 中断不触发 | 中断寄存器未配置、GPIO未配置为输入 | 读取中断源寄存器(0x30)确认中断标志 |
4.4.2 使用逻辑分析仪调试
逻辑分析仪是调试I2C/SPI通信的利器。将逻辑分析仪的通道连接到SCL/SCLK和SDA/MOSI/MISO,设置合适的采样率(至少为通信速率的4倍),即可解码出完整的通信帧。重点观察:起始条件是否正常、地址字节是否正确、ACK位是否存在、数据字节是否与预期一致。
4.4.3 软件层面的调试技巧
在驱动开发初期,建议采用轮询方式读取传感器数据,确认通信链路正常后再切换为中断方式。每次读写寄存器后,可回读该寄存器验证写入是否成功。例如,写入0x31寄存器后,立即读取0x31,若返回值与写入值一致,则说明通信正常。此外,利用GD32的串口打印调试信息,将读取到的原始寄存器值输出,便于对比分析。
4.5 本章总结与工程实践要点
传感器接口设计是嵌入式系统开发的基石。本章从协议原理、硬件连接、寄存器操作到故障排查,构建了完整的知识体系。在实际项目中,建议遵循以下原则:
- 优先选择I2C接口,因其引脚占用少、接线简单,适合大多数加速度传感器应用场景。
- 硬件设计时预留测试点,在SCL、SDA、CS、INT1等关键信号线上预留焊盘,便于调试时连接逻辑分析仪。
- 驱动代码分层设计,将底层寄存器读写函数与上层数据处理逻辑分离,便于移植和复用。
- 重视电源完整性,传感器对电源噪声敏感,去耦电容必须靠近VDD引脚放置。
- 建立通信自检机制,上电后读取设备ID寄存器(ADXL345的DEVID为0xE5),验证通信链路正常后再进行后续配置。
掌握这些核心要点,你就能在GD32平台上快速、稳定地驱动加速度传感器,为后续的数据分类和本地告警功能奠定坚实基础。