一、系统架构设计
1.1 整体架构
WiFi网络 ↔ ESP8266/ESP32 ↔ UART ↔ STM32 ↔ CAN ↔ CAN总线设备
(AT指令) (协议转换) (CAN帧)
1.2 数据流向
- 下行:WiFi数据 → ESP8266串口透传 → STM32解析 → CAN总线发送
- 上行:CAN总线接收 → STM32封装 → ESP8266串口发送 → WiFi网络
二、硬件连接方案
2.1 元器件清单
| 组件 | 型号 | 说明 |
|---|---|---|
| 主控MCU | STM32F103C8T6/F407 | 带CAN和UART外设 |
| WiFi模块 | ESP8266-01S/ESP32 | 支持AT指令透传 |
| CAN收发器 | TJA1050/SN65HVD230 | 5V转CAN电平 |
| 电平转换 | AMS1117-3.3V | ESP8266需3.3V供电 |
| 串口转换 | CH340G | 调试用USB转串口 |
2.2 引脚连接(以STM32F103C8T6为例)
| STM32引脚 | 连接目标 | 功能 | 备注 |
|---|---|---|---|
| PA9 | ESP8266 TX | USART1_RX | WiFi模块发送 |
| PA10 | ESP8266 RX | USART1_TX | WiFi模块接收 |
| PA11 | CAN收发器 RX | CAN1_RX | CAN接收 |
| PA12 | CAN收发器 TX | CAN1_TX | CAN发送 |
| PB6 | CH340G TX | USART1_TX | 调试输出 |
| PB7 | CH340G RX | USART1_RX | 调试输入 |
| 3.3V | ESP8266 VCC | 电源 | 最大电流300mA |
| GND | 所有模块GND | 地 | 必须共地 |
⚠️ 注意:ESP8266工作电压为3.3V,STM32的5V引脚需通过AMS1117降压到3.3V供电。
三、软件架构设计
3.1 模块划分
├── 主程序 (main.c)
├── WiFi驱动层 (wifi.c/h)
│ ├── AT指令解析
│ ├── TCP/UDP连接管理
│ └── 数据透传处理
├── CAN驱动层 (can.c/h)
│ ├── CAN初始化配置
│ ├── 帧发送/接收
│ └── 滤波器设置
├── 协议转换层 (protocol.c/h)
│ ├── 数据分包/重组
│ ├── 帧格式定义
│ └── CRC校验
└── 系统服务层 (system.c/h)
├── 状态机管理
├── 错误处理
└── 日志输出
3.2 通信协议设计
参考工业网关设计,采用帧头+命令+数据+校验的格式:
+--------+--------+--------+--------+--------+--------+--------+
| 帧头 | 命令 | 目标 | 长度 | 数据 | CRC16 | 帧尾 |
| 2字节 | 1字节 | 1字节 | 2字节 | N字节 | 2字节 | 2字节 |
| 0xAA55 | | | | | | 0x55AA |
+--------+--------+--------+--------+--------+--------+--------+
字段说明:
- 命令:0x01=WiFi→CAN发送,0x02=CAN→WiFi转发,0x03=配置参数
- 目标:高4位接口类型(0x4=CAN),低4位端口号(0x0=CAN1)
- 长度:数据段长度(最大1024字节)
- CRC16:采用MODBUS多项式0xA001
四、核心代码实现
4.1 CAN初始化配置
c
// can.h
#ifndef __CAN_H
#define __CAN_H
#include "stm32f1xx_hal.h"
#define CAN_TX_ID 0x123 // 发送ID
#define CAN_RX_ID 0x456 // 接收ID
#define CAN_MAX_DATA_LEN 8 // CAN标准帧最大数据长度
typedef struct {
uint32_t id; // 帧ID
uint8_t data[8]; // 数据
uint8_t len; // 数据长度
uint8_t format; // 0=标准帧,1=扩展帧
uint8_t type; // 0=数据帧,1=远程帧
} CAN_FrameTypeDef;
// 函数声明
void CAN_Init(uint32_t baudrate);
uint8_t CAN_SendFrame(CAN_FrameTypeDef *frame);
uint8_t CAN_ReceiveFrame(CAN_FrameTypeDef *frame);
void CAN_SetFilter(uint32_t filter_id, uint32_t mask);
#endif
c
// can.c
#include "can.h"
CAN_HandleTypeDef hcan;
CAN_FilterTypeDef can_filter;
// CAN初始化
void CAN_Init(uint32_t baudrate)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 9; // 分频系数
hcan.Init.Mode = CAN_MODE_NORMAL; // 正常模式
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_13TQ; // BS1=13
hcan.Init.TimeSeg2 = CAN_BS2_2TQ; // BS2=2
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = ENABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
// 初始化CAN
if (HAL_CAN_Init(&hcan) != HAL_OK) {
Error_Handler();
}
// 配置滤波器(接收所有帧)
can_filter.FilterBank = 0;
can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
can_filter.FilterIdHigh = 0x0000;
can_filter.FilterIdLow = 0x0000;
can_filter.FilterMaskIdHigh = 0x0000;
can_filter.FilterMaskIdLow = 0x0000;
can_filter.FilterFIFOAssignment = CAN_RX_FIFO0;
can_filter.FilterActivation = ENABLE;
can_filter.SlaveStartFilterBank = 14;
HAL_CAN_ConfigFilter(&hcan, &can_filter);
// 启动CAN
HAL_CAN_Start(&hcan);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
}
// 发送CAN帧
uint8_t CAN_SendFrame(CAN_FrameTypeDef *frame)
{
CAN_TxHeaderTypeDef tx_header;
uint32_t tx_mailbox;
tx_header.StdId = frame->id;
tx_header.ExtId = 0;
tx_header.RTR = frame->type;
tx_header.IDE = frame->format;
tx_header.DLC = frame->len;
tx_header.TransmitGlobalTime = DISABLE;
if (HAL_CAN_AddTxMessage(&hcan, &tx_header, frame->data, &tx_mailbox) != HAL_OK) {
return 0;
}
// 等待发送完成
while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 3);
return 1;
}
// CAN接收中断回调
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef rx_header;
CAN_FrameTypeDef rx_frame;
// 读取CAN帧
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_frame.data);
rx_frame.id = rx_header.StdId;
rx_frame.len = rx_header.DLC;
rx_frame.format = rx_header.IDE;
rx_frame.type = rx_header.RTR;
// 将CAN帧放入处理队列
Protocol_ProcessCANFrame(&rx_frame);
}
4.2 WiFi模块驱动(ESP8266)
c
// wifi.h
#ifndef __WIFI_H
#define __WIFI_H
#include "stm32f1xx_hal.h"
#define WIFI_BUFFER_SIZE 1024
#define WIFI_TIMEOUT_MS 5000
typedef enum {
WIFI_STATE_RESET = 0,
WIFI_STATE_READY,
WIFI_STATE_CONNECTING,
WIFI_STATE_CONNECTED,
WIFI_STATE_ERROR
} WIFI_StateTypeDef;
// 函数声明
void WIFI_Init(UART_HandleTypeDef *huart);
uint8_t WIFI_ConnectAP(const char *ssid, const char *password);
uint8_t WIFI_ConnectServer(const char *ip, uint16_t port);
uint8_t WIFI_SendData(uint8_t *data, uint16_t len);
void WIFI_ReceiveCallback(uint8_t *data, uint16_t len);
#endif
c
// wifi.c
#include "wifi.h"
#include "string.h"
#include "stdio.h"
UART_HandleTypeDef *wifi_huart;
WIFI_StateTypeDef wifi_state = WIFI_STATE_RESET;
uint8_t wifi_rx_buffer[WIFI_BUFFER_SIZE];
uint16_t wifi_rx_index = 0;
// AT指令发送
static uint8_t WIFI_SendATCommand(const char *cmd, const char *expect, uint32_t timeout)
{
char response[128];
uint32_t start_time = HAL_GetTick();
// 发送AT指令
HAL_UART_Transmit(wifi_huart, (uint8_t*)cmd, strlen(cmd), 1000);
HAL_UART_Transmit(wifi_huart, (uint8_t*)"\r\n", 2, 100);
// 等待响应
while (HAL_GetTick() - start_time < timeout) {
if (HAL_UART_Receive(wifi_huart, (uint8_t*)response, sizeof(response)-1, 10) == HAL_OK) {
response[sizeof(response)-1] = '\0';
if (strstr(response, expect) != NULL) {
return 1; // 成功
}
if (strstr(response, "ERROR") != NULL) {
return 0; // 失败
}
}
}
return 0; // 超时
}
// WiFi初始化
void WIFI_Init(UART_HandleTypeDef *huart)
{
wifi_huart = huart;
// 重启模块
HAL_Delay(1000);
WIFI_SendATCommand("AT+RST", "ready", 3000);
HAL_Delay(2000);
// 设置模式为STA
if (WIFI_SendATCommand("AT+CWMODE=1", "OK", 1000)) {
wifi_state = WIFI_STATE_READY;
}
}
// 连接WiFi热点
uint8_t WIFI_ConnectAP(const char *ssid, const char *password)
{
char cmd[128];
if (wifi_state != WIFI_STATE_READY) {
return 0;
}
sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", ssid, password);
if (WIFI_SendATCommand(cmd, "OK", 10000)) {
wifi_state = WIFI_STATE_CONNECTING;
return 1;
}
return 0;
}
// 连接TCP服务器
uint8_t WIFI_ConnectServer(const char *ip, uint16_t port)
{
char cmd[64];
// 设置单连接模式
if (!WIFI_SendATCommand("AT+CIPMUX=0", "OK", 1000)) {
return 0;
}
// 建立TCP连接
sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%d", ip, port);
if (WIFI_SendATCommand(cmd, "CONNECT", 5000)) {
wifi_state = WIFI_STATE_CONNECTED;
// 进入透传模式
WIFI_SendATCommand("AT+CIPMODE=1", "OK", 1000);
WIFI_SendATCommand("AT+CIPSEND", ">", 1000);
return 1;
}
return 0;
}
// 串口接收中断处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == wifi_huart) {
uint8_t data;
HAL_UART_Receive_IT(wifi_huart, &data, 1);
// 处理接收数据
if (wifi_rx_index < WIFI_BUFFER_SIZE - 1) {
wifi_rx_buffer[wifi_rx_index++] = data;
// 检测帧结束(换行符或特定协议)
if (data == '\n' || wifi_rx_index >= WIFI_BUFFER_SIZE - 1) {
wifi_rx_buffer[wifi_rx_index] = '\0';
Protocol_ProcessWiFiData(wifi_rx_buffer, wifi_rx_index);
wifi_rx_index = 0;
}
}
}
}
4.3 协议转换层
c
// protocol.h
#ifndef __PROTOCOL_H
#define __PROTOCOL_H
#include <stdint.h>
#define PROTOCOL_HEADER 0xAA55
#define PROTOCOL_TAIL 0x55AA
#define MAX_DATA_LEN 1024
#define CAN_MAX_PACKET_SIZE 8
// 命令定义
typedef enum {
CMD_WIFI_TO_CAN = 0x01, // WiFi数据转发到CAN
CMD_CAN_TO_WIFI = 0x02, // CAN数据转发到WiFi
CMD_CONFIG_CAN = 0x03, // 配置CAN参数
CMD_CONFIG_WIFI = 0x04, // 配置WiFi参数
CMD_QUERY_STATUS = 0x05, // 查询状态
} Protocol_CommandTypeDef;
// 协议帧结构
#pragma pack(push, 1)
typedef struct {
uint16_t header; // 帧头 0xAA55
uint8_t command; // 命令
uint8_t target; // 目标接口
uint16_t length; // 数据长度
uint8_t data[MAX_DATA_LEN]; // 数据
uint16_t crc16; // CRC校验
uint16_t tail; // 帧尾 0x55AA
} Protocol_FrameTypeDef;
#pragma pack(pop)
// 函数声明
uint16_t Protocol_CRC16(uint8_t *data, uint16_t len);
uint8_t Protocol_PackWiFiToCAN(uint8_t *wifi_data, uint16_t wifi_len,
CAN_FrameTypeDef *can_frames, uint8_t *frame_count);
uint8_t Protocol_UnpackCANToWiFi(CAN_FrameTypeDef *can_frame, uint8_t *wifi_data, uint16_t *wifi_len);
void Protocol_ProcessWiFiData(uint8_t *data, uint16_t len);
void Protocol_ProcessCANFrame(CAN_FrameTypeDef *frame);
#endif
c
// protocol.c
#include "protocol.h"
#include "can.h"
#include "wifi.h"
#include "string.h"
// CRC16计算(MODBUS)
uint16_t Protocol_CRC16(uint8_t *data, uint16_t len)
{
uint16_t crc = 0xFFFF;
uint16_t i, j;
for (i = 0; i < len; i++) {
crc ^= data[i];
for (j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
// WiFi数据打包为CAN帧(支持分包)
uint8_t Protocol_PackWiFiToCAN(uint8_t *wifi_data, uint16_t wifi_len,
CAN_FrameTypeDef *can_frames, uint8_t *frame_count)
{
uint16_t offset = 0;
uint8_t packet_index = 0;
uint8_t total_packets = (wifi_len + CAN_MAX_PACKET_SIZE - 1) / CAN_MAX_PACKET_SIZE;
if (total_packets > 16) { // 最多16个包
return 0;
}
while (offset < wifi_len && packet_index < 16) {
uint8_t data_len = (wifi_len - offset) > CAN_MAX_PACKET_SIZE ?
CAN_MAX_PACKET_SIZE : (wifi_len - offset);
// 构建CAN帧头
can_frames[packet_index].id = CAN_TX_ID;
can_frames[packet_index].len = data_len + 4; // 4字节控制头
can_frames[packet_index].format = 0; // 标准帧
can_frames[packet_index].type = 0; // 数据帧
// 控制头
can_frames[packet_index].data[0] = (total_packets == 1) ? 0x01 : // 单帧
(packet_index == 0) ? 0x02 : // 分包起始
(offset + data_len >= wifi_len) ? 0x04 : 0x03; // 分包结束/中间
can_frames[packet_index].data[1] = total_packets; // 总包数
can_frames[packet_index].data[2] = packet_index; // 当前包序号
can_frames[packet_index].data[3] = data_len; // 数据长度
// 复制数据
memcpy(&can_frames[packet_index].data[4], &wifi_data[offset], data_len);
offset += data_len;
packet_index++;
}
*frame_count = packet_index;
return 1;
}
// CAN帧解包为WiFi数据
uint8_t Protocol_UnpackCANToWiFi(CAN_FrameTypeDef *can_frame, uint8_t *wifi_data, uint16_t *wifi_len)
{
static uint8_t reassembly_buffer[1024];
static uint16_t reassembly_len = 0;
static uint8_t expected_packets = 0;
static uint8_t received_packets = 0;
uint8_t frame_type = can_frame->data[0];
uint8_t total_packets = can_frame->data[1];
uint8_t packet_index = can_frame->data[2];
uint8_t data_len = can_frame->data[3];
if (frame_type == 0x01) { // 单帧
memcpy(wifi_data, &can_frame->data[4], data_len);
*wifi_len = data_len;
return 1;
}
else if (frame_type == 0x02) { // 分包起始
expected_packets = total_packets;
received_packets = 1;
reassembly_len = 0;
memcpy(reassembly_buffer, &can_frame->data[4], data_len);
reassembly_len = data_len;
}
else if (frame_type == 0x03 || frame_type == 0x04) { // 分包数据/结束
if (packet_index == received_packets) {
memcpy(&reassembly_buffer[reassembly_len], &can_frame->data[4], data_len);
reassembly_len += data_len;
received_packets++;
if (frame_type == 0x04 || received_packets == expected_packets) {
memcpy(wifi_data, reassembly_buffer, reassembly_len);
*wifi_len = reassembly_len;
return 1;
}
}
}
return 0;
}
// 处理WiFi接收数据
void Protocol_ProcessWiFiData(uint8_t *data, uint16_t len)
{
Protocol_FrameTypeDef *frame = (Protocol_FrameTypeDef *)data;
// 验证帧头帧尾
if (frame->header != PROTOCOL_HEADER || frame->tail != PROTOCOL_TAIL) {
return;
}
// 验证CRC
uint16_t calc_crc = Protocol_CRC16(&frame->command, frame->length + 3); // command+target+length+data
if (calc_crc != frame->crc16) {
return;
}
// 根据命令处理
switch (frame->command) {
case CMD_WIFI_TO_CAN: {
CAN_FrameTypeDef can_frames[16];
uint8_t frame_count;
if (Protocol_PackWiFiToCAN(frame->data, frame->length, can_frames, &frame_count)) {
for (int i = 0; i < frame_count; i++) {
CAN_SendFrame(&can_frames[i]);
}
}
break;
}
case CMD_CONFIG_CAN:
// 配置CAN参数(波特率、滤波器等)
break;
case CMD_QUERY_STATUS:
// 返回状态信息
break;
}
}
// 处理CAN接收数据
void Protocol_ProcessCANFrame(CAN_FrameTypeDef *frame)
{
uint8_t wifi_data[1024];
uint16_t wifi_len;
if (Protocol_UnpackCANToWiFi(frame, wifi_data, &wifi_len)) {
// 构建协议帧
Protocol_FrameTypeDef protocol_frame;
protocol_frame.header = PROTOCOL_HEADER;
protocol_frame.command = CMD_CAN_TO_WIFI;
protocol_frame.target = 0x40; // CAN接口
protocol_frame.length = wifi_len;
memcpy(protocol_frame.data, wifi_data, wifi_len);
// 计算CRC(不包括帧头帧尾)
uint16_t crc_len = 1 + 1 + 2 + wifi_len; // command+target+length+data
protocol_frame.crc16 = Protocol_CRC16((uint8_t*)&protocol_frame.command, crc_len);
protocol_frame.tail = PROTOCOL_TAIL;
// 通过WiFi发送
WIFI_SendData((uint8_t*)&protocol_frame, sizeof(protocol_frame.header) + crc_len +
sizeof(protocol_frame.crc16) + sizeof(protocol_frame.tail));
}
}
4.4 主程序框架
c
// main.c
#include "main.h"
#include "can.h"
#include "wifi.h"
#include "protocol.h"
#include "stdio.h"
UART_HandleTypeDef huart1; // WiFi串口
UART_HandleTypeDef huart2; // 调试串口
CAN_HandleTypeDef hcan1;
// 系统状态
typedef enum {
SYS_INIT = 0,
SYS_WIFI_CONNECTING,
SYS_WIFI_CONNECTED,
SYS_RUNNING,
SYS_ERROR
} SystemStateTypeDef;
SystemStateTypeDef system_state = SYS_INIT;
int main(void)
{
// HAL库初始化
HAL_Init();
SystemClock_Config();
// 外设初始化
MX_GPIO_Init();
MX_USART1_UART_Init(); // WiFi串口
MX_USART2_UART_Init(); // 调试串口
MX_CAN1_Init();
// 模块初始化
CAN_Init(500000); // CAN波特率500kbps
WIFI_Init(&huart1);
printf("WiFi-CAN Gateway Starting...\r\n");
// 连接WiFi
printf("Connecting to WiFi...\r\n");
if (WIFI_ConnectAP("Your_SSID", "Your_Password")) {
printf("WiFi Connected!\r\n");
system_state = SYS_WIFI_CONNECTING;
} else {
printf("WiFi Connection Failed!\r\n");
system_state = SYS_ERROR;
}
// 连接TCP服务器
printf("Connecting to Server...\r\n");
if (WIFI_ConnectServer("192.168.1.100", 8080)) {
printf("Server Connected!\r\n");
system_state = SYS_WIFI_CONNECTED;
} else {
printf("Server Connection Failed!\r\n");
system_state = SYS_ERROR;
}
// 开启中断
HAL_UART_Receive_IT(&huart1, wifi_rx_byte, 1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
system_state = SYS_RUNNING;
printf("Gateway Ready!\r\n");
// 主循环
while (1) {
// 状态指示灯
if (system_state == SYS_RUNNING) {
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(500);
}
// 系统监控
System_Monitor();
HAL_Delay(10);
}
}
// 系统监控函数
void System_Monitor(void)
{
static uint32_t last_heartbeat = 0;
// 发送心跳包(每30秒)
if (HAL_GetTick() - last_heartbeat > 30000) {
uint8_t heartbeat[] = "HEARTBEAT";
WIFI_SendData(heartbeat, sizeof(heartbeat));
last_heartbeat = HAL_GetTick();
}
// 检查WiFi连接状态
if (system_state == SYS_RUNNING) {
// 可以定期发送AT命令检查连接
}
}
五、通信协议示例
5.1 WiFi到CAN数据流
WiFi数据: AA 55 01 40 00 08 11 22 33 44 55 66 77 88 XX XX 55 AA
│ │ │ │ │ └─ 数据: 8字节
│ │ │ │ └─ 长度: 0x0008
│ │ │ └─ 目标: 0x40 (CAN1)
│ │ └─ 命令: 0x01 (WiFi→CAN)
│ └─ 帧头: 0xAA55
└─ 解析后发送CAN帧:
CAN ID: 0x123
CAN数据: 01 01 00 08 11 22 33 44 55 66 77 88
5.2 CAN到WiFi数据流
CAN接收: ID=0x456, 数据=01 01 00 04 AA BB CC DD
│
└─ 解包后WiFi数据:
AA 55 02 40 00 04 AA BB CC DD XX XX 55 AA
参考代码 STM32 串口转CAN,接入WIFI模块,可实现WIFI转CAN www.youwenfan.com/contentcsv/103069.html
六、调试与测试
6.1 测试工具
| 工具 | 用途 |
|---|---|
| CANalyzer/CANoe | CAN总线分析 |
| 串口调试助手 | WiFi模块AT指令测试 |
| 网络调试助手 | TCP/UDP通信测试 |
| Wireshark | 网络抓包分析 |
6.2 测试步骤
-
硬件连接测试
- 测量各模块供电电压(ESP8266必须3.3V)
- 检查串口通信(发送AT指令看响应)
- 检查CAN总线终端电阻(120Ω)
-
WiFi模块测试
cAT // 测试通信 AT+RST // 重启 AT+CWMODE=1 // STA模式 AT+CWJAP="SSID","password" // 连接WiFi AT+CIPSTART="TCP","192.168.1.100",8080 // 连接服务器 -
CAN通信测试
- 使用CAN测试仪发送标准帧
- 观察WiFi端是否收到数据
- 测试大数据分包传输
-
压力测试
- 连续发送1000帧数据
- 测试最大数据长度(1024字节)
- 测试长时间运行稳定性
七、常见问题解决
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| ESP8266不响应 | 供电不足/电压不对 | 确保3.3V供电,电流>300mA |
| CAN通信失败 | 波特率不匹配/终端电阻缺失 | 检查两端波特率设置,添加120Ω终端电阻 |
| 数据丢失 | 缓冲区溢出/处理速度慢 | 增大缓冲区,优化中断处理 |
| WiFi频繁断开 | 信号弱/路由器设置 | 调整天线位置,检查路由器MAC过滤 |
| 分包重组错误 | 序号混乱/超时未处理 | 添加超时重传机制,严格校验序号 |
八、性能优化建议
- DMA传输:使用DMA处理串口数据,减少CPU占用
- 双缓冲机制:CAN和WiFi数据使用双缓冲避免冲突
- 优先级设置:CAN接收中断优先级高于串口
- 看门狗:添加独立看门狗防止死机
- 数据压缩:对重复数据使用压缩算法
- 加密传输:添加AES加密保证数据安全
九、完整工程结构
WiFi_CAN_Gateway/
├── Core/
│ ├── Src/
│ │ ├── main.c
│ │ ├── stm32f1xx_it.c
│ │ ├── system_stm32f1xx.c
│ │ └── ...
│ └── Inc/
│ ├── main.h
│ └── ...
├── Drivers/
│ ├── STM32F1xx_HAL_Driver/
│ └── CMSIS/
├── Middlewares/
├── Application/
│ ├── Src/
│ │ ├── can.c
│ │ ├── wifi.c
│ │ ├── protocol.c
│ │ ├── system.c
│ │ └── debug.c
│ └── Inc/
│ ├── can.h
│ ├── wifi.h
│ ├── protocol.h
│ ├── system.h
│ └── debug.h
├── Test/
│ ├── can_test.c
│ └── wifi_test.c
└── README.md