4. UART串口通信
任务目标
在Zephyr环境下配置UART外设,实现开发板与PC之间的字符串双向收发。通过串口终端发送字符串至开发板,开发板接收后原样回传(echo),同时开发板主动发送一条启动提示信息,以此验证串口驱动的基本收发流程。
环境与依赖
- 硬件:支持Zephyr的开发板(以
qemu_cortex_m3为例,实际板卡需适配对应DTS) - 软件:Zephyr SDK(≥3.2)、west工具链
- 依赖:
CONFIG_SERIAL=y(Zephyr默认启用)、CONFIG_UART_LINE_CTRL=n(本案例不使用流控)
实现原理
Zephyr的UART驱动基于struct device抽象,通过device_get_binding()获取UART设备实例。轮询模式下使用uart_poll_in()接收单字节、uart_poll_out()发送单字节。本案例采用轮询方式实现简单echo,避免引入中断与DMA的复杂度,聚焦驱动基本API调用。
完整代码
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
/* 获取UART设备,设备树标签为uart0 */
#define UART_DEV DT_NODELABEL(uart0)
void main(void)
{
const struct device *uart_dev;
uint8_t rx_byte;
int ret;
/* 1. 获取UART设备实例 */
uart_dev = DEVICE_DT_GET(UART_DEV);
if (!device_is_ready(uart_dev)) {
printk("UART device not ready\n");
return;
}
/* 2. 发送启动提示 */
const char boot_msg[] = "Zephyr UART Echo Ready!\r\n";
for (int i = 0; boot_msg[i] != '\0'; i++) {
uart_poll_out(uart_dev, boot_msg[i]);
}
/* 3. 轮询接收并回显 */
while (1) {
ret = uart_poll_in(uart_dev, &rx_byte);
if (ret == 0) {
/* 收到字节,原样回传 */
uart_poll_out(uart_dev, rx_byte);
/* 收到回车换行时额外输出换行,便于终端显示 */
if (rx_byte == '\r') {
uart_poll_out(uart_dev, '\n');
}
}
k_msleep(10); /* 避免忙等,降低CPU占用 */
}
}
构建与运行
- 创建项目:在Zephyr工作目录下新建
uart_echo应用,将上述代码保存为src/main.c,并创建prj.conf(本案例无需额外配置,默认串口已启用)。 - 构建(以qemu为例):
west build -b qemu_cortex_m3 -t run - 连接PC串口:若使用真实板卡,通过USB转串口连接开发板UART0对应引脚,PC端使用minicom或PuTTY打开对应串口(波特率115200,8N1)。
验证方法
- 启动提示:程序运行后,串口终端应显示
Zephyr UART Echo Ready!。 - 回显测试:在终端输入任意字符串(如
Hello)并回车,终端应逐字符回显相同内容,且每次回车后额外输出一个换行。 - 通过标准:若终端完整显示启动提示,且输入字符能原样返回(包括回车换行行为正常),则判定UART收发功能验证通过。
常见问题
- 无输出:检查开发板UART引脚映射是否与
uart0一致;确认终端波特率与Zephyr设备树中current-speed属性匹配(默认115200)。 - 乱码:多为波特率不匹配或接地问题,检查串口线连接与终端设置。
- qemu下无串口交互:qemu的UART默认映射到stdio,需在终端窗口直接输入字符测试,无需额外连接。