血压信号采集系统设计论文51单片机版文档格式.docx
《血压信号采集系统设计论文51单片机版文档格式.docx》由会员分享,可在线阅读,更多相关《血压信号采集系统设计论文51单片机版文档格式.docx(24页珍藏版)》请在冰豆网上搜索。
示波法是根据在袖带内压力下脉搏波幅度变化的特征,来识别动脉收缩压、平均压及舒张压。
采用示波法测量血压不能从某一脉搏波信息中获得血压数值,而必须根据放气过程中脉搏波随袖带压变化的趋势图来判断血压值。
2.2总体方案概述
2.2.1系统组成部分
电子血压计由压力传感器、初级运算放大电路、滤波电路、次级放大电路、数模转换电路、显示电路、按键和单片机组成。
压力传感器完成对血压信号的采集,运算放大电路及滤波电路对采集来的信号进行预处理得到两路所需信号,A/D转换电路对这两路信号进行数模转换,单片机作为电子血压计的控制核心,完成对信号的存储与计算,并通过计算所得数据来控制外围电路,进行血压数据的显示与报警。
整个系统总体上主要由以下几个部分组成:
(1)信号采集部分
信号采集部分主要包括一个压力传感器、前置放大器、带通滤波器与低通滤波器主要完成袖带压力及脉搏信号检测。
(2)数模转换部分
该部分由多路A/D转换器组成,转换内容为袖带压力和袖带压力脉动波。
在本设计中A/D转换器为单片机的外设。
(3)中央处理单元
中央处理单元的主要组成部分为单片机AT89C52,其主要完成的工作有:
通过串口接收单片机给出的系统参数设置及控制命令,并向单片机传送测量数据,其中包括计算收缩压、舒张压、平均压数据、对气泵及模数转换的控制、测量过程中的各种算法实现。
微控制器对气泵充气与排气进行控制,同时控制报警。
(4)显示模块
采用LCD1602显示人体的收缩压、舒张压、脉搏。
2.2.2总体框图
系统的工作过程:
压力传感器采集到信号后,送入运算放大电路。
由于本文选用的是幅值系数法,需要分离出袖带压信号和脉搏波信号,根据袖带压信号和脉搏波信号的频率特征,其中一路信号由低通滤波器分离出袖带压信号,另一路由带通滤波器分离出脉搏波信号,一并送入A/D转换器。
袖带气压和脉搏波经数字信号处理后可得到收缩压、舒张压以及平均压。
将计算所得结果输出至LCD1602显示。
当舒张压或收缩压的值超出其正常值时,显示报警标识符“!
!
”。
气泵的充气以及排气也是由微处理器控制的。
系统组成框图如下:
三、硬件设计
3.1压力传感器BP01
本系统采用了德利康公司的BP01型压力传感器来采集血压信号,BP01型压力传感器是为监测血压而专门设计的,主要用于便携式电子血压计。
具有高线性、低噪声和外界应力小的特点,采用内部标定和温度补偿方式,从而提高了测量的精度、稳定性以及可重复性,在全量程范围内,精度为±
1%,零点失调不大于±
300μV。
本系统内部集成运放LM324的输入正端为可设定的直流偏置电压Vref,LM324的输出端和输入正端提供了压力传感器电桥偏置的回路。
偏置电压:
BP01的电路连接如下图:
3.2信号预处理电路设计
3.2.1前置放大电路
从传感器BP01输出的信号为0~15mV的差分信号,动脉血压的参数范围为10~400mmHg。
由于生理信号具有幅度小,频率底,内阻高等特点,且存在较强的背景噪声和干扰,无法进行直接记录与显示,针对此类生物信号的特殊性,初级放大电路应具有很高的共模抑制比,以及高增益、低噪声和高输入阻抗、有合适的通频带宽和动态范围等等特点。
生理信号的这些特性对测量放大器的要求很高,为了满足这些要求,我们选择前置放大器。
前置放大电路原理图如下图所示:
UIB,UIC接成同相输入形式,主要用来提高输入阻抗,提供电压缓冲,UID组成差动放大器,用以抑制UIB,UIC传递过来的共模电压,并提供一定的差模增益,以提高共摸抑制比。
3.2.2袖带压力信号处理
从压力传感器中获得的血压信号包含袖带内压力信号,该信号是缓慢变化的(低频),要想提高袖带压力信号需采用低通滤波器。
故本设计采用二阶有源低通滤波器,如下图所示:
3.2.3脉搏波信号的处理
传感器BP01输出的血压信号包括袖带压力信号和脉搏波信号,但其中还夹杂着来自外界的高频干扰和直流或低频分量。
一般来说,脉搏波信号的频率范围为0.6~6.4Hz。
为此本文设计的带通滤波器:
通过频率为0.4~6.6HZ以获取脉搏波信号。
带通滤波器为两级带通滤波器的级联,因为级联后的带通滤波器将提供出更高的增益,并且级联后的滤波器的频率响应比一级带通滤波器的频率响应会更尖锐。
两带通滤波器的级联如下图所示:
第一级带通滤波器:
低截止频率:
高截止频率:
第二级带通滤波器:
3.2.4预处理总电路图
3.3数模转换电路设计
3.3.1ADC0808数模转换芯片
本实验的数模转换芯片采用的是ADC0808,如右图所示:
ADC0808由一个8路模拟开关、一个地址锁存与译码
器、一个A/D转换器和一个三态输出锁存器组成。
各引脚
功能如下:
IN0-IN7:
8位模拟量输入引脚.
OUT1-OUT8:
8位数字量输出引脚。
A、B、C:
地址输入线,用于选通IN0-IN7
上的一路模拟量输入。
START:
A/D转换启动信号输入端,当START上跳沿时,所有内部寄存器清零;
下跳沿时,开始进行A/D转换;
在转换期间,START应保持低电平。
ALE:
地址锁存允许信号输入端,当ALE线为高电平时,地址锁存与译码器将A,B,C三条地址线的地址信号进行锁存,经译码后被选中的通道的模拟量进转换器进行转换。
EOC:
转换结束信号输出引脚,开始转换时为低电平,当转换结束时为高电平。
3.3.2ADC0808与单片机的连接
AD转换电路电路图如下:
3.4数据显示部分
本设计用的是LCD1602做显示,如下图:
四、系统软件设计
系统软件设计的流程图如下所示:
数模转换的程序流图如下所示:
五、系统调试与仿真
本设计采用了KeiluVision2和ProteusISIS进行仿真调试。
当按钮按下后显示模块显示当前袖带压力值,如下图所示:
此时气泵开始充气,当直流量>
4V时,气泵开始均匀放气并开始测量交流信号,当直流量<
1V时,测量结束并显示测量值。
若测量血压数据正常,仿真结果如下图所示:
若测量血压数据偏高,仿真结果如下图所示:
若测量血压数据偏低,仿真结果如下图所示:
六、PCB布线结果
PCB底层布线图
PCB顶层布线图
PCB标识层布线图
PCB总布线图
七、心得体会
此次关于“血压信号采集系统设计”的课程设计,我们从任务分配、查阅资料、最初的方案设计、数据处理到最后的画图、仿真。
在这为期3周的过程中,我们每个组员都收获很多。
对于血压计的原理有了更加深入的了解,更好地熟悉并掌握了ProtelDXP的操作。
针对每个过程、每个细节都有了更深入的体会。
当然也让我们更加清楚地看到其中出现的不足之处。
在画图仿真过程中出现了些细节上的小问题,但是通过大家不厌其烦地多次修改、调试,最终达到了实验目的。
八、参考文献
[1]吴咏春主审.可编程控制器原理与程序设计.大连理工出版社.2009;
[2]郭冀珍.电子血压计可不可靠.高血压杂志[J].2005
[3]席德勋.现代电子技术,高等教育出版社,1999
[4]赵小安.MCS-51单片机原理及应用.天津大学出版社.2001
九、附录
总电路图
仿真总图
程序编码
#include<
reg52.h>
#defineuintunsignedint
#defineucharunsignedchar
#definead0_7P0//AD数据口
sbitA=P2^0;
sbitstart=P2^3;
//下降沿启动AD转换,上升沿寄存器清零,转换过程为低电平
sbitclock=P2^4;
sbitEOC=P2^5;
//AD转换结束输出高电平
sbitALE=P2^6;
//地址锁存允许地址输入端,高电平有效
sbitOE=P2^7;
//读数据控制,高电平有效
sbitrs=P3^0;
//定义液晶显示器控制端口
sbitrw=P3^1;
sbiten=P3^2;
sbitkey=P3^3;
sbitMT=P3^4;
ucharcodetable[17]={"
H=128L=82"
};
ucharcodetable1[17]={"
Sum=75"
ucharcodetable2[13]={"
0123456789!
"
ucharcodetable3[17]={"
testing..."
uchardatabuf[9];
//用于数字显示
uinti;
intdata_H,data_L,Sum,max;
voidstart_ad();
//启动AD转换子程序
voiddelay(uchartime);
voidwrite_com(ucharcom);
//写指令函数
voidwrite_data(uchardat);
//写数据函数
voidmatch();
//数据分析子程序
voiddisplay();
//显示子程序
voiddisplay1();
voidmain()
{
TMOD=0X22;
//定时器设置
TH0=0XFF;
//定时器0置初值1us500KHz
TL0=0XFF;
EA=1;
//开总中断
ET0=1;
//定时器0中断开启
TR0=1;
//启动定时0
MT=1;
while
(1)
{match();
}
voiddelay(uchartime)//延时
{
uintj;
for(;
time>
0;
time--)
for(j=0;
j<
125;
j++);
}
voidwrite_com(ucharcom)//写指令函数
en=0;
rs=0;
P1=com;
en=1;
voidwrite_data(uchardat)//写数据函数
rs=1;
P1=dat;
voidtime0(void)interrupt1using1//定时中断子程序
//重赋初值
//重新启动定时器
clock=!
clock;
voidstart_ad()//启动AD转换子程序
{
//通道0
A=0;
ALE=1;
//允许地址输入
start=0;
delay
(1);
start=1;
//上升沿数据清零
//下降沿开始转换
while(!
EOC)//转换结束关闭地址输入端
{}
ALE=0;
//读数据
OE=1;
//允许读
data_H=ad0_7;
//把数据存到data_H中
OE=0;
//停止AD读取
//通道1
A=1;
data_L=ad0_7;
}
voiddisplay()//显示子程序
buf[0]=data_H/100;
//高压显示百位
buf[1]=(data_H-buf[0]*100)/10;
//高压显示十位
buf[2]=(data_H-buf[0]*100)%10;
//高压显示个位
buf[3]=data_L/100;
//低压显示百位
buf[4]=(data_L-buf[3]*100)/10;
//低压显示十位
buf[5]=(data_L-buf[3]*100)%10;
//低压显示个位
buf[6]=Sum/100;
//脉搏显示百位
buf[7]=(Sum-buf[3]*100)/10;
//脉搏显示十位
buf[8]=(Sum-buf[3]*100)%10;
//脉搏显示个位
if(buf[0]==0)
buf[0]=10;
if(buf[3]==0)
buf[3]=10;
if(buf[6]==0)
buf[6]=10;
//初始化
rw=0;
write_com(0x38);
//设置16X2显示,5X7点阵,8位数据接口
write_com(0x0c);
//设置开显示,不显示光标
write_com(0x06);
//写一个字符后地址指针加1
write_com(0x01);
//显示清零,数据指针清零
write_com(0x80+i);
//第一行写
write_data(table[0]);
write_data(table[1]);
write_data(table[2]);
//显示高压值(收缩压)
write_data(table2[buf[0]]);
write_data(table2[buf[1]]);
write_data(table2[buf[2]]);
write_data(table[6]);
write_data(table[7]);
write_data(table[8]);
write_data(table[9]);
write_data(table[10]);
write_data(table[11]);
write_data(table[12]);
//显示低压值(舒张压)
write_data(table2[buf[3]]);
write_data(table2[buf[4]]);
write_data(table2[buf[5]]);
write_com(0x80+0x40+i);
//第二行写
write_data(table1[0]);
write_data(table1[1]);
write_data(table1[2]);
write_data(table1[3]);
write_data(table1[4]);
//显示脉搏次数
write_data(table2[buf[6]]);
write_data(table2[buf[7]]);
write_data(table2[buf[8]]);
write_data(table1[8]);
write_data(table1[9]);
write_data(table1[10]);
write_data(table1[11]);
write_data(table1[12]);
//显示报警标志“!
“
if((buf[0]==10&
&
buf[1]<
9)||buf[0]==2||(buf[0]==1&
buf[1]>
3)
||(data_L<
65||data_L>
90))//高压低于90高于140报警,低压低于60高于90报警
write_data(table2[11]);
write_data(table2[11]);
voiddisplay1()
buf[4]=(data_L-buf[3]*100)/10;
buf[5]=(data_L-buf[3]*100)%10;
write_data(table3[0]);
write_data(table3[1]);
write_data(table3[2]);
write_data(table3[3]);
write_data(table3[4]);
write_data(table3[5]);
write_data(table3[6]);
write_data(table3[7]);
write_data(table3[8]);
write_data(table3[9]);
write_data(table3[10]);
write_data(table3[11]);
write_data(table3[12]);
write_data(table3[13]);
write_data(table3[14]);
write_data(table3[15]);
write_data(table2[10]);
voidmatch()//数据分析子程序
if(key!
=1)
{
Sum=0;
MT=0;
while(data_L<
180)
{
start_ad();
display1();
}
MT=1;
max=0;
while(data_L>
90)
{start_ad();
if(data_L>
data_L=180;
if(max<
data_H)
max=data_H;
data_H=0.8*max;
data_L=0.5*max;
Sum=0.48*max;
if(Sum>
95)
Sum=100;
if(Sum<
65)
Sum=72;
display();
..