新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于STM32指甲式脈搏血氧儀七大核心功能解析與實現(xiàn)

基于STM32指甲式脈搏血氧儀七大核心功能解析與實現(xiàn)

作者:嵌入式芯視野 時間:2025-08-04 來源:今日頭條 收藏

基于的SpO2-EVM

血氧儀開發(fā)套件 血氧儀開發(fā)套件

1. 血氧飽和度測量(40%~100%,精度 ±2%@70%~100%)

技術(shù)指標(biāo)解析

  • 測量范圍:覆蓋臨床緊急低氧(40%)到正常(100%)場景,滿足 ICU 重癥監(jiān)護(hù)與家庭健康監(jiān)測需求;

  • 精度分級:70%~100% 時 ±2%(臨床診斷級),40%~70% 時 ±4%(低氧預(yù)警級),符合 YY/T 0784-2010 行業(yè)標(biāo)準(zhǔn)。

方案實現(xiàn)

  • 硬件基礎(chǔ):12 位 ADC(ADS1258)采集光信號,分辨率達(dá) 0.08mV(3.3V 參考電壓);雙波長 LED(660nm 紅光 / 940nm 近紅外)分時驅(qū)動,減少環(huán)境光干擾。

  • 軟件算法:采用 Beer-Lambert 定律結(jié)合校準(zhǔn)系數(shù)查表法,如前文中SPO2_Calculate函數(shù)通過 AC/DC 比值計算 SpO2;動態(tài)溫度補(bǔ)償:內(nèi)置溫度傳感器修正光吸收系數(shù)隨溫度的漂移。

2. 脈率測量(30~250bpm,精度 ±1bpm)

技術(shù)指標(biāo)解析

  • 范圍覆蓋:從新生兒靜息心率(30bpm)到運動極限心率(250bpm);

  • 精度控制:±1bpm 滿足臨床心率變異性(HRV)分析需求。

方案實現(xiàn)

  • 信號處理:帶通濾波提取脈搏波頻率(0.5~5Hz),抑制運動偽影;峰值檢測算法(如前文中PulseRate_Detect函數(shù))結(jié)合滑動平均濾波(8 點緩沖),消除異常脈沖。

  • 抗干擾設(shè)計:采用自適應(yīng)閾值跟蹤脈搏波幅度變化,避免弱信號漏檢;周期校驗機(jī)制:若相鄰脈率差 > 20%,則丟棄該次測量結(jié)果。

3. 弱信號處理(弱灌注強(qiáng)度≤0.3%)

技術(shù)指標(biāo)解析

  • 灌注指數(shù)(PI):≤0.3% 表示極弱血流(如失血性休克、低溫癥),傳統(tǒng)設(shè)備易測量失敗。

STM32 方案實現(xiàn)

  • 硬件增強(qiáng):高增益儀表運放(ISL28470)放大微弱光電流信號,增益可達(dá) 1000 倍;低噪聲電源(ISL9001)抑制紋波對前端信號的干擾。

  • 軟件優(yōu)化:自適應(yīng)增益控制:當(dāng) PI<1% 時,自動提高 LED 驅(qū)動電流(如前文中NLAS4053模擬開關(guān)調(diào)節(jié));小波變換去噪:分解信號至不同頻段,保留脈搏波特征分量。

4. 彩色 OLED 同屏顯示

功能架構(gòu)

  • 顯示內(nèi)容:數(shù)值區(qū):SpO2(大字體突出)、脈率、PI 值;波形區(qū):實時脈搏波(128 點趨勢圖);狀態(tài)區(qū):電池電量、信號質(zhì)量圖標(biāo)。

  • STM32 驅(qū)動方案:SPI 接口控制 OLED 驅(qū)動 IC(如 SSD1351),刷新率≥25fps;動態(tài)刷新率調(diào)節(jié):弱信號時提高刷新率至 50fps,增強(qiáng)波形穩(wěn)定性。

5. 無信號自動關(guān)機(jī)

功耗管理邏輯

  • 檢測機(jī)制:連續(xù) 20 秒檢測到 PI<0.2% 且 SpO2 值固定不變(如 40%),判定為無有效信號;硬件 watchdog(X5043)監(jiān)控 MCU 運行狀態(tài),防止程序卡死導(dǎo)致功耗異常。

  • 低功耗實現(xiàn):STM32 進(jìn)入 STANDBY 模式,功耗 < 10μA;切斷 LED、OLED 等外設(shè)電源,僅保留 RTC(ISL12022M)計時。


6. 歷史數(shù)據(jù)存儲與管理

存儲架構(gòu)

  • 硬件配置:串行 Flash(M25P16,16Mbit)可保存≥2000 條記錄(每條含 SpO2、脈率、時間戳);I2C 接口 EEPROM(M24C64)存儲校準(zhǔn)參數(shù)與用戶配置。

  • 軟件功能:周期性存儲:每 5 分鐘自動保存一次數(shù)據(jù),支持手動觸發(fā)保存;數(shù)據(jù)管理:支持按日期查詢、刪除指定記錄,F(xiàn)IFO 循環(huán)覆蓋舊數(shù)據(jù)。

7. 屏幕旋轉(zhuǎn)功能

實現(xiàn)方案

  • 硬件:三軸加速度傳感器(LIS33DE)檢測設(shè)備姿態(tài),分辨率達(dá) ±2g;

  • 程序示例:基于 STM32F103 的血氧儀數(shù)據(jù)處理

  • 以下是核心功能的 C 語言實現(xiàn)(使用 HAL 庫):

/* 頭文件與宏定義 */#include "stm32f10x_hal.h"#include "math.h"#define SAMPLE_RATE 1000        // 采樣率1kHz#define BUFFER_DEPTH 256        // 數(shù)據(jù)緩沖區(qū)深度#define RED_LED_PORT GPIOA      // 紅光LED端口#define RED_LED_PIN GPIO_PIN_0  #define IR_LED_PORT GPIOA       // 近紅外LED端口#define IR_LED_PIN GPIO_PIN_1#define ADC_CHANNEL_RED 0       // 紅光ADC通道#define ADC_CHANNEL_IR 1        // 近紅外ADC通道/* 全局變量 */ADC_HandleTypeDef hadc;
DMA_HandleTypeDef hdma_adc;uint16_t adcBuffer[2][BUFFER_DEPTH];  // ADC數(shù)據(jù)緩沖區(qū) {紅光, 近紅外}float redSignal[BUFFER_DEPTH];        // 紅光信號float irSignal[BUFFER_DEPTH];         // 近紅外信號uint8_t spo2Value = 97;               // 血氧飽和度uint16_t pulseRate = 72;              // 脈率(bpm)uint8_t perfusionIndex = 0;           // 灌注指數(shù)/* 函數(shù)聲明 */void SystemInit(void);void MX_GPIO_Init(void);void MX_ADC_Init(void);void MX_DMA_Init(void);void SPO2_Calculate(void);void PulseRate_Detect(void);void OLED_Display(void);void PowerManagement_Check(void);/* 主函數(shù) */int main(void){  /* 系統(tǒng)初始化 */
 HAL_Init();
 SystemInit();  
 /* 外設(shè)初始化 */
 MX_GPIO_Init();
 MX_ADC_Init();
 MX_DMA_Init();  
 /* 啟動ADC_DMA傳輸 */
 HAL_ADC_Start_DMA(&hadc, (uint32_t*)adcBuffer, 2 * BUFFER_DEPTH);  
 /* 主循環(huán) */
 while (1)
 {    /* 血氧與脈率計算 */
   SPO2_Calculate();
   PulseRate_Detect();    
   /* 顯示數(shù)據(jù) */
   OLED_Display();    
   /* 低功耗檢查 */
   PowerManagement_Check();    
   /* 延時處理 */
   HAL_Delay(10);
 }
}/* ADC初始化 */void MX_ADC_Init(void){
 ADC_ChannelConfTypeDef sConfig = {0};

 hadc.Instance = ADC1;
 hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
 hadc.Init.Resolution = ADC_RESOLUTION_12B;
 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
 hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 hadc.Init.ContinuousConvMode = ENABLE;
 hadc.Init.NbrOfConversion = 2;  // 紅光+近紅外雙通道
 HAL_ADC_Init(&hadc);  /* 配置紅光通道 */
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
 HAL_ADC_ConfigChannel(&hadc, &sConfig);  
 /* 配置近紅外通道 */
 sConfig.Channel = ADC_CHANNEL_1;
 HAL_ADC_ConfigChannel(&hadc, &sConfig);
}/* 血氧飽和度計算 */void SPO2_Calculate(void){  static float redAC[BUFFER_DEPTH], redDC[BUFFER_DEPTH];  static float irAC[BUFFER_DEPTH], irDC[BUFFER_DEPTH];  float ratio, spo2;  
 /* 1. 轉(zhuǎn)換ADC值為電壓信號(假設(shè)參考電壓3.3V) */
 for (uint16_t i = 0; i < BUFFER_DEPTH; i++) {
   redSignal[i] = (float)adcBuffer[0][i] * 3.3f / 4096.0f;
   irSignal[i] = (float)adcBuffer[1][i] * 3.3f / 4096.0f;
 }  
 /* 2. 分離AC和DC分量(簡化版,實際需濾波) */
 for (uint16_t i = 0; i < BUFFER_DEPTH; i++) {
   redDC[i] = redSignal[i] * 0.95f + redDC[i] * 0.05f;  // 一階低通濾波求DC
   redAC[i] = redSignal[i] - redDC[i];                  // AC分量
   
   irDC[i] = irSignal[i] * 0.95f + irDC[i] * 0.05f;
   irAC[i] = irSignal[i] - irDC[i];
 }  
 /* 3. 計算AC/DC比值 */
 float sumRedAC = 0, sumRedDC = 0;  float sumIrAC = 0, sumIrDC = 0;  for (uint16_t i = 0; i < BUFFER_DEPTH; i++) {
   sumRedAC += fabs(redAC[i]);
   sumRedDC += fabs(redDC[i]);
   sumIrAC += fabs(irAC[i]);
   sumIrDC += fabs(irDC[i]);
 }  
 float ratioRed = sumRedAC / sumRedDC;  float ratioIr = sumIrAC / sumIrDC;  
 /* 4. 計算灌注指數(shù)(PI) */
 perfusionIndex = (uint8_t)((ratioRed + ratioIr) * 10);  
 /* 5. 根據(jù)Beer-Lambert定律計算SpO2(簡化公式) */
 ratio = ratioRed / ratioIr;  if (ratio > 1.0f) ratio = 1.0f / ratio;  // 范圍限定
 spo2 = 94.0f - 25.0f * ratio;           // 經(jīng)驗公式,實際需校準(zhǔn)
 
 /* 6. 結(jié)果校準(zhǔn)與限幅 */
 if (spo2 > 100) spo2 = 100;  if (spo2 < 40) spo2 = 40;
 spo2Value = (uint8_t)spo2;
}/* 脈率檢測 */void PulseRate_Detect(void){  static uint32_t lastPeakTime = 0;  static float peakBuffer[8] = {0};  static uint8_t peakIndex = 0;  uint32_t currentTime = HAL_GetTick();  float maxAmplitude = 0;  uint16_t peakPosition = 0;  
 /* 1. 尋找脈搏波峰值(簡化版,實際需帶通濾波) */
 for (uint16_t i = 0; i < BUFFER_DEPTH; i++) {    if (redSignal[i] > maxAmplitude) {
     maxAmplitude = redSignal[i];
     peakPosition = i;
   }
 }  
 /* 2. 計算脈搏周期(需排除異常峰值) */
 if (maxAmplitude > 0.1f && currentTime - lastPeakTime > 300 && currentTime - lastPeakTime < 2000) {    uint32_t periodMs = currentTime - lastPeakTime;
   pulseRate = (uint16_t)(60000.0f / periodMs);  // ms轉(zhuǎn)bpm
   lastPeakTime = currentTime;    
   /* 3. 滑動平均濾波,平滑脈率顯示 */
   peakBuffer[peakIndex] = pulseRate;
   peakIndex = (peakIndex + 1) % 8;    
   float avgPulse = 0;    for (uint8_t i = 0; i < 8; i++) {
     avgPulse += peakBuffer[i];
   }
   pulseRate = (uint16_t)(avgPulse / 8);
 }
}/* OLED顯示函數(shù) */void OLED_Display(void){  /* 實際項目中需調(diào)用OLED驅(qū)動庫 */
 char displayBuf[32];  
 /* 顯示血氧飽和度 */
 sprintf(displayBuf, "SpO2: %d%%", spo2Value);
 OLED_DrawString(0, 0, displayBuf);  
 /* 顯示脈率 */
 sprintf(displayBuf, "PR: %dbpm", pulseRate);
 OLED_DrawString(0, 20, displayBuf);  
 /* 顯示灌注指數(shù) */
 sprintf(displayBuf, "PI: %d", perfusionIndex);
 OLED_DrawString(0, 40, displayBuf);  
 /* 繪制簡化脈搏波形 */
 for (uint16_t i = 0; i < 128; i++) {    uint16_t point = i * BUFFER_DEPTH / 128;    uint8_t y = (uint8_t)(redSignal[point] * 30 + 50);
   OLED_DrawPoint(i, y);
 }
}/* 低功耗管理 */void PowerManagement_Check(void){  static uint32_t noSignalTime = 0;  static uint8_t signalStatus = 0;  
 /* 1. 檢測信號有效性(通過灌注指數(shù)判斷) */
 if (perfusionIndex > 1) {
   signalStatus = 1;
   noSignalTime = HAL_GetTick();
 } else {    if (signalStatus) {
     signalStatus = 0;
     noSignalTime = HAL_GetTick();
   }
 }  
 /* 2. 無信號超過20秒則關(guān)機(jī) */
 if (!signalStatus && HAL_GetTick() - noSignalTime > 20000) {    /* 關(guān)閉外設(shè),進(jìn)入待機(jī)模式 */
   HAL_ADC_Stop_DMA(&hadc);
   HAL_GPIO_WritePin(RED_LED_PORT, RED_LED_PIN, GPIO_PIN_RESET);
   HAL_GPIO_WritePin(IR_LED_PORT, IR_LED_PIN, GPIO_PIN_RESET);
   OLED_PowerOff();    
   /* 進(jìn)入低功耗模式 */
   HAL_PWR_EnterSTANDBYMode();
 }
}
  • 應(yīng)用場景:支持手持、桌面等多場景使用,自動適配顯示方向。

功能協(xié)同與臨床價值示意圖


典型應(yīng)用案例

  • 秦皇島康泰醫(yī)學(xué):采用 STM32F101C6T6 方案,結(jié)合 LIS33DE 與 M25P80 Flash,實現(xiàn) 24 小時連續(xù)監(jiān)測,數(shù)據(jù)可通過 USB 導(dǎo)出至醫(yī)院 HIS 系統(tǒng);

  • 北京超思電子:在遠(yuǎn)程血氧監(jiān)護(hù)儀中加入 4G 通信模塊,當(dāng) SpO2<90% 且持續(xù) 5 分鐘時,自動向家屬手機(jī)推送報警信息,結(jié)合歷史數(shù)據(jù)存儲功能,支持醫(yī)生遠(yuǎn)程調(diào)閱趨勢圖。

技術(shù)對比表(STM32 方案 vs 傳統(tǒng)方案)

功能點

STM32 方案優(yōu)勢

傳統(tǒng)方案局限

弱信號處理

自適應(yīng)增益 + 小波去噪,PI≤0.3% 可用

PI<1% 時測量失效

數(shù)據(jù)存儲

16Mbit Flash 支持 7 天連續(xù)記錄

僅保存最近 200 條記錄

屏幕旋轉(zhuǎn)

實時姿態(tài)檢測,用戶體驗更友好

固定方向顯示,視角受限

功耗控制

STANDBY 模式 < 10μA,續(xù)航≥15 小時

待機(jī)功耗 > 50μA,續(xù)航 < 8 小時



關(guān)鍵詞: STM32

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉