从AD8232到STM32:单导联心电采集系统全栈设计与工程实践

发布时间:2026/9/4 3:23:06
从AD8232到STM32:单导联心电采集系统全栈设计与工程实践 简介本资源是一套完整的心电采集系统整机开发方案面向电子工程师、嵌入式开发者及医疗硬件初学者解决从生物信号采集、模拟调理、模数转换到实时处理与上位机显示的全链路实现问题。压缩包共111个文件涵盖Altium Designer格式的PCB工程.pcbdoc与原理图.schdoc、基于ARM Cortex-M0MKL25Z4的C语言源程序.c/.h为主含uart、USB、系统初始化等模块、编译中间文件.o/.d/.axf/.hex及配置文件.uvproj/.uvopt整体大小仅2.98MB结构清晰、模块分明便于快速定位硬件驱动、信号滤波算法与通信协议实现。已有637人学习下载资源中包含可直接烧录运行的单片机固件、配套上位机交互逻辑及完整软硬协同调试路径特别适合用于课程设计、毕业设计或便携式心电设备原型开发助读者贯通PCB设计、低功耗嵌入式编程与生物电信号处理三大核心能力。1. 项目概述从零到一的心电采集系统全栈实现最近在整理过去的项目资料翻出了一个压箱底的宝贝——一套完整的单导联心电采集系统方案。这个项目当年花了不少心血从模拟前端电路设计、PCB工程到单片机固件开发最后整合成一个可以稳定工作的整机。今天就把这个“心电采集 ,PCB工程原理图,硬件电路,源程序C语言,整机方案.zip”彻底拆开跟大家聊聊一个医疗级或者说准医疗级生理信号采集设备是怎么从图纸变成实物的。如果你是一名电子爱好者、生物医学工程专业的学生或者正在尝试涉足便携式健康设备开发的硬件工程师这套涵盖硬件电路、PCB设计、C语言固件的完整方案应该能给你提供一个非常扎实的参考模板。它解决的不仅仅是一个“采集心电信号”的问题更是一整套应对微弱生物电信号、强工频干扰、安全隔离以及低功耗嵌入式系统的工程化方案。2. 核心需求与设计思路拆解2.1 心电信号的特点与采集挑战心电信号ECG是心脏电活动在体表的表现其典型幅值仅在0.5mV到5mV之间属于极其微弱的模拟信号。直接用它来驱动任何显示或处理电路都是不可能的。更棘手的是我们生活的环境中充斥着50Hz/60Hz的工频干扰其强度可能比心电信号本身高出几个数量级。此外电极与皮肤接触会产生半电池电位人体自身也会产生肌电、呼吸等噪声。因此一个心电采集电路的核心任务可以归结为三点第一将微弱的差分信号如右手与左手之间的电位差放大上千倍第二从强大的共模干扰如工频干扰中提取出有效的差分信号第三将放大后的信号限制在安全的频率范围内心电主要能量在0.05Hz~150Hz并安全地传递给后续的数字处理单元。基于这些挑战经典的电路架构采用了“仪表放大器 高通滤波 低通滤波 工频陷波 二级放大”的级联方案。仪表放大器负责高共模抑制比CMRR的初步放大滤除大部分工频干扰高通滤波去除电极直流偏移和低频漂移低通滤波限制带宽抑制高频噪声工频陷波器如50Hz双T型陷波进一步滤除残余的工频干扰最后一级放大将信号调理到适合ADC采样的电压范围例如0-3.3V。2.2 系统整体架构设计本方案采用经典的“模拟前端 数字处理”架构。模拟前端负责信号的拾取、放大和初步滤波是整个系统性能的基石。数字部分则以一颗低功耗单片机为核心负责ADC采样、数字滤波、算法处理如心率计算以及数据通信或存储。模拟前端我们选择了ADI公司的AD8232集成仪表放大器芯片作为核心。这颗芯片是便携式心电应用的明星产品它内部集成了仪表放大器、右腿驱动RLD电路、导联脱落检测以及可配置的高通/低通滤波器极大简化了外围电路设计性能也相当可靠。主控单元选用意法半导体的STM32F103C8T6也就是大家熟悉的“蓝莓派”核心。它拥有足够的处理能力运行实时数字滤波算法内置的12位ADC足以满足心电信号的采样精度要求并且外设丰富成本低廉。电源与安全系统采用锂电池供电通过低压差线性稳压器LDO产生干净的3.3V模拟和数字电源。最关键的是在模拟前端与人体电极接触的部分必须考虑电气安全。本方案在电极输入路径上设计了高压保护电路如使用TVS管和限流电阻并确保设备外壳、电路板布局满足基本的隔离要求这是产品化设计中不可忽视的一环。输出与交互为了便于调试和观察系统设计了两种输出方式一是通过单片机的DAC或PWM模拟输出连接至耳机插孔可以用普通电脑音箱或示波器监听心电音二是通过串口UART将数字化后的波形数据实时上传到上位机如PC进行显示和分析。3. 硬件电路核心模块详解3.1 模拟前端电路AD8232的实战应用AD8232的电路设计是重中之重。原理图中三个电极RA右臂、LA左臂、RL右腿通过标准3.5mm接口接入。RA和LA接入AD8232的差分输入端IN IN-RL则连接到右腿驱动输出端。关键外围元件参数设计增益设置电阻RgAD8232的增益公式为 G 1 (100 kΩ / Rg)。心电信号经过初步放大我们通常希望第一级增益在100倍左右这样既能放大信号又不会过早饱和。计算可得 Rg ≈ 1 kΩ。这里我选择了一个1.0kΩ、1%精密的薄膜电阻增益的准确性直接影响到后续ADC量程的利用率。高通滤波器HPF芯片内部集成了一个单极点高通滤波器其截止频率由连接在HPF引脚上的电容Chpf决定。公式为 f_HPF 1 / (2π * 0.5MΩ * Chpf)。为了滤除由电极-皮肤界面产生的低于0.5Hz的缓慢直流偏移我们将截止频率设置为0.5Hz。计算得 Chpf 1 / (2π * 0.5MΩ * 0.5Hz) ≈ 0.636μF。实际选用一个0.68μF的陶瓷电容这是一个非常规值但容易获取且接近设计值。低通滤波器LPF同样由连接在LPF引脚上的电容Clpf设置公式为 f_LPF 1 / (2π * 0.5MΩ * Clpf)。心电信号的有效频率上限约为150Hz为了抗混叠和抑制高频噪声我们将低通截止频率设为160Hz。计算得 Clpf ≈ 2000pF。实际选用一个2.2nF2200pF的电容略高于计算值使带宽稍窄更有利于抑制高频干扰。右腿驱动RLD电路这是一个负反馈系统用于降低人体共模电压。它将IN和IN-的平均值即共模电压反相放大后通过RL电极反馈回人体从而主动抵消环境引入的共模干扰是提高共模抑制比的关键。其反馈网络Rf, Cf需要仔细计算以保持稳定通常Rf在兆欧级Cf在数十皮法。注意AD8232的电源引脚必须连接高质量的去耦电容典型值为一个10μF的钽电容或电解电容并联一个0.1μF的陶瓷电容并尽可能靠近芯片电源引脚放置。这是保证放大器稳定工作、抑制电源噪声的基石布局时绝不能妥协。3.2 电源与保护电路设计心电采集设备通常由电池供电因此电源管理既要高效又要干净。LDO选型我们选用TI的TPS7A系列LDO它为模拟电路提供3.3V电源。这款LDO具有极低的噪声约20μVrms和高的电源抑制比PSRR能有效隔离来自电池或数字电路的噪声。数字部分单片机的3.3V可以由同一颗LDO提供但最好在模拟和数字电源域之间用一个磁珠如600Ω100MHz进行隔离并在数字侧增加额外的0.1μF去耦电容。电池充电与管理采用一颗单节锂电池充电管理芯片如TP4056搭配Micro-USB接口实现方便的充电功能。同时需要一个电量检测电路通常由电阻分压后送入单片机的ADC输入引脚软件通过查表法估算剩余电量。输入保护电路在电极输入路径上每个输入端都串联一个高值电阻如100kΩ-1MΩ用于限流。之后并联双向TVS管如SMBJ5.0A到地用于钳位静电放电ESD或意外的高压冲击。这些保护元件必须在信号链路的最前端确保后续精密放大器的安全。3.3 主控与外围接口电路STM32F103C8T6的最小系统包括晶振、复位电路、Boot模式选择电路和调试接口SWD。ADC采样电路AD8232的输出是单端信号直接连接到STM32的某个ADC输入通道如PA0。在ADC输入引脚处我增加了一个RC低通滤波器R1kΩ C100pF其截止频率约1.6MHz主要作用是作为抗混叠滤波器的补充并抑制高频噪声。同时STM32的ADC输入最好在引脚附近放置一个0.1μF的电容到地以提供电荷缓冲。DAC/音频输出为了实时监听心电我们使用STM32的一个DAC通道或一个PWM加低通滤波模拟DAC来重建模拟信号。输出经过一个简单的RC滤波后驱动一个音频插孔。这样就能用电脑音箱听到“扑通-扑通”的心跳声非常直观。串口通信使用USART1PA9-TX PA10-RX连接一个USB转串口芯片如CH340G实现与PC的通信。波特率设置为115200或更高以传输连续的波形数据。4. PCB设计要点与实战技巧4.1 层叠与布局规划这是一个两层板的设计。虽然四层板在噪声控制上更有优势但通过精心的两层板布局完全能满足要求并控制成本。层叠顶层Top Layer主要放置关键模拟器件和信号线底层Bottom Layer作为地平面和电源走线层。保持底层地平面的完整性至关重要。布局分区将PCB板清晰地划分为几个区域电极输入/保护区域、模拟前端区域AD8232及其周边、模拟电源区域LDO、滤波电容、数字区域单片机、晶振、数字接口、数字电源区域。区域之间用“壕沟”无铜区进行物理隔离特别是模拟地和数字地之间最终通过一个“星形”接地点或0欧姆电阻在一点连接。关键器件布局AD8232必须位于模拟区域的核心。它的去耦电容10μF和0.1μF必须紧贴其电源引脚回流路径最短。增益电阻Rg、滤波电容Chpf和Clpf也应靠近AD8232相关引脚放置。STM32的模拟电源VDDA和参考电压VREF的滤波电容同样需要紧靠引脚。4.2 布线规则与信号完整性地平面处理底层尽量保持完整的地平面为所有信号提供低阻抗的返回路径。切忌在关键模拟信号线下方走数字信号线防止噪声耦合。模拟信号走线从电极输入到AD8232再到ADC输入这条路径上的走线需要特别呵护。应使用尽可能短的走线避免与数字线、电源线平行走线。如果必须交叉应成90度角交叉。走线宽度可以稍细如0.2mm但两侧需要有充足的地平面包围形成微带线结构有助于控制阻抗和屏蔽。电源走线模拟电源AVDD走线应加粗并从LDO输出后先经过滤波电容再到达负载。数字电源走线同样加粗。在进入不同区域前使用磁珠或0欧姆电阻进行隔离。右腿驱动RLD输出走线这条走线虽然驱动的是反馈信号但也应视为敏感模拟线避免被噪声污染。4.3 生产文件输出与打样设计完成后需要生成制造文件Gerber和装配文件。Gerber文件通常包括顶层丝印.GTO、顶层阻焊.GTS、顶层铜层.GTL、底层铜层.GBL、底层阻焊.GBS、底层丝印.GBO、钻孔图.TXT和钻孔表.DRL。使用嘉立创等厂商时通常直接上传PCB源文件如Altium Designer的.PcbDoc或打包好的Gerber文件即可。位号与丝印确保所有元件的位号如R1 C2清晰可辨且没有重叠或放在焊盘上。在嘉立创EDA或AD中可以通过“查找相似对象”功能批量选择所有位号统一修改其字体大小和线宽。DRC检查在投板前务必运行设计规则检查DRC确保线宽、线距、焊盘尺寸等都符合PCB厂家的工艺能力如最小线宽/线距6mil。实操心得在第一次打样时我特意在PCB的四个角落和模拟/数字分界处放置了一些“测试点”——其实就是裸露的过孔或焊盘。这些点可以用来焊接飞线方便用示波器测量关键节点的电压和波形对于调试和排查问题 invaluable。例如你可以在AD8232的输入、输出、电源引脚都引出测试点。5. 固件C语言开发与算法实现5.1 开发环境配置与工程搭建我使用STM32CubeMX进行芯片的图形化初始化生成基于HAL库的工程框架然后在Keil MDK-ARM中进行代码编写和调试。VSCode配合EIDE插件也是一个越来越流行的选择编辑体验更佳。时钟配置将系统时钟SYSCLK配置为72MHz这是STM32F103在3.3V下的最高频率能提供足够的处理能力。ADC配置配置ADC1在独立模式、连续转换模式下工作。采样率设置为500HzNyquist频率远高于心电150Hz的上限。使用定时器如TIM2触发ADC转换以确保采样间隔绝对均匀这对后续的数字信号处理至关重要。ADC分辨率设为12位右对齐。DAC配置配置DAC通道1工作在定时器触发模式下触发频率与ADC采样率一致实现实时回放。串口配置配置USART1为异步模式波特率1152008位数据位无校验1位停止位。开启DMA传输用于高效发送ADC数据到上位机。5.2 主程序逻辑与数据流主程序采用“前台后台”或简单轮询架构即可因为心电处理对实时性要求并非极端苛刻。int main(void) { // HAL初始化时钟、外设等 HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_DAC1_Init(); MX_TIM2_Init(); MX_USART1_UART_Init(); // 启动ADC和DAC的定时器触发 HAL_TIM_Base_Start(htim2); HAL_ADC_Start_DMA(hadc1, (uint32_t*)adc_buffer, BUFFER_SIZE); HAL_DAC_Start_DMA(hdac1, DAC_CHANNEL_1, (uint32_t*)dac_buffer, BUFFER_SIZE, DAC_ALIGN_12B_R); while (1) { // 检查ADC缓冲区是否已满半满或全满通过DMA中断标志 if (adc_data_ready) { // 调用数字信号处理函数 ECG_ProcessBuffer(adc_buffer, processed_buffer); // 将处理后的数据复制到DAC缓冲区用于输出 memcpy(dac_buffer, processed_buffer, sizeof(processed_buffer)); // 通过串口DMA发送原始或处理后的数据可选 // HAL_UART_Transmit_DMA(huart1, (uint8_t*)processed_buffer, sizeof(processed_buffer)); adc_data_ready 0; // 清除标志 } // 其他任务如按键扫描、电量检测等 // ... } }5.3 核心数字信号处理算法这是固件的灵魂所在主要在ECG_ProcessBuffer函数中实现。数字工频陷波器尽管模拟前端已有陷波但数字域再做一次可以更干净地去除50Hz干扰。我实现了一个二阶IIR陷波滤波器。其传递函数需要根据采样频率Fs500Hz和陷波频率F050Hz计算系数。这里直接给出一个适用于500Hz采样50Hz陷波的直接II型Biquad系数示例// 系数需要预先计算好 float b0 0.96907f; float b1 -1.61803f; // 这个值需要精确计算此处仅为示例 float b2 0.96907f; float a1 -1.61803f; // 与b1相同 float a2 0.93814f; // 然后使用这些系数进行滤波实际计算需要使用双线性变换法从模拟域转换到数字域过程稍复杂。网上有很多在线的滤波器设计工具可以生成C代码系数。数字带通滤波器进一步将信号限制在0.5Hz-40Hz之间为了突出R波便于检测可以适当压缩高频。这可以通过一个高通滤波器截止0.5Hz和一个低通滤波器截止40Hz级联实现。同样使用IIR滤波器如巴特沃斯型阶数不宜过高2-4阶即可以避免相位失真和稳定性问题。心率检测算法处理后的信号中R波是幅度最大、斜率最陡峭的部分。一个简单可靠的算法是“Pan-Tompkins”算法的简化版。微分计算信号的差分突出斜率。平方将微分后的信号取平方使所有点变为正并放大R波。滑动窗口积分对平方后的信号进行一段时间的积分如150ms窗口生成一个包含R波位置信息的包络。自适应阈值检测在积分后的信号上设置一个动态阈值。当信号超过阈值时认为检测到一个R波峰值。阈值需要根据信号的平均值和峰值动态更新以适应信号幅度的变化。// 简化的峰值检测伪代码 float threshold 0.5 * peak_amplitude; // 初始阈值 for(int i0; ibuffer_size; i) { if(integrated_signal[i] threshold is_peak 0) { // 找到峰值位置 r_peak_index i; is_peak 1; // 更新阈值例如threshold 0.875*threshold 0.125*integrated_signal[i]; // 计算心率60 / (当前R波与上一个R波的时间差(秒)) } if(integrated_signal[i] threshold * 0.6) { // 滞后避免重复检测 is_peak 0; } }6. 系统集成、调试与问题排查6.1 整机装配与初始上电PCB打样回来并焊接好所有元件后先不要连接电极。首先进行目视检查然后用万用表检查电源与地之间是否短路。确认无误后连接电池或USB电源上电。电源测试用万用表测量各关键点的电压LDO输出是否为稳定的3.3VAD8232的电源引脚电压是否正确STM32的VDD和VDDA电压是否正常静态工作点测试不接输入时用万用表测量AD8232的输出引脚OUT电压。它应该稳定在电源电压的一半即Vref通常为1.65V如果采用3.3V单电源且Vref接在电源中点。如果输出饱和在电源轨0V或3.3V可能是电路焊接问题、芯片损坏或参考电压设置错误。6.2 信号通路调试这是最关键的环节需要一台示波器。注入测试信号使用函数发生器产生一个频率1Hz、幅度1mVpp的正弦波通过两个串联的电阻如10kΩ模拟差分信号注入到RA和LA输入端。用示波器观察AD8232的输出端。你应该能看到一个被放大约100倍根据你的增益设置的正弦波且中心电压在1.65V左右。改变输入频率观察高通和低通滤波器的效果。工频干扰测试将输入端悬空或短接到一起模拟共模信号用示波器观察输出。此时输出应该是一条非常平稳的直线噪声很小。如果看到明显的50Hz正弦波说明共模抑制不足检查右腿驱动电路是否工作、电路板布局地平面是否完整、电源去耦是否良好。ADC采样测试连接AD8232输出到STM32的ADC输入。在代码中开启ADC并通过串口打印原始采样值。给输入端注入一个已知的测试信号观察打印出来的数值是否与预期相符。检查ADC的采样值是否在0-4095范围内正常波动。6.3 常见问题与解决方案实录在实际调试中我遇到了以下几个典型问题这里分享排查思路问题输出信号基线严重漂移甚至饱和。排查首先检查电极是否连接良好电极膏是否涂抹均匀。如果电极接触不良阻抗极高会引入巨大的直流偏移。然后用示波器直流耦合档测量AD8232的HPF引脚电压看其是否稳定在Vref附近。如果不稳检查Chpf电容是否焊接正确、有无漏电。解决确保电极与皮肤良好接触。如果问题依旧尝试增大Chpf电容值进一步降低高通截止频率如到0.05Hz但要注意这会延长电路稳定时间。问题信号中混杂有规律的“毛刺”或高频振荡。排查这很可能是电源噪声或电路自激振荡。用示波器探头使用接地弹簧避免长地线环路直接测量AD8232电源引脚上的波形。如果看到高频纹波说明电源去耦不足。解决在AD8232的电源引脚最近处补焊一个高质量的0.1μF陶瓷电容X7R或X5R材质并与原有的10μF电容并联。检查电路板布局确保信号走线远离数字噪声源如晶振、单片机IO口。问题心率检测算法在运动或干扰大时误检或漏检。排查将原始ADC数据通过串口发送到PC用Python如Matplotlib绘制波形。观察在误检/漏检时段信号的形态发生了什么变化。是R波幅度变小了还是噪声变大了解决优化数字滤波器参数尝试调整带通滤波的范围。改进心率算法中的自适应阈值逻辑例如引入噪声水平估计让阈值更智能地跟随信号质量变化。也可以增加一个“信号质量指数”的判断当信号质量太差时暂停心率显示而不是给出错误结果。问题串口发送数据到上位机上位机显示波形断断续续。排查检查串口波特率是否匹配。检查单片机端是否因为处理数据任务过重导致无法及时填充串口发送缓冲区。可以在串口发送完成中断或DMA传输完成中断中设置标志位在主循环中判断确保上一包数据发送完成后再准备下一包。解决使用DMA进行串口发送彻底解放CPU。确保发送的数据包大小是固定的并且上位机程序按照相同的包长度和格式进行解析。可以在数据包中加入帧头、帧尾和校验和提高通信可靠性。这套方案从电路原理到PCB实作再到软件算法形成了一个完整的闭环。它不仅仅是一个学习项目其设计思路和工程实现方法对于开发其他类型的生物电采集设备如肌电、脑电也有很高的参考价值。硬件设计的严谨性决定了信号的质量上限而软件算法的鲁棒性则决定了产品的可用性下限。在实际动手时耐心调试每一个环节理解每一个元件、每一行代码背后的用意远比单纯地复制粘贴更有收获。最后务必记住任何用于接触人体的电子设备安全永远是第一位的在原型阶段就要养成良好的安全设计习惯。本文还有配套的精品资源点击获取