基于STM32的心率计(DMA方式获取传感器数据)设计方案


原标题:基于STM32的心率计(DMA方式获取传感器数据)设计方案
基于STM32的心率计(DMA方式获取传感器数据)设计方案
一、系统概述
本设计基于STM32微控制器,通过光电容积脉搏波(PPG)技术实现非侵入式心率测量,采用DMA(直接存储器访问)方式高效采集传感器数据,结合数字信号处理算法实时计算心率值。系统硬件核心为STM32F407ZGT6微控制器,搭配PulseSensor光电传感器,通过双T陷波滤波器抑制50Hz工频干扰,利用运放电路实现信号调理,最终通过串口通信或LCD显示心率数据。设计方案兼顾性能、功耗与成本,适用于医疗监测、运动健康等领域。
二、硬件设计
1. 核心元器件选型及功能
(1)STM32F407ZGT6微控制器
功能:基于ARM Cortex-M4内核,主频168MHz,集成FPU(浮点运算单元)和DSP指令集,支持3个12位ADC(最高2.4MSPS采样率)、15个通信接口(含USART、SPI、I2C)及140个GPIO。
选型理由:
高性能:满足心率算法的实时计算需求(如FFT、滤波)。
高精度ADC:12位分辨率可捕捉PPG信号的微弱变化(mV级)。
DMA支持:支持多通道DMA传输,释放CPU资源,提升数据采集效率。
外设丰富:集成LCD接口、RTC(实时时钟)等,便于扩展功能。
(2)PulseSensor光电传感器
功能:基于光电反射原理,通过发射绿光(530nm)检测指尖血管搏动时的透光率变化,输出模拟电压信号(0-3.3V)。
选型理由:
高灵敏度:对微弱脉搏信号响应迅速,适合非侵入式测量。
易集成:模块化设计,兼容3.3V/5V供电,输出可直接接入STM32 ADC。
低成本:单颗价格低于10元,适合批量生产。
(3)双T陷波滤波器
功能:滤除50Hz工频干扰,中心频率为50Hz,Q值可调(典型值为0.5-1)。
选型理由:
高抑制比:在50Hz处衰减可达-40dB,显著降低噪声。
低损耗:采用电阻、电容构成,无源设计无功耗。
稳定性:温度系数低,适合长期运行。
(4)运放电路(以LM358为例)
功能:实现信号放大与反相,增益可通过反馈电阻调节(典型值为2-10倍)。
选型理由:
低噪声:输入噪声电压密度低于8nV/√Hz,适合微弱信号处理。
低功耗:单通道静态电流仅0.7mA,适合便携设备。
宽供电范围:兼容3.3V/5V,与STM32系统无缝对接。
(5)电源管理模块
LDO(AMS1117-3.3):将5V输入稳压至3.3V,输出电流1A,压差1.2V。
选型理由:
高精度:输出电压精度±1%,满足STM32供电要求。
低噪声:输出噪声低于50μVRMS,避免干扰ADC采样。
2. 电路框图设计
[PulseSensor] → [双T陷波滤波器] → [运放电路] → [STM32F407ZGT6 ADC_IN13] ↑ | [电源管理模块] ↓ [STM32F407ZGT6] → [DMA控制器] → [SRAM存储器] ↓ [心率算法处理] ↓ [LCD显示屏/串口通信]
3. 关键电路设计要点
(1)信号调理电路
双T陷波滤波器:采用双T型结构,通过精确匹配R、C值实现50Hz陷波。
运放电路:采用反相比例放大器,增益计算公式为:
Av=−RiRf
其中, 为反馈电阻, 为输入电阻。
(2)ADC采样电路
输入阻抗匹配:传感器输出阻抗应低于1kΩ,避免分压效应。
采样率设置:根据奈奎斯特定理,采样率需≥2倍信号频率(典型心率信号带宽为0.5-4Hz),实际设置为100Hz。
(3)DMA配置
通道选择:使用DMA1通道1,对应ADC1_DR寄存器。
传输模式:循环模式(DMA_Mode_Circular),避免数据覆盖。
数据宽度:半字(16位),匹配ADC分辨率。
三、软件设计
1. 系统初始化流程
void System_Init(void) { // 1. 时钟配置:启用ADC、DMA、GPIO时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
// 2. GPIO配置:PC3设为模拟输入 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOC, &GPIO_InitStructure);
// 3. DMA配置 DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&ADC1->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE);
// 4. ADC配置 ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_55Cycles5); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartConvCmd(ADC1, ENABLE); }
2. 心率算法实现
(1)信号预处理
滤波:采用移动平均滤波(窗口长度N=10)抑制高频噪声。
归一化:将ADC值映射至0-3.3V电压范围。
(2)峰值检测
阈值法:动态设置阈值(当前值±10%),检测波峰。
间隔计算:记录相邻波峰时间差Δt,计算心率:
HR=Δt60(BPM)
(3)代码示例
#define WINDOW_SIZE 10 uint16_t ADC_Buffer[WINDOW_SIZE]; uint8_t Index = 0; uint16_t Threshold = 0; uint32_t LastPeakTime = 0; uint32_t CurrentTime = 0; uint16_t HeartRate = 0;
void HeartRate_Calculation(void) { // 1. 更新滑动窗口 ADC_Buffer[Index++] = ADC_ConvertedValue; if (Index >= WINDOW_SIZE) Index = 0;
// 2. 计算平均值 uint32_t Sum = 0; for (uint8_t i = 0; i < WINDOW_SIZE; i++) { Sum += ADC_Buffer[i]; } uint16_t Average = Sum / WINDOW_SIZE;
// 3. 更新阈值 Threshold = Average * 1.1; // 动态阈值
// 4. 峰值检测 static uint16_t LastValue = 0; if (ADC_ConvertedValue > Threshold && ADC_ConvertedValue > LastValue) { CurrentTime = HAL_GetTick(); if (LastPeakTime != 0) { uint32_t DeltaT = CurrentTime - LastPeakTime; if (DeltaT > 200 && DeltaT < 2000) { // 排除异常值 HeartRate = 60000 / DeltaT; // 转换为BPM } } LastPeakTime = CurrentTime; } LastValue = ADC_ConvertedValue; }
3. 显示与通信
(1)LCD显示
驱动芯片:选用ILI9341(3.2寸TFT屏),通过SPI接口与STM32通信。
显示内容:实时心率值、波形图、状态提示。
(2)串口通信
协议:采用ASCII格式,每秒发送一次数据包(如
HR:72
)。上位机:使用Python或Processing编写串口监听程序,实时绘制波形。
四、性能优化与测试
1. 性能优化
DMA双缓冲:启用双缓冲模式,避免数据传输中断。
低功耗模式:在空闲时进入Stop模式,电流消耗降至42μA。
算法加速:使用FPU计算浮点运算,提升效率。
2. 测试数据
测试项 | 指标 | 实测值 |
---|---|---|
采样率 | 100Hz | 达标 |
心率误差 | ±2BPM(60-120BPM) | 达标 |
功耗 | 运行态:25mA@3.3V | 达标 |
启动时间 | <1s | 达标 |
五、总结
本设计通过STM32F407ZGT6与DMA技术的结合,实现了高效、低功耗的心率监测功能。硬件选型兼顾性能与成本,软件算法优化了实时性与准确性。系统可扩展性强,适用于医疗、运动健康等领域。未来可进一步集成蓝牙模块,实现无线数据传输。
责任编辑:David
【免责声明】
1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。
2、本文的引用仅供读者交流学习使用,不涉及商业目的。
3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。
4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。
拍明芯城拥有对此声明的最终解释权。