国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于STM32F4的心電監(jiān)護(hù)儀

這篇具有很好參考價值的文章主要介紹了基于STM32F4的心電監(jiān)護(hù)儀。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

從題目中可以看出該課題來源于2020年省電賽A題的無線運動傳感器節(jié)點的設(shè)計,該作品得過湖北省電賽二等獎,同時也是我本科畢業(yè)設(shè)計,這里我把自己做的關(guān)于心電部分的工作進(jìn)行一次總結(jié),也對我的大學(xué)四年進(jìn)行一次總結(jié)。

一、硬件設(shè)計

  1. 處理器板子的選擇

本研究的處理器模塊選擇正點原子公司的STM32F4最小系統(tǒng)板子,如圖1所示,該最小系統(tǒng)板子搭載STM32F407ZGT6芯片,并具有 192KB的SRAM、1024KB的FLASH、豐富的定時器資源(12個16位定時器,2個32位定時器)、112個通用I/O口、2個DMA控制器以及1個FSMC接口,其中通過FSMC接口可以使得刷屏的速度可達(dá)3300W像素/秒,另外該板子還外擴(kuò)了1M字節(jié)的SRAM芯片,更加有利于該處理器驅(qū)動4.3寸的LCD,這樣極大加快心電監(jiān)測儀的刷屏速度,而且STM32F407ZGT6這款芯片還集成FPU和DSP指令,可以加快數(shù)字濾波器的處理速度,而且該最小系統(tǒng)板子還將FSMC接口和其他IO口一并引出。
基于STM32F4的心電監(jiān)護(hù)儀

  1. 心電采集板—ADS1292R模塊的介紹

本研究最重要的地方便是心電采集板,關(guān)于心電信號的采集板的芯片選擇TI公司的ADS1292R,外圍電路參考TI公司所給的原理圖和建議繪制,如圖所示。
基于STM32F4的心電監(jiān)護(hù)儀
關(guān)于ADS1292R的外圍電路的介紹和使用,這里推薦這篇博文,ADS1292R的使用

  1. 溫度模塊----LMT70

溫度檢測模塊采用LMT70溫度傳感器。其優(yōu)點是:超小型、高精度、低功耗的模擬溫度傳感器。而缺點是:接觸式的溫度傳感器,測體表溫度存在一定誤差。但是考慮到溫度測量的精度以及測量方便,最終選擇LMT70作為測溫傳感器,同時選擇采用ADS1118具有PGA、電壓基準(zhǔn)、16位的高精度ADC對LMT70數(shù)據(jù)的溫度模擬量進(jìn)行采集。
基于STM32F4的心電監(jiān)護(hù)儀

  1. 系統(tǒng)不帶屏幕的外觀

基于STM32F4的心電監(jiān)護(hù)儀

二、GUI的設(shè)計

本系統(tǒng)為了更好的人機(jī)交互,采用4.3寸觸摸屏搭載開源圖形庫LVGL,一方面將顯示波形和數(shù)據(jù)與心電信號的采集和處理隔離開,另一方面是為了交互的方便和美觀,系統(tǒng)運行界面如下圖所示。整體界面主要有菜單、返回、圖表、數(shù)據(jù)欄、導(dǎo)聯(lián)狀態(tài)燈以及開啟心電采集按鈕。
基于STM32F4的心電監(jiān)護(hù)儀
系統(tǒng)的菜單是通過LVGL的roller控件繪制的,roller里面選項的事件則是通過回調(diào)函數(shù)的形式調(diào)用。由于選中roller的選項,LVGL就會返回選項的值,因此我自己設(shè)計了函數(shù)指針數(shù)組來注冊回調(diào)函數(shù),并且將這個選中的序號通過數(shù)組方式調(diào)用函數(shù),代碼如下所示:

void (*oper_fuc[4])();//函數(shù)指針數(shù)組
void Menuitem_Init(void)
{
    oper_fuc[0]=send_type_server;
    oper_fuc[1]=Set_chart_div_line;
    oper_fuc[2]=clear_step;
	oper_fuc[3]=smooth_filter;
}
static void roller_event_handler(lv_obj_t * obj, lv_event_t event)
{
    static unsigned char count=0;
	 if(event==LV_EVENT_VALUE_CHANGED)
    {
        count=lv_roller_get_selected(obj);
    }
    if(event==LV_EVENT_CLICKED)
    {
        oper_fuc[count]();
    }
}

roller_event_handler是選中roller中的事件函數(shù),在事件函數(shù)里面來回調(diào)選項的處理函數(shù)。roller中總共寫了4個選項,分別為
send_type選擇發(fā)送類型(支持發(fā)送到本地顯示或者串口發(fā)送給上位機(jī))、set_div_line是否設(shè)置圖表的等分線、
clear_step清除界面上的數(shù)據(jù)、
smooth_filter是否進(jìn)行平滑濾波
基于STM32F4的心電監(jiān)護(hù)儀
本系統(tǒng)還設(shè)計導(dǎo)聯(lián)狀態(tài)指示燈,前面討論過ADS1292R可以檢測電聯(lián)的脫落狀態(tài),因而這里用LVGL的led控件作為導(dǎo)聯(lián)的狀態(tài)指示,當(dāng)檢測到導(dǎo)聯(lián)接入人體,led控件就會點亮。設(shè)計了紅心周期性跳動,當(dāng)檢測到導(dǎo)聯(lián)接入人體后,紅心就會周期性跳動,當(dāng)心電數(shù)據(jù)采樣開始后,紅心隨著心率值的改變而跳動著。同時還設(shè)計了采樣開始/停止按鈕,可以隨時暫停和開始采樣心電信號。
除了以上看得見的設(shè)計之外,還創(chuàng)建了四個周期性的任務(wù),任務(wù)優(yōu)先級從高到低分別為:更新數(shù)據(jù)欄里的數(shù)據(jù)、更新導(dǎo)聯(lián)狀態(tài)、檢查心電信號的縱軸范圍、系統(tǒng)狀態(tài)的檢查。

三、導(dǎo)聯(lián)體系的選擇

心電信號本質(zhì)上是測量人體體表的電信號,將電極通過一定的導(dǎo)聯(lián)體系就可以記錄到心電圖,因而選擇合適的電極是觀察心電圖至關(guān)重要的選擇。在醫(yī)學(xué)上常見的導(dǎo)聯(lián)體系分別為標(biāo)準(zhǔn)12導(dǎo)聯(lián)體系、Lewis導(dǎo)聯(lián)、Fontaine導(dǎo)聯(lián)、Cabrera導(dǎo)聯(lián)、Nehb導(dǎo)聯(lián)、frank導(dǎo)聯(lián)、Mason-Likar導(dǎo)聯(lián)等。標(biāo)準(zhǔn)12導(dǎo)聯(lián)體系是醫(yī)院所使用的,它由3個雙極肢體導(dǎo)聯(lián)、6個單極胸前導(dǎo)聯(lián)、3個單極加壓肢體導(dǎo)聯(lián)所組成。
該系統(tǒng)的主要目的是實時檢測心率和QRS寬度,因此選擇的導(dǎo)聯(lián)應(yīng)該基于能觀察心電中R波較大的原則。因而選擇標(biāo)準(zhǔn)12導(dǎo)聯(lián)中標(biāo)準(zhǔn)肢體導(dǎo)聯(lián)I(見圖左),或者M(jìn)ason-Likar導(dǎo)聯(lián)(見圖右)。
基于STM32F4的心電監(jiān)護(hù)儀

四、心電電極選擇

人體的內(nèi)阻很高,因而心電信號是一個高內(nèi)阻且幅度很低的信號,如果處理不好就會造成心電信號的衰減,因此就需要從兩方面解決:
(1)降低與電極的接觸阻抗(2)提高采集電路的輸入阻抗。
基于STM32F4的心電監(jiān)護(hù)儀
目前,市面上有三種電極,分別為濕電極、干電極和非接觸式電極,這三種電極中濕電極的接觸電阻最小,因而對于模擬前端的輸入電阻不需要太大。濕電極主要由電極片、Ag/AgCl 涂層、導(dǎo)電膠等物質(zhì)組成。 醫(yī)學(xué)電極貼片與身體接觸的是水凝膠(親水化合物),“黑色”部分為Ag/AgCl,使用導(dǎo)電金屬和導(dǎo)線與儀器連接,實物如圖所示。
基于STM32F4的心電監(jiān)護(hù)儀

五、心電信號時域和頻域特征

人體的心電信號是一種非平穩(wěn)、非線性、隨機(jī)性比較強(qiáng)的微弱生理信號,幅值約為毫伏(mV)級,頻率在0.05-100Hz之間。心電信號的每一個心跳循環(huán)由一系列有規(guī)律的波形組成,它們分別是P波、QRS復(fù)合波和T波,而這些波形的起點、終點、波峰、波谷、以及間期分別記錄著心臟活動狀態(tài)的詳細(xì)信息
基于STM32F4的心電監(jiān)護(hù)儀
心電信號各個波段的詳細(xì)說明如下:
基于STM32F4的心電監(jiān)護(hù)儀
心電各個波段的功率譜如下:
基于STM32F4的心電監(jiān)護(hù)儀
心電信號的噪聲分析如下:
基于STM32F4的心電監(jiān)護(hù)儀
讀者想對心電信號進(jìn)一步了解可以參考如下鏈接:http://www.mythbird.com/ecgxin-hao-te-zheng/。

六、軟件設(shè)計

6.1、系統(tǒng)總體設(shè)計

系統(tǒng)先從硬件初始化開始,其中包括串口初始化、觸摸屏初始化、外部SRAM初始化、ADS1292R初始化、LMT70初始化、LVGL心跳定時器初始化。
其次就是LVGL初始化,主要是一些主題和變量的初始化。然后創(chuàng)建系統(tǒng)的UI界面和一些定時的任務(wù)。
最后初始化心電數(shù)據(jù)緩存、 數(shù)字低通濾波器初始化、心率數(shù)據(jù)緩存初始化。
完成以上的初始化,系統(tǒng)便進(jìn)入主循環(huán),等待心電數(shù)據(jù)輸入緩存中出現(xiàn)數(shù)據(jù),隨后開始濾波,將濾波之后的數(shù)據(jù)寫入心電輸出緩存中,然后輪詢LVGL的任務(wù)和觸摸屏掃描。就這樣不停地循環(huán)。其中心電輸入緩存中的數(shù)據(jù)是通過中斷從ADS1292R的輸出引腳中讀取,而心電輸出緩存則是原始數(shù)據(jù)經(jīng)過低通處理后的數(shù)據(jù),等待LVGL顯示任務(wù)的到來并顯示在觸摸屏上。系統(tǒng)總體框圖和軟件框圖如下所示
基于STM32F4的心電監(jiān)護(hù)儀
基于STM32F4的心電監(jiān)護(hù)儀

6.2、系統(tǒng)總體設(shè)計

在前面討論過心電信號頻譜和噪聲,因而要對心電信號進(jìn)行濾波,為了同時實現(xiàn)心電信號的實時濾波和心電波形實時顯示,所以有必要設(shè)計一個緩存區(qū)來解決這個難題。這里我打算用我自己設(shè)計的兩個循環(huán)隊列解決這個難題。
基于STM32F4的心電監(jiān)護(hù)儀
為了使得在濾波的時候,心電數(shù)據(jù)依然能夠采集,設(shè)計兩個循環(huán)隊列,如上圖所示,其中IN_Buffer和OUT_Buffer的每個矩形框表示25x4個字節(jié)的空間,這取決一次需要多少字節(jié)的數(shù)據(jù)濾波。這里一次濾波需要25個int型的數(shù)據(jù),因而每個緩存需要25x4字節(jié)。圖中的藍(lán)色填充表示緩存區(qū)中填滿了數(shù)據(jù),每次讀完數(shù)據(jù)之后都需要切換緩存區(qū),且IN_Buffer和OUT_Buffer的讀寫操作相反,即IN_Buffer的讀操作是OUT_Buffer的寫操作,程序框圖如下圖所示。
基于STM32F4的心電監(jiān)護(hù)儀
圖上所示的三個程序均是并行處理的,
程序1是通過外部中斷的服務(wù)函數(shù)調(diào)用的,
程序2則是在UI畫圖程序里面通過定時器周期性的調(diào)用
程序3則是在主程序中的濾波函數(shù)里面調(diào)用
程序1代碼如下(ADS1292R采用中斷方式讀取數(shù)據(jù)):

void EXTI9_5_IRQHandler(void)
{
    if(EXTI->IMR&EXTI_Line5 && ADS_DRDY==0)//數(shù)據(jù)接收中斷
    {
        ADS1292_Read_Data(ads1292_Cache);//數(shù)據(jù)存到9字節(jié)緩沖區(qū)
        Update_ECG_Data(ads1292_Cache);
        Cheack_lead_stata(ads1292_Cache);
		if(state_pcb.SampleStartFlag==true)
			WriteAdsInBuffer(ecg_info.ecg_data);//數(shù)據(jù)寫入緩存區(qū)
    } 
	EXTI_ClearITPendingBit(EXTI_Line5);
}

程序2代碼如下(LVGL的心跳在定時器中周期調(diào)用,同時程序2也在其中運行,主要從濾波后的數(shù)據(jù)緩存中取出數(shù)據(jù)進(jìn)行波形顯示):

void Wave_show(void)
{
    int value=0;
    if(ReadEcgOutBuffer(&value)!=0) {
        if(ecg_graph.send_type==GRAPH) {
         ecg_graph.y_pose=Transf_EcgData_To_Vert(value,ecg_graph.sacle);
			  chart_add_data(ecg_graph.y_pose);
            set_data_into_heart_buff(ecg_graph.y_pose);
        } else if(ecg_graph.send_type==USART) {
            //EcgSendByUart(value);
			printf("%d\r\n",(int)alg(value/200));
        }
    }
}
//定時器3中斷服務(wù)程序
void TIM3_IRQHandler(void)
{ 	static u8 show_cnt=0;   		  			    
	if(TIM3->SR&TIM_IT_Update)//溢出中斷
	{	show_cnt++;
		lv_tick_inc(1);//lvgl的1ms心跳
		if(show_cnt==3){
		show_cnt=0;
		 Wave_show();
		}
	}				   
	TIM3->SR = (uint16_t)~TIM_IT_Update;
}

程序3代碼如下(在濾波函數(shù)中調(diào)用,用于承上啟下,即從IN緩存中取出數(shù)據(jù),濾波之后寫入OUT緩存中):

void arm_fir_f32_lp(void)
{
	float32_t *inputf32, *outputf32;
	if(ReadAdsInBuffer() && WriterEcgOutBuffer()){//指針定位成功
		/* 初始化輸入輸出緩存指針 */
		inputf32 = (float32_t *)InFifoDev.rp;
		outputf32 =(float32_t *)OutFifoDev.wp;
		
	  /* 實現(xiàn)FIR濾波 */
		arm_fir_f32(&S, inputf32, outputf32, BLOCK_SIZE);
		//my_memcpy(OutFifoDev.wp,InFifoDev.rp,BLOCK_SIZE*4);
		InFifoDev.state[InFifoDev.read_front]=Empty;
		InFifoDev.read_front=(InFifoDev.read_front+1)%PACK_NUM;//切換讀緩存塊
	
		OutFifoDev.state[OutFifoDev.writer_rear]=Full;
		OutFifoDev.writer_rear=(OutFifoDev.writer_rear+1)%PACK_NUM;//切換寫緩存塊
	}

}

關(guān)于緩存切換代碼如下:

static void WriteAdsInBuffer(int date)
{
	static u8 cnt=0;
	if(InFifoDev.state[InFifoDev.writer_rear]==Empty){//緩存塊可寫
		InFifoDev.wp=&AdsInBuffer[InFifoDev.writer_rear*(BLOCK_SIZE)];//將寫指針定位寫緩存塊
		InFifoDev.wp[cnt++]=date;
		if(cnt==BLOCK_SIZE){
			cnt=0;
			InFifoDev.state[InFifoDev.writer_rear]=Full;
			InFifoDev.writer_rear=(InFifoDev.writer_rear+1)%PACK_NUM;//切換寫緩存塊
			
		}
	}
}

//定位讀指針
//成功則返回1,不成功則返回0
u8 ReadAdsInBuffer(void)
{
	if(InFifoDev.state[InFifoDev.read_front]==Full){//緩存塊可讀
		InFifoDev.rp=&AdsInBuffer[InFifoDev.read_front*(BLOCK_SIZE)];//將讀指針定位讀緩存塊
		return 1;
	}
	return 0;
}

//定位讀指針
u8 WriterEcgOutBuffer(void)
{
	if(OutFifoDev.state[OutFifoDev.writer_rear]==Empty){//緩存塊可寫
		OutFifoDev.wp=&EcgOutBuffer[OutFifoDev.writer_rear*(BLOCK_SIZE)];//將讀指針定位讀緩存塊
		return 1;
	}
	return 0;
}

//成功則返回1,不成功則返回0
u8 ReadEcgOutBuffer(int32_t *p)
{
	static u8 cnt=0;
	if(OutFifoDev.state[OutFifoDev.read_front]==Full){//緩存塊可讀
		OutFifoDev.rp=&EcgOutBuffer[OutFifoDev.read_front*(BLOCK_SIZE)];//將寫指針定位讀緩存塊
		*p=OutFifoDev.rp[cnt++];
		if(cnt==BLOCK_SIZE){
			cnt=0;
			OutFifoDev.state[OutFifoDev.read_front]=Empty;
			OutFifoDev.read_front=(OutFifoDev.read_front+1)%PACK_NUM;//切換寫讀緩存塊
		}
		return 1;
	}
	return 0;
}

6.3、心電信號濾波

  1. 工頻噪聲濾除

濾除工頻噪聲的數(shù)字濾波算法主要有經(jīng)典濾波器、小波變換、自適應(yīng)濾波。小波變換能將心電信號進(jìn)行多層分解,可以使得心電信號與工頻噪聲分離,但是計算量大,所占用的中間變量也比較多,對于單片機(jī)來說,處理的速度也不夠快,因而對于系統(tǒng)的實時性這一指標(biāo)很難實現(xiàn)。自適應(yīng)濾波能夠自動跟蹤工頻噪聲的改變,但是需要增加一個輸入信號作為參考,因而增加了系統(tǒng)的復(fù)雜性。在前面也討論過心電信號95%的能量都是集中在0~40Hz,而工頻噪聲則在50Hz左右,過渡帶比較寬,因而可以選擇截止頻率為40Hz的低通濾波器。
該低通濾波器利用MATLAB的FDATOOL生成,只需要選擇低通濾波器是FIR結(jié)構(gòu),選擇Blackman-Harris窗函數(shù),濾波器的階數(shù)定為50,選擇采樣頻率為250Hz,截止頻率為40Hz,參數(shù)如下圖所示:
基于STM32F4的心電監(jiān)護(hù)儀
然后利用FDATOOL生成的沖激響應(yīng)的數(shù)組,選擇ARM官方的DSP庫,調(diào)用arm_fir_f32函數(shù),既可以完成一次濾波。但是在這之前,需要調(diào)用arm_fir_init_f32進(jìn)行初始化。
濾波器系數(shù)如下:

const float32_t fir32LP[NUM_TAPS] = {
  -7.484454468902e-22,-3.269336712398e-06,-1.365915864079e-05,-5.014073980636e-06,
  6.804735231975e-05,0.0001662336497003,7.965197426322e-05,-0.0003784662837741,
  -0.0008928563387901,-0.0005280588787408, 0.001284875839485, 0.003225662215767,
     0.0022425431358,-0.003157084585057,-0.009028737319977,-0.007219934929014,
   0.006057868257093,  0.02144319498633,  0.01971312591228,-0.009448071870685,
   -0.04806332586811, -0.05291973061693,  0.01224382260678,   0.1388254178822,
     0.2663085232723,   0.3199984843521,   0.2663085232723,   0.1388254178822,
    0.01224382260678, -0.05291973061693, -0.04806332586811,-0.009448071870685,
    0.01971312591228,  0.02144319498633, 0.006057868257093,-0.007219934929014,
  -0.009028737319977,-0.003157084585057,   0.0022425431358, 0.003225662215767,
   0.001284875839485,-0.0005280588787408,-0.0008928563387901,-0.0003784662837741,
  7.965197426322e-05,0.0001662336497003,6.804735231975e-05,-5.014073980636e-06,
  -1.365915864079e-05,-3.269336712399e-06,-7.484454468902e-22
};

static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1];
arm_fir_instance_f32 S;
void arm_fir_Init(void)
{
	arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&fir32LP[0], &firStateF32[0], BLOCK_SIZE);
}

濾波函數(shù)見程序3(往上找)

  1. 基線漂移

基線漂移與工頻噪聲不同,它是由于呼吸和電極滑動變化所異致的,其頻率一般低于1Hz左右。常見對于基線漂移濾除的數(shù)字算法有高通濾波器、中值濾波、小波變換、形態(tài)學(xué)濾波、曲線擬合等,其中高通濾波器可能會對心電信號的ST波段產(chǎn)生影響,畢竟基線漂移的頻率也在ST波段里面。曲線擬合對較大的基線漂移處理能力較弱,處理的效果與處理數(shù)據(jù)的長度成正相關(guān),因而不適用實時處理的系統(tǒng)。小波變換計算量大,也不適用實時處理的系統(tǒng)。相比之下,形態(tài)學(xué)濾波對心電信號的基線漂移濾除效果更好,計算量也比中值濾波小。但是形態(tài)學(xué)濾波要求數(shù)據(jù)長度足夠長,因而會改變前面的緩存結(jié)構(gòu),并且在本系統(tǒng)中并未太嚴(yán)重的基線漂移,系統(tǒng)的任務(wù)也比較多,多方面權(quán)衡之下,選擇不處理基線漂移。

  1. 肌電噪聲的抑制

肌電噪聲主要是由于人體肌肉顫抖導(dǎo)致體表的電位發(fā)生變化,這種噪聲通過電極貼傳導(dǎo)至心電模擬前端,并且這種噪聲持續(xù)時間較短,使得ECG信號波形產(chǎn)生細(xì)小的波紋,這種噪聲頻率分布比較廣,前面已經(jīng)將心電信號通過截止頻率為40Hz的低通濾波器,因而需要5點平滑濾波將細(xì)小的波紋濾除,為了不影響心電信號的實時處理,因而改進(jìn)版的平滑濾波器代碼如下:

/*
 * 滑動平均值濾波。
 * 每調(diào)用一次,就加入一個新數(shù)據(jù),并得到當(dāng)前的濾波值。
 */
float alg(float new_val)
{
    /* 用一個減法,就做了"丟棄最舊的數(shù)據(jù),加入最新的數(shù)據(jù)"這一操作 */
    sum += (new_val - buf[pos]);
    buf[pos] = new_val;
    pos = (pos + 1) % MAX_COUNT;
    /* 個數(shù)不足時,cnt是實際個數(shù),個數(shù)足夠時,cnt最多也只是MAX_COUNT */
    pcnt += (pcnt < MAX_COUNT);
    return sum / MAX_COUNT;
}

6.4、心率和QRS寬度檢測

心率和QRS寬度檢測作為本系統(tǒng)的算法核心,有了心率值和QRS寬度值才能進(jìn)一步判斷常見的心律失常。心率基本上都是檢測兩個R波之間的時隙來計算的,常見檢測R的算法主要有閾值法、模板法和語句描述法。
而本系統(tǒng)的心率和QRS寬度檢測算法是在一起檢測的,所采用的算法是幅度閾值檢測和差分檢測相結(jié)合,因為觀察心電信號的R波,發(fā)現(xiàn)R波是具有窄的脈沖,且脈沖的幅度是心電信號最高的,因而采用幅度和一階差分共同約束找到R波,同時在找R波的同時還可以估計出QRS的寬度,算法的框圖如圖
基于STM32F4的心電監(jiān)護(hù)儀
心率檢測和QRS寬度檢測算法是采用狀態(tài)機(jī)的編程思想,通過R波幅度大且從Q到R一直遞增,并且R波到S波的一階差分值很大,從而將R波定位出來,檢測兩個R波之前的時間,然后通過如下公式就可以計算出心率:
H R = ( 60 ? S a m p l e R a t e ) / c o u n t HR=(60*SampleRate) /count HR=(60?SampleRate)/count

而QRS寬度則是由
Q R S = Q R S c n t ? 2.2 ? 1000 / ( S a m p l e R a t e ) QRS=QRScnt*2.2* 1000/(SampleRate) QRS=QRScnt?2.2?1000/(SampleRate)

上式中的2.2是估計值,因為QRS_cnt是在檢測到R波之后才開始計數(shù),并且未到S波谷停止計數(shù),觀察QRS波,發(fā)現(xiàn)Q到R與R到S近似對稱,因而采用2.2這個估計值,這也是實時檢測的缺陷,檢測的樣本不多。
心率算法和QRS寬度檢測代碼如下:

/**
  * @Brief 測量心率
  * @Call
  * @Param
  * @Note
  * @Retval
  */
void ecg_heart_rate(int data)
{
	int Signal=data;
			
	if(Signal>hr.vmax)
		hr.vmax=Signal;
	if(Signal<hr.vmin)
		hr.vmin=Signal;
	thresh=hr.vmax-(hr.vmax-hr.vmin)/5;
	  
	for( uint16_t i = 0; i <= DATA_NUM_CAL_HR - 2; i++ )
    {
        DataArrayCalHR[i] =	DataArrayCalHR[i + 1];
    }
	 DataArrayCalHR[DATA_NUM_CAL_HR - 1] = Signal;
    Diff_Arrray( DiffDataArrayCalHR, DataArrayCalHR, DATA_NUM_CAL_HR );     //差分
	
	if(hr.flag==StartDetected){
		uint8_t FlagAllDiffRise = true;

            for( uint16_t i = 0; i <= DATA_NUM_CAL_HR - 2; i++ ) //判斷波形是否一直上升
            {
                if( DiffDataArrayCalHR[i] <= 0 )
                {
                    FlagAllDiffRise = false;
                    break;
                }
            }
			if(FlagAllDiffRise==true){
				hr.flag=QWave;
			}
	}
    else if(hr.flag==QWave)//已經(jīng)找Q波
    {
		if(DataArrayCalHR[DATA_NUM_CAL_HR-1]>thresh){
			if(hr.count>125){
				if( hr.firstBeat==true )//如果已經(jīng)找到 過R波
				{
				hr.rate=(float)60*SAMPLE_RATE/(hr.count);
				hr.count=0;//清除計數(shù)
				hr.flag=RWave;
				QRScntflag=true;
				} else if(hr.firstBeat==false) {
				hr.firstBeat=true;
				hr.count=0;//清除計數(shù)
				hr.flag=RWave;
				QRScntflag=true;
				}
			}			
		}
   }
	 else if(hr.flag==RWave ){
		if(DiffDataArrayCalHR[0]<-(hr.vmax-hr.vmin)/5){
				hr.flag=SWave;
		}
	}
	else if(hr.flag==SWave){
			if(hr.QRS_cnt<15){
			hr.flag=StartDetected;
			hr.QRS=hr.QRS_cnt*22*100/SAMPLE_RATE;
			hr.QRS_cnt=0;
			QRScntflag=false;
			}else {
			hr.flag=StartDetected;
			hr.QRS=0;
			hr.QRS_cnt=0;
			QRScntflag=false;
			}
	}
		if(hr.count>420){
				hr.firstBeat=false;
				hr.flag=StartDetected;
				hr.vmax=Heart_MIN;
				hr.vmin=Heart_MAX;
				hr.rate=0;
				thresh=0;
				hr.count=0;//清除計數(shù)
			}
}

七、實機(jī)演示

實機(jī)演示

八、總結(jié)與展望

本系統(tǒng)因為沒有加入操作系統(tǒng)的管理,造成實現(xiàn)的功能較為少,并且數(shù)據(jù)分析功能因為缺乏強(qiáng)大處理器造成數(shù)據(jù)分析功能所需要的指標(biāo)太少,要想對心電信號實現(xiàn)自動化分析,必須對心電信號更多的信息進(jìn)行提前,而且由于處理器的限制使得一些強(qiáng)大的數(shù)字算法是用不了,而且將采集—濾波—顯示集成一體化本身就顯得笨重,會讓每個處理單元相互牽制,嚴(yán)重的會影響系統(tǒng)的采樣率,造成一些不必要的誤差。所以日后會有針對選擇更為強(qiáng)大的處理器,會將采集、濾波、顯示分開來。同時為了減少外界噪聲,應(yīng)該選擇更為干凈的電源和屏蔽外殼,系統(tǒng)也不能以這種模塊化的方式拼接在一起,日后會選擇畫PCB,將所有模塊集成在PCB上,在套上屏蔽殼,這樣能夠最大程度減少外界噪聲干擾。并且無線通信模塊保留著,但是上位機(jī)并未實現(xiàn),因而日后需要增加這一項功能??偨Y(jié)以上的不足如下:

  1. 使用更為強(qiáng)大的處理器,將采集、濾波、顯示分開來。
  2. 所有模塊應(yīng)該集成在PCB上,在增加屏蔽殼。
  3. 開發(fā)上位機(jī)軟件,實現(xiàn)心電數(shù)據(jù)的無線通信的功能。

代碼我會放在github上,鏈接如下:
https://github.com/lvzhe-speed/STM32_ECG
后面我去考研了,希望能夠考上,以后會每一年至少寫一篇技術(shù)博客,謝謝各位大佬前來斧正,歡迎探討,一起技術(shù)進(jìn)步。其實我也想借此說一下,不能因為一次失敗就否定自己之前的努力,100-1=0這也許是別人對你的評價,但自己不能認(rèn)同這個錯誤的式子,人生不僅有加法,也有減法。也希望對別人多一點諒解,每個人都不容易,也許今日之菜鳥,明日之大鵬,總會翱翔九天。文章來源地址http://www.zghlxwxcb.cn/news/detail-437962.html

到了這里,關(guān)于基于STM32F4的心電監(jiān)護(hù)儀的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【stm32開發(fā)筆記】基于HAL庫的STM32F4添加DSP庫

    【stm32開發(fā)筆記】基于HAL庫的STM32F4添加DSP庫

    本文分兩種方法添加DSP庫:1.CubeMX直接配置ioc添加; 2.KEIL內(nèi)添加; 簡述:補(bǔ)齊全部lib庫-添加DSP包-使能DSP勾選-添加頭文件及魔術(shù)棒配置-測試 1.補(bǔ)齊lib庫。( 如果使用直接默認(rèn)添加的庫,是不支持FPU的,所以需要補(bǔ)齊后找到所需的lib文件進(jìn)行替換,在MX的工程管理欄,選擇復(fù)制所

    2024年02月16日
    瀏覽(146)
  • 基于STM32F4的CANOpen移植教程(超級詳細(xì))

    基于STM32F4的CANOpen移植教程(超級詳細(xì))

    本專題相關(guān)教程: 基于STM32F4的CANOpen移植教程 基于STM32F4的CANopen快速SDO通信 linux下CANopen for python的使用 基于Linux C的CANopen移植 CANopen補(bǔ)充–時間計算出錯 CANopen補(bǔ)充–主站檢測節(jié)點是否在線 為了在STM32F4上能夠運行CANopen(CanFestival),跟著網(wǎng)上的教程操作,發(fā)現(xiàn)總是不夠詳細(xì)。

    2024年02月02日
    瀏覽(29)
  • 關(guān)于LWIP用法之HTTPD:基于STM32F4搭建web服務(wù)器

    關(guān)于LWIP用法之HTTPD:基于STM32F4搭建web服務(wù)器

    一,STM32CUBEMX配置(使用的是6.4.0版本) 前提是在配置好LWIP的情況下(能ping通你的開發(fā)板),使能HTTPD功能。 然后是使能LWIP_HTTPD_CGI, 使能:LWIP_HTTPD_SUPPORT_POST(), 使能 :HTTPD_USE_CUSTOM_FSDATA。 會發(fā)現(xiàn)fs.c這個文件的#include HTTPD_FSDATA_FILE,這一句編譯報錯,解決辦法:1) 在KEIL中l(wèi)wipop

    2023年04月08日
    瀏覽(23)
  • 金科威GoldWayUT4000監(jiān)護(hù)儀協(xié)議對接

    金科威GoldWayUT4000監(jiān)護(hù)儀協(xié)議對接

    通過網(wǎng)口,成功對接到參數(shù): Sys、Dia、Map、Temp、HR、SPO2、Resp、RR、EtCO2、InCO2等數(shù)值。 ?

    2024年02月15日
    瀏覽(38)
  • 運動控制器設(shè)計——基于FreeModbus在STM32F4平臺實現(xiàn)ModbusTCP和ModbusRTU

    運動控制器設(shè)計——基于FreeModbus在STM32F4平臺實現(xiàn)ModbusTCP和ModbusRTU

    本文筆者最近的項目是設(shè)計一款運動控制器,MCU使用的是STM32F429,要求是通過Modbus TCP協(xié)議實現(xiàn)與示教器通訊,并通過ModbusRTU實現(xiàn)與觸摸屏通訊。 本文將介紹在STM32F4上實現(xiàn) ModbusTCP和ModbusRTU通訊 的過程。筆者才疏學(xué)淺,如有錯誤還請指正。 Modbus協(xié)議是典型的主-從通訊結(jié)構(gòu),鏈

    2024年02月05日
    瀏覽(15)
  • GD32F4移植STM32F4

    GD32F4移植STM32F4

    近期在項目中采用了GD32F407VET6替換原項目中的STM32F407VET6,網(wǎng)傳GD的兼容性很好,之前也用F1系統(tǒng)的替換了一下,按照CSND各位大佬的經(jīng)驗一步步改進(jìn)了代碼,測試直接通過,現(xiàn)在也一直在項目中實際應(yīng)用了,一直沒有出問題。 所以這SMT時,嘉立創(chuàng)沒有STM的貨果斷換成了GD,可換時

    2024年02月16日
    瀏覽(32)
  • 基于STM32F4的FFT+測頻率幅值相位差,波形顯示,示波器,時域頻域分析相關(guān)工程

    一入電賽深似海,此話不假,個人感覺很累,但是收獲確實多。本人去年參加了國賽,電賽提前半個月就開始著手準(zhǔn)備了,只記得那時候不是調(diào)試就是在調(diào)試的路上,也因此留下了寶貴的我姑且稱之為“經(jīng)驗”,作為一名小白,借此機(jī)會跟各位老白和小白分享一下。我訓(xùn)練較

    2024年02月03日
    瀏覽(16)
  • 【STM32】STM32F4 GPIO詳解與配置

    【STM32】STM32F4 GPIO詳解與配置

    GPIO是通用輸入輸出端口的簡稱,為STM32可控制的引腳,STM32芯片的GPIO引腳與外部設(shè)備連接起來,從而實現(xiàn)與外部通訊、控制以及數(shù)據(jù)采集的功能。STM32芯片的GPIO被分成很多組,每組有16個引腳,所有的GPIO引腳都有基本的輸入輸出功能。 其中保護(hù)二極管使GPIO能夠5V電壓容忍。在

    2024年02月07日
    瀏覽(25)
  • STM32F4Timer

    STM32F4Timer

    ref https://blog.csdn.net/zhuxinmingde/article/details/131784852?ops_request_misc=request_id=biz_id=102utm_term=STM32%20%E9%AB%98%E7%BA%A7%EF%BC%8C%E6%99%AE%E9%80%9A%EF%BC%8C%E5%9F%BA%E6%9C%AC%E5%AE%9A%E6%97%B6%E5%99%A8utm_medium=distribute.pc_search_result.none-task-blog-2 all sobaiduweb~default-1-131784852.142 v99 controlspm=1018.2226.3001.4187 1. Timer re

    2024年02月02日
    瀏覽(22)
  • 【STM32】STM32F4 GPIO口映射與復(fù)用

    【STM32】STM32F4 GPIO口映射與復(fù)用

    STM32F4 有很多的內(nèi)置外設(shè),這些外設(shè)的外部引腳都是與 GPIO 復(fù)用的。也就是說,一個 GPIO 如果可以復(fù)用為內(nèi)置外設(shè)的功能引腳,那么當(dāng)這個 GPIO 作為內(nèi)置外設(shè)使用的時候,就叫做復(fù)用。 這部分知識在《STM32F4 中文參考手冊》第七章和芯片數(shù)據(jù)手冊有詳細(xì)的講解哪些 GPIO 管腳是

    2024年02月15日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包