《STM32数据记录仪从采集到存储项目实战》

3、数据采集基础:传感器接口类型、ADC原理与配置、DMA传输机制

数据记录仪的本质是将物理世界中的模拟量或数字量转换为MCU可处理的数字信号,并最终落盘存储。在STM32项目中,传感器接口选型、ADC采样精度与DMA传输效率直接决定了数据记录仪的实时性、完整性与准确性。本章将围绕传感器接口类型(模拟、数字、I2C、SPI、UART)、ADC核心原理与配置方法、DMA传输机制三个维度展开,并结合实际工程案例说明如何构建一条高效、低CPU占用的数据采集链路。

STM32数据记录仪采集链路架构 传感器接口类型 模拟输出 (0~3.3V) 运放/分压/滤波 数字IO (PWM/脉冲) 频率/占空比测量 I2C (SDA/SCL) 地址寻址/多设备 SPI (MOSI/MISO/SCK/CS) 高速/全双工 UART (TX/RX) 异步/远距离 模拟 数字 I2C SPI UART STM32 内部处理 ADC 12bit/16bit 规则组/注入组 DMA 循环/普通模式 内存到内存 TIM 定时触发 TRGO → ADC 启动采样 NVIC 中断 DMA半传输/传输完成中断 双缓冲 RAM (Ping-Pong) 数据存储 SD卡 (SPI/SDIO) FATFS文件系统 Flash (W25Q64) SPI接口/掉电保存 USB虚拟串口 实时上传/调试 环形缓冲区 乒乓切换/防丢数据 数据流 模拟信号经ADC采样→DMA搬运→双缓冲→存储介质;数字接口直接通过外设寄存器读取 图:STM32数据记录仪采集链路架构图

3.1 传感器接口类型与选型判断

核心原理:传感器接口决定了信号从物理量到MCU可识别数据的传输路径。模拟接口输出连续电压或电流信号,需经ADC量化;数字接口(I2C、SPI、UART)则直接输出数字码流,MCU通过对应外设控制器解析。选择接口类型时需综合考虑采样率、分辨率、传输距离、功耗和引脚占用。

接口类型典型传感器最大速率引脚数适用场景STM32外设
模拟NTC热敏电阻、压力传感器、光敏电阻取决于ADC采样率1低速、低成本、高分辨率需求ADC + DMA
数字IO霍尔开关、编码器、风速计取决于定时器输入捕获1频率/脉宽测量TIM + IC
I2CSHT30温湿度、BMP280气压、MPU6050400kbps (Fast Mode)2 (SDA/SCL)多设备、低速、板内通信I2C + DMA
SPIMAX31865热电偶、ADXL345加速度、W25Q64 Flash可达45Mbps4 (MOSI/MISO/SCK/CS)高速、大数据量、板内通信SPI + DMA
UARTGPS模块、激光雷达、气体传感器可达921600bps2 (TX/RX)远距离、异步通信、与PC交互USART + DMA

判断方法:首先确认传感器数据手册中的输出类型。若为电压输出(如0-3.3V),则走模拟通道;若为数字协议,则需匹配对应外设。其次评估采样率需求:若单通道采样率超过10kHz,建议使用SPI或并行接口;若低于1kHz且设备数量多,I2C更合适。最后考虑系统复杂度——I2C通过地址区分设备,但速率受限;SPI速率高但需额外CS引脚管理。

经验提醒:在数据记录仪项目中,优先将高速传感器(如加速度计、麦克风)挂在SPI或SDIO接口上,将低速环境传感器(温湿度、气压)挂在I2C总线上。这样既能保证带宽,又能简化PCB布线。UART适合与外部设备通信(如GPS),但注意电平转换(RS232/RS485)。

3.2 ADC原理与STM32配置要点

核心原理:ADC(模数转换器)将连续模拟电压映射为离散数字值。STM32内置逐次逼近型(SAR)ADC,分辨率12位(部分系列支持16位),转换结果存储在数据寄存器中。关键参数包括:参考电压(VREF+)、采样时间(Sample Time)、转换周期(Conversion Cycle)和通道扫描模式。

操作流程:配置ADC需完成以下步骤:

  1. 时钟使能:开启GPIO、ADC和DMA时钟(如RCC->APB2ENR |= RCC_APB2ENR_ADC1EN)。
  2. GPIO模拟模式:将采样引脚配置为模拟输入(GPIO_Mode_AN)。
  3. ADC参数配置:设置分辨率、对齐方式(右对齐)、扫描模式、连续转换或单次转换。
  4. 采样时间设置:根据源阻抗选择采样周期(如239.5周期),确保内部采样电容充满。
  5. DMA请求使能:开启ADC的DMA输出,避免CPU频繁读取数据寄存器。
// 以STM32F407 ADC1 通道0 (PA0) 为例
ADC_InitTypeDef ADC_InitStruct;
ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;      // 单通道
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; // 连续转换
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStruct);

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_84Cycles);
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);

案例拆解:某工业数据记录仪需采集4-20mA电流环信号,经250Ω精密电阻转换为1-5V电压。由于STM32 ADC输入范围0-3.3V,需先经分压电阻(如30kΩ/20kΩ)将电压降至0.66-3.3V。此时源阻抗较高,需将采样时间设为最大(如480周期),否则采样值会偏低。实测发现,若采样时间设为84周期,读数偏差达2.5%;改为480周期后偏差降至0.3%。

风险提示:ADC输入电压严禁超过VREF+(通常为3.3V),否则可能损坏引脚。若传感器输出超过3.3V,必须使用分压电阻或运放进行电平移位。同时注意参考电压的稳定性——VREF+引脚需外接去耦电容(100nF+10μF),否则转换结果会随电源波动。

3.3 DMA传输机制与双缓冲设计

核心原理:DMA(直接内存访问)允许外设(如ADC、SPI、UART)在无需CPU干预的情况下,将数据直接搬运到内存缓冲区。STM32的DMA控制器支持循环模式、双缓冲模式和突发传输。对于数据记录仪,DMA可显著降低CPU负载,使主循环专注于数据处理和存储。

判断方法:当外设产生数据的速度高于CPU处理速度,或需要连续采集大量数据时,必须使用DMA。例如,以10kHz采样率、12位分辨率连续采集,每秒产生20KB数据,若用中断方式,CPU将忙于响应中断而无法执行其他任务。此时DMA循环模式配合双缓冲是最佳方案。

特性普通模式循环模式双缓冲模式
传输结束后行为停止,需重新配置自动重置并继续在两个缓冲区之间切换
CPU干预每次传输完成需中断仅在缓冲区满时中断半传输/传输完成中断
适用场景单次数据块传输连续数据流采集高速连续采集+实时处理
数据丢失风险低高(若处理不及时)低(乒乓切换)

操作流程(双缓冲实现):

  1. 定义两个缓冲区 uint16_t buf1[1024], buf2[1024];
  2. 配置DMA为循环模式,内存地址交替指向buf1和buf2。
  3. 使能DMA半传输中断(Half Transfer)和传输完成中断(Transfer Complete)。
  4. 在半传输中断中处理buf1数据,在传输完成中断中处理buf2数据。
// DMA双缓冲配置伪代码
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;          // 循环模式
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)buf1;  // 内存基地址
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStruct.DMA_BufferSize = 1024;
DMA_Init(DMA2_Stream0, &DMA_InitStruct);

// 使能双缓冲
DMA_DoubleBufferModeConfig(DMA2_Stream0, (uint32_t)buf2, DMA_Memory_1);
DMA_DoubleBufferModeCmd(DMA2_Stream0, ENABLE);

// 中断处理
void DMA2_Stream0_IRQHandler(void) {
  if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_HT)) {  // 半传输
    process_data(buf1, 1024);
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HT);
  }
  if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TC)) {  // 传输完成
    process_data(buf2, 1024);
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC);
  }
}

案例复盘:某便携式振动记录仪需以25.6kHz采样率连续采集三轴加速度数据(每轴16位),总数据率约153.6KB/s。采用ADC1+DMA循环模式,双缓冲区各8KB。DMA半传输中断将数据写入SD卡FATFS缓冲区,传输完成中断处理下一批。实测CPU占用率从中断方式的78%降至12%,且未出现数据丢失。关键优化点:将DMA优先级设为最高,并将缓冲区大小对齐到SD卡扇区(512字节)的整数倍,减少写入次数。

总结复盘:数据采集链路的核心是“接口匹配+高效搬运”。模拟信号需关注ADC采样时间和参考电压稳定性;数字接口需根据速率选择I2C/SPI/UART;DMA双缓冲是保证连续采集不丢数据的关键。实际项目中,建议先用逻辑分析仪验证传感器输出波形,再配置STM32外设参数,最后通过DMA中断统计丢包率来验证系统可靠性。