第一章:血氧仪系统架构概述
大家好,我是老张。做血氧仪开发有些年头了。今天咱们聊聊系统架构。
很多人一上来就盯着算法,或者纠结传感器选型。其实,先把整个链路理清楚,后面会省很多事。我个人习惯,拿到项目先画一张大图——从手指头到屏幕,信号是怎么走的。
1.1 完整信号链路:从指尖到屏幕
血氧仪的核心原理,说白了就是光学测量。你想想看,手指里动脉血和静脉血对红光和红外光的吸收率不一样。我们通过这个差异,算出SpO2值。
信号链路大致分四段:
- 光电转换:LED发光穿过手指,被光电二极管接收。光信号变成微弱的电流信号。
- 模拟前端调理:电流转电压,放大,滤波。去掉噪声,把信号拉到ADC能采样的范围。
- 模数转换与数字处理:ADC采样,然后做数字滤波、去基线漂移、提取脉搏波。
- 算法计算与显示:根据红光和红外光的交流分量比值,算出血氧饱和度。最后驱动OLED或LCD显示。
嗯,这里要注意:每一级都会引入误差。我在项目中遇到过,模拟前端的地没处理好,导致整个波形都是毛刺,算法根本算不准。
关键点:信号链路的信噪比,决定了血氧仪的精度下限。别指望算法能弥补硬件上的缺陷。
1.2 硬件模块划分
硬件上,我习惯把血氧仪拆成这几个模块。你照着这个思路去设计,不容易漏东西。
| 模块 | 核心器件 | 我的经验 |
|---|---|---|
| 传感器驱动 | 红光LED(660nm)、红外LED(940nm)、光电二极管 | LED的驱动电流要精确控制,我曾经因为电阻选错,导致光强不够,信号弱得可怜。 |
| 模拟前端(AFE) | 跨阻放大器、可编程增益放大器、低通滤波器 | AFE芯片的布局要远离数字电路。我吃过亏,数字噪声串进来,波形上全是毛刺。 |
| 主控MCU | ARM Cortex-M0/M4,带ADC和DMA | 建议选带硬件I2C和SPI的,省事。ADC采样率至少100Hz,否则脉搏波细节抓不住。 |
| 电源管理 | 锂电池、升压芯片、LDO | 血氧仪对电源纹波敏感。我习惯在AFE供电前加一级LC滤波。 |
| 显示与交互 | OLED屏、按键、蜂鸣器 | OLED刷新率别太高,否则功耗扛不住。我一般控制在30Hz。 |
避坑指南:我曾经在AFE和MCU之间用了长排线,结果信号串扰得一塌糊涂。后来改成短走线+屏蔽罩,问题才解决。布局时,模拟地和数字地要单点连接。
1.3 软件任务分解
软件这块,我习惯按实时性要求来分任务。说白了,就是哪些事必须马上做,哪些可以等等再做。
1.3.1 高实时性任务(中断级)
- ADC采样与DMA传输:定时器触发ADC,DMA自动把数据搬到内存。CPU几乎不花时间。
- LED时序控制:红光和红外LED要分时点亮,不能同时亮。我一般用定时器中断来切换。
- 按键消抖:用定时器中断做10ms消抖,别在主循环里傻等。
1.3.2 中等实时性任务(主循环或RTOS任务)
- 数字滤波与波形提取:IIR高通滤波器去掉直流分量,提取脉搏波。这个计算量不大,但每来一个采样点都要算。
- 心率计算:通过脉搏波峰值间隔算心率。我习惯用滑动窗口,窗口长度2秒。
- 血氧算法:计算红光和红外光的AC/DC比值,查表或公式算出SpO2。
1.3.3 低实时性任务(后台处理)
- 显示刷新:每秒更新30次就够了。别跟ADC抢CPU。
- 数据存储与通信:如果需要记录历史数据,或者通过蓝牙上传,放后台慢慢做。
- 低功耗管理:检测到手指离开,进入休眠模式。我一般用定时器唤醒,每100ms检查一次。
警告:千万别在ADC中断里做血氧算法!中断服务程序要短平快。我曾经犯过这个错,导致中断嵌套,采样数据丢失。算法放主循环或低优先级任务里跑。
1.4 一个典型的软件流程图
我画个伪代码,你感受一下整体流程:
// 伪代码:血氧仪主循环
void main() {
init_hardware(); // 初始化时钟、GPIO、ADC、DMA
init_algorithm(); // 初始化滤波器系数、血氧查找表
while(1) {
// 1. 检查是否有新采样数据(由DMA中断设置标志)
if (new_sample_ready) {
process_digital_filter(); // 高通+低通滤波
extract_pleth_waveform(); // 提取脉搏波
calculate_hr(); // 计算心率
calculate_spo2(); // 计算血氧
new_sample_ready = 0;
}
// 2. 更新显示(每33ms一次)
if (display_tick) {
update_oled_screen();
display_tick = 0;
}
// 3. 处理按键和低功耗
handle_key_press();
check_power_management();
// 4. 进入休眠(等待中断唤醒)
enter_sleep_mode();
}
}
你看,这个结构很清晰。ADC采样靠DMA,不占CPU。主循环只做滤波和计算。显示和按键都是定时轮询。功耗也能控制住。
1.5 总结一下
系统架构这东西,说白了就是分而治之。硬件上把模拟和数字分开,软件上把实时和非实时分开。你照着这个思路去搭框架,后面调试会轻松很多。
我记得第一次做血氧仪时,没注意模拟前端的地回路,结果波形上全是50Hz工频干扰。后来花了两天时间重新布线,才把问题搞定。嗯,这些坑,后面章节我会一个个细讲。
下一章,咱们聊聊模拟前端的调试技巧。那个环节最容易出问题,也最考验耐心。