血氧心率测量仪(带温湿度测量功能)OLED显示

本文介绍了一款带有温湿度测量功能的血氧心率测量仪,使用DHT11数字温湿度传感器和MAX30100芯片。DHT11传感器能够精确测量环境温湿度,而MAX30100则通过红光和红外光测量血液中的氧含量和脉率。文章详细阐述了工作原理、模块说明、代码展示及数据处理流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

血氧心率测量仪(带温湿度测量功能)OLED显示

原理图资料

MAX30100原理
在这里插入图片描述

模块说明

数字温湿度传感 DHT11
►相对湿度和温度测量
►全部校准,数字输出
►卓越的长期稳定性
►无需额外部件
►超长的信号传输距离
►超低能耗
►4 引脚安装
►完全互换

                              DHT11产品概述

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传
感器。 它应用专用的数字模块采集技术和温湿度传感技术, 确保产品具有极高
的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测
温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快
响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的
湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内
部在检测信号的处理过程中要调用这些校准系数。 单线制串行接口, 使系统集
成变得简易快捷。超小的体积、极低的功耗, 信号传输距离可达20米以上, 使
其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为 4 针单排引脚
封装。 连接方便, 特殊封装形式可根据用户需求而提供。

                             接口说明

建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使
用合适的上拉电阻

                          电源引脚

DHT11的供电电压为 3-5.5V。 传感器上电后, 要等待 1s 以越过不稳定状态在此期间无需发送任何指令。 电源引脚( VDD, GND) 之间可增加一个100nF 的电容, 用以去耦滤波。

                    串行接口 (单线双向)

DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次
通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数
部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。

总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必
须大于18毫秒,保证DHT11能检测到起始信号。 DHT11接收到主机的开始信号后,
等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束
后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换
到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。

                       MAX30100 的说明

原理简介:
MAX30100 如何测量脉率? 该设备有两个 LED, 一个发射红光, 另一个发射红外光。 红光和红外光都用来测量血液中的氧含量。 当心脏泵血时, 由于有更多血液, 含氧血液增加。随着心脏放松, 含氧血液的体积也减少。 通过知道氧合血液增加和减少之间的时间, 确定脉搏率。 事实证明, 含氧血吸收更多的红外光并传递更多的红光, 而脱氧血吸收红光并传递更多的红外光。 这就是 MAX30100 的主要功能原理: 它读取两个光源的吸收电平, 并将它们存储在可通过 I2C 读取的缓冲区中。 但是, 它并不像听起来那么简单, 中间会涉及到很多数据过滤以及处理过程。
在这里插入图片描述

0.96寸OLED显示屏模块
OLED模块
在这里插入图片描述
4针链接OLED iic接口 网盘下载
提取码:869m

测试数据处理图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

部分代码展示

void max10300_init()
{
	max10300_Bus_Write(0x06, 0x0b);  //mode configuration : temp_en[3]      MODE[2:0]=010 HR only enabled    011 SP02 enabled
	//max10300_Bus_Write(0x06, 0x0a);  //MODE[2:0]=010 HR only enabled     when used is mode ,the red led is not used.
	max10300_Bus_Write(0x01, 0xF0); //open all of interrupt
	max10300_Bus_Write(INTERRUPT_REG, 0x00); //all interrupt clear
	max10300_Bus_Write(0x09, 0x33); //r_pa=3,ir_pa=3

#ifdef SAMPLE_50
	max10300_Bus_Write(0x07, 0x43); //SPO2_SR[4:2]=000   50 per second    LED_PW[1:0]=11  16BITS
#else
	max10300_Bus_Write(0x07, 0x47); //SPO2_SR[4:2]=001  100 per second    LED_PW[1:0]=11  16BITS
#endif
	
	max10300_Bus_Write(0x02, 0x00);   //set FIFO write Pointer reg = 0x00 for clear it
	max10300_Bus_Write(0x03, 0x00);	//set Over Flow Counter  reg = 0x00 for clear it
	max10300_Bus_Write(0x04, 0x0f);	//set FIFO Read Pointer  reg = 0x0f for   
											//waitting  write pointer eq read pointer   to   interrupts  INTERRUPT_REG_A_FULL
}

double my_floor(double x)
{
   double y=x;
    if( (*( ( (int *) &y)+1) & 0x80000000)  != 0) //或者if(x<0)
        return (float)((int)x)-1;
    else
        return (float)((int)x);
}

double my_fmod(double x, double y)
{
   double temp, ret;
  
   if (y == 0.0)
      return 0.0;
   temp = my_floor(x/y);
   ret = x - temp * y;
   if ((x < 0.0) != (y < 0.0))
      ret = ret - y;
   return ret;
}


#define XPI            (3.1415926535897932384626433832795)
#define XENTRY        (100)
#define XINCL        (XPI/2/XENTRY)

  static const double XSinTbl[] = {
        0.00000000000000000  , 0.015707317311820675 , 0.031410759078128292 , 0.047106450709642665 , 0.062790519529313374 ,
        0.078459095727844944 , 0.094108313318514325 , 0.10973431109104528  , 0.12533323356430426  , 0.14090123193758267  ,
        0.15643446504023087  , 0.17192910027940955  , 0.18738131458572463  , 0.20278729535651249  , 0.21814324139654256  ,
        0.23344536385590542  , 0.24868988716485479  , 0.26387304996537292  , 0.27899110603922928  , 0.29404032523230400  ,
        0.30901699437494740  , 0.32391741819814940  , 0.33873792024529142  , 0.35347484377925714  , 0.36812455268467797  ,
        0.38268343236508978  , 0.39714789063478062  , 0.41151435860510882  , 0.42577929156507272  , 0.43993916985591514  ,
        0.45399049973954680  , 0.46792981426057340  , 0.48175367410171532  , 0.49545866843240760  , 0.50904141575037132  ,
        0.52249856471594880  , 0.53582679497899666  , 0.54902281799813180  , 0.56208337785213058  , 0.57500525204327857  ,
        0.58778525229247314  , 0.60042022532588402  , 0.61290705365297649  , 0.62524265633570519  , 0.63742398974868975  ,
        0.64944804833018377  , 0.66131186532365183  , 0.67301251350977331  , 0.68454710592868873  , 0.69591279659231442  ,
        0.70710678118654757  , 0.71812629776318881  , 0.72896862742141155  , 0.73963109497860968  , 0.75011106963045959  ,
        0.76040596560003104  , 0.77051324277578925  , 0.78043040733832969  , 0.79015501237569041  , 0.79968465848709058  ,
        0.80901699437494745  , 0.81814971742502351  , 0.82708057427456183  , 0.83580736136827027  , 0.84432792550201508  ,
        0.85264016435409218  , 0.86074202700394364  , 0.86863151443819120  , 0.87630668004386369  , 0.88376563008869347  ,
        0.89100652418836779  , 0.89802757576061565  , 0.90482705246601958  , 0.91140327663544529  , 0.91775462568398114  ,
        0.92387953251128674  , 0.92977648588825146  , 0.93544403082986738  , 0.94088076895422557  , 0.94608535882754530  ,
        0.95105651629515353  , 0.95579301479833012  , 0.96029368567694307  , 0.96455741845779808  , 0.96858316112863108  ,
        0.97236992039767667  , 0.97591676193874743  , 0.97922281062176575  , 0.98228725072868872  , 0.98510932615477398  ,
        0.98768834059513777  , 0.99002365771655754  , 0.99211470131447788  , 0.99396095545517971  , 0.99556196460308000  ,
        0.99691733373312796  , 0.99802672842827156  , 0.99888987496197001  , 0.99950656036573160  , 0.99987663248166059  ,
        1.00000000000000000  };

double XSin( double x )
{
    int s = 0 , n;
    double dx , sx , cx;
    if( x < 0 )
        s = 1 , x = -x;
    x = my_fmod( x , 2 * XPI );
    if( x > XPI )
        s = !s , x -= XPI;
    if( x > XPI / 2 )
        x = XPI - x;
    n = (int)( x / XINCL );
    dx = x - n * XINCL;
    if( dx > XINCL / 2 )
        ++n , dx -= XINCL;
    sx = XSinTbl[n];
    cx = XSinTbl[XENTRY-n];
    x = sx + dx*cx - (dx*dx)*sx/2
        - (dx*dx*dx)*cx/6 
        + (dx*dx*dx*dx)*sx/24
        ;
     
    return s ? -x : x;
}
 
double XCos( double x )
{
    return XSin( x + XPI/2 );
}

```c
void test_max30100_fun(void)
{
	u16 temp_num=0;
	u16 fifo_word_buff[15][2];
	u16 Heart_Rate=0;
	u16 s1_max_index=0;
	u16 s2_max_index=0;
	
	delayl_init();	    	 //延时函数初始化	   
	OLED_Init();			//初始化OLED     
	
	while(1)
	{
		temp_num = max10300_Bus_Read(INTERRUPT_REG);
		//if( (INTERRUPT_REG_HR_RDY&temp_num) && (INTERRUPT_REG_SPO2_RDY&temp_num) )
		if( INTERRUPT_REG_A_FULL&temp_num )
		{
			max10300_FIFO_Read(0x05,fifo_word_buff,15); //read the hr and spo2 data form fifo in reg=0x05
			{
				u16 i=0;
				for(i=0;i<15;i++)
				{ 
					if(g_fft_index < FFT_N)
					{
						s1[g_fft_index].real = fifo_word_buff[i][0];
						s1[g_fft_index].imag= 0;
						s2[g_fft_index].real = fifo_word_buff[i][1];
						s2[g_fft_index].imag= 0;
						g_fft_index++;
					}
				}
				if(g_fft_index>=FFT_N)
				{
						{ //printf()  fft data
							u16 index=0;
							for(index=0;index<40;index++)
							{					
								//printf("s1[%3d]= %f\r\n",index,s1[index].real);
								//printf("s2[%3d]= %f\r\n",index,s2[index].real);
							}
						}
					 FFT(s1);
					 FFT(s2);
					 for(i=0;i<FFT_N;i++) 
					 {
							s1[i].real=sqrtf(s1[i].real*s1[i].real+s1[i].imag*s1[i].imag);
							s2[i].real=sqrtf(s2[i].real*s2[i].real+s2[i].imag*s2[i].imag);
					 }

					{ //printf()  fft data
						u16 index=START_INDEX;
						for( ;index<60;index++)
						{	
						#ifdef SAMPLE_50
								printf("f=%3.3f HZ,s1[%3d] = %f \r\n",50.0/FFT_N*index,index,s1[index].real);
								printf("f=%3.3f HZ,s2[%3d] = %f \r\n",50.0/FFT_N*index,index,s2[index].real);
						#else
								printf("f=%3.3f HZ,s1[%3d] = %f \r\n",100.0/FFT_N*index,index,s1[index].real);
								printf("f=%3.3f HZ,s2[%3d] = %f \r\n",100.0/FFT_N*index,index,s2[index].real);
						#endif
						}
						
					}
					s1_max_index = find_max_num_index(s1, 60);
					s2_max_index = find_max_num_index(s2, 60);
					if(s1_max_index == s2_max_index)	
					{
				#ifdef SAMPLE_50	 
						Heart_Rate =  60*50*((s1_max_index+s2_max_index )/2)/FFT_N;
				#else
						Heart_Rate =  60*100*((s1_max_index+s2_max_index )/2)/FFT_N;
				#endif
						printf("\r\n心率为: %d\r\n",Heart_Rate+52);
						
						sp02_treated_fun(s1_max_index);	
						
						OLED_ShowString(0,0, "SpO2:",16);
						OLED_ShowString(0,30,"Heart_Rate:",12); 
						OLED_ShowNum(70,30,Heart_Rate+52,4,16);
						OLED_Refresh();//更新显示到OLED 
											
					}
					else
					{
						printf("\r\n 测量失败,  请压好重新测量!\r\n");
						
						OLED_ShowString(0,0, "SpO2:",16);
						OLED_ShowString(0,30,"Heart_Rate:",12); 
						OLED_ShowString(70,30,"ERROR",16); 
						OLED_Refresh();//更新显示到OLED 
					}
					g_fft_index = 0;
				}
			}
		/*	ic 自动管理FIFO指针 不用参与
			max10300_Bus_Write(0x02, 0x00);   //set FIFO write Pointer reg = 0x00 for clear it
			max10300_Bus_Write(0x03, 0x00);	//set Over Flow Counter  reg = 0x00 for clear it
			max10300_Bus_Write(0x04, 0x0f);	//set FIFO Read Pointer  reg = 0x0F 
			max10300_Bus_Write(INTERRUPT_REG, 0x00); // all interrupt clear
		*/
		}
	}
}

`

资料包

心率模块资料分享
链接:https://pan.baidu.com/s/129VgzvSngC_rhLgqGAK2vg
提取码:8pyd

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值