You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32通过UART组帧收发多字节数据控制触摸传感器LED咨询

ESP32 UART触摸传感器通信实现方案

以下实现基于ESP-IDF官方UART驱动,所有代码可直接在GCC环境下编译运行。

1. UART多字节数据发送实现

ESP-IDF内置了完整的UART驱动,无需手动实现时序,按以下步骤操作即可发送多字节数据:

  • 第一步:配置UART参数(波特率、数据位、停止位、奇偶校验),绑定收发引脚
  • 第二步:安装UART驱动,分配内部缓存
  • 第三步:调用uart_write_bytes接口直接发送任意长度的字节数组

初始化代码示例

#include "driver/uart.h"
#include "esp_err.h"

// 定义UART参数
#define UART_PORT_NUM      UART_NUM_2
#define UART_BAUD_RATE     9600 // 按触摸传感器实际要求修改
#define UART_TX_PIN        17   // 按实际硬件连接修改
#define UART_RX_PIN        16   // 按实际硬件连接修改
#define UART_BUF_SIZE      1024

void uart_init(void) {
    const uart_config_t uart_config = {
        .baud_rate = UART_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    // 配置UART参数
    uart_param_config(UART_PORT_NUM, &uart_config);
    // 绑定引脚
    uart_set_pin(UART_PORT_NUM, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    // 安装驱动,分配收发缓存
    uart_driver_install(UART_PORT_NUM, UART_BUF_SIZE * 2, UART_BUF_SIZE * 2, 0, NULL, 0);
}

发送多字节数据直接调用:

// 示例:发送长度为len的字节数组data
uint8_t data[] = {0x7B, 0x05, 0x03, 0x01, 0x02, 0x06, 0x7D};
int len = sizeof(data);
uart_write_bytes(UART_PORT_NUM, (const char*)data, len);

2. 数据包帧组装实现

必须严格按照协议规则组装帧,否则传感器无法识别指令,组装逻辑如下:

  1. 确定数据域的长度N,整帧总长度L = 1(起始码) + 1(命令) + 1(长度) + N(数据) + 1(校验和) + 1(结束码) = N + 5
  2. 长度字段值为 L - 4,即等于 N + 1
  3. 校验和计算规则:将长度字段和所有数据域的字节累加,取结果的低8位
  4. 按顺序填充帧字节:起始码0x7B -> 命令字节 -> 长度字段 -> 数据域 -> 校验和 -> 结束码0x7D

通用组帧函数示例

/**
 * @brief 组装符合协议的UART帧
 * @param cmd 命令字节
 * @param data 数据域指针
 * @param data_len 数据域长度
 * @param frame_buf 输出的帧缓存,需保证大小足够(至少data_len+5字节)
 * @return 组装完成的帧总长度
 */
int build_uart_frame(uint8_t cmd, uint8_t *data, int data_len, uint8_t *frame_buf) {
    int total_len = data_len + 5;
    // 填充起始码、命令、长度
    frame_buf[0] = 0x7B;
    frame_buf[1] = cmd;
    frame_buf[2] = total_len - 4; // 协议要求长度为L-4
    // 填充数据域
    for (int i = 0; i < data_len; i++) {
        frame_buf[3 + i] = data[i];
    }
    // 计算校验和
    uint8_t checksum = frame_buf[2]; // 先加长度字段
    for (int i = 0; i < data_len; i++) {
        checksum += data[i];
    }
    frame_buf[3 + data_len] = checksum;
    // 填充结束码
    frame_buf[3 + data_len + 1] = 0x7D;
    return total_len;
}

LED控制调用示例

// 启动LED闪烁,周期200ms(对应参数0x02)
uint8_t start_data[] = {0x01, 0x02};
uint8_t start_frame[10] = {0};
int start_frame_len = build_uart_frame(0x05, start_data, sizeof(start_data), start_frame);
uart_write_bytes(UART_PORT_NUM, (const char*)start_frame, start_frame_len);

// 停止LED闪烁
uint8_t stop_data[] = {0x00, 0x00};
uint8_t stop_frame[10] = {0};
int stop_frame_len = build_uart_frame(0x05, stop_data, sizeof(stop_data), stop_frame);
uart_write_bytes(UART_PORT_NUM, (const char*)stop_frame, stop_frame_len);

3. UART响应数据读取实现

使用uart_read_bytes接口即可读取传感器返回的数据,建议设置超时时间避免阻塞,读取后可按协议规则校验帧合法性。

读取响应代码示例

/**
 * @brief 读取UART响应帧
 * @param resp_buf 响应缓存
 * @param buf_size 缓存大小
 * @param timeout_ms 超时时间,单位ms
 * @return 读取到的帧长度,小于0为读取失败
 */
int read_uart_response(uint8_t *resp_buf, int buf_size, int timeout_ms) {
    // 先读取起始码
    uint8_t start_code = 0;
    int len = uart_read_bytes(UART_PORT_NUM, &start_code, 1, pdMS_TO_TICKS(timeout_ms));
    if (len != 1 || start_code != 0x7B) {
        return -1; // 无效起始码
    }
    resp_buf[0] = start_code;
    // 读取到结束码0x7D为止
    int pos = 1;
    while (pos < buf_size) {
        len = uart_read_bytes(UART_PORT_NUM, &resp_buf[pos], 1, pdMS_TO_TICKS(timeout_ms));
        if (len != 1) {
            return -2; // 读取超时
        }
        if (resp_buf[pos] == 0x7D) {
            pos++;
            break;
        }
        pos++;
    }
    // 可选:校验校验和合法性
    uint8_t checksum = resp_buf[2];
    for (int i = 3; i < pos - 2; i++) {
        checksum += resp_buf[i];
    }
    if (checksum != resp_buf[pos - 2]) {
        return -3; // 校验和错误
    }
    return pos;
}

调用示例

uint8_t resp_buf[32] = {0};
int resp_len = read_uart_response(resp_buf, sizeof(resp_buf), 1000);
if (resp_len > 0) {
    // LED控制成功的响应为 0x7B 0x55 0x01 0x01 0x7D
    if (resp_buf[1] == 0x55) {
        // 命令执行成功
    }
}

内容的提问来源于stack exchange,提问作者horsemann07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 10:36:06