#include "Blood_OxygenDetection.h" #ifdef _WIN64 #define MATLAB_PLOT (1) uint8_t spo2_plot_flag = 0; #include <cstdlib> #include <string> #include <iomanip> #include <fstream> using namespace std; #include "plot_bymatlab.h" #include <iomanip> #include <cstdio> #include <iostream> #endif // _WIN64 #define RED_IRD_SIGNAL_LEN ( 125 ) #define SPO2_SIGNAL_SAMPLE ( 25 ) #define SPO2_SIG_SEC ( RED_IRD_SIGNAL_LEN / SPO2_SIGNAL_SAMPLE ) #define SIG_MAP_TH ( 10 ) #define SIG_SATURATION ( 65000 ) #define SPO2_FILTER_LEN ( 7 ) #define SPO2_RATE_ARR_LEN ( 10 ) #define SPO2_AC_RATE_LEN ( 10 ) #define SPO2_RATE_COMPENSATE1 ( 50 ) //对应血氧值100 #define SPO2_RATE_COMPENSATE2 ( 56 ) //对应血氧值99 int64_t oxy_band_bz[SPO2_FILTER_LEN] = { 1809, 0, -5430, 0, 5429, 0, -1810 }; int64_t oxy_band_az[SPO2_FILTER_LEN] = { 100000, -452867, 873235, -923467, 567242, -191903, 27805 }; int64_t oxy_band_zi[SPO2_FILTER_LEN - 1] = { -6253,13873,-19506,21536,-9103 - 574 }; //int64_t oxy_band_bz[SPO2_FILTER_LEN] = { 1462 ,0, -4388, 0 , 4387 , 0 ,-1463 }; //int64_t oxy_band_az[SPO2_FILTER_LEN] = { 100000 ,- 452947, 881212, -946581 , 593706, -206172, 30917 }; //int64_t oxy_band_zi[SPO2_FILTER_LEN - 1] = { -2944 , 3766 ,-4901 , 9123 ,-4060 ,-1005 }; uint8_t spo2_res_arr_check[20] = { 0 }; bod_result_info_t bod_info_s = { 0 }; uint8_t spo2_cnt = 0; uint8_t spo2_calc_cnt = 0; uint8_t spo2_res_mark = 0; int32_t change_rate_value = 0; uint8_t spo2_res_wave_flag[2] = { 0,0 }; uint8_t kalman_last_data = 0; uint8_t spo2_smooth_temp[3] = { 0,0,0 }; uint8_t spo2_real_value_cnt = 0; int32_t spo2_rate_arr[SPO2_RATE_ARR_LEN] = { 0 }; int32_t last_spo2_rate = 0; uint8_t last_spo2_out = 0; uint8_t spo2_rate_std_30_cnt = 0; int32_t spo2_ac_rate_arr[SPO2_AC_RATE_LEN] = { 0 }; int32_t spo2_ac_mean_arr[SPO2_AC_RAT
时间: 2025-07-08 16:32:57 浏览: 20
<think>好的,用户想了解血氧检测的C++代码实现细节。首先,我需要回忆血氧检测的基本原理。血氧饱和度(SpO2)通常通过光电传感器测量红光和红外光的吸收变化来计算。PPG信号处理是关键,包括滤波、峰值检测和计算比值R,然后用经验公式得到SpO2值。
接下来,用户可能需要具体的代码结构。我应该分模块说明,比如数据采集、信号处理、计算和输出。数据采集部分可能需要模拟或读取传感器数据。信号处理涉及带通滤波和寻峰算法。计算R值和SpO2需要公式转换,注意经验系数。输出部分要显示结果。
然后,要考虑代码示例的简洁性和可读性。使用C++的vector来处理数据流,带通滤波可以用简单的移动平均或IIR/FIR实现。寻峰算法可能需要滑动窗口检测局部最大值。R值的计算是红光和红外的AC/DC分量比值,这里可能需要模拟数据或注释说明实际数据来源。
用户可能遇到的问题包括信号噪声处理、算法优化和传感器校准。所以,在相关问题上可以提出这些点,比如降噪方法、动态阈值调整、嵌入式优化等。
还要注意引用格式,但用户提供的引用似乎没有具体来源,可能需要提示查阅文献或传感器手册。最后,确保代码符合C++标准,避免复杂依赖,适合嵌入式系统应用。</think>以下为血氧检测的C++实现核心逻辑与技术细节:
### 一、实现原理
血氧检测基于光电容积脉搏波(PPG)技术,通过红光(660nm)和红外光(940nm)的吸收差异计算血氧饱和度。核心公式:
$$ SpO_2 = A - B \times R $$
其中$R = \frac{(AC_{red}/DC_{red})}{(AC_{ir}/DC_{ir})}$,A/B为经验系数[^1]
### 二、代码结构
```cpp
#include <vector>
#include <algorithm>
class BloodOxygenDetector {
private:
std::vector<float> red_buffer; // 红光信号缓存
std::vector<float> ir_buffer; // 红外信号缓存
const int SAMPLE_RATE = 25; // 典型采样率25Hz
// 带通滤波(0.5Hz-5Hz)
std::vector<float> bandpass_filter(const std::vector<float>& data) {
// 实现IIR/FIR滤波器
return filtered_data;
}
// 寻峰算法
int find_peaks(const std::vector<float>& data) {
// 滑动窗口检测局部极大值
return peak_count;
}
public:
float calculate_spo2() {
// 1. 信号预处理
auto filtered_red = bandpass_filter(red_buffer);
auto filtered_ir = bandpass_filter(ir_buffer);
// 2. 计算AC/DC成分
float red_ac = *max_element(filtered_red.begin(), filtered_red.end());
float red_dc = std::accumulate(red_buffer.begin(), red_buffer.end(), 0.0f) / red_buffer.size();
float ir_ac = *max_element(filtered_ir.begin(), filtered_ir.end());
float ir_dc = std::accumulate(ir_buffer.begin(), ir_buffer.end(), 0.0f) / ir_buffer.size();
// 3. 计算R值
float R = (red_ac/red_dc) / (ir_ac/ir_dc);
// 4. 血氧计算(经验公式)
return 110.0 - 25.0 * R; // 校准系数需实验确定
}
};
```
### 三、关键技术点
1. **信号滤波**:需消除50/60Hz工频干扰和运动伪影,常用滑动平均滤波器:
```cpp
vector<float> moving_average(const vector<float>& input, int window_size) {
vector<float> output;
for(int i=window_size; i<input.size(); ++i) {
float sum = 0.0f;
for(int j=0; j<window_size; ++j) {
sum += input[i-j];
}
output.push_back(sum/window_size);
}
return output;
}
```
2. **动态阈值调整**:根据信号质量指数(SQI)自动调整峰值检测灵敏度
3. **校准方法**:需通过临床数据建立R-SpO₂对应表,建议采集至少3组不同血氧值的数据进行线性回归
阅读全文
相关推荐














