在嵌入式系统开发中,传感器数据采集的实时性和精确性往往直接影响整个系统的性能表现。传统轮询方式或简单中断触发采样存在两个致命缺陷:一是CPU需要频繁介入导致资源浪费,二是采样时刻与传感器工作周期难以精确对齐。我在工业级温湿度监测项目中就遇到过这样的困境——当需要同时采集4路PT100温度传感器和2路湿度传感器时,常规方法要么采样间隔不稳定,要么CPU负载飙升到60%以上。
这个项目的核心目标是通过STM32的定时器触发DMA传输来实现传感器与ADC采样的硬件级同步。具体要实现三个关键指标:
采用TIM2作为主定时器产生基准时钟,通过TRGO输出触发信号。关键配置参数:
c复制TIM_TimeBaseInitTypeDef TIM_BaseStruct;
TIM_BaseStruct.TIM_Prescaler = 84-1; // 1MHz计数频率
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_Period = 1000-1; // 1ms周期
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_BaseStruct);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
从定时器TIM3配置为从模式,接收TIM2的触发信号:
c复制TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Trigger);
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); // ITR1对应TIM2
使用DMA双循环缓冲避免数据竞争,关键配置:
c复制DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_BufferSize = SAMPLE_COUNT * 2; // 双缓冲
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&adc_buffer;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
// 启用半传输和全传输中断
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);
以MAX31865铂电阻测温芯片为例,其转换周期典型值为21ms。我们设计时序如下:
c复制// TIM3 PWM通道配置
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse = 10; // 10μs脉宽
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInit(TIM3, &TIM_OCInitStructure, TIM_Channel_1);
使用STM32的采样保持时间寄存器精确控制采样时刻:
c复制ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_480Cycles);
// 在84MHz时钟下对应5.71μs采样时间
通过交叉触发实现多传感器同步:
实测发现ADC采样时刻存在约200ns的随机抖动。通过以下措施改善:
优化后抖动降低到±50ns以内。
当采样16位ADC值存入32位数组时,发现数据错位问题。解决方法:
c复制#pragma pack(push, 1)
typedef struct {
uint16_t adc1_val;
uint16_t adc2_val;
} adc_pair_t;
#pragma pack(pop)
volatile adc_pair_t adc_buffer[SAMPLE_COUNT];
在间歇工作模式下:
测试条件:STM32F407@168MHz,6路传感器同步采样
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 采样间隔误差 | ±15μs | ±0.8μs |
| CPU占用率(10kHz) | 42% | 6% |
| 功耗(连续模式) | 38mA | 22mA |
| 数据包丢失率 | 0.3% | 0% |
对于高阻抗传感器,建议:
多板卡同步场景:
调试技巧: