现在设计一个UART设备的驱动框架,针对AT指令模块和Modbus协议。要整合状态机、时间窗机制,同时满足各种AT指令设备的需求,并且考虑Modbus的解析。
首先,AT指令设备包括ESP32、NB-IoT模块、4G模块等,这些都是通过UART使用AT指令控制的。另外还需要支持Modbus协议,所以框架需要兼容不同协议。
AT指令通常需要状态机来处理异步响应,比如发送AT命令后等待OK或ERROR。同时,多个模块可能同时使用UART,需要考虑如何管理并发请求,需要队列机制。时间窗口机制可能用于处理超时,比如发送指令后在一定时间内没有响应则认为失败。此外,不同的AT模块可能有不同的响应格式,需要可配置的解析方法。
Modbus协议基于主从架构,有固定的报文结构,所以解析部分需要与AT指令分开处理。可能需要不同的解析回调函数。
接下来,需要设计UART驱动结构体,包含基本的发送接收函数,并且支持DMA。设备结构体需要包含AT指令的状态机、命令队列、超时处理,以及Modbus相关的解析参数。状态机的设计是关键。每个AT指令可能需要多个状态:发送命令、等待响应、处理响应、错误处理等。需要通用的状态转移机制,允许用户注册自定义的状态处理函数。
那么对于Modbus,需要处理RTU和ASCII模式,校验计算,超时管理。需要在设备结构体中包含Modbus的专用配置,如从机地址、功能码处理函数等。另外,需要考虑缓冲区管理,接收不定长的数据,如何分割不同的响应帧。环形缓冲区是一个好的选择,同时结合事件触发解析。
现在需要统一的事件处理机制,比如数据接收完成事件、超时事件,触发相应的解析函数。对于AT指令,可能需要将接收到的数据按行分割,逐行处理;而Modbus则需要按报文长度或帧间隔来解析。在代码结构上,驱动层负责底层的UART传输,设备层分为AT指令设备和Modbus设备,各自实现不同的解析逻辑。使用链表管理所有UART设备,当接收到数据时,根据设备配置分发到对应的处理函数。
那么实际在测试过程中,多个设备共享同一个UART端口时的冲突,需要硬件或软件上的片选机制,但UART通常没有硬件片选,所以需要软件控制不同的使能引脚,或者在协议层通过地址区分。需要处理AT指令的并发问题,比如上一个命令还未完成响应,又发送新命令。这时需要命令队列来管理待发送的指令,确保顺序执行。超时处理需要定时器支持,当发送命令后启动定时器,若超时则触发重试或错误回调。时间窗机制可能涉及动态调整超时时间,根据历史响应时间优化。
对于Modbus,需要处理主站和从站的不同角色,但大多数情况下这些模块作为主站,所以框架可能需要支持主站功能,包括生成请求帧和解析响应帧。
1. 定义UART驱动结构体,包含初始化、发送、接收等基本操作,支持中断/DMA。
2. 定义UART设备基类结构体,包含接收缓冲区、事件处理回调、协议类型(AT或Modbus)。
3. 对于AT指令设备,设计状态机、命令队列、超时管理,允许注册自定义命令和响应处理。
4. 对于Modbus设备,设计RTU/ASCII模式支持,校验计算,请求/响应解析函数。
5. 使用链表管理所有设备,数据接收时根据设备配置分发到对应的解析函数。
6. 实现状态机引擎,处理AT指令的状态转移和超时。
7. 实现Modbus协议解析器,处理帧的组装和拆分。
8. 提供统一的API接口,如发送AT命令、发送Modbus请求,处理异步响应。
直接上代码:
#include "stm32f1xx_hal.h"
#include
#include
/* 协议类型枚举 */
typedef enum {
PROTOCOL_AT, // AT指令协议
PROTOCOL_MODBUS // Modbus协议
} UART_ProtocolType;
/* 事件类型定义 */
typedef enum {
EVENT_UART_RX_DATA, // 接收到数据
EVENT_UART_TX_COMPLETE, // 发送完成
EVENT_TIMEOUT, // 超时事件
EVENT_MODBUS_MSG // Modbus报文事件
} UART_EventType;
/* UART驱动结构体 */
typedef struct {
UART_HandleTypeDef *huart; // HAL UART句柄
DMA_HandleTypeDef *hdma_rx; // DMA接收句柄
DMA_HandleTypeDef *hdma_tx; // DMA发送句柄
// 方法抽象
int (*init)(struct UARTDriver *driver);
int (*send)(struct UARTDriver *driver, uint8_t *data, uint16_t len);
int (*receive)(struct UARTDriver *driver, uint16_t len);
} UARTDriver;
/* 通用UART设备基类 */
typedef struct UARTDevice {
char dev_name[16]; // 设备标识
UARTDriver *driver; // 关联的驱动
UART_ProtocolType protocol; // 协议类型
struct list_head list; // 链表节点
// 接收缓冲区管理
uint8_t *rx_buffer; // 环形缓冲区
uint16_t buf_size; // 缓冲区大小
volatile uint16_t wr_idx; // 写索引
volatile uint16_t rd_idx; // 读索引
// 事件回调
void (*eventHandler)(struct UARTDevice *dev, UART_EventType event);
// 协议相关联合体
union {
struct { /* AT指令协议专用 */
struct ATCommand *cmd_queue; // 命令队列
uint8_t q_size; // 队列容量
uint8_t q_front; // 队首索引
uint8_t q_rear; // 队尾索引
uint8_t retry_count; // 当前重试次数
uint32_t timeout; // 超时时间(ms)
void (*responseParser)(struct UARTDevice *dev, char *response);
} at;
struct { /* Modbus协议专用 */
uint8_t slave_addr; // 从机地址
uint32_t last_req_time; // 最后请求时间
uint16_t crc_error_count; // CRC错误计数
void (*modbusHandler)(struct UARTDevice *dev, uint8_t func_code,
uint16_t reg_addr, uint16_t data);
} modbus;
};
} UARTDevice;
/******************** AT指令状态机实现 ********************/
typedef enum {
AT_STATE_IDLE, // 空闲状态
AT_STATE_SENDING, // 发送中
AT_STATE_WAIT_RESPONSE, // 等待响应
AT_STATE_ERROR // 错误状态
} AT_State;
typedef struct ATCommand {
char *command; // AT命令字符串
char *expect_response; // 预期响应
uint8_t max_retries; // 最大重试次数
void (*callback)(struct UARTDevice *dev, int result); // 完成回调
uint32_t timeout; // 命令超时时间
} ATCommand;
/* AT指令状态机上下文 */
typedef struct {
AT_State current_state;
ATCommand current_cmd;
uint32_t state_timer;
} AT_StateMachine;
/* AT指令队列操作 */
int AT_Enqueue_Command(UARTDevice *dev, ATCommand cmd) {
if((dev->at.q_rear + 1) % dev->at.q_size == dev->at.q_front) {
return -1; // 队列满
}
dev->cmd_queue[dev->at.q_rear] = cmd;
dev->at.q_rear = (dev->at.q_rear + 1) % dev->at.q_size;
return 0;
}
/******************** Modbus协议处理 ********************/
typedef enum {
MODBUS_RTU,
MODBUS_ASCII
} ModbusMode;
/* Modbus帧结构 */
typedef struct {
uint8_t slave_addr;
uint8_t func_code;
uint16_t start_addr;
uint16_t reg_count;
uint16_t crc;
} ModbusFrame;
/* CRC16计算 */
uint16_t Modbus_CRC16(uint8_t *data, uint16_t len) {
uint16_t crc = 0xFFFF;
for(int pos = 0; pos < len; pos++) {
crc ^= (uint16_t)data[pos];
for(int i = 8; i != 0; i--) {
if((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
/* Modbus帧解析 */
int Modbus_Parse_Frame(UARTDevice *dev) {
// 实现帧完整性检查和解析
// 返回0表示有效帧,-1表示错误
}
/******************** 通用驱动实现 ********************/
/* 环形缓冲区操作 */
uint16_t UART_Get_Rx_Data(UARTDevice *dev, uint8_t *buf, uint16_t max_len) {
uint16_t available = (dev->wr_idx >= dev->rd_idx) ?
(dev->wr_idx - dev->rd_idx) :
(dev->buf_size - dev->rd_idx + dev->wr_idx);
uint16_t to_read = (available > max_len) ? max_len : available;
for(int i=0; irx_buffer[(dev->rd_idx + i) % dev->buf_size];
}
dev->rd_idx = (dev->rd_idx + to_read) % dev->buf_size;
return to_read;
}
/* UART接收完成回调 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
// 遍历设备链表查找匹配的驱动
struct list_head *pos;
UARTDevice *dev;
list_for_each(pos, &uart_dev_list) {
dev = list_entry(pos, UARTDevice, list);
if(dev->driver->huart == huart) {
dev->eventHandler(dev, EVENT_UART_RX_DATA);
}
}
}
/******************** AT指令状态机处理 ********************/
void AT_State_Machine_Handler(UARTDevice *dev) {
AT_StateMachine *sm = &dev->state_machine;
switch(sm->current_state) {
case AT_STATE_IDLE:
if(dev->at.q_front != dev->at.q_rear) {
sm->current_cmd = dev->cmd_queue[dev->at.q_front];
dev->at.q_front = (dev->at.q_front + 1) % dev->at.q_size;
dev->driver->send(dev->driver,
(uint8_t*)sm->current_cmd.command,
strlen(sm->current_cmd.command));
sm->current_state = AT_STATE_SENDING;
sm->state_timer = HAL_GetTick();
}
break;
case AT_STATE_SENDING:
if(dev->last_event == EVENT_UART_TX_COMPLETE) {
sm->current_state = AT_STATE_WAIT_RESPONSE;
sm->state_timer = HAL_GetTick();
}
break;
case AT_STATE_WAIT_RESPONSE:
if(HAL_GetTick() - sm->state_timer > sm->current_cmd.timeout) {
if(++dev->at.retry_count >= sm->current_cmd.max_retries) {
sm->current_state = AT_STATE_ERROR;
if(sm->current_cmd.callback) {
sm->current_cmd.callback(dev, -1);
}
} else {
sm->current_state = AT_STATE_IDLE; // 重试
}
}
// 响应处理在数据接收事件中完成
break;
case AT_STATE_ERROR:
// 错误恢复处理
break;
}
}
/******************** Modbus协议处理 ********************/
void Modbus_Process_Frame(UARTDevice *dev) {
uint8_t frame[256];
uint16_t len = UART_Get_Rx_Data(dev, frame, sizeof(frame));
if(Modbus_Parse_Frame(dev, frame, len) == 0) {
dev->eventHandler(dev, EVENT_MODBUS_MSG);
}
}
/******************** 设备事件分发 ********************/
void UART_Device_EventHandler(UARTDevice *dev, UART_EventType event) {
switch(dev->protocol) {
case PROTOCOL_AT:
if(event == EVENT_UART_RX_DATA) {
char response[256];
uint16_t len = UART_Get_Rx_Data(dev, (uint8_t*)response, sizeof(response)-1);
response[len] = '\0';
dev->at.responseParser(dev, response);
}
AT_State_Machine_Handler(dev);
break;
case PROTOCOL_MODBUS:
if(event == EVENT_UART_RX_DATA) {
Modbus_Process_Frame(dev);
}
break;
}
}
/******************** 应用示例 ********************/
/* ESP8266 AT指令响应解析示例 */
void ESP8266_Response_Parser(UARTDevice *dev, char *response) {
if(strstr(response, "OK")) {
// 处理成功响应
} else if(strstr(response, "ERROR")) {
// 处理错误响应
}
}
/* Modbus处理函数示例 */
void Modbus_Read_Holding_Regs(UARTDevice *dev, uint8_t func_code,
uint16_t reg_addr, uint16_t data) {
if(func_code == 0x03) {
// 处理保持寄存器读取
}
}
int main(void) {
// 初始化HAL库、时钟、UART等
/* 初始化UART驱动 */
UARTDriver uart1_driver = {
.huart = &huart1,
.init = UART_Driver_Init,
.send = UART_Driver_Send,
.receive = UART_Driver_Receive
};
uart1_driver.init(&uart1_driver);
/* 注册ESP8266设备 */
UARTDevice esp8266 = {
.dev_name = "ESP8266",
.driver = &uart1_driver,
.protocol = PROTOCOL_AT,
.rx_buffer = malloc(256),
.buf_size = 256,
.eventHandler = UART_Device_EventHandler,
.at = {
.cmd_queue = malloc(sizeof(ATCommand)*5),
.q_size = 5,
.responseParser = ESP8266_Response_Parser,
.timeout = 2000
}
};
UART_Device_Register(&esp8266);
/* 注册Modbus设备 */
UARTDevice modbus_sensor = {
.dev_name = "MB_SENSOR",
.driver = &uart1_driver,
.protocol = PROTOCOL_MODBUS,
.rx_buffer = malloc(128),
.buf_size = 128,
.eventHandler = UART_Device_EventHandler,
.modbus = {
.slave_addr = 0x01,
.modbusHandler = Modbus_Read_Holding_Regs
}
};
UART_Device_Register(&modbus_sensor);
/* 发送AT指令示例 */
ATCommand wifi_cmd = {
.command = "AT+CWMODE=1\r\n",
.expect_response = "OK",
.max_retries = 3,
.timeout = 1000,
.callback = NULL
};
AT_Enqueue_Command(&esp8266, wifi_cmd);
/* 主循环 */
while(1) {
// 处理超时事件
if(HAL_GetTick() - last_tick > 100) {
Process_Timeout_Events();
last_tick = HAL_GetTick();
}
}
}
/******************** 高级功能扩展 ********************/
/* 多协议混合解析 */
void Advanced_Protocol_Parser(UARTDevice *dev) {
// 自动检测协议类型
if(dev->rx_buffer[0] == 'A' && dev->rx_buffer[1] == 'T') {
dev->protocol = PROTOCOL_AT;
} else if(dev->rx_buffer[0] == dev->modbus.slave_addr) {
dev->protocol = PROTOCOL_MODBUS;
}
}
/* 自动重连机制 */
typedef struct {
uint32_t connect_interval;
uint8_t max_retries;
void (*reset_procedure)(UARTDevice *dev);
} AutoReconnectCfg;
void Auto_Reconnect_Handler(UARTDevice *dev) {
static uint32_t last_attempt = 0;
if(HAL_GetTick() - last_attempt > dev->auto_reconnect.connect_interval) {
dev->auto_reconnect.reset_procedure(dev);
last_attempt = HAL_GetTick();
}
}
/* 流量控制实现 */
typedef struct {
uint8_t rts_pin;
uint8_t cts_pin;
GPIO_TypeDef *flow_port;
void (*flow_control)(struct UARTDevice *dev, uint8_t state);
} FlowControlCfg;
void Hardware_Flow_Control(UARTDevice *dev, uint8_t state) {
HAL_GPIO_WritePin(dev->flow.flow_port, dev->flow.rts_pin, state);
}
关键设计说明
/* 系统架构层次划分 */
+-----------------------+
| 应用层 | // AT指令应用、Modbus业务逻辑
+-----------------------+
| 协议处理层 | // AT状态机、Modbus解析
+-----------------------+
| 设备驱动层 | // UART驱动、DMA管理
+-----------------------+
| 硬件抽象层(HAL) | // STM32 HAL库
+-----------------------+
/* 增强型状态机设计 */
typedef struct {
AT_State state;
uint32_t timer;
uint8_t retries;
ATCommand *cmd;
void (*transition)(struct StateMachine *sm, UART_EventType event);
} StateMachine;
/* 状态转移表示例 */
const StateTransition transitions[] = {
{AT_STATE_IDLE, EVENT_CMD_QUEUED, AT_STATE_SENDING, SendCommand},
{AT_STATE_SENDING, EVENT_TX_COMPLETE, AT_STATE_WAITING, StartTimeout},
{AT_STATE_WAITING, EVENT_RX_MATCH, AT_STATE_IDLE, ProcessSuccess},
{AT_STATE_WAITING, EVENT_TIMEOUT, AT_STATE_RETRY, HandleRetry}
};
/* Modbus高级功能 */
typedef struct {
uint8_t func_code;
uint16_t (*data_formatter)(uint8_t *raw, uint16_t len);
void (*exception_handler)(uint8_t code);
} ModbusFunctionHandler;
const ModbusFunctionHandler func_handlers[] = {
{0x03, FormatReadRegisters, HandleReadException},
{0x06, FormatWriteRegister, HandleWriteException},
{0x10, FormatWriteRegisters, HandleMultiWriteException}
};
/* 软件流控制配置 */
typedef struct {
uint8_t xon_char;
uint8_t xoff_char;
uint16_t high_watermark;
uint16_t low_watermark;
} SoftwareFlowControl;
void Check_Flow_Control(UARTDevice *dev) {
if(dev->rx_available > dev->flow.high_watermark) {
Send_XOFF(dev);
} else if(dev->rx_available < dev->flow.low_watermark) {
Send_XON(dev);
}
}
/* 设备配置接口 */
typedef struct {
int (*set_baudrate)(UARTDevice *dev, uint32_t baud);
int (*set_parity)(UARTDevice *dev, uint32_t parity);
int (*load_config)(UARTDevice *dev, void *config);
int (*save_config)(UARTDevice *dev, void *config);
} UARTConfigAPI;
const UARTConfigAPI config_ops = {
.set_baudrate = UART_Set_Baudrate,
.set_parity = UART_Set_Parity,
.load_config = Load_Device_Config,
.save_config = Save_Device_Config
};
后续明天写,还有很多要讲,这里面东西还是不少的,拜拜。