基于STM32与AD620的心电信号采集系统设计与实现

发布时间:2026/9/20 14:25:27
基于STM32与AD620的心电信号采集系统设计与实现 1. 项目缘起与整体设计思路心电信号采集这个方向在生物医学电子里算是经典中的经典。我最早接触它是在做一个便携式健康监测终端的时候当时市面上能买到的成品心电模块要么贵得离谱要么噪声大得没法看索性自己从运放和单片机开始搭一套。这套基于STM32的心电采集仪核心目标很明确把人体体表那点几十微伏到几毫伏的心电信号干净地放大、滤波、数字化然后通过串口或者屏幕把波形实时呈现出来。它适合电子类专业的学生做毕业设计也适合想入门生物电信号采集的硬件工程师拿来练手。先说清楚这套系统到底在干什么。人体心电信号有几个非常“难伺候”的特点幅度极小典型值只有1mV左右最微弱的有用成分可能只有几十微伏频率很低主要能量集中在0.05Hz到100Hz之间而且它天然带着一大堆干扰——50Hz工频干扰、电极接触噪声、人体自身的肌电噪声、还有直流极化电压。你要做的就是在一堆噪声里把那个微弱的有用信号“捞”出来还不能把它弄变形。这就决定了整个设计的主线前级高共模抑制比放大 中间级高通滤波去基线漂移 低通滤波去高频噪声 后级再放大到ADC能识别的范围。为什么选STM32而不是51或者别的MCU原因很实际。心电信号采样率一般要做到250Hz到1kHz12位分辨率是底线STM32F103系列自带12位ADC转换速率1MHz配合DMA搬运完全不占CPU。而且STM32的定时器可以精确控制采样周期这对心电这种对时间轴要求严格的信号来说太重要了。另外STM32的串口、SPI、I2C资源丰富后面想加OLED屏、SD卡存储、蓝牙传输都很方便。相比之下51单片机做心电采集光是ADC外挂和时序控制就够你喝一壶的。模拟前端这块AD620和OP07是绕不开的两个器件。AD620是经典的三运放仪表放大器增益用一个电阻就能设定共模抑制比高输入阻抗大特别适合做心电信号的第一级。OP07则是低失调电压的精密运放虽然带宽不高但做滤波和电平抬升非常稳。这两个器件搭配起来成本可控性能也够用。当然有人会问AD820怎么样AD820是单运放输入偏置电流更低但做仪表放大需要自己搭三运放结构匹配电阻要求高对新手不太友好。AD620集成度高省事这是选它的核心理由。整个系统的信号链路我理一下电极从人体采集信号经过AD620做第一级差分放大增益设在100倍左右然后过一个由OP07构成的高通滤波器截止频率0.05Hz把电极极化产生的直流漂移压掉接着再过一个低通滤波器截止频率100Hz到150Hz把高频噪声和工频干扰的谐波滤掉之后再用一级OP07做同相放大把信号抬到0到3.3V范围内同时加一个直流偏置让信号落在ADC量程中间最后送进STM32的ADC引脚由定时器触发采样DMA搬运到内存再做数字滤波和波形显示。这个链路里每一步都有讲究后面我会逐个拆开讲。先记住一个原则模拟部分决定信号质量的上限数字部分只是尽量不把这个上限拉低。很多人把精力全花在STM32的代码上结果模拟前端一塌糊涂采出来的波形全是噪声那就本末倒置了。2. 模拟前端核心细节与实操要点2.1 AD620第一级放大电路的设计与计算AD620的增益公式是G 1 49.4kΩ / Rg其中Rg是接在1脚和8脚之间的增益电阻。我要的增益是100倍代入公式100 1 49400 / Rg解得Rg 49400 / 99 ≈ 499Ω。实际选型时用500Ω的金属膜电阻精度1%就够了算下来增益是99.8倍完全可接受。这里有个细节Rg的精度直接影响增益精度但心电采集对绝对增益精度要求没那么高1%足够了没必要上0.1%的贵电阻。AD620的输入端接法要注意。人体心电信号是差分信号左右手电极分别接IN和IN-右腿驱动电极单独处理。这里必须提右腿驱动电路它是抑制共模干扰的关键。原理很简单从AD620的两个输入端各取一个电阻通常各1MΩ汇合后经过一个反相放大器反馈到右腿电极。这样人体上的共模电压被反相放大后驱动回人体形成负反馈共模干扰被大幅压制。没有右腿驱动50Hz工频干扰能大到把心电信号完全淹没。我实测过不加右腿驱动时示波器上看输出全是50Hz正弦加了之后心电波形立刻清晰。AD620的电源用±5V双电源供电这样输入共模范围更宽输出动态范围也大。电源引脚各接一个0.1μF陶瓷电容和10μF钽电容去耦位置尽量靠近芯片引脚。参考端5脚接地如果后面要做电平抬升也可以在这里加偏置电压但建议第一级参考端直接接地保持差分纯净。注意AD620的输入偏置电流约1nA输入端如果直接接电极电极阻抗不平衡会产生额外失调。实际使用时输入端对地各接一个10MΩ电阻提供偏置电流回路这个电阻要匹配误差控制在1%以内。2.2 OP07高通滤波与低通滤波的配合第一级放大之后信号里混着电极极化产生的直流电压可能有好几百毫伏如果不滤掉后面再放大就饱和了。高通滤波器用OP07搭一个一阶有源高通截止频率0.05Hz。计算RCf 1 / (2πRC)取C 1μF则R 1 / (2π × 0.05 × 1e-6) ≈ 3.18MΩ。实际用3.3MΩ电阻和1μF电容截止频率约0.048Hz够用了。这里电容要选漏电流小的钽电容或者薄膜电容电解电容漏电流大会导致输出漂移。低通滤波器同样用OP07截止频率设150Hz二阶压控电压源结构这样滚降更陡。二阶低通需要两个电阻两个电容计算稍微麻烦点。我一般取C1 C2 0.1μF然后根据f 1 / (2πRC)反推R。150Hz对应R ≈ 1 / (2π × 150 × 0.1e-6) ≈ 10.6kΩ取10kΩ标准值实际截止频率约159Hz。二阶滤波器的Q值设0.707这样通带最平坦。反馈电阻根据Q值算具体公式网上都有这里不展开记住Q0.707对应反馈电阻比输入电阻约0.586倍就行。为什么高通和低通要分开做不用一个带通分开做的好处是每一级可以独立调整调试时先调高通看基线稳不稳再调低通看噪声大不大互不干扰。而且OP07做滤波时每一级增益可以设成1避免增益带宽积不够导致高频衰减。OP07的增益带宽积只有0.6MHz如果一级又滤波又放大很容易自激。2.3 后级电平抬升与ADC驱动经过前三级之后信号幅度大概在1V到2V峰峰值但它是双极性的有正有负。STM32的ADC只能测0到3.3V所以必须把信号抬到1.65V附近。用OP07搭一个同相加法器一路输入是滤波后的心电信号另一路是1.65V的基准电压两路相加后输出。基准电压用TL431或者电阻分压加电压跟随器产生分压电阻取10kΩ和10kΩ从3.3V分压得到1.65V再用OP07做电压跟随器降低输出阻抗。后级放大倍数设2倍左右这样1mV的心电信号经过前级100倍变成100mV再经过后级2倍变成200mV落在ADC量程内。ADC的参考电压用STM32内部的3.3V12位分辨率下1LSB 3.3V / 4096 ≈ 0.8mV。200mV的信号对应250个LSB分辨率足够看清心电波形的主要特征。如果想更精细可以把后级增益提到5倍但要注意输出不能超过3.3V否则削顶。ADC输入端加一个RC低通截止频率设1kHz左右R取1kΩC取0.1μF滤掉高频开关噪声。这个RC还有另一个作用STM32的ADC采样时内部采样电容会瞬间抽取电流这个RC可以缓冲避免信号被拉低。采样时间设55.5个ADC周期保证采样电容充分充电。实操心得OP07做电压跟随器时输出端一定要串一个几十欧姆的电阻再接到ADC防止容性负载导致振荡。我一开始没加波形上总是有高频毛刺加了33Ω电阻后干净了。3. STM32数字部分与系统联调3.1 定时器触发ADC与DMA搬运配置STM32F103的ADC1接在PA0引脚对应通道0。配置步骤我按实际工程顺序说。先开时钟RCC_APB2ENR使能ADC1、GPIOA、AFIORCC_APB1ENR使能DMA1。然后配置PA0为模拟输入GPIO_Mode_AIN。ADC配置独立模式扫描模式关闭连续转换关闭外部触发选择定时器2的TRGO事件数据对齐右对齐通道数1。定时器2配置成向上计数预分频和重装载值决定采样率。我要的采样率是500Hz系统时钟72MHz预分频设72-1得到1MHz计数频率重装载值设2000-1这样更新频率就是1MHz / 2000 500Hz。TRGO输出选择更新事件。DMA配置通道1外设地址是ADC1的DR寄存器内存地址是一个uint16_t数组方向外设到内存循环模式外设和内存数据宽度都是半字内存增量使能。缓冲区大小设500这样每1秒DMA传输完成中断一次在中断里处理数据。这里有个坑STM32F103的ADC和DMA配合时如果DMA没使能就启动ADC会丢数据。正确顺序是先配置DMA并使能再使能ADC最后启动定时器。我踩过这个坑波形上总是隔一段丢一个点查了半天才发现是顺序问题。3.2 数字滤波与波形显示采到的原始数据里还有残余噪声数字滤波做两级一级50Hz陷波一级16点滑动平均。50Hz陷波用二阶IIR系数用MATLAB或者Python算好直接写成C数组。滑动平均简单开一个16长度的环形缓冲区每次新数据进来替换最老的求和除以16。滑动平均的截止频率大概在采样率的1/16左右500Hz采样对应约31Hz对心电信号的主要成分影响不大但能把高频噪声压得很低。波形显示用0.96寸OLEDSSD1306驱动I2C接口。显示时把500个点的缓冲区映射到128列屏幕上每列取4个点的平均值纵轴根据信号幅度自适应缩放。刷新率控制在20帧每秒太高了OLED响应不过来。显示内容除了波形还可以叠加心率数值心率检测用简单的峰值检测算法找滑动窗口内的最大值如果超过阈值且距离上一个峰值超过300ms就算一次心跳。串口输出也保留波特率115200每采样点发两个字节上位机用Python的matplotlib实时画图。这样调试时看波形更方便OLED只是便携显示。3.3 系统联调与噪声排查联调时先不接人体把输入端短接看输出噪声。理想情况下短接时输出应该在1.65V附近波动不超过几个LSB。如果波动大先查电源纹波用示波器AC耦合看±5V和3.3V纹波应该在10mV以内。电源纹波大多半是去耦电容没放够或者地线走线太长。然后接信号发生器输入1mV峰峰值、10Hz正弦波看输出是否干净放大。如果波形失真查后级放大是否饱和。如果噪声大查AD620的Rg电阻是否靠近芯片走线是否对称。我遇到过Rg电阻走线一长一短导致共模抑制比下降50Hz干扰明显后来把两个电阻对称放在芯片两侧就好了。最后接人体用一次性心电电极左右手和右腿。接上后先看基线如果基线漂移大查高通滤波的电容是否漏电。如果波形上有规律的尖峰那是工频干扰查右腿驱动是否正常工作。正常的心电波形应该能看到明显的P波、QRS波群和T波QRS波群幅度最大R波尖锐。常见问题速查表现象可能原因排查方法输出饱和到电源轨前级增益过大或直流漂移未滤除检查高通滤波电容测量各级输出直流电平波形全是50Hz正弦右腿驱动未工作或共模抑制比低检查右腿驱动反馈回路确认Rg电阻匹配波形有高频毛刺ADC驱动RC未加或OP07振荡在OP07输出串33Ω电阻ADC输入加RC采样点丢失DMA和ADC使能顺序错误先使能DMA再使能ADC最后启动定时器基线缓慢漂移高通截止频率过高或电极极化降低高通截止频率更换新电极4. 常见问题与排查技巧实录4.1 电源与地线布局的坑模拟部分和数字部分共用一组电源时数字开关噪声会串到模拟电源上心电波形上会出现与STM32主频相关的周期性噪声。解决办法是模拟部分用独立的LDO供电比如从5V经AMS1117-3.3给数字部分再从另一路AMS1117-5.0或者直接±5V给模拟部分。如果只有一组电源至少在电源入口处用磁珠或者电感隔离模拟和数字地单点连接。地线布局上模拟地和数字地要分开走最后在ADC下方单点汇合。我见过有人把模拟地和数字地混在一起走结果噪声大得没法用。PCB布局时AD620和OP07的地线要尽量短而粗去耦电容的地引脚直接打过孔到地平面。4.2 电极与人体接触的注意事项心电电极接触不良是新手最容易忽略的问题。一次性电极的导电胶干了之后接触阻抗急剧上升信号幅度下降噪声增大。测试时如果发现波形幅度忽大忽小先换新电极。电极贴的位置也有讲究左右手电极贴在手腕内侧右腿电极贴在右脚踝内侧贴之前用酒精棉擦拭皮肤去除油脂和死皮接触阻抗能降一个数量级。还有一点人体本身就是一个天线会拾取空间中的电磁干扰。测试时远离电脑电源、显示器、日光灯这些设备工频辐射很强。我一般在电池供电下测试整个系统用9V电池经稳压供电完全浮地干扰最小。4.3 STM32开发环境与烧录问题Keil5安装STM32芯片包是第一步很多人卡在这里。芯片包从Keil官网下载双击安装后Keil会自动识别。如果Keil5里没有STM32库检查Pack Installer里是否安装了对应的Device Family Pack。标准库新建工程时要把启动文件、系统文件、外设驱动文件都加进去头文件路径也要配好。我习惯用STM32CubeMX生成初始化代码省去手动配置寄存器的麻烦但ADC和DMA的细节还是自己写更可控。烧录用ST-Link接线是SWDIO、SWCLK、GND、3.3V四根线。如果ST-Link Utility识别不到芯片先检查接线再检查芯片是否被禁用JTAG。STM32F103的PA13和PA14是SWD引脚如果程序里把这两个引脚配成普通GPIO下次就烧不进去了。解决办法是按住复位键点击烧录松开复位键趁芯片还没运行用户程序时抢烧。或者用BOOT0拉高进入系统存储器启动模式用串口烧录。独家避坑STM32的ADC在采样时如果引脚悬空读出来的值是随机的。调试时如果发现ADC值乱跳先确认引脚是否接了信号。另外ADC的参考电压如果直接用VDDA而VDDA和VDD之间有压差读数会不准。最好在VDDA和VSSA之间加一个1μF加0.1μF的去耦并且VDDA通过磁珠从VDD取电。4.4 心电信号质量的主观评价采到波形之后怎么判断好坏我一般看三点。第一基线稳不稳好的波形基线应该是一条直线漂移不超过0.5mV。第二QRS波群是否清晰R波尖锐Q波和S波对称幅度在0.5mV到2mV之间。第三P波和T波是否可见P波在QRS之前幅度小但圆滑T波在QRS之后幅度较大且平缓。如果P波和T波完全看不到说明低通截止频率太低或者增益不够。还有一个简单办法用手捏住电极人为制造一个干扰看系统恢复稳定的速度。好的系统在干扰消失后一两秒内基线就回正差的系统要好几秒甚至一直漂。这反映了高通滤波器的响应速度截止频率越低恢复越慢但基线越稳需要折中。5. 后续扩展与个人体会这套心电采集仪的基础版做完之后可以扩展的方向很多。加一个SD卡模块把原始数据存成CSV文件方便后期用MATLAB做HRV分析。加一个蓝牙模块把波形传到手机APP上显示做成便携式。还可以把单导联扩展成三导联用三片AD620分别采集I、II、III导联STM32的ADC多通道扫描模式轮流采样。甚至可以把STM32换成带浮点运算的F4系列在片内做实时FFT分析心电频谱。我个人在实际操作中的体会是模拟前端的调试时间要占总时间的七成以上。很多人急着写代码结果模拟部分没调好代码写得再漂亮也采不到干净信号。我的习惯是先用示波器把每一级输出都看一遍确认每一级的波形都符合预期再接ADC。示波器看模拟波形串口看数字波形两者对照问题出在模拟还是数字一目了然。最后分享一个小技巧AD620的增益电阻Rg可以用一个精密电位器代替调试时先用电位器调到一个合适的增益测出阻值后再换成固定电阻。这样比反复焊电阻方便得多。电位器要用多圈精密型的单圈电位器分辨率不够调不准。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询