269 基于单片机MAX30100血氧、心率检测系统设计

        基于美信MAX30100/MAX30102传感器设计的血氧和心率检测,以单片机STM32F103CBT6为主控核心,其中涉及电源模块、心率血氧模块、蓝牙模块。电源模块是提供所有系统的供电,心率血氧是整个系统功能的实现,MCU读取心率血氧信号,分析数据,蓝牙模块是实现无线的一种方式,连接外部和单片机。

        本设计可以通过手机蓝牙连接。测量者可将手指放于被测处,测得的数据可在单片机上直观显示或者是电脑显示。在数据显示的问题上,本设计采用了二种方法,一种是手机蓝牙连接,利用手机蓝牙连接硬件电路的蓝牙模块,通过蓝牙传输数据送往手机显示,第二种是单片机液晶屏显示,被测者可在液晶屏上直接获取自己的血氧脉搏的数据。 最终,被测者可获得自己的心率和血氧值。

完整版 电路图和程序代码 下载地址

https://pan.baidu.com/s/1ylRhT3VqKW0-es7jW5IABg?pwd=8888

#include "IIC.h"
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h" 
#include <math.h>
#include <stdio.h>
#include "stm32f10x_i2c.h"
#include "12864.h"

#define SAMPLE_50   //如果定义此宏就是50采样率   否则是100


extern void test_max30100_fun(void);
extern u8 max10300_Bus_Read(u8 Register_Address);
extern void max10300_init(void);


int main(void)
 {		
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	delay_init();	    	 //延时函数初始化	 
  LED_Init();	 
	uart_init(9600);	 //串口初始化为115200
	bsp_InitI2C();
	max10300_init();	
	LCD12864_InitPort();  //端口初始化
	LCD12864_Init();	    //液晶初始化
	delay_ms(70);	 
	printf("\r\n stm32 init runing \r\n");
  LCD12864_Clear();     //清屏	
	delay_ms(70); 
	LCD_ShowString(1,1,"淮北师范大学");	
	LCD_ShowString(2,0,"stm32 init run");
  LCD_ShowString(3,0,"心率:");	
  LCD_ShowString(4,0,"血氧:");	 
  while(1)
	{
		test_max30100_fun();
	}	 
} 


#define max10300_WR_address 0xAE

u8 max10300_Bus_Write(u8 Register_Address, u8 Word_Data)
{

	/* 采用串行EEPROM随即读取指令序列,连续读取若干字节 */

	/* 第1步:发起I2C总线启动信号 */
	i2c_Start();

	/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
	i2c_SendByte(max10300_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;
}



u8 max10300_Bus_Read(u8 Register_Address)
{
	u8  data;


	/* 第1步:发起I2C总线启动信号 */
	i2c_Start();

	/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
	i2c_SendByte(max10300_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(max10300_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;
}

void i2c_Delay(void)
{
	uint8_t i;

	/* 
		CPU主频168MHz时,在内部Flash运行, MDK工程不优化。用台式示波器观测波形。
		循环次数为5时,SCL频率 = 1.78MHz (读耗时: 92ms, 读写正常,但是用示波器探头碰上就读写失败。时序接近临界)
		循环次数为10时,SCL频率 = 1.1MHz (读耗时: 138ms, 读速度: 118724B/s)
		循环次数为30时,SCL频率 = 440KHz, SCL高电平时间1.0us,SCL低电平时间1.2us

		上拉电阻选择2.2K欧时,SCL上升沿时间约0.5us,如果选4.7K欧,则上升沿约1us

		实际应用选择400KHz左右的速率即可
	*/
	for (i = 0; i < 25; i++);
}


#if 1

void max10300_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(max10300_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(max10300_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();
}

#else
void max10300_FIFO_Read(u8 Register_Address,u16  Word_Data[][2],u8 count)
{
	u8 i=0;
	u8 no = count;
	u8 data1, data2;
	
	while(I2C_GetFlagStatus(USR_I2C_USED, I2C_FLAG_BUSY))
		; //调用库函数检测I2C器件是否处于BUSY状态
		

	I2C_AcknowledgeConfig(USR_I2C_USED, ENABLE);   /*允许1字节1应答模式*/


	I2C_GenerateSTART(USR_I2C_USED, ENABLE);
	 while(!I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_MODE_SELECT))
	 	; //清除EV5
	
	I2C_Send7bitAddress(USR_I2C_USED, max10300_WR_address, I2C_Direction_Transmitter);
	while(!I2C_CheckEvent(USR_I2C_USED,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
		; //ADDR=1,清除EV6 
		
	I2C_SendData(USR_I2C_USED, Register_Address);
	 while(! I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
	 	;//移位寄存器非空,数据寄存器已经空,产生EV8,发送数据到DR既可清除该事件

	I2C_GenerateSTART(USR_I2C_USED, ENABLE);
	 while(!I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_MODE_SELECT))
	 	; //清除EV5
	
	I2C_Send7bitAddress(USR_I2C_USED, max10300_WR_address, I2C_Direction_Receiver);
	while(!I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));


 	while (no)
    {	
	
		while(!I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_BYTE_RECEIVED)); // EV7 
	    data1 = I2C_ReceiveData(USR_I2C_USED);

		while(!I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_BYTE_RECEIVED)); // EV7
	    data2 = I2C_ReceiveData(USR_I2C_USED);

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



       while(!I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_BYTE_RECEIVED)); // EV7
		data1 = I2C_ReceiveData(USR_I2C_USED);

	    if(no==1)
		{
     		I2C_AcknowledgeConfig(I2C1, DISABLE);	//最后一位后要关闭应答的
    		I2C_GenerateSTOP(I2C1, ENABLE);			//发送停止位
		
		}

		while(!I2C_CheckEvent(USR_I2C_USED, I2C_EVENT_MASTER_BYTE_RECEIVED)); // EV7
		data2 = I2C_ReceiveData(USR_I2C_USED);

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

		
	    /* Decrement the read bytes counter */
	    no--;
    }
	
	I2C_AcknowledgeConfig(USR_I2C_USED, ENABLE);//将应答位使能回去,等待下次通信
	I2C_GenerateSTOP(I2C1, ENABLE);			//发送停止位
}

#endif

#define INTERRUPT_REG  					      0X00
#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)

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值