基于CMS8S6990单芯片的血氧仪硬件设计与软件实现详解
2026/6/7 12:19:33 网站建设 项目流程

1. 项目概述:从脉搏波到血氧指夹的探索

作为一名长期泡在实验室里,跟各种生理信号采集电路打交道的人,我对脉搏波信号有着一种近乎偏执的兴趣。尤其是近红外光电容积脉搏波(PPG)信号,它就像一扇窗,能让我们无创地窥探人体内部的氧合状态。这些年,从分立元件搭建的前级放大,到高精度ADC的选型,我折腾过不少方案,深知在追求信号质量、功耗和体积平衡的路上有多“坎坷”。所以,当我在行业资讯里瞥见中微半导体(CMSemicon)推出的CMS8S6990这颗芯片时,眼睛一下子就亮了——它几乎是为“单芯片血氧仪”这个想法量身定做的。

这颗基于经典8051内核的MCU,其精妙之处在于高度集成:内部集成了两路运算放大器用于信号调理,用PWM+PGA模拟DAC来精准驱动发光管,再加上内置ADC完成采集。这意味着,过去需要一堆运放、DAC和MCU才能搭起来的系统,现在可能一颗芯片加少量外围元件就能搞定,对于开发指夹式、腕带式等便携血氧设备来说,诱惑力巨大。很幸运,我成功申请到了一块CMS8S6990的开发板,还附带了一个完整的血氧指夹样品。这第一篇评测,我就结合这个指夹方案,把硬件设计思路、软件框架,以及实际啃代码时遇到的“坑”和“雷”,给大家掰开揉碎了讲清楚。无论你是刚接触医疗电子的新手,还是正在选型的老鸟,希望这篇近万字的深度拆解能给你带来实实在在的参考。

2. 硬件系统深度拆解:如何在一颗芯片内构建血氧采集链

拿到指夹实物,第一印象就是紧凑。拆开外壳,PCB板布局非常工整,核心就是那颗CMS8S6990。它的硬件设计清晰地反映了单芯片方案的思路:最大化利用芯片内部资源,最小化外围电路。下面我们分模块来细看。

2.1 电源与按键管理电路:小巧身躯里的“电源管家”

血氧指夹通常由纽扣电池供电,对功耗和体积极其敏感。这个方案的电源电路设计得很巧妙,它实现了一个多功能按键:关机状态下短按开机,开机状态下长按关机,开机状态下短按则切换屏幕显示方向

注意:这种复合功能的单按键设计在便携设备中非常常见,但软件上需要做好按键消抖和长短按的状态机判断,否则极易误触发。

其硬件实现核心是利用单片机的两个GPIO引脚。一个引脚配置为输入,用于检测按键状态;另一个引脚配置为输出,用于控制一个PMOS(P沟道MOS管)的栅极,这个MOS管串联在系统主电源VCC的通路上。当系统需要关机时,MCU控制这个GPIO输出高电平,关闭MOS管,彻底切断后续电路的供电,实现真正的“零”待机功耗(仅保留MCU极低功耗模式的自身消耗)。开机流程则是:按键被按下,触发MCU的唤醒(如果MCU处于低功耗模式)或中断,MCU随即控制电源MOS管的GPIO输出低电平,导通MOS管,为整个系统上电。

这种设计的好处显而易见:

  1. 结构紧凑:省去了独立的电源管理芯片和复杂的机械开关。
  2. 功能丰富:单一按键实现多种操作,提升用户体验。
  3. 功耗极低:硬件断电,比软件待机更彻底。

2.2 发光管(LED)驱动电路:H桥与模拟DAC的精准共舞

血氧测量基于“郎伯-比尔定律”,需要交替发射660nm(红光)和940nm(红外光)两种波长的光穿过手指,并被另一侧的光电二极管(PD)接收。因此,如何高效、精准地驱动这两颗LED是关键。

该方案采用了经典的H桥驱动电路。具体来说,使用四个三极管(或MOSFET)组成两个桥臂,分别控制红光LED(R_LED)和红外光LED(IR_LED)。

  • 当 IR_1=1, IR_2=0 时:对应桥臂导通,电流流经R_LED,红光点亮,红外光熄灭。
  • 当 IR_1=0, IR_2=1 时:另一个桥臂导通,电流流经IR_LED,红外光点亮,红光熄灭。

这样,MCU只需两个IO口(IR_1和IR_2)就能实现两颗LED的交替点亮,非常简单高效。但更精彩的部分在于电流控制。LED的发光强度需要根据手指厚度、肤色等因素进行动态调整,以保证接收到的信号幅度在ADC的最佳量程内,既不过载也不至于信噪比太低。

CMS8S6990的方案是:使用芯片内部的一路PWM(脉冲宽度调制)输出,经过一个简单的RC低通滤波网络,将数字PWM波转换成平滑的模拟电压。这个电压再送入芯片内部的PGA(可编程增益放大器)进行放大,以提供足够的驱动能力。PGA的输出最终用于控制H桥电路中作为恒流源的三极管的基极电流,从而精确控制流过LED的电流。

实操心得:这里的PWM模拟DAC的精度和稳定性至关重要。RC网络的时间常数需要仔细计算,要确保能充分滤除PWM的开关噪声,同时响应速度又能跟上软件调节的需求。通常,PWM频率选择在几十到几百KHz,RC滤波器的截止频率应远低于PWM频率(至少1/10以下)。

2.3 信号放大与调理电路:运放的艺术与动态范围扩展

光电二极管接收到透射过来的光信号,输出的是微弱的电流信号(通常在nA到uA级)。信号调理电路的任务就是将它放大并转换为MCU的ADC可以处理的电压信号。

CMS8S6990内部集成了两路运算放大器(Op-Amp),这里被完美利用:

  1. 第一级:I-V转换(跨阻放大器)。使用内部运放0(或1,根据具体配置)搭建跨阻放大器。光电二极管并联在运放的反向输入端和输出端之间,运放的同向输入端接一个参考电压。这样,输出端电压Vout = -Ipd * RfIpd为光电二极管电流,Rf为反馈电阻),完成了电流到电压的线性转换。反馈电阻Rf的阻值决定了转换增益,需要根据信号强度选择。
  2. 第二级:可调增益放大。第一级输出的电压信号可能仍然较小,或者需要进一步调理。使用内部另一个运放搭建同相或反相放大电路,进行二级放大,将信号幅度调整到ADC输入的最佳范围(例如0-3.3V)。

动态范围调整的妙招:方案中另一个亮点是利用了另一路PWM模拟的DAC。这个DAC的输出电压被连接到第一级运放(I-V转换)的同向输入端。改变这个电压,实际上就改变了运放的“虚地”电位,从而可以整体抬升或降低输出信号的直流偏置(DC Offset)。这个功能极其重要,因为不同人的手指厚度、血管状态差异巨大,导致接收到的光信号基线(直流分量)可能相差很远。通过软件算法动态调整这个偏置电压,可以将有用的交流脉搏波信号(AC分量)“平移”到ADC量程的中央区域进行放大,极大地扩展了系统的适应范围,这就是资料中提到的“第一级运放偏置调节算法”的硬件基础。

2.4 核心控制与显示单元

控制系统就是CMS8S6990本身,电路极其简洁,几乎只需要一颗电源去耦电容,这充分体现了高集成度芯片的优势——降低BOM成本和PCB设计难度。

显示单元采用的是一块0.96英寸的OLED屏幕,通过I2C或SPI接口与MCU连接。这种屏幕自发光、对比度高、功耗低,非常适合便携式设备。驱动这类屏幕已有非常成熟的库,开发起来很方便。

3. 软件架构与流程解析:从流程图到代码骨架

官方提供的《CMS8S6990血氧仪方案V1.2》文档里有一张软件流程图,虽然比较顶层和笼统,但它清晰地勾勒出了整个系统的运行骨架。结合代码,我们可以将其具体化。

3.1 主循环与状态机

系统上电初始化后,会进入一个主循环。这个循环的核心是一个状态机,通常包含以下几个状态:

  • IDLE/待机状态:等待用户操作,处理按键事件(开机/关机/旋转屏幕)。
  • INIT/初始化状态:进行设备自检、传感器检测(是否放入手指)、参数初始化。
  • MEASURE/测量状态:这是最核心的状态,循环执行“发光-采集-计算”的流程。
  • DISPLAY/显示状态:更新血氧值(SpO2)、脉率(PR)和脉搏波形到OLED屏幕。
  • ERROR/错误状态:处理信号质量过低、传感器脱落等异常情况。

3.2 核心测量流程拆解

在MEASURE状态下,程序会以固定的频率(例如100Hz或更高)执行以下步骤,这是一个典型的时分复用驱动和采集过程:

  1. 切换LED光源:控制IR_1IR_2引脚,点亮红光LED,关闭红外LED。
  2. 设置驱动电流:通过PWM模拟DAC输出,经PGA放大后,设定红光LED的驱动电流。初始值可以是一个预设值,后续根据信号强度进行自适应调整(AGC,自动增益控制)。
  3. 延时稳定:等待一小段时间(微秒级),让LED发光稳定,光电二极管和放大电路的输出达到稳态。
  4. ADC采样:启动内置ADC,对经过两级放大后的红光通道电压信号进行连续多次采样(例如,采样10个点求平均,以抑制噪声)。
  5. 存储数据:将采样值存入红光数据缓冲区。
  6. 切换至红外光:控制IR_1IR_2引脚,关闭红光LED,点亮红外LED。
  7. 重复步骤2-5:设置红外光电流,延时,ADC采样,数据存入红外数据缓冲区。
  8. 完成一个周期:此时,我们得到了一个红光数据点和一个红外数据点。如此循环,就得到了红光和红外光的两条随时间变化的PPG波形数据。

3.3 算法处理流程

采集到原始数据后,需要在MCU中进行实时处理:

  1. 预处理:对红光和红外光原始数据序列进行数字滤波(如带通滤波器,通常通带为0.5Hz ~ 5Hz,以滤除基线漂移和高频噪声)。
  2. 特征提取:从滤波后的波形中,寻找每个脉搏波的波峰(AC最大值)和波谷(AC最小值),计算每个周期的交流分量(AC)和直流分量(DC)。
  3. 计算R值:对于一对基本同步的红光和红外光数据,计算其交流分量与直流分量的比值(AC/DC)。然后计算红光与红外光的这个比值的比值,即R = (AC_red / DC_red) / (AC_ir / DC_ir)
  4. 查表或计算SpO2:血氧饱和度SpO2R值存在经验性的负相关关系。通常采用经验公式SpO2 = A - B * R(A, B为通过实验标定得到的常数),或者使用预先存储的R-SpO2对照表进行插值查找,得到最终的血氧百分比数值。
  5. 计算脉率(PR):通过计算连续脉搏波峰之间的时间间隔,即可得到瞬时心率(脉率)。

注意事项:算法中的滤波器和参数(如A, B常数)需要经过严格的临床验证和校准。不同的传感器(LED和PD的型号、排列)、不同的测量部位(指尖、耳垂)都会影响这些参数。开发者通常需要与算法团队紧密合作,或使用经过验证的算法库。

4. 示例代码“排雷”与库函数修正实录

拿到官方示例工程,迫不及待地编译,结果迎面就是一盆冷水。下面是我在学习和编译过程中遇到的几个具体问题及解决方法,这些“坑”很可能你也会遇到。

4.1 编译错误:符号重定义

问题描述:解压工程后,使用Keil C51编译器进行编译,立即报错error C231: '_putchar' redefinition

排查过程:这个错误提示_putchar函数被重复定义了。首先查看报错指向的文件和行号。通常,_putchar是标准库中用于字符输出的函数,在很多开发环境中,需要用户自己实现(例如,重定向到串口)。在CMS8S6990的示例中,很可能在某个源文件(如uart.cmain.c)里已经实现了一个_putchar函数。

解决方案:在工程中全局搜索_putchar。果然,在main.c或某个用户文件中找到了它的定义。同时,编译器可能从自带的库文件(比如stdio.h相关的底层库)中也发现了它的声明或弱定义,导致了冲突。

  • 方法一(推荐):检查并注释掉用户文件中自定义的_putchar函数。因为对于这个血氧仪项目,很可能并不需要这个函数,它是其他示例遗留下来的。
  • 方法二:如果项目确实需要重定向printf到串口进行调试,那么应该保留用户自定义的_putchar,并检查是否有库文件被不必要地包含。可以尝试在项目设置中,取消勾选“Use MicroLIB”或调整其他库链接选项。

我采用了方法一,在代码中找到_putchar函数并将其定义部分注释掉后,编译通过。

4.2 库函数寄存器配置错误

官方提供的底层库函数(例如OPA_CMS8S6990.cPGA_CMS8S6990.c)是操作内部运放和PGA的关键,但其中存在几处笔误或配置错误。

错误1:运算放大器偏置寄存器配置错位

  • 原始错误代码:在配置运放偏置时,可能出现了类似OPnADJE = 0xaa;的语句,且注释或上下文暗示这是配置偏置调整寄存器。
  • 问题分析:查阅CMS8S6990的用户手册发现,OPnADJE寄存器(n代表运放编号0或1)是用于使能偏置调整功能的控制寄存器之一,而偏置调整的具体值应该写入另一个寄存器,例如OPnADJ
  • 修正方案:正确的操作通常是先配置偏置值,再使能调整功能。例如:
    // 假设 OffsetAdj 是计算好的偏置值 OPnADJ = OffsetAdj; // 设置偏置值 OPnADJE = 0x01; // 使能偏置调整功能
    需要根据具体寄存器的位定义来修正。

错误2:PGA控制寄存器注释与代码不匹配

  • 问题描述:在PGA_CMS8S6990.c文件中,第80行左右的注释写着配置PGACON2,但实际的代码操作的是PGACON3寄存器。
  • 修正方案:将注释修正,使其与实际代码保持一致。即,将注释// Set PGACON2修改为// Set PGACON3。注释错误虽然不影响编译和运行,但会给后续的代码阅读和维护带来困扰。

错误3:PGA调整值掩码(Msk)错误

  • 问题描述:同一文件中,第147行附近,代码中使用了PGA_PAGACON1_PGAADJ_Msk这个掩码来清除某个位域,但根据上下文和寄存器定义,这里应该是对PGACON3寄存器的PGAADJ字段进行操作。
  • 修正方案:将PGA_PAGACON1_PGAADJ_Msk修改为PGA_PAGACON3_PGAADJ_Msk。这是一个硬性错误,会导致配置无法正确生效。

错误4:函数命名笔误

  • 问题描述:某个用于使能PGA输出的函数,其名称存在拼写错误,例如void PGA_EnableOutPut(void);被写成了void PGA_EnableOutpt(void);(缺少‘u’)。
  • 修正方案:将函数名修正为void PGA_EnableOutPut(void);。同时,检查所有调用该函数的地方,确保一致。

错误5:定时器中断周期注释错误

  • 问题描述:在定时器初始化相关的代码或注释中,注明“TIMER3为1ms中断一次”,但根据定时器的时钟源和重载值计算,实际中断周期可能是2ms或其他值。
  • 修正方案:根据系统主频和定时器的配置寄存器值,重新计算中断周期。例如,若系统时钟为24MHz,定时器预分频为12,16位自动重载值为0xFC18(64536),则中断周期 T = (65536 - 64536) * (12 / 24MHz) = 1000 * 0.5us = 0.5ms。应将注释修正为实际计算结果。

实操心得:在使用厂商提供的库函数时,尤其是早期版本的库,一定要保持“怀疑精神”,关键配置最好能对照数据手册(Datasheet)或用户手册(User Manual)的寄存器描述亲自核对一遍。这些文档才是终极权威。将发现的问题反馈给原厂或社区,也是推动生态完善的好方法。

5. 方案总结与开发建议

中微半导体CMS8S6990血氧仪方案,其核心价值在于高度集成快速开发。它将信号链上的关键模拟部件(双运放、PGA)和灵活的PWM-DAC与一个增强型的8051内核MCU封装在一起,大幅简化了硬件设计。对于想要快速推出血氧监测功能的设备厂商来说,这无疑大大降低了门槛,缩短了研发周期。

优势总结

  1. BOM成本与PCB面积双降:一颗芯片替代多颗IC,外围电路极简。
  2. 信号链优化:内部运放和PGA匹配度好,噪声控制理论上优于分立方案。独特的偏置调节算法硬件支持,提升了动态范围。
  3. 开发资源丰富:基于8051内核,开发工具链成熟,工程师群体庞大。中微提供了基础的外设驱动库和示例,上手相对容易。

需要注意的方面

  1. 算法是灵魂:芯片提供了优秀的“硬件舞台”,但最终测量精度和稳定性取决于其上运行的血氧算法。这需要深厚的生物医学信号处理知识和大量的临床数据标定。对于大多数公司,自行开发算法难度大、周期长、风险高,可以考虑采购经过认证的第三方算法模块。
  2. 模拟性能的极限:虽然集成运放和ADC很方便,但其性能指标(如输入失调电压、温漂、噪声密度、ADC的ENOB等)可能与顶级的分立器件有差距。在对精度要求极高的医疗级设备中,需要仔细评估。
  3. 库函数与文档的完善度:如本文第四部分所述,早期提供的软件库可能存在一些瑕疵。开发者需要具备一定的调试和排查能力。

给开发者的建议

  • 第一步:吃透数据手册。重点关注内部运放、PGA、ADC的电气特性、寄存器配置方法,以及PWM模拟DAC的线性度和滤波设计。
  • 第二步:搭建最小信号链测试平台。先用开发板连接指夹传感器,屏蔽复杂的应用逻辑,专注于测试LED驱动、信号放大、ADC采集这一条通路是否工作正常,信号波形是否干净。
  • 第三步:验证基础算法。在PC端(如MATLAB/Python)先用采集到的真实数据验证R值计算、滤波和SpO2反演算法的可行性,再移植到MCU中。
  • 第四步:进行系统优化。包括低功耗设计(利用MCU的休眠模式)、按键防抖、显示刷新、运动伪迹识别与抑制等。
  • 第五步:严格测试与校准。在不同人群、不同生理状态下进行大量测试,必要时建立校准流程,确保产品的可靠性和一致性。

这颗芯片的出现,反映了半导体厂商对可穿戴医疗设备市场需求的快速响应。它未必适合所有高端应用场景,但对于消费级、家用级的血氧监测设备,以及需要快速集成血氧功能的复合型设备(如智能手表、健康一体机等),CMS8S6990提供了一个非常有竞争力的“交钥匙”方案原型。剩下的,就看你如何在这个坚实的硬件基础上,雕琢出稳定、可靠的软件和算法了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询