【前言】
现在对健康的监护人们越来越需要高,国庆假期鼓捣一个健康监护仪,目前可以实现测心率、血氧、血压健康监护仪,现在分享如下:
【硬件】
1、NUCLEO-H755开发板。
2、ST7789LCD屏
3、健康监测模块 心率血氧检测模块反射式检测传感器
【程序框图】

CM4开启usart2,开启中断接收,当从CM7内核接收到OpenAMP的信号后,解析命,通过向传感器发送开始监测/停止监测的命。当开始监测后,传感器会周期的将数据回传给CM4。CM4接收到数据后,通过OpenAMP发送给CM7内核。
CM7开启了TouchGFX用户交互界面,当GUI点击开启转换后,通过OpenAMP向CM4内核发送开始/停止信号;同时如果OpenAMP接收到数据后,置位接收标志,在touchGFX的handleTickEvent周期函数,判断是否有数据更新,如何有更新,就将数据列新到的用户界面。
【GUI界面设计】
打开touchGFX Designer,制作界面如下:

界面中bntRun,添加一个虚拟函数,当按下后,判断其标签来实现按键按下事件,来通知CM4是否开启或者停止采集。
void screenView::funRun()
{
// 获取bntRun的标签文本
touchgfx::TypedText btnRunText = bntRun.getLabelText();
// 判断按钮文本是否为"START"
if (touchgfx::Unicode::strncmp(btnRunText.getText(), TypedText(T_START).getText(), 5) == 0)
{
// 改变按钮文本为"STOP"
MKS_RUN(0x8a);
bntRun.setLabelText(touchgfx::TypedText(T_STOP));
bntRun.invalidate();
}
else if (touchgfx::Unicode::strncmp(btnRunText.getText(), TypedText(T_STOP).getText(), 4) == 0)
{
// 改变按钮文本为"START"
MKS_RUN(0x88);
bntRun.setLabelText(touchgfx::TypedText(T_START));
bntRun.invalidate();
}
// Override and implement this function in screen
}在handleTickEvent事件中周期判断是否接到数据,如果有更新数据
void screenView::handleTickEvent()
{
// 调用基类的处理函数
// screenViewBase::handleTickEvent();
//
// 检查是否有新数据需要处理
if (message_received == 1)
{
// 处理接收到的数据
handleReceivedData();
// 重置标志
message_received = 0;
}
}
void screenView::handleReceivedData()
{
Unicode::snprintf(valHartBuffer,10,"%d",default_mks_params.heart);
valHart.invalidate();
Unicode::snprintf(valSpo2Buffer,10,"%d",default_mks_params.spo2);
valSpo2.invalidate();
Unicode::snprintf(valbpBuffer1, VALBPBUFFER1_SIZE, "%d", default_mks_params.diastolic_pressure);
Unicode::snprintf(valbpBuffer2, VALBPBUFFER2_SIZE, "%d", default_mks_params.systolic_pressure);
valbp.invalidate();
}【CM7事件处理】
1、事件发送
void MKS_RUN(uint8_t state)
{
if(state == 0x88)
{
default_mks_params.cmd = 0x88;
OPENAMP_send(&rp_endpoint, &default_mks_params, sizeof(default_mks_params));
}
else if(state == 0x8A)
{
default_mks_params.cmd = 0x8A;
OPENAMP_send(&rp_endpoint, &default_mks_params, sizeof(default_mks_params));
}
}当接收到touchGFX的命令,通OPENAMP_sen将事件发送给CM4。
2、事件接收
static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data,
size_t len, uint32_t src, void *priv)
{
default_mks_params = *((mks_control_params_t *) data);
message_received=1;
return 0;
}当有从CM4的事件接收时,在此回函数,解析数据,并置位message_receivied置,touchGFX事件会即接收并完成数据的更新。
【CM4事件处理】
1、OpenAmp接收事件:
static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data,
size_t len, uint32_t src, void *priv)
{
default_mks_params = *((mks_control_params_t *) data);
uint8_t txData;
if(default_mks_params.cmd == 0x8A)
{
txData = 0x8A;
HAL_UART_Transmit(&huart2,&txData,1,0xffff);
}
else if(default_mks_params.cmd == 0x88)
{
txData = 0x88;
HAL_UART_Transmit(&huart2,&txData,1,0xffff);
}
return 0;
}当有从CM7事件接收到时,向usart2即传感器转输命令,开始或停止数据采集。
2、中断回调
RT_PACK *rt_pack = (RT_PACK *)usart2_rx_buffer; // ӳ�仺�������ṹ��
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2)
{
UART_Start_Receive_IT(&huart2, usart2_buf, 1);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2)
{
if(usart2_buf[0] == PACKET_HEADER)
{
usart2_rx_in_progress = 1;
usart2_rx_count = 0;
usart2_rx_complete = 0;
usart2_rx_buffer[usart2_rx_count++] = usart2_buf[0];
}
else if(usart2_rx_in_progress)
{
if(usart2_rx_count < RECEIVE_LENGTH)
{
usart2_rx_buffer[usart2_rx_count++] = usart2_buf[0];
if(usart2_rx_count >= RECEIVE_LENGTH)
{
usart2_rx_complete = 1;
usart2_rx_in_progress = 0;
}
}
}
}
UART_Start_Receive_IT(&huart2, usart2_buf, 1);
}
void process_rt_packet(void)
{
if (usart2_rx_complete)
{
if (rt_pack->head == 0xFF)
{
int8_t* ecg_wave = rt_pack->acdata;
uint32_t heart_rate = rt_pack->heartrate;
uint32_t spo2_val = rt_pack->spo2;
uint8_t micro_circ = rt_pack->bk;
uint8_t fatigue_index = rt_pack->rsv[0];
uint32_t systolic_pressure = rt_pack->rsv[3];
uint32_t diastolic_pressure = rt_pack->rsv[4];
uint8_t sdann_val = rt_pack->sdann;
uint8_t rmssd_val = rt_pack->rmssd;
uint8_t* rr_interval = rt_pack->rra;
send_hart(heart_rate, spo2_val, systolic_pressure, diastolic_pressure);
}
usart2_rx_complete = 0;
}
}在这里按照程序框图,当判断接收到完整的一个数据包时,通过send_hart函数将参数传输出OpenAmp发送函数:
void send_hart(uint32_t heart,uint32_t spo2,uint8_t systolic_pressure,uint8_t diastolic_pressure)
{
default_mks_params.heart = heart;
default_mks_params.spo2 = spo2;
default_mks_params.systolic_pressure = systolic_pressure;
default_mks_params.diastolic_pressure = diastolic_pressure;
OPENAMP_send(&rp_endpoint, &default_mks_params, sizeof(default_mks_params));
}【实现效果】

我要赚赏金
