简易心电图仪摘要:本系统主要以TI公司的低功耗msp430单片机为控制核心,由放大电路、右腿驱动电路、滤波网络、心电波形显示、存储与回放等模块组成。
利用高精度仪表放大器INA128和精密放大器OP07级联的方式对两路心电信号放大。
采用有源高低通滤波电路对心电信号进行综合处理。
设计还采用了右腿驱动电路抑制干扰,提高了放大器的共模抑制比。
单片机和液晶显示器实现了对心电波形的显示、存储与回放。
最终达到各项指标的要求,实现了低功耗的特点。
关键字:示波器滤波网络右腿驱动OP07 NE5532目录一、绪论 (3)(一)研究背景 (3)(二)心电图仪的发展现状 (3)(三)研究意义 (4)二、总体设计 (4)(一)便携式要求 (4)(二)设计框图 (5)三、硬件设计 (5)(一)电极的选择 (5)(二)导联方式的选择 (6)(三)放大电路 (7)(四)滤波网络 (8)四、软件设计 (9)(一)软件设计框图 (9)(二)程序源代码 (11)五、测试 (11)(一)测试仪器 (11)(二)系统测试 (11)(三)测试结果 (12)附录 (13)附录一 (13)附录二 (13)一、绪论(一)研究背景有很多病情较轻或者处在康复期内的心脏病患者,在较长时期内都离不开心电监护系统;或者有些心脏病偶发患者需要长期、连续观察心电参数,以捕捉某一瞬间出现的症状;也有些偏远地区的医院遇到疑难病症,病人在较长时间内需要得到上级医院专家的观察。
基于上述情况,开放一种便携的家用心电图仪,使得病人在家里可以观察并记录自己的心电信号,以备医生检查需求。
本设计介绍的就是一款体积小、重量轻、成本低、质量高、操作简单的便携式心电图仪。
(二)心电图仪的发展现状20世纪80年代心电图仪的特点是小型化、记录时间长,回放系统使用了计算机,并能够准确计算心率、异位心搏和ST段改变,打印系统已经普遍配备激光打印机。
20世纪90年代后的心电图仪的特点是体积小、佩戴舒适、存储容量打、电波保真度搞等。
进入21世纪之后,心电图仪采用当今高速发展的无线网络,提高了系统报警及时性和全面性;采用数字信号处理器(DSP)以及ARM 作为处理核心,以强大的运算能力处理心电信号,省去大量模拟硬件电路;采用图形操作系统,为用户提供了友好界面,直观方便;存储器向着大容量发展,对于心电信号的存储显得游刃有余,为用户保存数据提供了方便;对低功耗的技术的深入,大大延长了系统的工作时间;将其他生理参数监护集成与动态心电监护系统中,实现了一机两用甚至多用,为有特殊需求的患者提供全面的监护;分析系统的发展促进了动态心电监护系统的智能化,大大减少人工劳动。
经过50年的发展,动态心电监护仪的功能和性能早已今非昔比,并且朝着人性化的方向发展,已经成为临床上一种不可缺少的医用电子仪器,对医疗事业的发展有着重大的意义。
(三)研究意义基于对心电图仪研究背景,可以看出便携式心电图仪的研究具有非常重要的意义。
在我国,心血管疾病逐年上升的趋势随着人民生活水平的提高、肥胖人群的增加而呈现加速,加上人民的保健意识也逐渐增强,因此需要一种可家庭自用且具有功耗低、存储量大、可显示等特点的便携式心电图仪来满足市场需求。
该便携式心电图仪的出现主要有以下几个意义:1.普及心电监护仪在家庭中的使用,缓解医院有限资源的压力。
2.该仪器采用电池供电,并采用低功耗设计,可长时间工作,加上便于携带满足现代人对生活的要求。
总之,该便携式心电图仪的成功研制将为我过的家庭保健做出相应的贡献。
二、总体设计(一)便携式要求1.电池供电设计时应根据设备的使用环境,充分考虑电池供电的负载能力和连续工作时间。
目前,可采用普通干电池供电,以利于随地采购。
2. 低功耗由于采用电池供电,便携式设备的低功耗设计显得尤为重要。
设计中应尽量采用低电压、低功耗器件,降低电路的电能耗,在电池电量固定的情况下增加仪器工作的时间,并根据不同的功能允许一些器件进入休眠(低功耗)状态,采取积极措施降低系统功耗。
3. 操作简单具有良好的人机界面,易学易用。
(二) 根据设计要求以及设计思路得以下设计框图图1:图1设计框图 三、硬件设计 (一) 电极的选择 电极的选择对信号的采用是非常重要的一个环节。
有下列几个选择原则: 1. 灵敏度高; 导联选择前置放大 后级放大滤波网络 示波器 单片机 液晶显示 右腿驱动2.电极失调电位低;3.电极噪声低;4.电极极化效应低;为了达到上述要求,采用卤化银材料制作的电极达到的效果最好,市面上的电极通常都是采用该材料制作,其次选择舒适度较为良好的,让患者长时间佩戴不会产生不良反应。
(二)导联方式的选择心电活动是心脏内部的电势连续变化而形成的,反映到人的整个躯体内,可以将其看成是一个随时间连续变化的空间矢量。
在人体适当部位贴上电极,将这个变化记录下来,就形成了心电波形。
在图2(a)中,心脏内部周期性的电荷计划作用在体内形成了如空心粗箭头所示的电极化矢量。
这个矢量在空中划出了一个如图3(b)中用粗黑虚线所示的轨迹。
三根长长的实线箭头组成了一个倒置的等边三角形,三个顶点代表在人体的两个手臂和一条腿上安防的电极,每一个边在代表三个不同的坐标轴。
而心电矢量在这些轴上的投影随时间不停的变换。
(a)(b)图2 三维心电矢量在三条坐标轴上的投影由此可知,采用不同的导联方式得到的心电波形会有所不同。
如果只采用某一个导联得到的波形反应的只是一维的,并不能完全反应心电在整个三维空间的活动,只有通过到个导联采集到的心电波形放在一起综合分析,才能得到完整的心电信息。
根据设计要求和设计条件,本次设计采用右腿驱动的导联方式。
如图3所示,将人体的左臂、右臂作为负信号分别接入放大器的正负输入端。
而右腿则与放大器的参考端子RF相连接,作为放大器的接地端。
图3 右腿驱动导联方式示意图(三)放大电路电路由两级放大构成。
精密仪表放大器INA128作为前级放大,放大100倍。
调节INA128的外围电阻,可以改变增益。
电压增益:G=1+50K Ω/Rg,G=100,则Rg=50KΩ/99=0.505KΩ。
此时,INA128的共模抑制比为120dB,已满足题目的共模抑制比大于80dB的要求。
虽然INA128可以实现放大1000的目的,但是考虑到增益过大INA128芯片的极化现象,故采用了前级放大100倍,后级放大10倍的方案。
后级放大仿真图见图4。
后级放大电路是OP07构成的同比例放大电路,比例系数:K=[(R4+R3)/R3]*[R1/(R2+R1)]=[(19k+1k)/1k]*[10k/(10k+10k)]=10。
为了抑制其他干扰信号,在放大电路的前级增加了右腿驱动,即比例系数为1的正比例电路。
右腿驱动电路仿真图见附录1。
图4 后级放大仿真图(四) 滤波网络 滤波网络的仿真图见图5。
滤波网络是二阶高通滤波电路和一阶低通滤波电路串联的三阶滤波电路。
题目要求低频截止频率为0.05HZ ,高频的截止频率500HZ ,所以可以设计一个截止频率为0.05HZ 的二阶高通滤波器和一个截止频率为500HZ 的一阶低通滤波器。
高通滤波的截止频率的计算公式:22112/1R C R C f π==363610301010010301010014.32/1⨯⨯⨯⨯Ω⨯⨯⨯⨯⨯--f f =0.05HZ低通的截止频率计算公式:HZf R C f 500102107.414.32/1532/136=Ω⨯⨯⨯⨯⨯==-π把高通滤波器和低通滤波器串联即可满足题目的要求。
图5 滤波网络仿真图四、软件设计(一) 软件设计框图YN YN图6 软件设计框图主程序开始系统初始化 扫描键值 存储键是否按回放键是否按执行存储子程序 执行回放子程序 执行回放子程序 按键,进入中断,LCD 显示“心电波形回放”,单片机从FLASH 中读取存储值,由单片机内部D/A 转换输出,并在示波器上清晰显示波形。
执行存储子程序 按键,进入中断,LCD 显示“心电波形存储开始”,单片机内部A/D 采样,读取并写入单片机的FLASH 中,完成后LCD 显示“存储完毕”。
软件设计介绍1.系统初始化系统初始化部分主要是对msp430单片机的I/O口的出入,这里将P1.0~P1.3设置为输入状态,P1.4~P1.7设置为输出状态。
同时,将单片机外部中断、定时器、液晶显示器等等进行初始化设置。
以上部分是为后面的模块使用。
在此模块中还将心电图测试仪的欢迎词写入。
达到打开仪器的时候液晶显示器上就会显示“欢迎使用心电测试”的效果。
2.键值扫描这一部分主要主要利用嵌套的循环函数,不断的检测外部有没有键被按下,如果没有,则进行下一次的循环扫描;如果有,则就判断是存储键被按下还是回放键被按下。
如果是存储键被按下,则程序进入存储子程序执行,如果是放键被按下怎程序进入回放子程序执行。
如果两个都不是,这程序继续进行循环扫描。
3.存储子程序与回放子程序这两个子程序事实上是单片机外部中断的子程序。
当存储键按下引起中断发生,程序控制单片机内部的A/D读取并写入单片机的FLASH,以实现图形的存储。
存储完成后能够在显示器上显示“存储完毕”。
当回放键按下引起中断发生,程序控制单片机读取存储在单片机FLASH中的数据,并通过单片机内部的D/A将数字信号转化为模拟信号,在液晶显示器上显示存储的心电波形图。
(二)程序源代码程序源代码见附录二。
五、测试(一)测试仪器1.EE1640C型函数信号发生器2.4位半数字万用表3.DS1062C示波器(二)系统测试人体心电图测试,按照标准I导联实测心电图,测得波形见图7。
图7 测试波形图(三)测试结果系统的整体测试结果和各个模块的测试结果都基本符合要求。
系统实现了心电信号放大1000倍,电路共模抑制比大于80dB的目的。
同时,系统也满足了低频截止频率为0.05HZ,高频的截止频率500HZ的滤波要求。
总之,系统可以正常放大显示心电信号。
由于软件的原因,系统没能实现心电信号的存储回放功能。
从系统的设计到制作我们学会很多有关精密仪表放大器和滤波器的知识,以后会更加努力学习相关知识。
参考文献:[1]谢自美:《电子线路设计·实验·测试(第三版)》,华中科技大学出版社,2006。
[2]黄智伟:《全国大学生电子设计竞赛技能训练》,北京航空航天大学出版社,2007。
[3]罗亚非,凌阳:《16位单片机应用基础(第一版)》,北京航空航天大学出版社,2005。
附录附录一:右腿驱动电路附录二:程序源代码#include <msp430F149.h>#include "Keypad.h"#include "lcd.h"#define uint unsigned int#define uchar unsigned char unsigned int AD_result=0; unsigned int D[2000]={0}; unsigned int t=0;extern unsigned char key_val; extern int a[5];extern int weishu;int OSC_Delay;//int zy;unsigned char GAIN_FLAG; unsigned char FLAG1=1,FLAG2=1;void deelay(uint n){uchar i;for(i = n;i > 0;i--)_NOP();}void DAtransfer(uint data){uint i;P3DIR|=0xE0;P3SEL|=0X00; //设置为一般的I/O口;P3OUT&=~0x20; //将P3.5-P3.6设置为输出P3OUT|=BIT7;deelay(200);for(i=0;i<16;i++){if(data&0x8000)P3OUT|=0x40;else P3OUT&=~0x40;P3OUT&=~0x80;deelay(200);data<<=1;P3OUT|=BIT7;deelay(200);}P3OUT&=~0x80;P3OUT|=BIT5;}/****单通道多次转换*****Vr+=3.3v,Vr-=0*****/void ADC12(void){P6SEL |= 0x01; // Enable A/D channel A0ADC12CTL0 &= ~ENC;ADC12CTL0 = ADC12ON+SHT0_8+MSC; // Turn on ADC12, set sampling timeADC12CTL1 = SHP+CONSEQ_2; // Use sampling timer, set modeADC12IE = 0x00; // disable ADC12IFG.0ADC12CTL0 |= ENC; // Enable conversionsADC12CTL0 |= ADC12SC; // Start conversion}void Timer_A(){TACTL = TASSEL_1 + TACLR + MC_1; // ACLK:32K,up mode ,clear TAR CCTL0 = CCIE; // CCR0 中断允许CCR0 = 32; //1khz_BIS_SR(LPM0_bits + GIE); // Enter LPM0, Enable interrupts }#pragma vector=TIMERA0_VECTOR //定时器A0的中断函数__interrupt void TimerA_ISR(void){unsigned int temp1;int num[4]={0,0,0,0};while((ADC12IFG & 0x01)==0) ; //判断有没有转换结束ADC12CTL0 &= ~ENC; // 关闭转换AD_result = ADC12MEM0; //读到AD转换的12位二进制数DAtransfer(AD_result);// D[t ++]=AD_result;temp1=(AD_result*3300)/4095;//显示电压值num[3]=temp1/1000;num[2]=temp1%1000/100;num[1]=temp1%100/10;num[0]=temp1%10;Writedata(num[3]+'0');Writedata('.');Writedata(num[2]+'0');Writedata(num[1]+'0');Writedata(num[0]+'0');ADC12CTL0 |= ENC; // 允许AD转换ADC12CTL0|=ADC12SC; //开始新的转换}void main(void){WDTCTL = WDTPW + WDTHOLD; // Stop WDT Init_Keypad();Ini_Lcd();Clear_GDRAM();// 设置CPU MCLK/SMCLK时钟频率BCSCTL1 &= ~XT2OFF;//清OSCOFF/XT2do{IFG1 &= ~OFIFG;//清OFIFGOSC_Delay = 255;while(OSC_Delay --) ;//延时等待}while(IFG1 & OFIFG);//直到OFIFG=0为止BCSCTL1 |= RSEL2 + RSEL1 + RSEL0;//MAXDCOCTL |= DCO0+DCO1;//MCLK = DCO=3MHz/4BCSCTL2 |= SELS+DIVM_2; // SMCLK = XT2(8MHz)//Menu_F();Writecommand(0x01);Disp_HZ(1,1,"欢迎使用心电测试:");delay_Nms(100);ADC12();Timer_A();/* Init_Keypad();do{Key_Event();}while(key_val!=1&&key_val!=5&&key_val!=4); while(1){switch(key_val){//case 1://case 5:FLAG3=1;zybujin();break;//case 3:delay(200);break;}}*/}#include <msp430F149.h>#include "lcd.h"/*跳线说明:* P1.0~P1.3设置为输入状态,P1.4~P1.7设置为输出状态* P1.0~P1.3通过10kΩ电阻与+5v相接,P1.4~P1.7通过300Ω电阻与键盘相接* */typedef unsigned char uchar;typedef unsigned int uint;int a[5];//存储键盘扫描的数据int weishu;/***************全局变量***************/uchar key_Pressed; //按键是否被按下:1--是,0--否uchar key_val; //存放键值uchar key_Flag; //按键是否已放开:1--是,0--否//设置键盘逻辑键值与程序计算键值的映射uchar key_Map[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};/*******************************************函数名称:Init_Keypad功能:初始化扫描键盘的IO端口参数:无返回值:无********************************************/void Init_Keypad(void){//P1高位必须接+5v电压// P1DIR =0Xff;// P1OUT =0X0f;P1DIR = 0xf0; //P1.0~P1.3设置为输入状态, P1.4~P1.7设置为输出状态P1OUT |= 0x0f; //输出为1key_Flag = 0;key_Pressed = 0;key_val = 16;}/*******************************************函数名称:Check_Key功能:扫描键盘的IO端口,获得键值参数:无返回值:无********************************************/void Check_Key(void){uchar row ,col,tmp1,tmp2;tmp1 = 0x10;for(row = 0;row < 4;row++) //行扫描{P1OUT = 0xf0; //P1.4~P1.7输出全1P1OUT -= tmp1; //P1.4~p1.7输出四位中有一个为0tmp1 <<=1;if ((P1IN & 0x0f) < 0x0f) //是否P1IN的P1.0~P1.3中有一位为0{tmp2 = 0x01; // tmp2用于检测出那一位为0for(col = 0;col < 4;col++) // 列检测{if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是{key_val = key_Map[row * 4 + col]; // 获取键值return; // 退出循环}tmp2 <<= 1; // tmp2右移1位}}}}/*******************************************函数名称:delay_15ms功能:延时约15ms,完成消抖功能参数:无返回值:无********************************************/void delay_15ms(){uint tmp;for(tmp = 12000;tmp > 0;tmp--);}/*******************************************函数名称:Key_Event功能:检测按键,并获取键值参数:无返回值:无********************************************/void Key_Event(void){uchar tmp;P1OUT &= 0x00; // 设置P1OUT全为0,等待按键输入tmp = P1IN; // 获取p1INif ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有键按下{key_Pressed = 1; // 如果有按键按下,设置key_Pressed标识delay_15ms(); //消除抖动Check_Key(); // 调用check_Key(),获取键值}else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按键已经释放{key_Pressed = 0; // 清除key_Pressed标识key_Flag = 1; // 设置key_Flag标识}else{_NOP();}}uchar zhi(uchar h){Key_Event();return key_val;}void para_input_display(void){int i=0;int return_flag=0;while(return_flag==0){Init_Keypad();do{Key_Event();} while(key_val==16);switch(key_val){case 0:Writedata('0');delay_Nms(300);a[i]=0;break;case 1:Writedata('1');delay_Nms(300);a[i]=1;break;case 2:Writedata('4');delay_Nms(300);a[i]=4;break;case 3:Writedata('7');delay_Nms(300);a[i]=7;break;case 4:Writedata('.');delay_Nms(300);a[i]=10;break;case 5:Writedata('2');delay_Nms(300);a[i]=2;break;case 6:Writedata('5');delay_Nms(300);a[i]=5;break;case 7:Writedata('8');delay_Nms(300);a[i]=8;break;case 8:return_flag=1;break;case 9:Writedata('3');delay_Nms(300);a[i]=3;break;case 10:Writedata('6');delay_Nms(300);a[i]=6;break;case 11:Writedata('9');delay_Nms(300);a[i]=9;break;case 12:break;case 13:break;case 14:break;case 15:break;}i++;}//weishu=i-1;}//************************************************************************ ******// 一、128*32液晶显示:(串行输出)// 1、可显示两行,每行显示8个汉字,// 2、跳线说明:// :(1)PSB=0(0V),LED+==+5V,LED-==+5V,VDD==+5V,VSS==0V// (2)P2.0|-->CS(可不接,如果不接,则CS=1(+5V))// P2.1|-->SID// P2.2|-->SCLK//////二、4*4键盘扫描显示:// 1、p1.0~1.3 需要上拉电阻10K接5v。