基于STM32的MAX30100心率计设计
作者:互联网
MAX30100和MAX30102是常用的测量心率的模块,MAX30100是能够读取心率、血氧的传感器,通信方式是通过IIC进行通信。其工作原理是通过红外led灯照射,能够得到心率的ADC值,通过算法处理相应的AD值得心率。
STM32使用IIC协议访问MAX30100时序如下图,此次使用STM32两个IO口模拟IIC协议,具体IO口见后续程序。
MAX30100内部功能框图如下图,由图可见,RED和IR照射然后使用ADC进行数据采集,采集后的AD值经过数字滤波器进入数据寄存器,然后使用IIC进行数据采集,在转换AD值时,也可以采集温度值(用于校正)。
MAX30100内部全部寄存器如下图,具体每位功能见数据手册(已上传)
MAX30100FIFO最大可存64B的数据,其中存储数据如下图,第一字节存储IR值高八位,第二字节存储IR值的低八位,第三字节存储RED的高八位,第四字节存储RED的第八位,第五字节存储IR的高八位,依次类推。其中,数据始终左对齐。
此次设计采用SPO2模式,即需要采集IR和RED值。以下是MAX30100在SPO2的时序图。第一步,IIC开始,设置模式。第二步,时隔29ms温度数据准备好,置相应的中断位。第三步。。。。(每一步具体描述见下图)
使用IIC访问MAX30100时,MAX30100器件地址为0XAE,写操作R/W=0,读操作R/W=1.具体格式如下图。
STM32通过IIC访问MAX30100时,向MAX30100某个寄存器写数据过程如下图。第一步IIC开始,第二步写从机地址+(R/W=0),第三步等待应答,第四步写寄存器地址,第五步等待应答,第六步写代写数据,第七步等待应答,第八步IIC停止。
STM32通过IIC访问MAX30100时,从MAX30100某个寄存器读数据过程如下图。第一步IIC开始,第二步写从机地址+(R/W=0),第三步等待应答,第四步写寄存器地址,第五步等待应答,第六步重新开始,第七步写从机地址+(R/W=1图中有误),第八步等待应答,第九步从寄存器读数据,第十步发送非应答,第十一步IIC停止。
STM32通过IIC访问MAX30100时,从MAX30100的寄存器连续读多个数据过程如下图。
MAX30100引脚连接:
SCL连接PB6, SDA连接PB7,VIN连接3.3V,共地,其它引脚可以不用连接。
代码如下:
MAX30100头文件:
#ifndef __MAX30100_H
#define __MAX30100_H
#include "stm32f10x.h"
typedef struct MAX30100_DEV
{
double temperature; //保存MAX30100内部温度
u16 ir; //保存MAX30100的IR值
u16 red; //保存MAX30100的RED值
u8 dat[4]; //暂时保存MAX30100的IR和RED值
u8 flag; //接收数据成功标志
}_MAX30100;
#define MAX30100_PORT GPIOB
#define MAX30100_INT_PIN GPIO_Pin_4
#define MAX30100_RD_PIN GPIO_Pin_2
#define MAX30100_IRD_PIN GPIO_Pin_3
#define MAX30100_INT PBin(4)
#define MAX30100_RD PBout(2)
#define MAX30100_IRD PBout(3)
//MAX30100 Slave Addr
#define Write_ADDR 0XAE
#define Read_ADDR 0XAF
#define RD 0X01
#define WR 0X00
//MAX30100内部寄存器定义
//INTERRUPT
#define Interrupt_Status 0x00//R
#define Interrupt_Enable 0x01//R/W
//FIFO ALL R/W
#define FIFO_Write_Pointer 0x02
#define FIFO_OverFlow_Counter 0x03
#define FIFO_Read_Pointer 0x04
#define FIFO_Data_Register 0x05
//CONFIGURATION ALL R/W
#define Mode_Configuration 0x06
#define SPO2_Configuration 0x07
//RESERVED 0x08 0x0A-0x15 0x8D
#define LED_Configuration 0x09
//TEMPERATURE ALL R/W
#define Temp_Integer 0x16
#define Temp_Fraction 0x17
//PART ID
#define Revision_ID 0xFE //R
#define Part_ID 0xFF //R/W //芯片ID值为0x11
#define INTERRUPT_REG_A_FULL (0X01<<7)
#define INTERRUPT_REG_TEMP_RDY (0X01<<6)
#define INTERRUPT_REG_HR_RDY (0X01<<5)
#define INTERRUPT_REG_SPO2_RDY (0X01<<4)
#define INTERRUPT_REG_PWR_RDY (0X01<<0)
#define SAMPLES_PER_SECOND 100 //检测频率
void MAX30100_Init(void);
u8 Read_Chip_ID(void);
double Read_Chip_Temp(void);
void MAX30100_Mode_Configure(void);
void MAX30100_Read_FIFO(void);
void MAX30100_INT_Init(void);
void MAX30100_Read_FIFO(void);
static void MAX30100_Write_One_Byte(u8 address,u8 saddress,u8 w_data);
static void MAX30100_Read_NumData(u8 address,u8 regaddress,u16 ir,u16 red);
#endif
IIC头文件:
```c
#ifndef __myiic_H
#define __myiic_H
#include "sys.h"
//IO方向设置
#define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
#define IIC_PORT GPIOB
#define IIC_SCL_PIN GPIO_Pin_6
#define IIC_SDA_PIN GPIO_Pin_7
//IO操作函数
#define IIC_SCL PBout(6) //SCL
#define IIC_SDA PBout(7) //SDA
#define READ_SDA PBin(7) //输入SDA
//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack); //IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
void IIC_Write_One_Byte_NData(u8 daddr,u8 regaddr);
#endif
MAX30100 .C文件部分函数:
```c
/*
* 函数名称:读MAX30100的ID号
* 参数: 无
* 返回值: ID值
*/
u8 Read_Chip_ID(void)
{
u8 dat;//IIC读出
dat=IIC_Read_One_Byte(Write_ADDR,Part_ID); // 读出芯片ID
delay_ms(100);
return dat;
}
/*
* 函数名称:读MAX30100内部FIFO数据
* 参数: 数据保存指针
* 返回值: 无
*/
void MAX30100_Read_FIFO(void)
{
uint16_t temp_num=0;
temp_num = IIC_Read_One_Byte(Write_ADDR,Interrupt_Status);
if (INTERRUPT_REG_A_FULL&temp_num)
{ MAX30100_Read_NumData(Write_ADDR,FIFO_Data_Register,_max30100.ir,_max30100.red);
}
}
IICC文件部分:
/*
* 函数名称:初始化IIC
* 参数: 无
* 返回值: 无
*/
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin =IIC_SCL_PIN|IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(IIC_PORT, &GPIO_InitStructure);
GPIO_SetBits(IIC_PORT,IIC_SCL_PIN|IIC_SDA_PIN); //PB6,PB7 输出高
}
将采集的数据通过拟合的公式计算出心率,每分钟跳动次数,正常成年人一般是60-100,心情激动的时候偏高一点。采集的数据通过TFT显示屏显示并通过串口打印出来。如下图:
器件ID:0x11(由芯片手册可得),内部温度22.14度
本人心率80几(正常)采集的时候有点小激动
下一步,通过相应的算法,将数据拟合成波形在显示屏实时显示。
标签:PIN,心率,STM32,IIC,寄存器,GPIO,MAX30100,define 来源: https://blog.csdn.net/liuxianfei0810/article/details/105243260