阿方
创作者认证
萤火工场CEM5861G-M11 使用RA6E2监测人体存在
本次点灯使用 RA 生态工作室的 RA-Eco-RA6E2 开发板
Demo e² Studio 项目可以在附件找到
目标
利用 CEM5861G-M11 毫米波雷达检测人体存在,实现:
目标存在点亮 LED2,目标移动点亮 LED1
系统框图
如何准确接收串口数据?
CEM5861G 在上电后会源源不断向上位机发送数据,我们需要用一种方式准确读取串口数据
我使用了状态机实现对数据帧的同步
首先,我定义了枚举变量 uart_rx_state_t
,其中有三个状态
STATE_FIND_HEAD1
正在寻找帧头第一位0x55
STATE_FIND_HEAD2
正在寻找帧头第二位0xA5
STATE_RECV_PAYLOAD
正在接收剩余数据
typedef enum
{
STATE_FIND_HEAD1 = 0, // 找帧头第一位 0x55
STATE_FIND_HEAD2 = 1, // 找帧头第二位 0xA5
STATE_RECV_PAYLOAD = 2 // 接收剩余数据
} uart_rx_state_t;
可以画出状态转移图:
将它写为代码:
void hal_entry(void)
{
/* TODO: add your own code here */
uint32_t idx = 0;
UART9_Init();
R_IOPORT_Open(&g_ioport_ctrl, g_ioport.p_cfg);
printf("Hello, CEM5861G!\r\n");
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_LOW);
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07, BSP_IO_LEVEL_LOW);
while (1)
{
switch (cem_state)
{
case STATE_FIND_HEAD1: // 找第帧头第一位 0x55
{
if (R_SCI_UART_Read(&g_uart9_ctrl, &cem_rx_byte, 1) == FSP_SUCCESS)
{
if (cem_rx_byte == 0x55)
cem_state = STATE_FIND_HEAD2;
}
break;
}
case STATE_FIND_HEAD2: //找第帧头第二位 0xA5
{
if (R_SCI_UART_Read(&g_uart9_ctrl, &cem_rx_byte, 1) == FSP_SUCCESS)
{
if (cem_rx_byte == 0xA5) // 帧头 OK,接下来接收余下 16 字节
{
cem_frame[0] = 0x55;
cem_frame[1] = 0xA5;
idx = 2;
cem_state = STATE_RECV_PAYLOAD;
}
else if (cem_rx_byte == 0x55) // 还是 0x55,继续找 0xA5
{
;
}
else // 异常,重新找 0x55
{
cem_state = STATE_FIND_HEAD1;
}
}
break;
}
case STATE_RECV_PAYLOAD: // 接收剩余 16 字节完成一帧
{
fsp_err_t err = uart_read_exact(&cem_frame[idx], CEM_FRAME_LEN - idx);
if (err != FSP_SUCCESS) //读取出错,重新开始
{
cem_state = STATE_FIND_HEAD1;
break;
}
// 开始校验
uint8_t sum = 0;
for (uint32_t i = 0; i < CEM_FRAME_LEN - 1; i++)
sum += cem_frame[i];
sum &= 0xFF;
if (sum != cem_frame[CEM_FRAME_LEN - 1]) // 校验失败,丢掉这一帧
{
// 校验失败,丢掉这一帧
printf("Checksum Error: sum=%02X, frame[17]=%02X\r\n", sum, cem_frame[CEM_FRAME_LEN - 1]);
cem_state = STATE_FIND_HEAD1;
break;
}
// 校验通过,使用第 9 个数据字节 DATA[1] 做控制
uint8_t data1 = cem_frame[3 + 5];
// P113[LED2]: 目标存在否
if (data1 == 0x00) // 目标不存在 - 灭
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_LOW);
else // 目标存在 - 亮
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_HIGH);
// P207[LED1]: 目标状态
if (data1 == 0x01) // 目标移动 - 亮
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07, BSP_IO_LEVEL_HIGH);
else if (data1 == 0x02) // 目标存在 - 灭
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_07, BSP_IO_LEVEL_LOW);
// 输出数据帧
for (int i = 0; i < CEM_FRAME_LEN; i++)
printf("%02X ", cem_frame[i]);
printf("\r\n");
cem_state = STATE_FIND_HEAD1;
break;
}
}
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
更好的读取串口数据
为了更好的读取串口数据,这里使用阻塞读取来实现读取指定长度的数据
fsp_err_t uart_read_exact(uint8_t *buf, uint32_t len)
{
uint32_t got = 0;
while (got < len)
{
fsp_err_t err = R_SCI_UART_Read(&g_uart9_ctrl, &buf[got], len - got);
if (err != FSP_SUCCESS)
return err;
got += (len - got);
}
return FSP_SUCCESS;
}
看看效果
视频
工程附件
CEM5861G_Demo.zip
版块:
萤火工场
2025/07/18 23:20
全部评论