串口中断接收协议数据并用状态机解析_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
相关推荐
wotaifuzao5 天前
(十)BLE GATT与ATT深度解剖-从属性表到CCCD-订阅收不到数据的终极答案
低功耗蓝牙·ble·nrf52·zephyr·gatt·cccd
星源~5 天前
zephyr-Linux环境下搭建步骤
linux·mcu·嵌入式开发·zephyr
dozenyaoyida14 天前
Zephyr BLE 上行链路源码拆解:一个空中报文怎么从 radio 跑到应用回调(NCS v3.2.1)
controller·嵌入式开发·ble·host·zephyr·协议栈·软链路层
dozenyaoyida16 天前
Zephyr BLE GATT Server 注册到收发调用链源码解析(NCS v3.2.1)
ble·zephyr·gatt·ble协议栈
iini1 个月前
nRF Connect SDK 开发新体验:VS Code + Claude Code + DeepSeek + Nordic MCP 全流程(蓝牙开发实例)
agent·ai编程·nrf connect sdk·zephyr·蓝牙开发·deepseek·mcp·claude code·nordic mcp
fitpolo2 个月前
详解Zephyr设备树与设备驱动模型
zephyr
乐鑫科技 Espressif2 个月前
用 AI 开发 Zephyr-IoT 应用
人工智能·物联网·esp32·乐鑫科技·zephyr
fitpolo2 个月前
Zephyr的SPI
zephyr
toradexsh2 个月前
基于 NXP i.MX8M Plus 测试 Zephyr RTOS
arm·rtos·nxp·imx8mp·zephyr