测试数据终端,以及数据是否能通过单片机上的串口5转发数据到串口6(重点)
打开串口助手(注意一定要注意使用的是要使用的是UTF-8编码,要不然会报错)

报错核心原因:编码不一致。
-
WebSocket 标准规定: 如果传输的是文本帧(Text Frame),内容必须是标准的 UTF-8 编码。
-
你的现状: 你使用的串口调试助手(例如 XCOM, SSCOM, 或 Windows 默认终端)输入中文"温度"时,默认使用的是 GBK 或 GB2312 编码(这是中文 Windows 的默认编码)。
-
冲突: Node.js 的
ws库接收到 GBK 编码的字节流,试图按 UTF-8 规则去校验,发现字节序列不对(UTF-8 的中文通常是 3 个字节,GBK 是 2 个字节),于是判定为"非法数据",直接抛出Invalid WebSocket frame错误。 -
为何服务器挂了: 因为你没有在代码中捕获这个
error事件,Node.js 遇到未捕获的异常会默认终止进程。
测试示例(记得在串口助手一定要修改当前编码规则)-这个通过我们的串口5传输数据至网页上,同时查看我们制作的网页上是否数据进行显示,数据异常时是否出现报警
温度:26°C,湿度:55%,摔倒标志:0,心率异常标志:0,气体异常标志:0,心率值:75 BPM(正常环境,正常标志位)
温度:28°C,湿度:80%,摔倒标志:1,心率异常标志:1,气体异常标志:1,心率值:145 BPM(正常环境,非正常标志位)
上传数据的示例代码(uart5_app.c)-现在请您返回RT-thread的开发
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2025-11-21 leader the first version
* 202x-xx-xx leader support communicate with uart6
* 2026-01-17 leader add sensor status print and forward to uart6
*/
#include <uart5_app.h>
// 包含串口6句柄声明(用于转发数据)
#define UART_NAME "uart5"
// 串口5设备句柄(区分串口6)
rt_device_t uart5_handle;
// 串口5接收信号量(区分串口6)
static struct rt_semaphore rx5_sem;
// 串口5接收回调函数
static rt_err_t uart5_input(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx5_sem);
return RT_EOK;
}
// 串口5任务:保留原接收转发功能 + 新增传感器状态打印与转发
static void uart5_task(void *parameter)
{
char ch;
// 新增:定义格式化缓冲区,存储传感器状态信息(足够容纳所有打印内容)
char sensor_buf[256];
rt_size_t buf_len;
while(1)
{
// 一、保留原功能:串口5接收字节数据,转发到串口6(阻塞式,有数据才处理)
// 非永久等待(避免阻塞传感器状态打印,可根据需求调整超时时间,单位:时钟节拍)
if (rt_sem_take(&rx5_sem, RT_TICK_PER_SECOND / 10) == RT_EOK)
{
// 读取串口5接收到的字节,逐个转发到串口6
while(rt_device_read(uart5_handle, -1, &ch, 1) == 1)
{
rt_device_write(uart6_handle, 0, &ch, 1);
}
}
// 二、新增功能:打印传感器状态,并转发到串口6
// 1. 格式化传感器状态信息到缓冲区(替代直接rt_kprintf,方便转发)
buf_len = rt_sprintf(sensor_buf,
"温度:%d°C\n"
"湿度:%d%%\n"
"摔倒标志:%d\n"
"心率异常标志:%d\n"
"气体异常标志:%d\n"
"心率值:%d BPM\n\n",
temp, humi, fall_flag, heartrate_flag, density_flag, hr);
// 2. 串口打印(保留原有的控制台输出功能)
rt_kprintf("%s", sensor_buf);
// 3. 核心:将格式化后的状态信息通过串口5转发到串口6
if (uart6_handle != RT_NULL)
{
rt_device_write(uart6_handle, 0, sensor_buf, buf_len);
}
// 4. 定时延时(避免高频打印占用CPU,可根据需求调整,单位:毫秒)
// 例如:每1000ms(1秒)更新一次传感器状态
rt_thread_mdelay(1000);
}
}
static int uart5_init(void)
{
// 查找串口5设备
uart5_handle = rt_device_find(UART_NAME);
if (uart5_handle == RT_NULL)
{
rt_kprintf("uart5 device find failed!\n");
return -RT_ERROR;
}
// 打开串口5(中断接收模式)
if (rt_device_open(uart5_handle, RT_DEVICE_FLAG_INT_RX) != RT_EOK)
{
rt_kprintf("uart5 device open failed!\n");
return -RT_ERROR;
}
// 初始化接收信号量
rt_sem_init(&rx5_sem, "rx5_sem", 0, RT_IPC_FLAG_FIFO);
// 设置接收回调函数
rt_device_set_rx_indicate(uart5_handle, uart5_input);
// 创建串口5任务(命名唯一,避免冲突)
rt_thread_t uart5_thread = rt_thread_create("uart5_task",
uart5_task,
RT_NULL,
2048, // 新增:增大栈大小(容纳格式化缓冲区,避免栈溢出)
25, // 优先级
10); // 时间片
if (uart5_thread != RT_NULL)
{
rt_thread_startup(uart5_thread);
}
else
{
rt_kprintf("uart5 thread create failed!\n");
return -RT_ERROR;
}
rt_kprintf("uart5 init success!\n");
return 0;
}
INIT_APP_EXPORT(uart5_init);
效果图(中间代表的是3个标志位)
