目标如下:
我想实现串口数据输入,然后printk()打印收到的内容, 串口输入的数据格式为 0x55AA 然后是字符TLV, 之后是两字节type字段,两字节length字段,高字节在前,低字节在后,之后是数据内容,根据length字段可知。 串口使用uart1, PA9,PA10. 帮我完成 app.overlay, 和 prj.conf,以及main.c
一. 设备树和prj.conf
设备树不用改, 默认的就有,我也走了弯路,
毕竟我啥也不懂,全靠AI瞎编忽悠我。
prj.conf 内容如下:
c
# 基础内核配置
CONFIG_PRINTK=y
CONFIG_CONSOLE=y
CONFIG_SERIAL=y
# 开启 UART 中断驱动支持(UART1 的硬件启用在 app.overlay 中通过设备树 status = "okay" 完成)
CONFIG_UART_INTERRUPT_DRIVEN=y
# 关闭冗余调试,按需开启
CONFIG_DEBUG=n
CONFIG_LOG=n
二 代码内容如下
就按下面写, 刚开始AI 说用 usart1, 实际编译报错,
就跟AI 说编译不过,让AI 一直改。 最后也就改好了。
还是要懂点基本知识,不然被忽悠,浪费token。
这些代码还是要看懂。 再说吧,现有能运行的代码才能谈看懂。
c
#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/sys/printk.h>
#include <zephyr/devicetree.h>
#include <string.h>
/* 编译期解析节点 usart1,不依赖运行时字符串查找 */
static const struct device *const uart_dev =
DEVICE_DT_GET(DT_NODELABEL(usart1));
/* 接收状态机 */
enum {
WAIT_55,
WAIT_AA,
WAIT_T,
WAIT_L,
WAIT_V,
WAIT_TYPE,
WAIT_LEN,
WAIT_DATA,
};
static uint8_t rx_buf[256];
static uint8_t state = WAIT_55;
static uint16_t type;
static uint16_t length;
static uint16_t data_cnt;
static void parse_byte(uint8_t c)
{
switch (state) {
case WAIT_55:
if (c == 0x55)
state = WAIT_AA;
break;
case WAIT_AA:
if (c == 0xAA)
state = WAIT_T;
else
state = WAIT_55;
break;
case WAIT_T:
state = (c == 'T') ? WAIT_L : WAIT_55;
break;
case WAIT_L:
state = (c == 'L') ? WAIT_V : WAIT_55;
break;
case WAIT_V:
if (c == 'V') {
state = WAIT_TYPE;
data_cnt = 0;
} else {
state = WAIT_55;
}
break;
case WAIT_TYPE:
rx_buf[data_cnt++] = c;
if (data_cnt >= 2) {
type = (rx_buf[0] << 8) | rx_buf[1];
data_cnt = 0;
state = WAIT_LEN;
}
break;
case WAIT_LEN:
rx_buf[data_cnt++] = c;
if (data_cnt >= 2) {
length = (rx_buf[0] << 8) | rx_buf[1];
data_cnt = 0;
state = (length > 0) ? WAIT_DATA : WAIT_55;
}
break;
case WAIT_DATA:
rx_buf[data_cnt++] = c;
if (data_cnt >= length) {
/* 打印接收到的数据 */
printk("TLV Frame Received:\n");
printk("Type: 0x%04X\n", type);
printk("Length: 0x%04X\n", length);
printk("Data:");
for (int i = 0; i < length; i++) {
printk(" %02X", rx_buf[i]);
}
printk("\n");
printk("%s\n", rx_buf);
state = WAIT_55;
}
break;
}
}
static void uart_cb(const struct device *dev, void *user_data)
{
uint8_t c;
while (uart_irq_update(dev) &&
uart_irq_is_pending(dev)) {
if (uart_irq_rx_ready(dev)) {
uart_fifo_read(dev, &c, 1);
parse_byte(c);
}
}
}
int main(void)
{
if (!device_is_ready(uart_dev)) {
printk("UART device not ready\n");
return -1;
}
uart_irq_callback_set(uart_dev, uart_cb);
uart_irq_rx_enable(uart_dev);
printk("complie time:%s %s\n", __DATE__, __TIME__);
printk("UART TLV Receiver Ready\n");
while (1) {
k_msleep(2000);
printk("uptime=%lld ms\n", k_uptime_get());
}
}
三 编译运行
我是直接覆盖了blink例程,所以还是编译samples/basic/blinky例程。
c
cd zephyr
west build -p always -b waveshare_open103z samples/basic/blinky
代码执行结果如下:
串口输入十六进制
55 aa 54 4c 56 0001 0005
然后输入字符ABCDE
c
?*** Booting Zephyr OS build v4.4.0-2726-g3c2422272499 ***
complie time:Jul 17 2026 14:49:04
UART TLV Receiver Ready
uptime=2010 ms
uptime=4011 ms
uptime=6012 ms
TLV Frame Received:
Type: 0x0001
Length: 0x0005
Data: 41 42 43 44 45
ABCDE
uptime=8014 ms
uptime=10015 ms