STM32控制脉搏血氧心率MAX30102模块程序(I2C)

一. 简介

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

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

//max30102.c

#include "max30102.h"

#include "i2c.h"

uint8_t max30102_Bus_Write(uint8_t Register_Address, uint8_t 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;

}

 

 

 

uint8_t max30102_Bus_Read(uint8_t Register_Address)

{

 uint8_t 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(0); /* 读1个字节 */

 

  i2c_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */

 }

 /* 发送I2C总线停止信号 */

 i2c_Stop();

 return data; /* 执行成功 返回data值 */

 

cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */

 /* 发送I2C总线停止信号 */

 i2c_Stop();

 return 0;

}

 

 

void max30102_FIFO_ReadWords(uint8_t Register_Address,uint16_t Word_Data[][2],uint8_t count)

{

 uint8_t i=0;

 uint8_t no = count;

 uint8_t data1;

 uint8_t 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(0); 

  i2c_Ack();

  data2 = i2c_ReadByte(0);

  i2c_Ack();

  Word_Data[i][0] = (((uint16_t)data1 << 8) | data2); //

 

  

  data1 = i2c_ReadByte(0); 

  i2c_Ack();

  data2 = i2c_ReadByte(0);

  if(1==no)

   i2c_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */

  else

   i2c_Ack();

  Word_Data[i][1] = (((uint16_t)data1 << 8) | data2); 

 

  no--; 

  i++;

 }

 /* 发送I2C总线停止信号 */

 i2c_Stop();

 

cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */

 /* 发送I2C总线停止信号 */

 i2c_Stop();

}

 

void max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data)

 max30102_Bus_Read(REG_INTR_STATUS_1);

 max30102_Bus_Read(REG_INTR_STATUS_2);

 

 /* 第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[0] = i2c_ReadByte(1); 

 Data[1] = i2c_ReadByte(1); 

 Data[2] = i2c_ReadByte(1); 

 Data[3] = i2c_ReadByte(1);

 Data[4] = i2c_ReadByte(1); 

 Data[5] = i2c_ReadByte(0);

 /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */

 /* 发送I2C总线停止信号 */

 i2c_Stop();

 

cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */

 /* 发送I2C总线停止信号 */

 i2c_Stop();

 

}

 

void max30102_init(void)

{

 GPIO_InitTypeDef GPIO_InitStructure;

 

  __HAL_RCC_GPIOB_CLK_ENABLE();

 GPIO_InitStructure.Pin = GPIO_PIN_14;

 GPIO_InitStructure.Mode = GPIO_MODE_INPUT;

 HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);

 

 i2c_GPIO_Config();

 

 max30102_reset();

  

 max30102_Bus_Write(REG_INTR_ENABLE_1,0xc0); // INTR setting

 max30102_Bus_Write(REG_INTR_ENABLE_2,0x00);

 max30102_Bus_Write(REG_FIFO_WR_PTR,0x00); //FIFO_WR_PTR[4:0]

 max30102_Bus_Write(REG_OVF_COUNTER,0x00); //OVF_COUNTER[4:0]

 max30102_Bus_Write(REG_FIFO_RD_PTR,0x00); //FIFO_RD_PTR[4:0]

 max30102_Bus_Write(REG_FIFO_CONFIG,0x0f); //sample avg = 1, fifo rollover=false, fifo almost full = 17

 max30102_Bus_Write(REG_MODE_CONFIG,0x03); //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED

 max30102_Bus_Write(REG_SPO2_CONFIG,0x27); // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)  

 max30102_Bus_Write(REG_LED1_PA,0x24); //Choose value for ~ 7mA for LED1

 max30102_Bus_Write(REG_LED2_PA,0x24); // Choose value for ~ 7mA for LED2

 max30102_Bus_Write(REG_PILOT_PA,0x7f); // Choose value for ~ 25mA for Pilot LED

 

 

 

           

}

 

void max30102_reset(void)

{

 max30102_Bus_Write(REG_MODE_CONFIG,0x40);

 max30102_Bus_Write(REG_MODE_CONFIG,0x40);

}

 

 

 

 

 

 

void maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)

{

 IIC_Write_One_Byte(I2C_WRITE_ADDR,uch_addr,uch_data);

}

 

void maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)

{

 IIC_Read_One_Byte(I2C_WRITE_ADDR,uch_addr,puch_data);

}

 

void maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)

{

 uint32_t un_temp;

 unsigned char uch_temp;

 char ach_i2c_data[6];

 *pun_red_led=0;

 *pun_ir_led=0;

 

  

  maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);

  maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);

  

  IIC_ReadBytes(I2C_WRITE_ADDR,REG_FIFO_DATA,(uint8_t *)ach_i2c_data,6);

  

  un_temp=(unsigned char) ach_i2c_data[0];

  un_temp<<=16;

  *pun_red_led+=un_temp;

  un_temp=(unsigned char) ach_i2c_data[1];

  un_temp<<=8;

  *pun_red_led+=un_temp;

  un_temp=(unsigned char) ach_i2c_data[2];

  *pun_red_led+=un_temp;

  

  un_temp=(unsigned char) ach_i2c_data[3];

  un_temp<<=16;

  *pun_ir_led+=un_temp;

  un_temp=(unsigned char) ach_i2c_data[4];

  un_temp<<=8;

  *pun_ir_led+=un_temp;

  un_temp=(unsigned char) ach_i2c_data[5];

  *pun_ir_led+=un_temp;

  *pun_red_led&=0x03FFFF; //Mask MSB [23:18]

  *pun_ir_led&=0x03FFFF; //Mask MSB [23:18]

}

//max30102.h

#define MAX30102_INT HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14)

#define I2C_WR    0        /* д¿ØÖÆbit */
#define I2C_RD    1        /* ¶Á¿ØÖÆbit */

#define max30102_WR_address 0xAE

#define I2C_WRITE_ADDR 0xAE
#define I2C_READ_ADDR 0xAF

//register addresses
#define REG_INTR_STATUS_1 0x00
#define REG_INTR_STATUS_2 0x01
#define REG_INTR_ENABLE_1 0x02
#define REG_INTR_ENABLE_2 0x03
#define REG_FIFO_WR_PTR 0x04
#define REG_OVF_COUNTER 0x05
#define REG_FIFO_RD_PTR 0x06
#define REG_FIFO_DATA 0x07
#define REG_FIFO_CONFIG 0x08
#define REG_MODE_CONFIG 0x09
#define REG_SPO2_CONFIG 0x0A
#define REG_LED1_PA 0x0C
#define REG_LED2_PA 0x0D
#define REG_PILOT_PA 0x10
#define REG_MULTI_LED_CTRL1 0x11
#define REG_MULTI_LED_CTRL2 0x12
#define REG_TEMP_INTR 0x1F
#define REG_TEMP_FRAC 0x20
#define REG_TEMP_CONFIG 0x21
#define REG_PROX_INT_THRESH 0x30
#define REG_REV_ID 0xFE
#define REG_PART_ID 0xFF

max30102.h加上i2c及相关函数定义即可调用

  • 4
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式冰箱

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值