基于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几(正常)采集的时候有点小激动
在这里插入图片描述
下一步,通过相应的算法,将数据拟合成波形在显示屏实时显示。

发布了16 篇原创文章 · 获赞 11 · 访问量 3378

猜你喜欢

转载自blog.csdn.net/liuxianfei0810/article/details/105243260