STM32 PulseSensor心跳傳感器驅動代碼

STM32CubeMX中準備工作:

1、設置AD 通道

2、設置一個定時器中斷,間隔時間2ms,我這里采用的是定時器7

3、代碼優化01

PulseSensor.c文件

#include "main.h"
#include "PulseSensor/PulseSensor.h"/******************外設部分用變量*********************/
//定時器間隔時間:2ms
volatile  uint8_t DelayPulseSensor_Output=0;  //500ms   
//AD采樣值
volatile  uint16_t ADPulseSensor;            // ADC轉換值,設置為halfword 半字節格式 采樣時間為239.5周期/******************心率算法采集部分*********************/
_Bool ReadHeartRateFlag = 0;				        //讀取到正確心率標志位uint16_t BPM;                   		    //脈搏率==就是心率
uint16_t Signal;               		    //傳入的原始數據。
uint16_t IBI = 600;            		    //節拍間隔,兩次節拍之間的時間(ms)。計算:60/IBI(s)=心率(BPM)
_Bool Pulse = false;     //脈沖高低標志。當脈波高時為真,低時為假。
_Bool QS = false;        //當發現一個節拍時,就變成了真實
uint16_t rate[10];                    //數組保存最后10個IBI值。
uint32_t sampleCounter = 0; //用于確定脈沖定時。
uint32_t lastBeatTime = 0;  //用于查找IBI
uint16_t P =512;                      //用于在脈沖波中尋找峰值
uint16_t T = 512;                     //用于在脈沖波中尋找波谷
uint16_t thresh = 512;                //用來尋找瞬間的心跳
uint16_t amp = 100;                   //用于保持脈沖波形的振幅
uint16_t Num;
_Bool firstBeat = true;  //第一個脈沖節拍
_Bool secondBeat = false;//第二個脈沖節拍,這兩個變量用于確定兩個節拍void PulseSensor_Read(uint16_t PulseSensorValue)
{unsigned char i = 0;unsigned int  runningTotal;//		讀取到的值右移2位,12位-->10位Signal = PulseSensorValue/4;     //讀取A/D轉換數據
//		Signal=Get_Adc_Average(ADC_Channel_0,1)>>2;//讀取A/D轉換數據sampleCounter = HAL_GetTick();              //利用系統滴答時鐘,單位:msNum = sampleCounter - lastBeatTime;          //監控最后一次節拍后的時間,以避免噪聲	 //發現脈沖波的波峰和波谷if(Signal < thresh && Num > (IBI/5)*3)  	//為了避免需要等待3/5個IBI的時間{ if (Signal < T)                         //T是閾值{T = Signal;                         //跟蹤脈搏波的最低點,改變閾值}}if(Signal > thresh && Signal > P)        	//采樣值大于閾值并且采樣值大于峰值{P = Signal;                             //P是峰值,改變峰值}                                        //開始尋找心跳,現在開始尋找心跳節拍//當脈沖來臨的時候,signal的值會上升if (Num > 250)                              //避免高頻噪聲{ if ( (Signal > thresh) && (Pulse == false) && (Num > (IBI/5)*3) ){        Pulse = true;                       //當有脈沖的時候就設置脈沖信號
//				LED_ON();							//打開LED,表示已經有脈沖了IBI = sampleCounter - lastBeatTime; //測量節拍的ms級的時間lastBeatTime = sampleCounter;       //錄下一個脈沖的時間。if(secondBeat)						//如果這是第二個節拍,如果secondBeat == TRUE,表示是第二個節拍{                        		secondBeat = false;             //清除secondBeat節拍標志i = 0;for( i=0; i<=9; i++)			//在啟動時,種子的運行總數得到一個實現的BPM。{                 rate[i] = IBI;                     		}}if(firstBeat)                        //如果這是第一次發現節拍,如果firstBeat == TRUE。{firstBeat = false;               //清除firstBeat標志secondBeat = true;               //設置secongBeat標志return;                          //IBI值是不可靠的,所以放棄它。}   //保留最后10個IBI值的運行總數。runningTotal = 0;                  	 //清除runningTotal變量     for(i=0; i<=8; i++)                  //轉換數據到rate數組中{rate[i] = rate[i+1];              // 去掉舊的的IBI值。 runningTotal += rate[i];          //添加9個以前的老的IBI值。}rate[9] = IBI;                        //將最新的IBI添加到速率數組中。runningTotal += rate[9];              //添加最新的IBI到runningTotal。runningTotal /= 10;                   //平均最后10個IBI值。BPM = 60000/runningTotal;             //一分鐘有多少拍。即心率BPMQS = true;                            //設置量化自我標志Quantified Self標志}                       }//脈沖開始下降if (Signal < thresh && Pulse == true)  		//當值下降時,節拍就結束了。{
//			LED0=1; 								//燈滅Pulse = false;                         	//重設脈沖標記,這樣方便下一次的計數amp = P - T;                           	//得到脈沖波的振幅。thresh = amp/2 + T;                    	//設置thresh為振幅的50%。P = thresh;                            	//重新設置下一個時間T = thresh;}//沒有檢測到脈沖,設置默認值if (Num > 2500)                    	 		//如果2.5秒過去了還沒有節拍{ thresh = 512;                          	//設置默認閾值P = 512;                               	//設置默認P值T = 512;                               	//設置默認T值lastBeatTime = sampleCounter;          	//把最后的節拍跟上來。      firstBeat = true;                      	//設置firstBeat為true方便下一次處理secondBeat = false;                    	//設置secondBeat為false方便重新處理QS = false; 							//清除標志}
}/* */
uint16_t PulseSensor_Output(_Bool SensorFlag)
{uint16_t BPM_Output;    //傳遞心率值if (SensorFlag)					//讀取到了心率信號{			SensorFlag = 0; 				//清除標志 等待下一次讀取if(BPM>HEART_MIN_ERROR&&BPM<HEART_MAX_ERROR)		//讀取到的值再正常心率區間 40-160內{ReadHeartRateFlag = 1;			//標志位置1//          printf("心率值:%d \n",BPM);BPM_Output=BPM;BPM=0;}else{ReadHeartRateFlag = 0;			//標志位清零BPM_Output=0;               //輸出0}	}return BPM_Output;
}

PulseSensor.h文件

#ifndef __PulseSensor_H
#define __PulseSensor_H #define true 1
#define false 0#define HEART_MAX_ERROR		160		//心率的不可到值,超過此值表示傳感器出錯
#define HEART_MIN_ERROR		40		//心率的不可到值,低于此值表示傳感器出錯extern volatile  uint8_t DelayPulseSensor_Output;  //500ms  
extern volatile  uint16_t ADPulseSensor;            // ADC轉換值,設置為半字節格式extern uint16_t IBI;          //相鄰節拍時間
extern uint16_t BPM;          //心率值             
extern uint16_t Signal;       //原始信號值            
extern _Bool QS;              //發現心跳標志void PulseSensor_Read(uint16_t PulseSensorValue);
uint16_t PulseSensor_Output(_Bool SensorFlag);
#endif

main.c中省略了設置,主要就是將取樣AD值放入定時器中斷里計算。

while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */ADPulseSensor=ADC_ConvertedValue[0];      //將AD采樣數據傳遞出去。if(DelayPulseSensor_Output >= 250)   //500ms 間隔{DelayPulseSensor_Output=0;printf("心率值:%d\n",PulseSensor_Output(QS));}}/*** 函數功能: 在非阻塞模式下的周期經過的回調* 輸入參數: 無* 返 回 值: 無* 說    明:系統中各定時*/
void HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef * htim)
{//TIM7 用于基礎定時計算,時間為:2msif(htim->Instance==TIM7){DelayPulseSensor_Output++;    //HAL_TIM_Base_Stop_IT(&htim7);     //關閉定時器PulseSensor_Read(ADPulseSensor);  //讀取心跳數據HAL_TIM_Base_Start_IT(&htim7);    //開啟定時器}
}

?結果如下,手按上去后,需要等個10秒左右,數據才穩定。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79561.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79561.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79561.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++項目容易犯錯的點

1. 矩陣q要先定義大小&#xff0c;再賦值。不可以直接賦值。下面這種方式是錯誤的Eigen::MatrixXd q&#xff1b;q<<1,2&#xff1b;正確的這樣的&#xff1a; Eigen::MatrixXd q(2,1); q<<1.4, 1.5; 2. 不要重復加載variables.h頭文件&#xff0c;這樣變量會被…

在阿里云 Ubuntu 24.04 上部署 RabbitMQ:一篇實戰指南

前言 RabbitMQ 是業界常用的開源消息中間件,支持 AMQP 協議,易于部署、高可用、插件豐富。本文以阿里云 ECS 上運行的 Ubuntu 24.04 LTS 為例,手把手帶你完成 RabbitMQ 從倉庫配置到運行的全流程,并分享在國內環境下常見的坑與對應解決方案。 環境概況 操作系統:Ubuntu …

【論文筆記】SOTR: Segmenting Objects with Transformers

【題目】&#xff1a;SOTR: Segmenting Objects with Transformers 【引用格式】&#xff1a;Guo R, Niu D, Qu L, et al. Sotr: Segmenting objects with transformers[C]//Proceedings of the IEEE/CVF international conference on computer vision. 2021: 7157-7166. 【網…

MinIO實現https訪問

Windows下實現MinIO的https訪問. 首先需要自己解決證書問題, 這里可以是個人證書 也可以是花錢買的證書. 現在使用個人開發者證書舉例子。 將證書數據解壓到你知道的目錄之下 然后直接使用命令啟動MinIO start minio.exe server --certs-dir D:\xxxxx\tools\certs …

基于 jQuery 實現靈活可配置的輸入框驗證功能

在 Web 表單開發中&#xff0c;輸入框驗證是保障數據準確性和安全性的關鍵環節。無論是用戶注冊、信息提交還是數據錄入場景&#xff0c;都需要對用戶輸入內容進行合法性檢查。本文將介紹如何使用 HTML、CSS 和 jQuery 構建一個可靈活配置的輸入框驗證系統&#xff0c;輕松應對…

Kotlin 04Flow stateIn 和 shareIn的區別

一 Kotlin Flow 中的 stateIn 和 shareIn 一、簡單比喻理解 想象一個水龍頭&#xff08;數據源&#xff09;和幾個水杯&#xff08;數據接收者&#xff09;&#xff1a; 普通 Flow&#xff08;冷流&#xff09;&#xff1a;每個水杯來接水時&#xff0c;都要重新打開水龍頭從…

WebRTC 服務器之SRS服務器概述和環境搭建

1.概述 SRS&#xff08;Simple Realtime Server&#xff09;是一款高性能、跨平臺的流媒體服務器&#xff0c;支持多種協議&#xff0c;包括 RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH 和 GB28181。本文介紹了 SRS&#xff0c;包括其用途、關鍵功能、架構和支持協議。SRS 旨…

Dify - Embedding Rerank

注意&#xff1a;v100顯卡會出現不適配&#xff0c;不推薦使用 1. 安裝 Docker ubuntu 22.04 docker 安裝&使用_ubuntu22.04 安裝docker-CSDN博客 2. 安裝vllm pip install -U xformers torch torchvision torchaudio triton --index-url https://download.pytorch.org/w…

LeetCode:鏈表的中間結點

1、題目描述 給你單鏈表的頭結點 head &#xff0c;請你找出并返回鏈表的中間結點。 如果有兩個中間結點&#xff0c;則返回第二個中間結點。 示例 1&#xff1a; 輸入&#xff1a;head [1,2,3,4,5] 輸出&#xff1a;[3,4,5] 解釋&#xff1a;鏈表只有一個中間結點&#xff…

LabVIEW溫控系統熱敏電阻滯后問題

在 LabVIEW 構建的溫控系統中&#xff0c;熱敏電阻因熱時間常數大&#xff08;2 秒左右&#xff09;產生的滯后效應&#xff0c;致使控溫出現超調與波動。在不更換傳感器的前提下&#xff0c;可從算法優化、硬件調整和系統設計等維度著手解決。 ? 一、算法優化? 1. 改進 PI…

技術犯規計入個人犯規嗎·棒球1號位

在棒球運動中&#xff0c;雖然沒有“技術犯規”這一特定術語&#xff0c;但存在多種違規行為或違反規則的情況&#xff0c;通常會導致判罰或處罰。以下是常見的違規行為及相關規則&#xff1a; 1. 投手違規&#xff08;Balk&#xff09; 定義&#xff1a;投手在壘上有跑壘員時…

Python核心技巧 類與實例:面向對象編程的基石

、核心概念圖解 &#x1f3af; 類 vs 實例 類&#xff1a;對象的藍圖&#xff08;如"汽車設計圖"&#xff09; 實例&#xff1a;類的具體實現&#xff08;如"你的特斯拉Model 3"&#xff09; class MyClass: # 類聲明 count 0 # 類…

協程補充---viewModelScope 相關知識點

viewModelScope.launch 默認在 Dispatchers.Default 線程池執行Dispatchers.Default 是一個后臺線程池&#xff0c;專門用于 CPU 密集型任務如果需要在主線程執行&#xff0c;必須顯式指定 Dispatchers.Main remember 是 Compose 的狀態管理函數(queueMenus) 是依賴項&#xff…

linux stm32mp157 GIC-V2 中斷處理過程分析

/* ** 中斷觸發時&#xff0c;調用的 handle_arch_irq 入口地址。 ** 因為此時&#xff0c;掛接的就是 gic_handle_irq 函數&#xff01;gic_handle_irq 是個全局函數指針&#xff0c; ** static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) ** 它是Lin…

動態指令參數:根據組件狀態調整指令行為

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

直方圖比較

目錄 1、直方圖比較的概念 2、直方圖比較的主要原因 3、典型應用場景 4、基礎直方圖比較 5、多通道直方圖比較 6、實時直方圖檢測 1、直方圖比較的概念 直方圖比較是通過數學方法計算兩個直方圖之間的相似度或差異度的技術。在計算機視覺中&#xff0c;直方圖是對圖像特征…

Windows11 VS code 安裝 Cline 調用 Github MCP 配置過程坑點匯總

背景 為了調研 MCP 在 windows 上如何使用本地的命令執行一些操作而實現自動化的過程&#xff0c;在 B 站視頻的指導下&#xff0c;進行相應填坑過程&#xff0c;最終運行起來&#xff0c;并實現 github 自動化編程并提交代碼的過程。 B 站 Cline 視頻演示 Cline Cline 是一…

kdump詳解

kdump 是 Linux 系統中的一種內核崩潰轉儲機制&#xff0c;用于在系統崩潰時將內存中的數據保存到磁盤上&#xff0c;以便后續分析系統崩潰的原因。以下是對 kdump 的詳細介紹&#xff1a; 1、工作原理 kdump 利用了 Linux 系統中的雙啟動機制。當系統啟動時&#xff0c;它會…

RGB三原色

本文來源 &#xff1a; 騰訊元寶 ??RGB三原色&#xff08;紅綠藍&#xff09;詳解?? RGB&#xff08;Red, Green, Blue&#xff09;是光學的三原色&#xff0c;通過不同比例的混合可以產生人眼可見的絕大多數顏色。它是現代顯示技術&#xff08;如屏幕、投影儀&#xff09…

CSS兼容性:挑戰與策略

CSS兼容性&#xff1a;挑戰與策略 引言 在前端開發的廣闊領域中&#xff0c;跨瀏覽器兼容性無疑是最棘手且難以預測的挑戰之一。當我們精心設計的網頁在Chrome中完美呈現&#xff0c;卻在Safari中布局崩潰&#xff0c;或在Firefox中交互失效時&#xff0c;這種挫折感是每位前…