这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【原创】惊帆JF141心率血氧模块简单使用--from哲

共2条 1/1 1 跳转至

【原创】惊帆JF141心率血氧模块简单使用--from哲

工程师
2024-06-21 16:24:53     打赏

模组图片:

图片1.png

让我们看一下产品规格书

图片2.png


,大概也就知道了,应该如何配置片机的串口来实现通信了。里我用的是PA9和PA10串口1,并且开启接收中断,用于及的接收数据。

图片3.png

模组的指令分为三种分别是采集、体检、休眠。

在这里我们想要的是简单使用,所以只关注最基础的采集指令就可以了。

需要指出的是在实际使用中虽然模组能近乎百分之百的响应指令,但是发送指令之后建议延时600ms左右(可以直接写到XU_Yang_SendByte(uint8_t Byte)函数中,之前忘记了,大家自己添加一下吧),等待模组进入工作状态再进行读取

既然我们知道了采集的开关指令,那么我们怎么知道接收的哪些是我们想要的心率和血样数据呢?

图片4.png

从中我就可以了解到采集开启之后,模会通串口送以0xFF实时数据包,里面不包括了心率和血氧数据,也包括了心跳的原始数据和微循等数据,我的目的是取心率和血氧,所以重点两个数据就可以了。

 

所以我既然知道了接受的数据什么子,需要的数据在哪个位置,那么我就可以来写接收中断函数了。

 

段代的思路是检测到包开始接受,接收到最大数量重新开始检测,如此循接收数据并将数据放在数里面方便用。

 

串口代是参考江科大的,所以也用了状机的思路。

 

上我可以看到,76个字,但我需要的只有仅仅两个字,所以我就想着定一个只有两个字的数直接用于接收需要的数据,但是使用的发现,干数据有点多,所以又取了前两个心跳数据来用于数据有效性检测。当然可能不是必的,大家也不必在纠结过

 

//在中断实现接收一个HEX数据包

void USART1_IRQHandler(void)

{

static uint8_t RxState;//用来记录状态数据

static uint8_t pRxPacket;//用来记录接收了几个数据

if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//再次确认标志位是否正确置位

{

uint8_t RxData = USART_ReceiveData(USART1);

//读取接收数据寄存器中的数据,存储到uint8_t RxData中

if(RxState == 0)//状态零(接收包头)

{

if(RxData == 0xFF)

{

RxState = 1;

pRxPacket=2;

}

}else if(RxState == 1)//状态1(接收数据)

{

if(pRxPacket>=66 && pRxPacket<68)

{

//将接收到的心率和血氧数据放在数组后两位

XU_Yang_RxPacket[pRxPacket-64]=RxData;

pRxPacket++;

}else if(pRxPacket<2)

{

//将接收到的监测数据有效性的数据放在数组前两位

XU_Yang_RxPacket[pRxPacket]=RxData;

pRxPacket++;

}else if(pRxPacket>=2 && pRxPacket<66)

{

pRxPacket++;

}else if(pRxPacket>=68)

{

pRxPacket=0;

RxState=0;

XU_Yang_RxFlag = 1;//将接收信号位置1,代表数据接收完成,可以读取

}


}

USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除接收数据寄存器非空标志位

}

}

 

里,我从中断中就接收到了需要的数据,但是些数据并不能直接使用,因当你不放置手指数据肯定是无效的,尽管你的手指放在上面,由于各种因素开始生的数据当然也是我不想要看到的,大家可以尝试一个下,用串口模块连接血氧模测试,会发现没有放手指,心跳数据一般都是0XC4,当放置手指之后,按照对应位的数据也会发现这些数据有些背常。我一般来写一个驱动函数的目的就是方便主函数的用,最好是那种,主函数一用,就能知道准确的数据。所以以此想法思路,我便可以写一下我取函数了。

 

首先就是取数据的隔,我上一个可以看出,实时数据包每隔1.64s送一次,所以理上我们对就收数据的隔也应该1.64s,但是我习惯让单片机找点事情做,所以就没有通时调时间间隔,而是让单片机一直筛选数据。

一下我出数据的思路:就是通判断数的前两位和后两位的束条件判断是否采集成功。

前两位心跳数据,当0xC4可以判定采集失,当后两位心率和血氧数据不在正常的范同理也可以判断采集失

在下面的代中也可以看到我里面将送开始与束采集的命令注掉了,因本来想着完数据之后就束采集,但是,发现频繁的开关致模不及,所以索性,就在主函数控制开启和关采集了。

/**

 * @brief       过滤无效数据,并返回数据是否采集成功(无效数据过多,代表采集失败,最多等待200次数据包),成功采集一次就跳出采集程序                

 * @param       无                  

* @retval       1 数据采集成功;0数据采集失败         

  */

 uint8_t XU_Yang_Receive(void)

{

uint8_t  num=0;//接收到几个数据包

// XU_Yang_SendByte(0x8A);//开始采集

while(1)

{

 if(XU_Yang_GetRxFlag()==1)

 {

//

 //过滤无效数据

if(XU_Yang_RxPacket[0]==0xC4 | XU_Yang_RxPacket[1]==0xC4 | (XU_Yang_RxPacket[2]<60 | XU_Yang_RxPacket[2]>130) | (XU_Yang_RxPacket[3]<80 | XU_Yang_RxPacket[3]>99) )

{//数据无效,将无效数据清除

for(uint8_t i=0;i<4;i++)

{

XU_Yang_RxPacket[i]=0;

}

num++;

//失败次数过多,采集失败

if(num >200)

{

delay_ms(10);//两次采集时间间隔过短导致了一直采集失败//原因未知//

num=0;

//    XU_Yang_SendByte(0x88);//结束采集

return 0;

}

}else//采集成功

{

num=0;

//   XU_Yang_SendByte(0x88);//结束采集

return 1;

}

 }

}

 

}

模块文件写好之后,主函数就简单多了

 

#include "stm32f10x.h"                  // Device header

#include "Delay.h"

#include "OLED.h"

#include "XU_Yang.h"

#include "Key.h"

uint8_t n;

//uint32_t u=0;

uint16_t s=650;

int main()

{

/*

现象:将手指放上去,刚开始时显示失败,等待大约15s左右,显示采集成功,采集成功后,数据更新也会加快,

*/

OLED_Init();

XU_Yang_Init();

OLED_ShowString(1,1,"RxPacket:");

OLED_ShowString(2,1,"000ci   00%");

XU_Yang_SendByte(0x8A);//开始采集

while(1)

{

while(s--)

{

n = XU_Yang_Receive();

}


if(n==1)

{

OLED_ShowString(3,1,"      ");

OLED_ShowNum(2,1,XU_Yang_RxPacket[2],3);

XU_Yang_RxPacket[2] = 0;

OLED_ShowNum(2,9,XU_Yang_RxPacket[3],3);

XU_Yang_RxPacket[3] = 0;

OLED_ShowString(3,1,"Right!");

}else if(n==0)

{

OLED_ShowNum(2,1,0,3);

OLED_ShowNum(2,9,0,3);

OLED_ShowString(3,1,"      ");

OLED_ShowString(3,1,"Lose!");

}

 

}

}

图片5.png


院士
2024-06-27 18:14:24     打赏
2楼

谢谢分享,学习了。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]