4. 串口回显
任务目标
在Contiki-NG中实现串口回显功能:MCU通过UART接收上位机发送的字节,并将每个字节原样发送回去。通过该案例理解Contiki串口驱动的注册机制、事件驱动的字节流接收方式,以及回调函数的使用方法。
环境与依赖
- 硬件:任意支持Contiki-NG的平台(如Zolertia RE-Mote、CC2538DK、Native模拟平台)
- 工具链:arm-none-eabi-gcc(嵌入式平台)或gcc(Native平台)
- 操作系统:Contiki-NG release 4.x
核心实现
Contiki-NG的串口驱动基于事件机制:当串口收到字节时,驱动层将字节放入缓冲区并触发一个回调函数。本案例通过serial_line_input注册回调,在回调中直接将收到的字节写回串口,实现回显。
#include "contiki.h"
#include "dev/serial-line.h"
#include "dev/uart1.h"
#include <stdio.h>
/* 串口接收回调函数:收到一行后原样回显 */
static int
echo_line_handler(const char *line, int len)
{
uart1_write_bytes((const uint8_t *)line, len);
uart1_writeb('\n');
return 0;
}
/* 串口驱动初始化 */
static void
init_uart(void)
{
uart1_init();
uart1_set_input(serial_line_input_byte);
serial_line_init();
serial_line_set_input(echo_line_handler);
}
/* 自动启动进程 */
AUTOSTART_PROCESSES(&echo_process);
PROCESS(echo_process, "Serial echo demo");
PROCESS_THREAD(echo_process, ev, data)
{
PROCESS_BEGIN();
init_uart();
printf("Serial echo ready. Type a line and press Enter.\n");
while(1) {
PROCESS_WAIT_EVENT();
}
PROCESS_END();
}
代码说明
uart1_init():初始化UART1外设,默认波特率115200(可在平台配置中修改)。uart1_set_input():将串口接收到的每个字节送入serial_line模块进行行缓冲。serial_line_set_input():注册行接收完成后的回调函数,当收到换行符时触发。- 回调函数
echo_line_handler将整行数据通过uart1_write_bytes()原样返回,并追加一个换行符便于观察。
构建与运行
以Native平台(模拟器)为例,在Contiki-NG源码根目录执行:
make TARGET=native examples/serial-echo/serial-echo
./examples/serial-echo/serial-echo.native
嵌入式平台(如CC2538DK)则使用:
make TARGET=cc2538dk BOARD=dk examples/serial-echo/serial-echo.upload
验证方法
- 运行程序后,终端显示
Serial echo ready提示。 - 在终端输入任意文本(如
hello)并回车。 - 预期输出:终端立即显示
hello(即输入内容原样返回)。 - 连续输入多行,每行均能正确回显,说明串口收发与字节流处理正常。
通过判定标准:所有输入行均能完整、无乱码地回显,且程序不崩溃、不卡死。
常见问题
- 无回显:检查串口波特率是否匹配(默认115200),确认
uart1_set_input已正确注册。 - 回显乱码:多为波特率不匹配或时钟配置错误,检查平台conf文件中UART时钟源设置。
- Native平台无输出:Native模拟器的串口映射到终端stdin/stdout,需在终端中直接输入。