串口中断接收协议数据并用状态机解析_printk()打印内容

目标如下:

我想实现串口数据输入,然后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
相关推荐
fitpolo6 天前
Zephyr的SPI
zephyr
toradexsh10 天前
基于 NXP i.MX8M Plus 测试 Zephyr RTOS
arm·rtos·nxp·imx8mp·zephyr
ScilogyHunter1 个月前
Zephyr串口驱动开发及构建完全指南
驱动开发·uart·zephyr
ScilogyHunter1 个月前
Zephyr Hello World应用开发构建完全指南
zephyr·hello world
ScilogyHunter1 个月前
Zephyr Twister测试框架完全指南
zephyr·twister
ScilogyHunter1 个月前
west init 命令详解
init·zephyr·west
ScilogyHunter1 个月前
使用Kconfig配置Zephyr工程完全指南
kconfig·zephyr
ScilogyHunter1 个月前
Zephyr设备树完全指南
zephyr
ScilogyHunter1 个月前
Zephyr项目按需配置完全指南
zephyr