• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 基于STM32指甲式脈搏血氧儀七大核心功能解析與實現

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

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

    基于的SpO2-EVM

    血氧儀開發套件 血氧儀開發套件

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

    技術指標解析

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

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

    方案實現

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

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

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

    技術指標解析

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

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

    方案實現

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

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

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

    技術指標解析

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

    STM32 方案實現

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

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

    4. 彩色 OLED 同屏顯示

    功能架構

    • 顯示內容:數值區:SpO2(大字體突出)、脈率、PI 值;波形區:實時脈搏波(128 點趨勢圖);狀態區:電池電量、信號質量圖標。

    • STM32 驅動方案:SPI 接口控制 OLED 驅動 IC(如 SSD1351),刷新率≥25fps;動態刷新率調節:弱信號時提高刷新率至 50fps,增強波形穩定性。

    5. 無信號自動關機

    功耗管理邏輯

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

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


    6. 歷史數據存儲與管理

    存儲架構

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

    • 軟件功能:周期性存儲:每 5 分鐘自動保存一次數據,支持手動觸發保存;數據管理:支持按日期查詢、刪除指定記錄,FIFO 循環覆蓋舊數據。

    7. 屏幕旋轉功能

    實現方案

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

    • 程序示例:基于 STM32F103 的血氧儀數據處理

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

    /* 頭文件與宏定義 */#include "stm32f10x_hal.h"#include "math.h"#define SAMPLE_RATE 1000        // 采樣率1kHz#define BUFFER_DEPTH 256        // 數據緩沖區深度#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數據緩沖區 {紅光, 近紅外}float redSignal[BUFFER_DEPTH];        // 紅光信號float irSignal[BUFFER_DEPTH];         // 近紅外信號uint8_t spo2Value = 97;               // 血氧飽和度uint16_t pulseRate = 72;              // 脈率(bpm)uint8_t perfusionIndex = 0;           // 灌注指數/* 函數聲明 */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);/* 主函數 */int main(void){  /* 系統初始化 */
     HAL_Init();
     SystemInit();  
     /* 外設初始化 */
     MX_GPIO_Init();
     MX_ADC_Init();
     MX_DMA_Init();  
     /* 啟動ADC_DMA傳輸 */
     HAL_ADC_Start_DMA(&hadc, (uint32_t*)adcBuffer, 2 * BUFFER_DEPTH);  
     /* 主循環 */
     while (1)
     {    /* 血氧與脈率計算 */
       SPO2_Calculate();
       PulseRate_Detect();    
       /* 顯示數據 */
       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. 轉換ADC值為電壓信號(假設參考電壓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. 計算灌注指數(PI) */
     perfusionIndex = (uint8_t)((ratioRed + ratioIr) * 10);  
     /* 5. 根據Beer-Lambert定律計算SpO2(簡化公式) */
     ratio = ratioRed / ratioIr;  if (ratio > 1.0f) ratio = 1.0f / ratio;  // 范圍限定
     spo2 = 94.0f - 25.0f * ratio;           // 經驗公式,實際需校準
     
     /* 6. 結果校準與限幅 */
     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轉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顯示函數 */void OLED_Display(void){  /* 實際項目中需調用OLED驅動庫 */
     char displayBuf[32];  
     /* 顯示血氧飽和度 */
     sprintf(displayBuf, "SpO2: %d%%", spo2Value);
     OLED_DrawString(0, 0, displayBuf);  
     /* 顯示脈率 */
     sprintf(displayBuf, "PR: %dbpm", pulseRate);
     OLED_DrawString(0, 20, displayBuf);  
     /* 顯示灌注指數 */
     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. 檢測信號有效性(通過灌注指數判斷) */
     if (perfusionIndex > 1) {
       signalStatus = 1;
       noSignalTime = HAL_GetTick();
     } else {    if (signalStatus) {
         signalStatus = 0;
         noSignalTime = HAL_GetTick();
       }
     }  
     /* 2. 無信號超過20秒則關機 */
     if (!signalStatus && HAL_GetTick() - noSignalTime > 20000) {    /* 關閉外設,進入待機模式 */
       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();    
       /* 進入低功耗模式 */
       HAL_PWR_EnterSTANDBYMode();
     }
    }
    • 應用場景:支持手持、桌面等多場景使用,自動適配顯示方向。

    功能協同與臨床價值示意圖


    典型應用案例

    • 秦皇島康泰醫學:采用 STM32F101C6T6 方案,結合 LIS33DE 與 M25P80 Flash,實現 24 小時連續監測,數據可通過 USB 導出至醫院 HIS 系統;

    • 北京超思電子:在遠程血氧監護儀中加入 4G 通信模塊,當 SpO2<90% 且持續 5 分鐘時,自動向家屬手機推送報警信息,結合歷史數據存儲功能,支持醫生遠程調閱趨勢圖。

    技術對比表(STM32 方案 vs 傳統方案)

    功能點

    STM32 方案優勢

    傳統方案局限

    弱信號處理

    自適應增益 + 小波去噪,PI≤0.3% 可用

    PI<1% 時測量失效

    數據存儲

    16Mbit Flash 支持 7 天連續記錄

    僅保存最近 200 條記錄

    屏幕旋轉

    實時姿態檢測,用戶體驗更友好

    固定方向顯示,視角受限

    功耗控制

    STANDBY 模式 < 10μA,續航≥15 小時

    待機功耗 > 50μA,續航 < 8 小時



    關鍵詞: STM32

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 青阳县| 岐山县| 景泰县| 秦皇岛市| 永春县| 乌拉特中旗| 西藏| 海南省| 神农架林区| 稷山县| 唐河县| 泗洪县| 鲁山县| 永川市| 南投市| 温州市| 福海县| 克拉玛依市| 班玛县| 松潘县| 金华市| 凉城县| 扶绥县| 大理市| 建平县| 且末县| 闻喜县| 大理市| 定边县| 平果县| 伽师县| 崇左市| 桂平市| 右玉县| 开平市| 瑞金市| 延边| 横山县| 库尔勒市| 太保市| 墨脱县|