前言
??本文使用搭載STM32F103VET6主控芯片的野火指南者、野火3.2寸LCD屏幕和MAX30102心率血氧傳感器實(shí)現(xiàn)心率血氧采集并顯示的效果。
(文末附完整程序下載鏈接)
一、設(shè)計(jì)任務(wù)
??1.可以通過MAX30102心率血氧傳感器對用戶的心率血氧進(jìn)行采集,并用實(shí)時(shí)顯示在LCD液晶屏上;
??2.可以設(shè)定一個(gè)固定的報(bào)警溫度值顯示在液晶屏上;
??3.用戶心率低于60或者高于閾值報(bào)警、用戶血氧低于閾值報(bào)警,報(bào)警形式包括:蜂鳴器發(fā)出滴滴聲,LCD中心率血氧字符根據(jù)不同情況顯示相應(yīng)的報(bào)警顏色,報(bào)警顏色有紅、藍(lán)、品紅;
??4.能夠通過按鍵動態(tài)修改報(bào)警溫度閾值;
??5.LCD顯示屏下方繪制心率波形圖;
??6.ESP8266將數(shù)據(jù)發(fā)送給TCP助手;
二、系統(tǒng)硬件設(shè)計(jì)
1.元器件選用
??1、STM32f103VET6單片機(jī)一塊
??2、ESP8266一塊
(此項(xiàng)目使用野火指南者,指南者自帶ESP8266,其他型號單片機(jī)杜邦線自連即可)
??3、MAX30102心率血氧傳感器
??4、3.2寸LCD顯示器
??5、杜邦線5根
2.系統(tǒng)模型設(shè)計(jì)
??按鍵1設(shè)置心率閾值,按鍵2設(shè)置血氧閾值,MAX30102檢測用戶心率和血氧值。
??當(dāng)檢測的用戶心率值大于心率閾值時(shí)LCD當(dāng)前心率一欄變?yōu)榧t色、蜂鳴器報(bào)警、LED紅燈閃爍、串口輸出警告。
??當(dāng)檢測的用戶心率值底于60時(shí)LCD當(dāng)前心率一欄變?yōu)槠芳t色、蜂鳴器報(bào)警、LED紅燈閃爍、串口輸出警告。
??當(dāng)檢測的用戶血氧濃度小于血氧閾值時(shí)LCD顯示血氧過低警告、蜂鳴器報(bào)警、藍(lán)燈閃爍、串口輸出心率過低警告。
??血氧波形圖將檢測到的血氧數(shù)據(jù)繪制出來,在未檢測時(shí)y軸繪制為0。相應(yīng)的顏色警告也會在波形圖中顯示。
??ESP8266將單片機(jī)采集的數(shù)據(jù)通過聯(lián)網(wǎng)的方式發(fā)送到TCP助手中并顯示。
?演示視頻:
波形顯示
3.硬件連接
??1、本系統(tǒng)使用野火指南者,由于該單片機(jī)自帶ESP8266,因此無需連接。如果使用其他型號單片機(jī),根據(jù)ESP8266用戶手冊連接即可。
??2、STM32F103與MAX30102的連接,VCC<->3.3V,GND<->GND,SCL<->PC7,SDA<->PC8,IM<->PC9。
總電路連接圖:
三、系統(tǒng)程序設(shè)計(jì)
1.程序流程
??基于STM32的血氧儀控制系統(tǒng)總體軟件的設(shè)計(jì),可以分為系統(tǒng)初始化、數(shù)據(jù)采集、數(shù)據(jù)處理、數(shù)據(jù)顯示和系統(tǒng)控制。系統(tǒng)初始化包括各模塊的初始化,包括MAX30102模塊、LCD顯示模塊、按鍵模塊、蜂鳴器模塊等。同時(shí)還需要初始化串口通信模塊。
??采集數(shù)據(jù)主要是獲取的血氧數(shù)據(jù),進(jìn)行數(shù)字轉(zhuǎn)換和濾波處理,得到血氧飽和度和脈搏率數(shù)據(jù)。數(shù)據(jù)處理是對采集到的血氧飽和度和脈搏率數(shù)據(jù)進(jìn)行處理。同時(shí),還需要對數(shù)據(jù)進(jìn)行校驗(yàn)和處理,確保數(shù)據(jù)的準(zhǔn)確性和可靠性。將處理后的數(shù)據(jù)通過LCD顯示模塊顯示出來。同時(shí),還需要通過蜂鳴器模塊進(jìn)行聲音提示,例如當(dāng)血氧飽和度低于一定閾值時(shí),發(fā)出警報(bào)聲。系統(tǒng)控制即通過按鍵控制模塊控制系統(tǒng)的工作模式,如調(diào)節(jié)警報(bào)閾值等。
程序設(shè)計(jì)流程圖:
WiFi運(yùn)行邏輯圖:
2.主程序
項(xiàng)目部分程序示例。
main.c
int main()
{
/* 初始化 */
USART_Config (); //初始化串口1
NVIC_Configuration();
CPU_TS_TmrInit(); //初始化DWT計(jì)數(shù)器,用于延時(shí)函數(shù)
LED_Init(); //初始化RGB彩燈
EXTI_Key_Config(); //KEY中斷初始化
BEEP_GPIO_Config(); //初始化蜂鳴器引腳
ESP8266_Init(); //初始化WiFi模塊使用的接口和外設(shè)
ILI9341_Init(); //LCD 初始化
max30102_init(); //max30102初始化
ILI9341_GramScan(6); //LCD顯示模式
ESP8266_StaTcpClient_Unvarnish_ConfigTest(); //對ESP8266進(jìn)行配置
max30102_read(); //數(shù)據(jù)預(yù)處理
LCD_SetFont(&Font8x16); //LCD顯示字體
LCD_SetColors(WHITE,BLACK);//LCD黑底白字,這樣顯示它別致
ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,顯示全黑 */
while (1)
{
max30102_control(); //max30102控制函數(shù)
ESP8266_Sendmax30102DataTest();//LCD顯示及串口\網(wǎng)絡(luò)數(shù)據(jù)發(fā)送
drawCurve(280,dis_hr);//LCD畫波形,第一個(gè)參數(shù)是LCD顯示起始位置,第二個(gè)是波形的數(shù)值
}
}
max30102_control(); max30102控制函數(shù)
void max30102_control()
{
i=0;
un_min=0x3FFFF;
un_max=0;
//將前100組樣本轉(zhuǎn)儲到存儲器中,并將最后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<aun_red_buffer[i])
un_max=aun_red_buffer[i];
}
//在計(jì)算心率之前采集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將樣本和計(jì)算結(jié)果發(fā)送到終端程序
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)," 當(dāng)前心率:---");
ILI9341_DispStringLine_EN_CH(LINE(6)," 當(dāng)前血氧:---");
}else{
sprintf((char *)str,"HR:%3d SpO2:%3d ",dis_hr,dis_spo2);//**HR:%3d SpO2:%3d
LCD_SetTextColor(GREEN);
sprintf(get_hr_char," 當(dāng)前心率:%d ",dis_hr);
LCD_ClearLine(LINE(4));
ILI9341_DispStringLine_EN_CH(LINE(4),get_hr_char);
LCD_SetTextColor(GREEN);
sprintf(get_spo2_char," 當(dāng)前血氧:%d%%",dis_spo2);
LCD_ClearLine(LINE(6));
ILI9341_DispStringLine_EN_CH(LINE(6),get_spo2_char);
}
}
ESP8266_Sendmax30102DataTest();LCD顯示以及數(shù)據(jù)發(fā)送
void ESP8266_Sendmax30102DataTest(void)
{
char cStr[170]={0};
uint8_t ucStatus;
LCD_SetTextColor(WHITE);
ILI9341_DispStringLine_EN_CH(LINE(1)," 血氧儀控制系統(tǒng) ");
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 );//蜂鳴器關(guān)
}else{ //max30102開始檢測
/* 顯示血氧 */
if(dis_spo2 >= set_spo2){
LCD_ClearLine(LINE(19));
LCD_SetTextColor(GREEN);//當(dāng)前血氧一欄顯示綠色
sprintf(get_spo2_char," 當(dāng)前血氧:%d%% ",dis_spo2);
LCD_ClearLine(LINE(6)); /* 清除單行文字 */
ILI9341_DispStringLine_EN_CH(LINE(6),get_spo2_char);
PBout(1)=1;//燈滅
BEEP( OFF );//蜂鳴器關(guān)
} else{ //當(dāng)前血氧低于閾值時(shí)顏色變藍(lán)
PBout(1)=0;//燈亮
BEEP( ON );//蜂鳴器開
LCD_SetTextColor(BLUE);
LCD_ClearLine(LINE(6)); /* 清除單行文字 */
sprintf(get_spo2_char," 當(dāng)前血氧:%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)){ //當(dāng)前心率一欄顯示綠色
LCD_ClearLine(LINE(18));
LCD_SetTextColor(GREEN);
LCD_ClearLine(LINE(4)); /* 清除單行文字 */
sprintf(get_hr_char," 當(dāng)前心率:%d ",dis_hr);
ILI9341_DispStringLine_EN_CH(LINE(4),get_hr_char);
PBout(5)=1;//燈滅
BEEP( OFF );//蜂鳴器關(guān)
}else if( ( dis_hr <= set_hr_min ) && ( dis_hr != 0) ){
LCD_SetTextColor(MAGENTA);
LCD_ClearLine(LINE(4)); /* 清除單行文字 */
sprintf(get_hr_char," 當(dāng)前心率:%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{ //當(dāng)前心率超過閾值時(shí)顏色變紅
BEEP( ON );//蜂鳴器開
PBout(5)=0;//燈亮
LCD_SetTextColor(RED);
LCD_ClearLine(LINE(4)); /* 清除單行文字 */
sprintf(get_hr_char," 當(dāng)前心率:%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 ); //發(fā)送 DHT11 溫濕度信息到網(wǎng)絡(luò)調(diào)試助手
}
if ( ucTcpClosedFlag ){ //檢測是否失去連接
ESP8266_ExitUnvarnishSend (); //退出透傳模式
do ucStatus = ESP8266_Get_LinkStatus (); //獲取連接狀態(tài)
while ( ! ucStatus );
if ( ucStatus == 4 ){ //確認(rèn)失去連接后重連
printf ( "\r\n正在重連熱點(diǎn)和服務(wù)器 ......\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重連熱點(diǎn)和服務(wù)器成功\r\n" );
}
while ( ! ESP8266_UnvarnishSend () );
}
}
drawCurve(280,dis_hr);LCD畫波形,第一個(gè)參數(shù)是LCD顯示起始位置,第二個(gè)是波形的數(shù)值
void drawCurve(int coord_x,short int rawValue)
{
//coord_xLCD顯示起始位置坐標(biāo)
u16 x,y;
int rawValue_value;
rawValue_value = rawValue*280;//rawValue_value波形高度,280可修改
y = coord_x - rawValue_value/280; //數(shù)據(jù)處理代碼
//這里之所以是120-rawValue/280,與屏幕的掃描方向有關(guān),如果出現(xiàn)上下顛倒的情況,可以改成120 +
if(firstPoint){//如果是第一次畫點(diǎn),則無需連線,直接描點(diǎn)即可
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{ //超出屏幕寬度,清屏,從第一個(gè)點(diǎn)開始繪制,實(shí)現(xiàn)動態(tài)更新效果
ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,顯示全黑 */
ILI9341_SetPointPixel(10,y);
lastX=0;
lastY=y;
}
}
}
總結(jié)
??基于STM32的血氧儀控制系統(tǒng)是一個(gè)適合初學(xué)者的STM32設(shè)計(jì),本系統(tǒng)設(shè)計(jì)包含了GPIO的配置、ESP8266的配置與使用、傳感器MAX30102的使用、按鍵中斷、串口發(fā)送信息、LCD顯示等的使用。本系統(tǒng)主要部分即心率血氧采集和WiFi數(shù)據(jù)傳輸,比較適合初學(xué)者學(xué)習(xí)理論知識后對知識的總結(jié)和融會貫通。
下載
??下載包所含基于STM32的血氧儀控制系統(tǒng)程序一份,流程圖、原理圖若干。文章來源:http://www.zghlxwxcb.cn/news/detail-620353.html
下載地址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文章來源地址http://www.zghlxwxcb.cn/news/detail-620353.html
到了這里,關(guān)于單片機(jī)課程設(shè)計(jì):基于STM32的心率血氧檢測報(bào)警系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!