STM32三导联蓝牙心电监护仪设计,C#上位机显示波形 附源码与电路和论文
资料下载地址:STM32三导联蓝牙心电监护仪设计,C#上位机显示波形 附源码与电路和论文
目录
摘要
1. 引言
2. 系统方案
3. 系统硬件设计
3.1 系统原理框图设计
3.2 系统主要元器件介绍
3.2.1 STM32F103VET6主控芯片
接口名称
|
接口功能
|
NRST
|
系统复位
|
PB3
|
OLED模块CS口
|
PB4
|
OLED模块DC口
|
PB5
|
OLED模块RST口
|
PB6
|
OLED模块DIN口
|
PB7
|
OLED模块CLK口
|
PCO
|
ADC1的通道10模拟前端信号输入
|
PA10
|
UART1_RX
|
PA9
|
UART1_TX
|
PB0
|
LED1
|
PC3
|
LED2
|
PC4
|
LED3
|
PA0
|
按键1
|
PC13
|
按键2
|
PA1
|
按键3
|
3.2.2 AD8232模拟前端芯片
3.2.3 SSD1306 OLED显示模块
3.2.4 HC-05蓝牙模块
考虑到心电信号采集系统的便携性,因此本设计使用无线的方式来进行数据的传输,经过多种蓝牙模块的比较最终选择HC-05蓝牙模块,HC-05是一款高性能的主从一体蓝牙串口模块,可以和各种自带蓝牙功能的外部设备连接包括手机、电脑等职能终端设备,HC-05蓝牙模块支持的通信频率为4800~1382400,并且可以同时兼容5V或3.3V单片机系统,在本设计中能够方便的通过TX、RX接口与STM32F103VET6连接。本模块使用非常灵活、方便。本设计中电脑通过与蓝牙模块配对连接后可以在电脑上实现COM口从而实现串口数据传输。蓝牙模块设置波特率为115200,同时通过AT指令将工作模式配置为从机模式以便于PC连接。
3.2.5 XL6009 DC-DC电源模块
3.3 系统模块电路设计
3.3.1 AD8232模拟前端电路设计
3.2.2 按键控制以及LED电路设计
本设计需要通过三个按键来实现硬件端的模式选择,以及相关功能的切换,使用实体按键可以做到操作方便可靠,可以通过简单的显示引导即可让用户知道该如何操作硬件,将STM32F103VET6的PA0、PA1、PC13配置成GPIO_INPUT模式来实现按键检测,按键通过一个上拉电阻与STM32F103VET6的IO口连接。同样为了使用户很清晰的知道硬件系统工作在什么模式,通过三个LED灯的亮灭来实时的呈现硬件系统的两种工作模式以及是否在检测ECG数据,将STM32F103VET6的PB0、PC3、PC4配置成GPIO_OUTPUT模式,同时将IO与一个510R的限流电阻串联连接到STM32F103的IO口上。当IO口输出低电平时LED亮,当IO口输出高电平时LED熄灭,图3-9与图3-10为按键与LED连接引脚图。
图3-9 按键电路
图3-10 LED灯电路
3.3.3 OLED显示模块电路设计
OLED显示模块通过四线串行模式与STM32F103VET6连接,一共需要5根数据线,其中OLED显示模块的CS、DC、RES、DIN、CLK分别与STM32F103VET6的PB3、PB4、PB5、PB6、PB7连接,在这5根线中,RES为OLED的复位信号线,CS为片选信号,DC为数据/指令控制管脚,DIN为串行数据传输脚,CLK为数据时钟,同时OLED模块使用3.3V电压供电。OLED模块电路连接图如图3-11所示。
3.3.4 蓝牙模块与MCU连接电路设计
蓝牙模块一共有四个管脚VCC、GND、TX、RX,其中VCC连接3.3V电源,GND与STM32F103VET6的GND连接,蓝牙模块的TX与STM32F103VET6的UART1_RX连接也就是与PA10管脚连接,蓝牙模块的RX管脚与UART1_TX即管脚PA9。通过上述连接可以实现将ECG数据使用MCU的串口发送到上位机实现上位机部分需要完成的功能。蓝牙模块电路连接图如图3-12所示。
图3-11 OLED模块连接图
图3-12 蓝牙模块连接图
3.3.5 电源模块
3.3.6 整体电路连接
4. 系统软件设计
4.2 子程序算法流程分析
4.2.1 模块初始化子程序设计
4.2.2 ADC配置以及DMA传输配置程序
4.2.3 数字滤波器设计程序
const float IIR_50Notch_A[3] = {
1,
-0.5577124773,
0.8047954884
};
x0=ADC_ConvertedValueLocal; //输入ADC采集到的信号
w0[0]=IIR_50Notch_A[0]*x0-IIR_50Notch_A[1]*w0[1]-IIR_50Notch_A[2]*w0[2];
y0=IIR_50Notch_B[0]*w0[0]+IIR_50Notch_B[1]*w0[1]+IIR_50Notch_B[2]*w0[2];
w0[2]=w0[1];
w0[1]=w0[0];
4.2.4 模式切换及OLED显示程序
为了做到很好的交互体验,通过三个按键K1、K2、K3负责对系统的工作状态进行控制,同时使用三个LED灯LED1、LED2、LED3来显示系统的工作状态。K1负责切换系统的工作模式,当按下K1时通过改变标志位MODE_FLAG的值可以实现系统在上位机模式与本地模式间切换,同时通过LED1与LED2的亮灭来显示状态,当系统工作在上位机模式是只需要进行数据的采样以及滤波,完成后将数据发送即可;当系统工作在本地模式时通过KEY2来实现心电信号检测的开始,按下KEY1检测开始,系统进行10000个参数的采样同时LED3亮,完成后LED3熄灭并将这些参数滤波并且以波形的方式显示在OLED显示模块上,K3是用于切换波形显示与心率,心率的计算方式与上位机使用的方式相同,在下文会详细介绍。OLED显示模块主要用来显示波形以及其他的参数,在OLED显示函数中主要用到个函数OLED_Clear()用于清除屏幕显示,OLED_ShowString()用于显示字符,OLED_ShowNum()用于显示数字,LCD_DrawLine()用于显示波形时进行两个点之间的画线操作,下图4-9详细的表述了系统切换模式时的工作原理。
4.3 上位机设计
4.3.1 串口数据接收程序
-
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { string serialReadString, text; string DataSymb; string DataMain; serialReadString = serialPort1.ReadExisting(); this.textBoxData.Invoke ( new MethodInvoker ( delegate { try { this.textBoxData.AppendText(serialReadString); text = textBoxData.Text; if (text.Length > 1) { if (DataEnable == true) { TextDataTotal += serialReadString; } else if(DataEnable == false) { //TextDataTotal = ""; } } } catch { } } ) ); }
4.3.2 波形显示控件设计
-
public List<float> x1 = new List<float>(); //新建四个链表用于存两条 public List<float> y1 = new List<float>(); //波形的数据 public List<float> x2 = new List<float>(); public List<float> y2 = new List<float>(); x1.Clear(); //链表初始化 y1.Clear(); x2.Clear(); y2.Clear(); zGraph1.f_ClearAllPix(); zGraph1.f_reXY(); zGraph1.f_InitMode(Pengpai.UI.ZGraph.GraphStyle.DefaultMoveMode); zGraph1.f_LoadOnePix(x1, y1, Color.Red, 2); zGraph1.f_AddPix(x2, y2, Color.Blue, 2); for (int i = 0; i < DataCalcTime; i++) //循环显示 { DrawLineSG(i, EcgDataNew[ i]); }
4.3.3 数据处理及保存
-
_Matrix_Calc m_c = new _Matrix_Calc(); _Matrix s = new _Matrix(N, D + 1); _Matrix s_tran = new _Matrix(D + 1, N); _Matrix F = new _Matrix(4, 4); _Matrix F_inv = new _Matrix(4, 4); _Matrix b1 = new _Matrix(N, 4); _Matrix b2 = new _Matrix(N, N); s.init_matrix(); s_tran.init_matrix(); F.init_matrix(); F_inv.init_matrix(); b1.init_matrix(); b2.init_matrix(); for (m = -M; m <= M; m++) //得到矩阵s { for (i = 0; i <= D; i++) { s.write(m + M, i, (float)Math.Pow(m, i)); } } m_c.transpos(ref s,ref s_tran); m_c.multiply(ref s_tran, ref s, ref F); m_c.inverse(ref F, ref F_inv); m_c.multiply(ref s, ref F_inv , ref b1); m_c.multiply(ref b1, ref s_tran , ref b2); for (int i = 0; i <= M; i++) //第0到M,一共M+1个点 { for (int j = 0; j < N; j++) EcgDataNew[ i] = EcgDataNew[ i] + B.read(j, i) * EcgDataOld[j]; } for (int i = M + 1; i <= L - M - 2; i++) //第M+1到L-M-2,一共L-2M-2个点 { for (int j = 0; j < N; j++) EcgDataNew[ i] = EcgDataNew[ i] + B.read(j, M) * EcgDataOld[i - M + j - 1]; } for (int i = 0; i <= M; i++) //第L-M-1到L-1个点,一共M+1个点 { for (int j = 0; j < N; j++) EcgDataNew[L - M + i - 1] = EcgDataNew[L - M + i - 1] + B.read(j, M + i) * EcgDataOld[L - N + j]; }
-
private void GetBMP() { float bmpnummax = 0; float bmpnummin = 0; float bmpavemax = 0; float bmpavemin = 0; float bmpfamax = 0; float bmpfamin = 0; bool tipmax = true; bool tipmin = true; int BMP = 0; for (int i = 0; i < txtline; i++) { if (EcgTxtDataNew[ i] >= bmpnummax) bmpnummax = EcgTxtDataNew[ i]; if (EcgTxtDataNew[ i] <= bmpnummin) bmpnummin = EcgTxtDataNew[ i]; } bmpmax.Text = bmpnummax.ToString(); bmpmin.Text = bmpnummin.ToString(); bmpfamax = bmpnummax * 3 / 5; bmpfamin = bmpnummin * 3 / 5; bmpnummax = 0; bmpnummin = 0; for (int i = 0; i < txtline; i++) { if (EcgTxtDataNew[ i] >= bmpnummax)// && tipmax == true) { bmpnummax = EcgTxtDataNew[ i]; } if (EcgTxtDataNew[ i] <= bmpnummin)//&& tipmin == true) { bmpnummin = EcgTxtDataNew[ i]; } if (bmpnummax > bmpfamax) { if(EcgTxtDataNew[ i]<bmpfamin) { BMP++; bmpnummax = 0; bmpnummin = 0; } } } BMP = (int)(60 * (float)BMP / ((float)txtline * 0.004)); HeartBit.Text = BMP.ToString(); }
5 评测与结论
5.1 硬件设计制作与系统调试
5.2 软件设计与调试
5.3 系统综合调试
姓名
|
测试心律
|
实际心律
|
徐XX
|
75
|
75
|
杨XX
|
69
|
70
|
曾XX
|
73
|
72
|
王XX
|
77
|
77
|
郑XX
|
70
|
70
|
原文地址:https://blog.csdn.net/qq_35654286/article/details/145173746
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!