3、传感器接口与数据采集:常见传感器类型、模拟与数字接口、ADC与I2C/SPI读取方法
GD32边缘告警系统的核心在于“感知”与“判断”。传感器作为系统的感知层,其数据采集的准确性、实时性和稳定性直接决定了后续本地判断逻辑与通信上报的质量。本章将围绕传感器选型、接口类型、以及GD32微控制器(MCU)的读取方法展开,重点剖析模拟传感器(温度、湿度、烟雾)与数字传感器(红外、温湿度数字芯片)在工程实践中的差异,并给出基于ADC、I2C、SPI总线的具体实现路径。
3.1 常见传感器类型与选型原则
在边缘告警系统中,传感器选型需要综合考虑检测对象、环境适应性、功耗、接口复杂度与成本。根据输出信号形式,传感器可分为模拟输出型与数字输出型两大类。模拟传感器直接输出连续变化的电压、电流或电阻值,需要MCU内部ADC进行量化;数字传感器则内置ADC或直接输出数字协议帧,通过I2C、SPI或单总线与MCU通信。
| 传感器类型 | 检测对象 | 输出形式 | 典型接口 | GD32读取方式 |
|---|---|---|---|---|
| NTC热敏电阻 | 温度 | 电阻值变化 | 模拟(分压电路) | ADC采样 + 查表/公式 |
| DHT22/AM2302 | 温度+湿度 | 单总线数字 | 单总线(GPIO模拟) | GPIO时序读取 |
| SHT30/SHT31 | 温度+湿度 | I2C数字 | I2C | I2C读寄存器 |
| MQ-2烟雾传感器 | 可燃气体/烟雾 | 模拟电压(0~5V) | 模拟(需电平匹配) | ADC采样 + 阈值判断 |
| HC-SR501红外人体 | 人体红外辐射 | 数字电平(高/低) | GPIO | GPIO中断/轮询 |
| BMP280气压 | 大气压/海拔 | I2C/SPI数字 | I2C/SPI | I2C/SPI读取校准参数 |
选型时需注意:模拟传感器响应速度快、成本低,但易受电源噪声和走线干扰;数字传感器内置校准和线性化处理,精度更高,但通信时序要求严格。在边缘告警场景中,温度、湿度建议优先选用I2C接口的数字传感器(如SHT30),烟雾传感器因成本敏感且检测原理特殊,通常保留模拟接口。
3.2 模拟接口与ADC读取方法
3.2.1 模拟信号调理电路
GD32F303的ADC输入范围通常为0~3.3V(VREF+),而部分传感器(如MQ-2)输出0~5V,直接接入会损坏引脚。因此必须设计信号调理电路:采用电阻分压将5V映射到3.3V以内,或使用运算放大器搭建电压跟随器与电平移位电路。对于NTC热敏电阻,典型接法是将其与固定电阻串联构成分压器,ADC采集分压点电压。
// NTC分压电路计算示例
// VCC = 3.3V, R_fixed = 10kΩ, NTC在25℃时阻值10kΩ
// V_adc = VCC * R_ntc / (R_fixed + R_ntc)
// 25℃时: V_adc = 3.3 * 10 / (10+10) = 1.65V
// 50℃时: NTC阻值约3.6kΩ, V_adc = 3.3 * 3.6 / (10+3.6) ≈ 0.87V
3.2.2 GD32 ADC配置与采样
GD32F303内置12位逐次逼近型ADC,支持最多16个外部通道。配置ADC时需设置时钟分频、采样时间、转换模式(单次/连续/扫描)以及触发方式。在边缘告警系统中,推荐使用DMA+定时器触发的方式,实现多通道循环采样而无需CPU干预。
// GD32 ADC+DMA 初始化核心代码
void adc_dma_init(void) {
// 使能时钟
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_DMA0);
// 配置PA1为模拟输入
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
// ADC配置
adc_clock_config(ADC_ADCCK_PCLK2_DIV6);
adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 1);
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
adc_external_trigger_config(ADC0, ADC_EXT_TRIGGER_ROUTINE, ENABLE);
adc_external_trigger_source_config(ADC0, ADC_EXT_TRIGGER_ROUTINE, ADC_EXT_TRIGGER_ROUTINE_T0_CH0);
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
adc_dma_mode_enable(ADC0);
adc_enable(ADC0);
adc_calibration_start(ADC0);
adc_software_trigger_enable(ADC0);
}
V = ADC_Value * 3.3 / 4095。对于NTC温度测量,建议使用Steinhart-Hart方程或查表法,避免使用简化B值公式在宽温域下产生较大误差。
3.3 数字接口:I2C与SPI读取方法
3.3.1 I2C总线读取(以SHT30为例)
I2C总线使用两根线(SCL、SDA)连接多个设备,通过7位从机地址区分。GD32的I2C外设支持主机模式、多主机模式和从机模式。读取SHT30温湿度数据时,需先发送测量命令(0x2C 0x06),等待约15ms后读取6字节数据(温度MSB、LSB、CRC、湿度MSB、LSB、CRC)。
// GD32 I2C0 读取SHT30温湿度
#define SHT30_ADDR 0x44 // 7位地址
#define CMD_MEASURE 0x2C06 // 高重复性测量
void sht30_read(float *temp, float *humi) {
uint8_t buf[6];
// 发送测量命令
i2c_start_on_bus(I2C0);
i2c_send_byte(I2C0, (SHT30_ADDR << 1) | 0); // 写
i2c_send_byte(I2C0, 0x2C);
i2c_send_byte(I2C0, 0x06);
i2c_stop_on_bus(I2C0);
delay_ms(20); // 等待测量完成
// 读取数据
i2c_start_on_bus(I2C0);
i2c_send_byte(I2C0, (SHT30_ADDR << 1) | 1); // 读
for (int i = 0; i < 6; i++) {
buf[i] = i2c_receive_byte(I2C0);
if (i < 5) i2c_ack_config(I2C0, I2C_ACK_ENABLE);
else i2c_ack_config(I2C0, I2C_ACK_DISABLE);
}
i2c_stop_on_bus(I2C0);
// 计算温湿度
uint16_t raw_t = (buf[0] << 8) | buf[1];
uint16_t raw_h = (buf[3] << 8) | buf[4];
*temp = -45.0f + 175.0f * raw_t / 65535.0f;
*humi = 100.0f * raw_h / 65535.0f;
}
3.3.2 SPI总线读取(以BMP280为例)
SPI总线使用四线(SCLK、MOSI、MISO、CS),传输速率远高于I2C,适合需要高速连续读取的场景。BMP280气压传感器支持SPI模式,读取时需先读取校准系数(存储在OTP中),再读取原始压力/温度数据,最后通过补偿公式计算实际值。
// SPI读取BMP280寄存器
uint8_t bmp280_read_reg(uint8_t reg) {
uint8_t val;
gpio_bit_reset(GPIOB, GPIO_PIN_12); // CS拉低
spi_i2s_data_transmit(SPI0, reg | 0x80); // 读标志
while (spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE) == RESET);
val = spi_i2s_data_receive(SPI0);
gpio_bit_set(GPIOB, GPIO_PIN_12); // CS拉高
return val;
}
3.4 实战案例:多传感器融合采集与数据校验
场景背景:某机房边缘告警节点需监测温度、湿度、烟雾浓度和人员入侵。硬件平台采用GD32F303VET6,传感器包括:SHT30(I2C)、MQ-2烟雾传感器(ADC)、HC-SR501红外(GPIO)。系统要求每500ms采集一轮数据,并通过串口上报给本地判断模块。
初始现象与目标:初期调试时发现SHT30读取偶发返回0xFFFF,MQ-2的ADC值波动超过±50mV,导致误告警。目标是将数据采集成功率提升至99.9%以上,并消除ADC噪声引起的误报。
分析判断过程:
- SHT30读取异常:通过逻辑分析仪抓取I2C波形,发现SDA线在通信过程中存在毛刺,且SCL高电平时间不足。判断为I2C上拉电阻过大(10kΩ)加上总线电容较大,导致上升沿过缓。
- MQ-2 ADC波动:检查电源纹波,发现3.3V电源在MQ-2加热丝启动时跌落约200mV。MQ-2的模拟输出直接受电源影响,且未做滤波处理。
实际操作步骤:
// 1. 修改I2C上拉电阻为4.7kΩ,并在SDA/SCL对地增加100pF电容
// 2. 软件增加I2C通信失败重试机制(最多3次)
// 3. MQ-2输出增加RC低通滤波:R=10kΩ, C=10μF,截止频率约1.6Hz
// 4. ADC采样采用多次平均:连续采样8次,去掉最大最小值后取平均
// 5. 增加软件去抖:连续3次超过阈值才触发告警
结果对比:优化后,SHT30读取成功率从98.2%提升至99.95%;MQ-2的ADC值波动从±50mV降至±8mV;误告警次数从每周约5次降为0次。代价是采样周期从300ms延长至500ms,但满足系统实时性要求。
复盘经验:边缘采集系统必须同时考虑硬件设计与软件容错。I2C上拉电阻并非越大越好,需根据总线长度和从机数量计算;模拟传感器必须做硬件滤波,不能完全依赖软件平均;任何通信协议都应实现超时与重试机制,防止单次故障导致整个采集链路阻塞。
3.5 常见误区与总结复盘
- 误区一:所有传感器都直接接入MCU引脚。实际上,5V传感器需电平转换,高阻抗传感器需加缓冲器。
- 误区二:ADC采样率越高越好。过高的采样率会引入更多高频噪声,且增加CPU负担。边缘告警场景中,10~100Hz采样率已足够。
- 误区三:I2C通信失败后立即报错。正确做法是重试2~3次,并检查总线状态(SDA/SCL是否被拉死)。
- 误区四:忽略传感器上电稳定时间。MQ-2需要预热3~5分钟才能输出稳定值,SHT30上电后首次读取需等待10ms。