血氧饱和度传感器MAX30102模块的原理及参数

描述

一. 简介

MAX30102是一个集成的脉搏血氧仪和心率监测仪生物传感器的模块(芯片)。 它集成了一个660nm红光LED、880nm红外光LED、光电检测器、光器件,以及带环境光抑制的低噪声电子威廉希尔官方网站 。 可通过软件关断模块,待机电流为零,实现电源始终维持供电状态,可运用于低功耗产品中。

MAX30102采用一个1.8V电源和一个独立的3.3V用于内部LED的电源,标准的I2C兼容的通信接口。 市面很多都将MAX30102芯片集成在一个PCB模块上,内部增加一个1.8V和3.3V LDO稳压威廉希尔官方网站 ,可对模块单独供5.0V电源,方便开发者进行开发。

二. MAX30102原理及参数

1. 芯片内部框图

模块

从框图看,芯片可分为两部分,一部分为模拟信号采集威廉希尔官方网站 ,通过RED和IR灯发出特定波长的光,采集人体反射回来的光,经过PD管将光信号转化为电信号,最终通过18bit ADC转换器转化为数字信号。

第二部分为数字处理威廉希尔官方网站 ,将ADC转换出来的原始数据进行滤波处理后放置于缓冲区内; 单片机通过IIC接口读写芯片内部寄存器,读取出相应的数据;

2. 模块威廉希尔官方网站

模块

芯片内部有3.3V-5.0V的LED电源和1.8V的逻辑电源,所以模块带有两路稳压威廉希尔官方网站 ,将5V电源分别转化为3.3V和1.8V;由于LED驱动电源的供电范围为3.3V-5.0V,3.3V稳压威廉希尔官方网站 可省去。

由于MAX30102的逻辑威廉希尔官方网站 的IIC通信电平为1.8V,这与我们常用的51单片机和STM32单片机的引脚电平不匹配。

这里有个解决方法,因为MAX30102的SDA、SCL、INT引脚为开漏,

模块

可以将模块上的R1、R2、R3电阻去掉,对于51单片机来说,在SDA、SCL、INT引脚上分别加一个4.7-10k电阻上拉至5V;对于STM32单片机,只需要将相应的控制引脚配置为上拉模式即可。

模块只需要接上5V电源,SDA、SCL、INT引脚与单片机连接即可; IRD、RD一般不接,以STM32单片机接线为例(单片机采用模拟IIC的控制方式),如图:

模块

三. MAX30102编程

MAX30102内部集成了一整套完整信号采集威廉希尔官方网站 ,包括光信号发射及接收、AD转换、环境光干扰消除及数字滤波部分,只将数字接口留给用户。 用户只需通过单片机的IIC接口(可用模拟IIC),对MAX30102内部的寄存器进行读写操作,就可以得到转换后的光强度数值。 最后需要通过相应的处理算法计算出心率值和血氧饱和度。

对于MAX30102的驱动程序,将其拆分出来,可分为标准IIC程序和MAX30102寄存器的读写操作,实现这两部分的编程,便完成MAX30102的驱动; 由于IIC程序比较常用,这里就不例举出来。 在完成IIC的通信程序后,实现以下程序;

(1)MAX30102写寄存器函数

u8 max30102_Bus_Write(u8 Register_Address, u8 Word_Data)
{
  /* 采用串行EEPROM随即读取指令序列,连续读取若干字节 */
  /* 第1步:发起I2C总线启动信号 */
  i2c_Start();
  /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  i2c_SendByte(max30102_WR_address | I2C_WR);/* 此处是写指令 */
  /* 第3步:发送ACK */
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第4步:发送字节地址 */
  i2c_SendByte(Register_Address);
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第5步:开始写入数据 */
  i2c_SendByte(Word_Data);
/* 第6步:发送ACK */
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 发送I2C总线停止信号 */
  i2c_Stop();
  return 1;/* 执行成功 */
   cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
  i2c_Stop();
  return 0;
}

(2)MAX30102读寄存器函数

u8 max30102_Bus_Read(u8 Register_Address)
{
  u8  data;
/* 第1步:发起I2C总线启动信号 */
  i2c_Start();
/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  i2c_SendByte(max30102_WR_address | I2C_WR);/* 此处是写指令 */
/* 第3步:发送ACK */
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第4步:发送字节地址, */
  i2c_SendByte((uint8_t)Register_Address);
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第6步:重新启动I2C总线。下面开始读取数据 */
  i2c_Start();
/* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  i2c_SendByte(max30102_WR_address | I2C_RD);/* 此处是读指令 */
/* 第8步:发送ACK */
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第9步:读取数据 */
  {
    data = i2c_ReadByte();/* 读1个字节 */
    i2c_NAck();/* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
  }
/* 发送I2C总线停止信号 */
  i2c_Stop();
  return data;/* 执行成功 返回data值 */
  cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
  i2c_Stop();
  return 0;
}

(3)MAX30102读缓冲器FIFO

void max30102_FIFO_Read(u8 Register_Address,u16  Word_Data[][2],u8 count)
{
  u8 i=0;
  u8 no = count;
  u8 data1, data2;
/* 第1步:发起I2C总线启动信号 */
  i2c_Start();
/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  i2c_SendByte(max30102_WR_address | I2C_WR);/* 此处是写指令 */
/* 第3步:发送ACK */
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第4步:发送字节地址, */
  i2c_SendByte((uint8_t)Register_Address);
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第6步:重新启动I2C总线。下面开始读取数据 */
  i2c_Start();
/* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  i2c_SendByte(max30102_WR_address | I2C_RD);/* 此处是读指令 */
/* 第8步:发送ACK */
  if (i2c_WaitAck() != 0)
  {
    goto cmd_fail;/* EEPROM器件无应答 */
  }
/* 第9步:读取数据 */
  while (no)
  {  
    data1 = i2c_ReadByte();
    i2c_Ack();
    data2 = i2c_ReadByte();
    i2c_Ack();
    Word_Data[i][0] = (((u16)data1 << 8) | data2);  //
    data1 = i2c_ReadByte();
    i2c_Ack();
    data2 = i2c_ReadByte();
    if(1==no)
      i2c_NAck();/* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
    else
      i2c_Ack();
     Word_Data[i][1] = (((u16)data1 << 8) | data2);
    no--;
    i++;
  }
/* 发送I2C总线停止信号 */
  i2c_Stop();
  cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
  i2c_Stop();
}

(4)MAX30102初始化(可根据自己的实际情况更改相应的配置)

void max30102_init()
{
  max30102_Bus_Write(0x09, 0x0b);  //mode configuration : temp_en[3]      MODE[2:0]=010 HR only enabled    011 SP02 enabled
  max30102_Bus_Write(0x01, 0xF0); //open all of interrupt
  max30102_Bus_Write(INTERRUPT_REG, 0x00); //all interrupt clear
  max30102_Bus_Write(0x03, 0x02); //DIE_TEMP_RDY_EN
  max30102_Bus_Write(0x21, 0x01); //SET   TEMP_EN
  max30102_Bus_Write(0x0a, 0x47); //SPO2_SR[4:2]=001  100 per second    LED_PW[1:0]=11  16BITS
  max30102_Bus_Write(0x0c, 0x47);
  max30102_Bus_Write(0x0d, 0x47);
}

(5)数据采集

此程序只演示读取出温度,读取血氧数据需要通过max30102_FIFO_Read函数读出;

int main(void)
{
  u8 temp_num=0;
  main_init();
  max30102_init();
  printf("\\r\\n MAX30102  init  \\r\\n");
  while(1)
  {
    delay_ms(1000);            
    max30102_init();
    temp_num = max30102_Bus_Read(0x1f);
    printf("当前温度 = %d\\r\\n",temp_num);
  }
}
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分