240 lines
7.4 KiB
C
240 lines
7.4 KiB
C
/**
|
||
* @file protocol.h
|
||
* @brief EDC 通讯协议 — I2C / UART 双通道, Cycle 收发, CRC16 校验
|
||
*
|
||
* 顶层概念:
|
||
* Point = { x, y, angle_x10 }
|
||
* Fragment = { source: Point, target: Point }
|
||
* Cycle = { cycle_id, frag_count (2~4), fragments[] }
|
||
*
|
||
* 帧格式 (大端序):
|
||
* ┌──────┬──────┬──────┬──────┬───────────────────┬──────────┐
|
||
* │ SOF1 │ SOF2 │ CMD │ LEN │ DATA (N bytes) │ CRC16 │
|
||
* │ 0xAA │ 0x55 │ 1B │ 1B │ variable │ 2B (LE) │
|
||
* └──────┴──────┴──────┴──────┴───────────────────┴──────────┘
|
||
* ◄──────── CRC 计算范围 (CMD + LEN + DATA) ─────────►
|
||
*
|
||
* Cycle 数据帧 DATA 区:
|
||
* cycle_id(2B, BE) + frag_count(1B, 2~4) + fragments(N × 12B)
|
||
*
|
||
* Fragment (12B, 大端):
|
||
* src.x(2B) src.y(2B) src.angle(2B) dst.x(2B) dst.y(2B) dst.angle(2B)
|
||
*
|
||
* 交互流程:
|
||
* MPU ──[CYCLE_DATA]──► MCU (I2C + UART 冗余下发)
|
||
* MCU ──[CYCLE_DONE]──► MPU (UART 上报完成, 含 cycle_id)
|
||
* MCU ──[CYCLE_REQ]───► MPU (UART 请求下一 Cycle)
|
||
*/
|
||
|
||
#ifndef EDC_PROTOCOL_H
|
||
#define EDC_PROTOCOL_H
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
#include <stddef.h>
|
||
#include "driver/gpio.h"
|
||
#include "driver/uart.h"
|
||
#include "driver/i2c_slave.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* ================================================================
|
||
* 协议常量
|
||
* ================================================================ */
|
||
|
||
#define EDC_PROTO_SOF1 0xAA
|
||
#define EDC_PROTO_SOF2 0x55
|
||
|
||
#define EDC_PROTO_FRAME_MAX 80 /* 最大帧长: 2+1+1+3+4*12+2 = 57 < 80 */
|
||
#define EDC_PROTO_FRAME_MIN 6 /* SOF(2) + CMD(1) + LEN(1) + CRC(2) */
|
||
|
||
#define EDC_FRAG_MIN 2 /* 每 Cycle 最少 fragment 数 */
|
||
#define EDC_FRAG_MAX 4 /* 每 Cycle 最多 fragment 数 */
|
||
#define EDC_FRAG_BYTES 12 /* 单个 fragment 字节数 (3×uint16×2) */
|
||
|
||
/* ---- I2C 默认 ---- */
|
||
#define EDC_I2C_PORT_DEFAULT 0
|
||
#define EDC_I2C_SLAVE_ADDR 0x2A
|
||
#define EDC_I2C_SDA_DEFAULT GPIO_NUM_2
|
||
#define EDC_I2C_SCL_DEFAULT GPIO_NUM_3
|
||
#define EDC_I2C_BUF_SIZE 256
|
||
|
||
/* ---- UART 默认 ---- */
|
||
#define EDC_UART_PORT_DEFAULT UART_NUM_0
|
||
#define EDC_UART_BAUDRATE 115200
|
||
#define EDC_UART_RX_DEFAULT GPIO_NUM_12
|
||
#define EDC_UART_TX_DEFAULT GPIO_NUM_11
|
||
#define EDC_UART_BUF_SIZE 512
|
||
|
||
/* ================================================================
|
||
* 命令字
|
||
* ================================================================ */
|
||
|
||
typedef enum {
|
||
EDC_CMD_CYCLE_DATA = 0x01, /* MPU → MCU: 下发 Cycle 数据 */
|
||
EDC_CMD_CYCLE_DONE = 0x02, /* MCU → MPU: Cycle 执行完成 */
|
||
EDC_CMD_CYCLE_REQUEST = 0x03, /* MCU → MPU: 请求下一个 Cycle */
|
||
EDC_CMD_RECOGNIZE = 0x04, /* MCU → MPU: 触发视觉识别 */
|
||
EDC_CMD_ACK = 0x80, /* 通用应答 */
|
||
EDC_CMD_NACK = 0xFF, /* 错误 */
|
||
} edc_cmd_t;
|
||
|
||
/* ================================================================
|
||
* 数据结构
|
||
* ================================================================ */
|
||
|
||
/** 单个坐标点 (source 或 target) */
|
||
typedef struct {
|
||
uint16_t x;
|
||
uint16_t y;
|
||
uint16_t angle_x10; /* 角度 × 10, 如 450 = 45.0° */
|
||
} edc_point_t;
|
||
|
||
/** 一个运动片段: 从 source 移动到 target */
|
||
typedef struct {
|
||
edc_point_t source;
|
||
edc_point_t target;
|
||
} edc_fragment_t;
|
||
|
||
/** 一个 Cycle: 包含 2~4 个 fragment */
|
||
typedef struct {
|
||
uint16_t cycle_id;
|
||
uint8_t frag_count; /* 实际 fragment 数 (2~4) */
|
||
edc_fragment_t fragments[EDC_FRAG_MAX];
|
||
uint32_t timestamp_ms; /* 本地时间戳 (不随帧传输) */
|
||
} edc_cycle_t;
|
||
|
||
/** 帧来源通道 */
|
||
typedef enum {
|
||
EDC_CH_NONE = 0,
|
||
EDC_CH_I2C = 1,
|
||
EDC_CH_UART = 2,
|
||
} edc_channel_t;
|
||
|
||
/** 每通道统计 */
|
||
typedef struct {
|
||
uint32_t cycles_ok;
|
||
uint32_t cycles_err;
|
||
uint32_t bytes_total;
|
||
} edc_channel_stat_t;
|
||
|
||
/** 统一收发统计 */
|
||
typedef struct {
|
||
edc_channel_stat_t i2c;
|
||
edc_channel_stat_t uart;
|
||
edc_channel_t last_channel;
|
||
uint32_t last_tick;
|
||
uint32_t done_sent; /* 已发送 DONE 次数 */
|
||
uint32_t request_sent; /* 已发送 REQUEST 次数 */
|
||
} edc_proto_stat_t;
|
||
|
||
/** 帧解析状态 */
|
||
typedef enum {
|
||
EDC_PARSE_OK = 0,
|
||
EDC_PARSE_WAITING = 1,
|
||
EDC_PARSE_CRC_ERR = -1,
|
||
EDC_PARSE_LEN_ERR = -2,
|
||
EDC_PARSE_SOF_ERR = -3,
|
||
EDC_PARSE_CMD_ERR = -4,
|
||
} edc_parse_result_t;
|
||
|
||
/** 帧解析上下文 (逐字节喂入) */
|
||
typedef struct {
|
||
uint8_t buf[EDC_PROTO_FRAME_MAX];
|
||
uint8_t len;
|
||
uint8_t idx;
|
||
edc_parse_result_t state;
|
||
} edc_frame_ctx_t;
|
||
|
||
/* ================================================================
|
||
* 配置
|
||
* ================================================================ */
|
||
|
||
typedef struct {
|
||
bool i2c_enable;
|
||
int i2c_port;
|
||
uint16_t i2c_addr;
|
||
gpio_num_t i2c_sda;
|
||
gpio_num_t i2c_scl;
|
||
|
||
bool uart_enable;
|
||
uart_port_t uart_port;
|
||
int uart_baudrate;
|
||
gpio_num_t uart_rx;
|
||
gpio_num_t uart_tx;
|
||
} edc_proto_config_t;
|
||
|
||
/* ================================================================
|
||
* CRC16 / 组帧 / 逐字节解析 (底层)
|
||
* ================================================================ */
|
||
|
||
uint16_t edc_crc16(const uint8_t *data, size_t len);
|
||
|
||
/** 将 Cycle 序列化为协议字节流 (含帧头与 CRC) */
|
||
int edc_cycle_pack(const edc_cycle_t *cycle, uint8_t *out);
|
||
|
||
/** 逐字节解析器 (与旧版兼容, 内部使用 edc_cycle_parse_byte) */
|
||
edc_parse_result_t edc_cycle_parse_byte(edc_frame_ctx_t *ctx, uint8_t byte,
|
||
edc_cycle_t *cycle);
|
||
|
||
/** 从完整缓冲区一次性解析 Cycle */
|
||
edc_parse_result_t edc_cycle_parse_buf(const uint8_t *data, size_t len,
|
||
edc_cycle_t *cycle);
|
||
|
||
/* ================================================================
|
||
* 统一收发器 API (I2C 从机 + UART 双向)
|
||
* ================================================================ */
|
||
|
||
/**
|
||
* @brief 初始化协议栈 (I2C 从机 + UART)
|
||
* @param cfg 传 NULL 使用默认值
|
||
*/
|
||
void edc_proto_init(const edc_proto_config_t *cfg);
|
||
|
||
/**
|
||
* @brief 轮询双通道接收 + 返回最新 Cycle (非阻塞)
|
||
* @return >0: 有新 Cycle; 0: 无; <0: 错误
|
||
*/
|
||
int edc_proto_poll(edc_cycle_t *cycle);
|
||
|
||
/**
|
||
* @brief 发送 CYCLE_DONE (通过 UART)
|
||
* @param cycle_id 已完成的 Cycle ID
|
||
*/
|
||
void edc_proto_send_done(uint16_t cycle_id);
|
||
|
||
/**
|
||
* @brief 发送 CYCLE_REQUEST (通过 UART)
|
||
*/
|
||
void edc_proto_send_request(void);
|
||
|
||
/**
|
||
* @brief 发送 RECOGNIZE 触发视觉识别 (通过 UART)
|
||
*/
|
||
void edc_proto_send_recognize(void);
|
||
|
||
/**
|
||
* @brief 获取统计信息
|
||
*/
|
||
void edc_proto_get_stats(edc_proto_stat_t *stat);
|
||
|
||
/* ---- FreeRTOS 任务 + 回调 ---- */
|
||
|
||
void edc_proto_task(void *pvParam);
|
||
|
||
/**
|
||
* @brief Cycle 回调 (弱符号, 用户实现)
|
||
* @param cycle 已校验的有效 Cycle
|
||
* @param ch 来源通道
|
||
*/
|
||
void edc_proto_on_cycle(const edc_cycle_t *cycle, edc_channel_t ch);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* EDC_PROTOCOL_H */
|
||
|