基于STM32的血氧仪控制系统

前言一、设计任务二、系统硬件设计1.元器件选用2.系统模型设计3.硬件连接

三、系统程序设计1.程序流程2.主程序

总结下载

前言

  本文使用搭载STM32F103VET6主控芯片的野火指南者、野火3.2寸LCD屏幕和MAX30102心率血氧传感器实现心率血氧采集并显示的效果。

(文末附完整程序下载链接)

一、设计任务

  1.可以通过MAX30102心率血氧传感器对用户的心率血氧进行采集,并用实时显示在LCD液晶屏上;   2.可以设定一个固定的报警温度值显示在液晶屏上;   3.用户心率低于60或者高于阈值报警、用户血氧低于阈值报警,报警形式包括:蜂鸣器发出滴滴声,LCD中心率血氧字符根据不同情况显示相应的报警颜色,报警颜色有红、蓝、品红;   4.能够通过按键动态修改报警温度阈值;   5.LCD显示屏下方绘制心率波形图;   6.ESP8266将数据发送给TCP助手;

二、系统硬件设计

1.元器件选用

  1、STM32f103VET6单片机一块   2、ESP8266一块 (此项目使用野火指南者,指南者自带ESP8266,其他型号单片机杜邦线自连即可)   3、MAX30102心率血氧传感器   4、3.2寸LCD显示器   5、杜邦线5根

2.系统模型设计

  按键1设置心率阈值,按键2设置血氧阈值,MAX30102检测用户心率和血氧值。   当检测的用户心率值大于心率阈值时LCD当前心率一栏变为红色、蜂鸣器报警、LED红灯闪烁、串口输出警告。   当检测的用户心率值底于60时LCD当前心率一栏变为品红色、蜂鸣器报警、LED红灯闪烁、串口输出警告。   当检测的用户血氧浓度小于血氧阈值时LCD显示血氧过低警告、蜂鸣器报警、蓝灯闪烁、串口输出心率过低警告。   血氧波形图将检测到的血氧数据绘制出来,在未检测时y轴绘制为0。相应的颜色警告也会在波形图中显示。   ESP8266将单片机采集的数据通过联网的方式发送到TCP助手中并显示。

 演示视频:

波形显示

3.硬件连接

  1、本系统使用野火指南者,由于该单片机自带ESP8266,因此无需连接。如果使用其他型号单片机,根据ESP8266用户手册连接即可。   2、STM32F103与MAX30102的连接,VCC<->3.3V,GND<->GND,SCL<->PC7,SDA<->PC8,IM<->PC9。

总电路连接图:

三、系统程序设计

1.程序流程

  基于STM32的血氧仪控制系统总体软件的设计,可以分为系统初始化、数据采集、数据处理、数据显示和系统控制。系统初始化包括各模块的初始化,包括MAX30102模块、LCD显示模块、按键模块、蜂鸣器模块等。同时还需要初始化串口通信模块。   采集数据主要是获取的血氧数据,进行数字转换和滤波处理,得到血氧饱和度和脉搏率数据。数据处理是对采集到的血氧饱和度和脉搏率数据进行处理。同时,还需要对数据进行校验和处理,确保数据的准确性和可靠性。将处理后的数据通过LCD显示模块显示出来。同时,还需要通过蜂鸣器模块进行声音提示,例如当血氧饱和度低于一定阈值时,发出警报声。系统控制即通过按键控制模块控制系统的工作模式,如调节警报阈值等。

程序设计流程图: WiFi运行逻辑图:

2.主程序

项目部分程序示例。 main.c

int main()

{

/* 初始化 */

USART_Config (); //初始化串口1

NVIC_Configuration();

CPU_TS_TmrInit(); //初始化DWT计数器,用于延时函数

LED_Init(); //初始化RGB彩灯

EXTI_Key_Config(); //KEY中断初始化

BEEP_GPIO_Config(); //初始化蜂鸣器引脚

ESP8266_Init(); //初始化WiFi模块使用的接口和外设

ILI9341_Init(); //LCD 初始化

max30102_init(); //max30102初始化

ILI9341_GramScan(6); //LCD显示模式

ESP8266_StaTcpClient_Unvarnish_ConfigTest(); //对ESP8266进行配置

max30102_read(); //数据预处理

LCD_SetFont(&Font8x16); //LCD显示字体

LCD_SetColors(WHITE,BLACK);//LCD黑底白字,这样显示它别致

ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */

while (1)

{

max30102_control(); //max30102控制函数

ESP8266_Sendmax30102DataTest();//LCD显示及串口\网络数据发送

drawCurve(280,dis_hr);//LCD画波形,第一个参数是LCD显示起始位置,第二个是波形的数值

}

}

max30102_control(); max30102控制函数

void max30102_control()

{

i=0;

un_min=0x3FFFF;

un_max=0;

//将前100组样本转储到存储器中,并将最后400组样本移到顶部

for(i=100;i<500;i++){

aun_red_buffer[i-100]=aun_red_buffer[i];

aun_ir_buffer[i-100]=aun_ir_buffer[i];

//update the signal min and max

if(un_min>aun_red_buffer[i])

un_min=aun_red_buffer[i];

if(un_max

un_max=aun_red_buffer[i];

}

//在计算心率之前采集100组样本。

for(i=400;i<500;i++){

un_prev_data=aun_red_buffer[i-1];

while(MAX30102_INT==1);

max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);

aun_red_buffer[i] = (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2]; // Combine values to get the actual number

aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5]; // Combine values to get the actual number

if(aun_red_buffer[i]>un_prev_data){

f_temp=aun_red_buffer[i]-un_prev_data;

f_temp/=(un_max-un_min);

f_temp*=MAX_BRIGHTNESS;

n_brightness-=(int)f_temp;

if(n_brightness<0)

n_brightness=0;

}else{

f_temp=un_prev_data-aun_red_buffer[i];

f_temp/=(un_max-un_min);

f_temp*=MAX_BRIGHTNESS;

n_brightness+=(int)f_temp;

if(n_brightness>MAX_BRIGHTNESS)

n_brightness=MAX_BRIGHTNESS;

}

//通过USART将样本和计算结果发送到终端程序

if(ch_hr_valid == 1 && n_heart_rate<120){//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && n_heart_rate<120 && n_sp02<101

dis_hr = n_heart_rate;

dis_spo2 = n_sp02;

}else{

dis_hr = 0;

dis_spo2 = 0;

}

}

maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);

if(dis_hr == 0 && dis_spo2 == 0) //**dis_hr == 0 && dis_spo2 == 0

{

sprintf((char *)str,"HR:--- SpO2:--- ");//**HR:--- SpO2:---

ILI9341_DispStringLine_EN_CH(LINE(4)," 当前心率:---");

ILI9341_DispStringLine_EN_CH(LINE(6)," 当前血氧:---");

}else{

sprintf((char *)str,"HR:%3d SpO2:%3d ",dis_hr,dis_spo2);//**HR:%3d SpO2:%3d

LCD_SetTextColor(GREEN);

sprintf(get_hr_char," 当前心率:%d ",dis_hr);

LCD_ClearLine(LINE(4));

ILI9341_DispStringLine_EN_CH(LINE(4),get_hr_char);

LCD_SetTextColor(GREEN);

sprintf(get_spo2_char," 当前血氧:%d%%",dis_spo2);

LCD_ClearLine(LINE(6));

ILI9341_DispStringLine_EN_CH(LINE(6),get_spo2_char);

}

}

ESP8266_Sendmax30102DataTest();LCD显示以及数据发送

void ESP8266_Sendmax30102DataTest(void)

{

char cStr[170]={0};

uint8_t ucStatus;

LCD_SetTextColor(WHITE);

ILI9341_DispStringLine_EN_CH(LINE(1)," 血氧仪控制系统 ");

LCD_SetTextColor(GREEN);

sprintf(set_hr_char," 心率阈值:%d ",set_hr_max);

LCD_ClearLine(LINE(3));

ILI9341_DispStringLine_EN_CH(LINE(3),set_hr_char);

LCD_SetTextColor(GREEN);

sprintf(set_spo2_char," 血氧阈值:%d%%",set_spo2);

LCD_ClearLine(LINE(5));

ILI9341_DispStringLine_EN_CH(LINE(5),set_spo2_char);

if(dis_hr == 0 && dis_spo2 == 0) //max30102未检测

{

printf("Max30102 not detected!/r/n");

LCD_SetTextColor(GREEN);

LCD_ClearLine(LINE(18));

LCD_ClearLine(LINE(19));

PBout(5)=1;//灯灭

PBout(1)=1;//灯灭

BEEP( OFF );//蜂鸣器关

}else{ //max30102开始检测

/* 显示血氧 */

if(dis_spo2 >= set_spo2){

LCD_ClearLine(LINE(19));

LCD_SetTextColor(GREEN);//当前血氧一栏显示绿色

sprintf(get_spo2_char," 当前血氧:%d%% ",dis_spo2);

LCD_ClearLine(LINE(6)); /* 清除单行文字 */

ILI9341_DispStringLine_EN_CH(LINE(6),get_spo2_char);

PBout(1)=1;//灯灭

BEEP( OFF );//蜂鸣器关

} else{ //当前血氧低于阈值时颜色变蓝

PBout(1)=0;//灯亮

BEEP( ON );//蜂鸣器开

LCD_SetTextColor(BLUE);

LCD_ClearLine(LINE(6)); /* 清除单行文字 */

sprintf(get_spo2_char," 当前血氧:%d%% ",dis_spo2);

ILI9341_DispStringLine_EN_CH(LINE(6),get_spo2_char);

ILI9341_DispStringLine_EN_CH(LINE(19)," 血氧过低 ");

printf("!!!血氧低于阈值!!!"); //串口输出

}

/* 显示心率 */

if((dis_hr <= set_hr_max) && (dis_hr >= set_hr_min)){ //当前心率一栏显示绿色

LCD_ClearLine(LINE(18));

LCD_SetTextColor(GREEN);

LCD_ClearLine(LINE(4)); /* 清除单行文字 */

sprintf(get_hr_char," 当前心率:%d ",dis_hr);

ILI9341_DispStringLine_EN_CH(LINE(4),get_hr_char);

PBout(5)=1;//灯灭

BEEP( OFF );//蜂鸣器关

}else if( ( dis_hr <= set_hr_min ) && ( dis_hr != 0) ){

LCD_SetTextColor(MAGENTA);

LCD_ClearLine(LINE(4)); /* 清除单行文字 */

sprintf(get_hr_char," 当前心率:%d ",dis_hr);

ILI9341_DispStringLine_EN_CH(LINE(4),get_hr_char);

ILI9341_DispStringLine_EN_CH(LINE(18)," 心率低于60 ");

printf("!!!心率低于60!!!"); //串口输出

BEEP( ON );//蜂鸣器开

PBout(5)=0;//灯亮

}else{ //当前心率超过阈值时颜色变红

BEEP( ON );//蜂鸣器开

PBout(5)=0;//灯亮

LCD_SetTextColor(RED);

LCD_ClearLine(LINE(4)); /* 清除单行文字 */

sprintf(get_hr_char," 当前心率:%d ",dis_hr);

ILI9341_DispStringLine_EN_CH(LINE(4),get_hr_char);

ILI9341_DispStringLine_EN_CH(LINE(18)," 心率过高 ");

printf("!!!心率超出阈值!!!"); //串口输出

}

}

if(dis_hr !=0 || dis_spo2 != 0 ){

sprintf ( cStr, "POST /devices/92648495/datapoints?type=5 HTTP/1.1\napi-key:Yn2cDHrWmsTL62QUjHYu4RNtgPw=\nHost:api.zj.cmcconenet.com\nContent-Length:23\n\n,;xinlv,%3d;xueyang,%3d",dis_hr,dis_spo2);

printf ( "%s", cStr ); //打印读取 DHT11 温湿度信息

ESP8266_SendString ( ENABLE, cStr, 0, Single_ID_0 ); //发送 DHT11 温湿度信息到网络调试助手

}

if ( ucTcpClosedFlag ){ //检测是否失去连接

ESP8266_ExitUnvarnishSend (); //退出透传模式

do ucStatus = ESP8266_Get_LinkStatus (); //获取连接状态

while ( ! ucStatus );

if ( ucStatus == 4 ){ //确认失去连接后重连

printf ( "\r\n正在重连热点和服务器 ......\r\n" );

while ( ! ESP8266_JoinAP ( macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd ) );

while ( ! ESP8266_Link_Server ( enumTCP, macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_Port, Single_ID_0 ) );

printf ( "\r\n重连热点和服务器成功\r\n" );

}

while ( ! ESP8266_UnvarnishSend () );

}

}

drawCurve(280,dis_hr);LCD画波形,第一个参数是LCD显示起始位置,第二个是波形的数值

void drawCurve(int coord_x,short int rawValue)

{

//coord_xLCD显示起始位置坐标

u16 x,y;

int rawValue_value;

rawValue_value = rawValue*280;//rawValue_value波形高度,280可修改

y = coord_x - rawValue_value/280; //数据处理代码

//这里之所以是120-rawValue/280,与屏幕的扫描方向有关,如果出现上下颠倒的情况,可以改成120 +

if(firstPoint){//如果是第一次画点,则无需连线,直接描点即可

ILI9341_SetPointPixel(10,y);

lastX=0;

lastY=y;

firstPoint=0;

}

else{

x=lastX+1;

if(x<240){ //不超过屏幕宽度

ILI9341_DrawLine(lastX,lastY,x,y);

lastX=x;

lastY=y;

}

else{ //超出屏幕宽度,清屏,从第一个点开始绘制,实现动态更新效果

ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */

ILI9341_SetPointPixel(10,y);

lastX=0;

lastY=y;

}

}

}

总结

  基于STM32的血氧仪控制系统是一个适合初学者的STM32设计,本系统设计包含了GPIO的配置、ESP8266的配置与使用、传感器MAX30102的使用、按键中断、串口发送信息、LCD显示等的使用。本系统主要部分即心率血氧采集和WiFi数据传输,比较适合初学者学习理论知识后对知识的总结和融会贯通。

下载

  下载包所含基于STM32的血氧仪控制系统程序一份,流程图、原理图若干。

下载地址1:https://download.csdn.net/download/qq_50185399/88553380 下载地址2:http://cloud.tao-space.top/2023/05/28/13/595/ https://download.csdn.net/download/qq_50185399/88553380

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: