组成
有两个发光二极管,一个光检测器,优化光学和低噪声的仿真信号处理,以检测脉搏血氧饱和度和心脏速率信号。
工作原理
只需要将手指头紧贴在传感器上,就能估计 脉搏血氧饱和度(SpO2)及脉搏(相当于心跳)。
携带氧气的红血球能吸收较多红外光(850-1000nm),未携带氧气的红血球则是吸收较多的红光(600-750nm),
因此pulse oximeter就是一个迷你的分光计,利用不同红血球之吸收光谱的原理,来分析血氧饱和度。
这种实时而快速的测量方式,也广泛被运用在许多临床的参考
如何使用
这个好像可以使用模拟IIC来读取数据,那如何连接引脚
引脚连接
给了51的代码,但是用的是STM32,还是HAL库,不能直接用的,还是得自己写,不过可以知道引脚是怎么连的// 1:VCC --〉 1.8V-5.5V电源 // 2:SCL --〉 P3.5// 3:SDA --〉 P3.7// 4:INT --〉 NC// 5:IRD --〉 NC// 6:RD --〉 NC //NC指的是不连接,不用接地也不用去管,可能有内部连接// 7:GND --〉 地对应的IIC接口//定义IIC接口sbit IIC_SCL =P3^5; //IIC的SCLsbit IIC_SDA =P3^7; //IIC的SDAbit IIC_ACK; //IIC的ACKint rda; //IIC读出这样看用四根线就可以了,分别是VCC,GND和IIC用的SCL和SDA
IIC工作原理简单介绍
串行总线一个数据线SDA一个时钟线SCL
I2C总线通过上拉电阻接正电源总线空闲时,两根线都是高电平当总线上的任一器件输出的低电平,都将使总线的信号变低,成线"与"关系I2C有三种状态信号:开始信号、结束信号和应答信号开始信号:SCL为高电平时,SDA由高电平转变为低电平跳变,表示开始通信。结束信号:SCL为高电平时,SDA由低电平转变为高电平跳变,结束结束通信。应答信号:接收数据的IC在接收到一个字节数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。
在数据传输过程中,SCL时钟为主设备控制,SCL为高的时候读取数据SDA的数据,SCL为低的时候,主设备改变SDA的数据准备传输下一位。数据从高位开始传输,当传输8位后,主设备会释放SDA总线。如果从设备正确接收到数据,则从设备会拉低SDA总线,则产生一个应答信号。如果从设备出错,不拉低SDA总线,由于上拉电阻的作用,SDA的电平会变为高电平,即为非应答信号。
数据传输总是以开始信号开始传输,以结束信号终止传输,中间可以传输多个字节的数据。
IIC操作寄存器步骤
读寄存器操作1) 发送起始信号2) 发送 I2C 写器件地址3) 等待应答4) 发送 I2C 要读的寄存器地址5) 等待应答6) 发送起始信号7) 发送 I2C 读器件地址8) 等待应答9) 接收返回数据10) 发送结束信号
读寄存器操作代码实现IIC_Start();IIC_SendData(ADX345_ADDR); //24C02дµØÖ·if(IIC_WaitAck()){return 0xFF;}IIC_SendData(0x32); //·¢ËͶÁµØÖ·£¨XÖáÊ×µØÖ·£©if(IIC_WaitAck()){return 0xFF;}IIC_Start();IIC_SendData(ADX345_ADDR + 1); //24C02¶ÁµØÖ·if(IIC_WaitAck()){return 0xFF; }/* ¶ÁÈ¡Áù¸ö×Ö½ÚÊý¾Ý */for(i=0; i<6; i++){if(i == 5) //½ÓÊÕ×îºóÒ»¸ö×Ö½Úʱ£¬·¢ËÍNACK{readValue[i] = IIC_ReceiveData(0);}else //·¢ËͽÓÊÕºóÓ¦´ð{readValue[i] = IIC_ReceiveData(1); }}IIC_Stop();
详细解释IIC_WaitAck() 等待应答函数其实就是控制IIC上SDA和SCL两条线上高低电平的变化那么如何控制?#define IIC_SDA_SET {GPIOB->BSRR = 1 << 11;}#define IIC_SDA_CLR {GPIOB->BRR = 1 << 11;}#define IIC_SCL_SET {GPIOB->BSRR = 1 << 10;}#define IIC_SCL_CLR {GPIOB->BRR = 1 << 10;}IIC_ReceiveData IIC接收一个8位数据,但是有参数,那参数是什么意思呢?参数为0,不应答参数为1,应答那怎么应答呢?应答函数static void IIC_SendAck(void){ IIC_SCL_CLR;IIC_SDA_OUT();IIC_SDA_CLR;HAL_Delay(2/1000);//IIC_DelayUs(2);IIC_SCL_SET;HAL_Delay(2/1000);//IIC_DelayUs(2);IIC_SCL_CLR; }不应答函数static void IIC_NoAck(void){ IIC_SCL_CLR;IIC_SDA_OUT();IIC_SDA_SET;HAL_Delay(2/1000);//IIC_DelayUs(2);IIC_SCL_SET;HAL_Delay(2/1000);//IIC_DelayUs(2);IIC_SCL_CLR; }两个函数的区别就在于在IIC_SDA_OUT();之后,应答要IIC_SDA_CLR;,不应答要IIC_SDA_SET;写寄存器操作1) 发送起始信号2) 发送 I2C 写器件地址3) 等待应答4) 发送要写入的寄存器地址5) 等待应答6) 发送要写入的数据7) 等待应答8) 发送结束信号
好像就是使用了发送输出函数和在初始化函数中涉及到了IIC操作
基本流程是使用IIC来读出数据,好像MAX30100采集到的不同数据放到了不同的寄存器里面,得知道哪个寄存器放了什么?
这样就可以根据寄存器中的数据进行计算了,因为给出的51样例只给出了一个放温度的寄存器的地址
那么怎么知道其他有用的数据放到哪个寄存器呢?怎么使用这些数据得出心率和血氧呢?
The MAX30100 is fully configurable through software registers, and the digital output data is stored in a 16-deep FIFO within the device. The FIFO allows the MAX30100 to be connected to a microcontroller or microprocessor on a shared bus, where the data is not being read continuously from the device’s registers.数字输出数据放到了一个16个深度(表示可以放16个血氧饱和度通道数据样品)的先进先出队列里,这个先进先出的方式允许了MAX30100在总线上和MCU连接,而且数据不会被从寄存器连续读取(这个结合IIC的操作寄存器的方式可以理解)
一般示例代码中都是把温度读了出来,那么这个温度有什么用呢?
The SpO2 algorithm is relatively insensitive to the wavelength of the IR LED, but the red LED’s wavelength is critical to correct interpretation of the data. The temperature sensor data can be used to compensate the SpO2 error with ambient temperature changes血氧饱和度算法对 IR LED不敏感,但是red LED对正确获取数据很关键,温度传感器数据可以用来矫正由于环境温度变化产生的误差。
那怎么知道那个寄存器中放着什么数据呢?
给出的MAX301002的读取温度的示例 temp_num = max30102_Bus_Read(0x1f); 寄存器地址是0x1f,查看MAX301002的数据手册,其实有一个表记录了每个寄存器的作用和地址,如下图
红色方框中就是存储温度的寄存器,其地址为0x1F这样的话,对于MAX30100,那么其温度寄存器的地址也可以确定了
现在的问题就是从寄存器里面读出数据然后计算了
创建工程实现读取寄存器数据计算心率血氧
主要文件是模拟IIC,使用IIC读取特定寄存器中的数据进行处理就可以获得心率血氧。
先写模拟IIC的文件,能实现IIC初始化,开始结束,读取和写入以及发送应答信号的功能。
使用STM32CUBEMX配置IIC是需要配置clock speed,有两种模式,最快的模式为400KHZ,但在实际使用中需要自己写模拟IIC文件,也用不到这个IIC,所以可以不用配置
上面是使用软件模拟IIC,但是HAL库本身就是提供了IIC操作函数的,而且是硬件IIC,可以使用HAL库的IIC方法,操作应该会更简单。
【注意】
SCL和SDA加上拉电阻的问题逛论坛的时候说SCL和SDA要加4.7k的上拉电阻,datasheet上也说要加,看了看原理图,SCL和SDA都加了一个472贴片电阻,这个472指的是47*10^2,正好是4.7k的电阻,所以不用担心烧坏了。