STM32 CAN总线数据采集与转发系统
- 工程结构
- [1.系统配置文件 system_config.h](#1.系统配置文件 system_config.h)
- [2. CAN总线配置文件 can_config.h](#2. CAN总线配置文件 can_config.h)
- [3. 网络配置文件 network_config.h](#3. 网络配置文件 network_config.h)
- [4. CAN总线驱动文件 can_bus.h](#4. CAN总线驱动文件 can_bus.h)
- [5. CAN总线驱动文件 can_bus.c](#5. CAN总线驱动文件 can_bus.c)
- [6. W5500网络驱动文件 w5500_net.h](#6. W5500网络驱动文件 w5500_net.h)
- [7. W5500网络驱动文件 w5500_net.c](#7. W5500网络驱动文件 w5500_net.c)
- [8. SD卡存储驱动文件 sd_storage.h](#8. SD卡存储驱动文件 sd_storage.h)
- [9. SD卡存储驱动文件 sd_storage.c](#9. SD卡存储驱动文件 sd_storage.c)
- [10. 数据处理文件 data_processor.h](#10. 数据处理文件 data_processor.h)
- [11. 看门狗驱动文件 watchdog.h](#11. 看门狗驱动文件 watchdog.h)
- [12. FreeRTOS任务管理文件 rtos_tasks.h](#12. FreeRTOS任务管理文件 rtos_tasks.h)
- [13. FreeRTOS任务管理文件 rtos_tasks.c](#13. FreeRTOS任务管理文件 rtos_tasks.c)
- [14. 主函数文件 main.c](#14. 主函数文件 main.c)
- [15. 使用说明](#15. 使用说明)
-
工程结构
text
复制代码
project/
├── Core/
│ ├── Inc/
│ │ ├── can_config.h
│ │ ├── network_config.h
│ │ ├── system_config.h
│ │ ├── can_bus.h
│ │ ├── w5500_net.h
│ │ ├── sd_storage.h
│ │ ├── data_processor.h
│ │ ├── watchdog.h
│ │ └── rtos_tasks.h
│ └── Src/
│ ├── main.c
│ ├── can_bus.c
│ ├── w5500_net.c
│ ├── sd_storage.c
│ ├── data_processor.c
│ ├── watchdog.c
│ └── rtos_tasks.c
├── Drivers/
│ └── STM32F4xx_HAL_Driver/
├── Middlewares/
│ ├── Third_Party/
│ │ └── FreeRTOS/
│ └── FATFS/
└── config/
└── FreeRTOSConfig.h
1.系统配置文件 system_config.h
c
复制代码
#ifndef __SYSTEM_CONFIG_H
#define __SYSTEM_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx_hal.h"
#include <stdint.h>
#include <stdbool.h>
// 系统版本
#define FIRMWARE_VERSION "V1.0.0"
#define HARDWARE_VERSION "HW-001"
// 调试配置
#define DEBUG_ENABLED 1
#define DEBUG_UART USART3
#define DEBUG_BAUDRATE 115200
// 系统时钟配置
#define SYSTEM_CLOCK_FREQ 168000000 // 168 MHz
#define HSE_VALUE 8000000 // 8 MHz 外部晶振
// FreeRTOS配置
#define RTOS_TICK_RATE_HZ 1000 // 系统节拍1ms
#define RTOS_HEAP_SIZE (30 * 1024) // 堆大小30KB
// 任务优先级
#define TASK_PRIORITY_IDLE 0
#define TASK_PRIORITY_LOW 1
#define TASK_PRIORITY_BELOW_NORMAL 2
#define TASK_PRIORITY_NORMAL 3
#define TASK_PRIORITY_ABOVE_NORMAL 4
#define TASK_PRIORITY_HIGH 5
#define TASK_PRIORITY_REALTIME 6
// 任务堆栈大小
#define TASK_STACK_SMALL 256
#define TASK_STACK_MEDIUM 512
#define TASK_STACK_LARGE 1024
#define TASK_STACK_XLARGE 2048
// 系统状态定义
typedef enum {
SYS_STATE_INIT = 0,
SYS_STATE_IDLE,
SYS_STATE_NORMAL,
SYS_STATE_WARNING,
SYS_STATE_ERROR,
SYS_STATE_FATAL
} SystemState_t;
// 错误代码定义
typedef enum {
ERROR_NONE = 0,
ERROR_CAN_INIT_FAILED,
ERROR_CAN_FILTER_FAILED,
ERROR_CAN_TX_FAILED,
ERROR_CAN_RX_FAILED,
ERROR_W5500_INIT_FAILED,
ERROR_W5500_CONFIG_FAILED,
ERROR_W5500_TCP_CONNECT_FAILED,
ERROR_W5500_TCP_SEND_FAILED,
ERROR_SD_INIT_FAILED,
ERROR_SD_MOUNT_FAILED,
ERROR_SD_FILE_OPEN_FAILED,
ERROR_SD_FILE_WRITE_FAILED,
ERROR_SD_FILE_READ_FAILED,
ERROR_SD_FULL,
ERROR_DATA_PROCESS_FAILED,
ERROR_WATCHDOG_TIMEOUT,
ERROR_RTOS_TASK_CREATE_FAILED,
ERROR_MEMORY_ALLOC_FAILED
} ErrorCode_t;
// 通用数据结构
typedef struct {
uint32_t timestamp;
SystemState_t system_state;
ErrorCode_t last_error;
uint32_t can_rx_count;
uint32_t can_tx_count;
uint32_t network_tx_count;
uint32_t sd_write_count;
uint32_t error_count;
float cpu_usage;
} SystemStatus_t;
// 调试输出宏
#if DEBUG_ENABLED
#define DEBUG_PRINT(fmt, ...) \
do { \
char debug_buf[256]; \
snprintf(debug_buf, sizeof(debug_buf), "[%lu] " fmt "\r\n", HAL_GetTick(), ##__VA_ARGS__); \
HAL_UART_Transmit(&DEBUG_UART, (uint8_t*)debug_buf, strlen(debug_buf), 100); \
} while(0)
#else
#define DEBUG_PRINT(fmt, ...)
#endif
// 断言宏
#define SYSTEM_ASSERT(expr) \
do { \
if (!(expr)) { \
DEBUG_PRINT("Assert failed: %s, line %d", __FILE__, __LINE__); \
Error_Handler(); \
} \
} while(0)
#ifdef __cplusplus
}
#endif
#endif /* __SYSTEM_CONFIG_H */
2. CAN总线配置文件 can_config.h
c
复制代码
#ifndef __CAN_CONFIG_H
#define __CAN_CONFIG_H
#include "system_config.h"
#ifdef __cplusplus
extern "C" {
#endif
// CAN总线配置
#define CAN_INTERFACE CAN1
#define CAN_BAUDRATE 500000 // 500 kbps
#define CAN_MODE CAN_MODE_NORMAL
// CAN过滤器配置
#define CAN_FILTER_BANK_COUNT 14 // STM32F407有14个过滤器组
#define CAN_FILTER_MODE CAN_FILTERMODE_IDMASK
#define CAN_FILTER_SCALE CAN_FILTERSCALE_32BIT
#define CAN_FILTER_FIFO CAN_FILTER_FIFO0
// CAN消息ID定义
typedef enum {
// 标准ID (11位)
CAN_ID_SENSOR_TEMP = 0x100,
CAN_ID_SENSOR_PRESSURE = 0x101,
CAN_ID_SENSOR_FLOW = 0x102,
CAN_ID_SENSOR_LEVEL = 0x103,
CAN_ID_SENSOR_VIBRATION = 0x104,
// 控制命令ID
CAN_ID_CMD_START = 0x200,
CAN_ID_CMD_STOP = 0x201,
CAN_ID_CMD_RESET = 0x202,
CAN_ID_CMD_CONFIG = 0x203,
// 系统状态ID
CAN_ID_SYS_STATUS = 0x300,
CAN_ID_SYS_ERROR = 0x301,
CAN_ID_SYS_HEARTBEAT = 0x302,
// 扩展ID (29位)
CAN_ID_EXT_LOG_DATA = 0x18000000,
CAN_ID_EXT_DEBUG = 0x18000001
} CanMessageId_t;
// CAN消息数据结构
typedef struct {
uint32_t id; // CAN消息ID
uint8_t data[8]; // 数据字节
uint8_t length; // 数据长度
uint8_t format; // 0-标准帧, 1-扩展帧
uint8_t type; // 0-数据帧, 1-远程帧
uint32_t timestamp; // 时间戳
} CanMessage_t;
// 传感器数据结构
typedef struct {
float temperature; // 温度 (°C)
float pressure; // 压力 (kPa)
float flow_rate; // 流量 (m³/h)
float level; // 液位 (%)
float vibration; // 振动 (mm/s)
uint32_t sensor_status; // 传感器状态字
uint32_t timestamp; // 采集时间戳
} SensorData_t;
// CAN过滤器配置结构
typedef struct {
uint32_t filter_id_high; // 过滤器ID高位
uint32_t filter_id_low; // 过滤器ID低位
uint32_t filter_mask_id_high; // 过滤器掩码高位
uint32_t filter_mask_id_low; // 过滤器掩码低位
uint32_t filter_fifo; // 过滤器FIFO分配
uint32_t filter_bank; // 过滤器组编号
uint32_t filter_mode; // 过滤器模式
uint32_t filter_scale; // 过滤器尺度
uint32_t filter_activation; // 过滤器激活状态
} CanFilterConfig_t;
// CAN统计信息
typedef struct {
uint32_t rx_total; // 接收总数
uint32_t tx_total; // 发送总数
uint32_t rx_error; // 接收错误
uint32_t tx_error; // 发送错误
uint32_t arbitration_lost; // 仲裁丢失
uint32_t bus_error; // 总线错误
uint32_t overflow_error; // 溢出错误
uint32_t last_error_code; // 最后错误代码
uint32_t last_error_timestamp; // 最后错误时间戳
} CanStatistics_t;
// CAN配置参数
#define CAN_RX_QUEUE_SIZE 100 // 接收队列大小
#define CAN_TX_QUEUE_SIZE 50 // 发送队列大小
#define CAN_RX_TIMEOUT_MS 10 // 接收超时(ms)
#define CAN_TX_TIMEOUT_MS 100 // 发送超时(ms)
#define CAN_ERROR_THRESHOLD 10 // 错误阈值
#define CAN_HEARTBEAT_INTERVAL 1000 // 心跳间隔(ms)
// 函数声明
void CAN_Config_InitFilters(void);
void CAN_Config_SetStandardFilter(uint8_t filter_bank, uint16_t id, uint16_t mask);
void CAN_Config_SetExtendedFilter(uint8_t filter_bank, uint32_t id, uint32_t mask);
ErrorCode_t CAN_Config_Validate(void);
// 默认过滤器配置
extern const CanFilterConfig_t g_default_filters[];
extern const uint8_t g_default_filter_count;
#ifdef __cplusplus
}
#endif
#endif /* __CAN_CONFIG_H */
3. 网络配置文件 network_config.h
c
复制代码
#ifndef __NETWORK_CONFIG_H
#define __NETWORK_CONFIG_H
#include "system_config.h"
#ifdef __cplusplus
extern "C" {
#endif
// W5500 SPI配置
#define W5500_SPI SPI2
#define W5500_SPI_CS_PIN GPIO_PIN_12
#define W5500_SPI_CS_PORT GPIOB
#define W5500_SPI_TIMEOUT 1000
#define W5500_SPI_CLOCK_SPEED 18000000 // 18 MHz
// W5500网络配置
#define W5500_MAC_ADDRESS {0x00, 0x08, 0xDC, 0x01, 0x02, 0x03}
#define W5500_IP_ADDRESS {192, 168, 1, 100}
#define W5500_SUBNET_MASK {255, 255, 255, 0}
#define W5500_GATEWAY {192, 168, 1, 1}
#define W5500_DNS_SERVER {8, 8, 8, 8}
// TCP服务器配置
#define TCP_SERVER_IP "192.168.1.50"
#define TCP_SERVER_PORT 5000
#define TCP_CLIENT_PORT 6000
#define TCP_KEEPALIVE_INTERVAL 30 // 保活间隔(秒)
#define TCP_RECONNECT_INTERVAL 5000 // 重连间隔(ms)
#define TCP_SEND_TIMEOUT 5000 // 发送超时(ms)
#define TCP_RECV_BUFFER_SIZE 2048 // 接收缓冲区大小
// 数据包配置
#define PACKET_HEADER_SIZE 8 // 包头大小
#define PACKET_MAX_SIZE 1024 // 最大包大小
#define PACKET_QUEUE_SIZE 50 // 数据包队列大小
// 网络协议定义
typedef enum {
PROTOCOL_RAW = 0, // 原始数据
PROTOCOL_JSON, // JSON格式
PROTOCOL_MODBUS_TCP, // Modbus TCP
PROTOCOL_CUSTOM_BINARY // 自定义二进制
} ProtocolType_t;
// 数据包头结构
typedef struct __attribute__((packed)) {
uint16_t magic; // 魔数 0x55AA
uint16_t version; // 协议版本
uint16_t type; // 数据类型
uint16_t length; // 数据长度
uint32_t timestamp; // 时间戳
uint16_t checksum; // 校验和
} PacketHeader_t;
// 网络状态结构
typedef struct {
uint8_t mac[6]; // MAC地址
uint8_t ip[4]; // IP地址
uint8_t subnet[4]; // 子网掩码
uint8_t gateway[4]; // 网关
uint8_t dns[4]; // DNS服务器
bool dhcp_enabled; // DHCP使能
bool link_status; // 链路状态
bool tcp_connected; // TCP连接状态
uint32_t tx_bytes; // 发送字节数
uint32_t rx_bytes; // 接收字节数
uint32_t tx_packets; // 发送包数
uint32_t rx_packets; // 接收包数
uint32_t connect_count; // 连接次数
uint32_t disconnect_count; // 断开次数
uint32_t last_connect_time; // 最后连接时间
uint32_t last_error_time; // 最后错误时间
} NetworkStatus_t;
// 网络配置参数
typedef struct {
uint8_t mac[6];
uint8_t ip[4];
uint8_t subnet[4];
uint8_t gateway[4];
uint8_t dns[4];
char server_ip[16];
uint16_t server_port;
uint16_t client_port;
ProtocolType_t protocol;
uint16_t packet_size;
uint32_t send_interval;
bool auto_reconnect;
uint32_t reconnect_interval;
} NetworkConfig_t;
// 默认网络配置
extern const NetworkConfig_t g_default_network_config;
// 函数声明
ErrorCode_t Network_Config_Validate(void);
void Network_Config_LoadDefaults(void);
void Network_Config_SaveToFlash(void);
void Network_Config_LoadFromFlash(void);
#ifdef __cplusplus
}
#endif
#endif /* __NETWORK_CONFIG_H */
4. CAN总线驱动文件 can_bus.h
c
复制代码
#ifndef __CAN_BUS_H
#define __CAN_BUS_H
#include "can_config.h"
#include "system_config.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif
// CAN句柄
extern CAN_HandleTypeDef hcan1;
// 消息队列句柄
extern osMessageQueueId_t can_rx_queue;
extern osMessageQueueId_t can_tx_queue;
// 函数声明
ErrorCode_t CAN_Init(void);
ErrorCode_t CAN_Start(void);
ErrorCode_t CAN_Stop(void);
ErrorCode_t CAN_Reset(void);
ErrorCode_t CAN_SendMessage(CanMessage_t *msg);
ErrorCode_t CAN_ReceiveMessage(CanMessage_t *msg, uint32_t timeout);
ErrorCode_t CAN_ConfigureFilters(void);
void CAN_ProcessRxFifo(CAN_HandleTypeDef *hcan, uint32_t fifo);
void CAN_ErrorCallback(CAN_HandleTypeDef *hcan);
void CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
void CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan);
void CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan);
void CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan);
void CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan);
CanStatistics_t* CAN_GetStatistics(void);
void CAN_ClearStatistics(void);
bool CAN_IsBusOff(void);
ErrorCode_t CAN_RecoverFromBusOff(void);
void CAN_SendHeartbeat(void);
void CAN_SendSystemStatus(SystemStatus_t *status);
// 工具函数
uint32_t CAN_CalculateBaudrate(uint32_t clock_freq, uint32_t baudrate);
uint16_t CAN_CalculateCRC16(uint8_t *data, uint8_t length);
bool CAN_ValidateMessage(CanMessage_t *msg);
// CAN中断回调
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan);
#ifdef __cplusplus
}
#endif
#endif /* __CAN_BUS_H */
5. CAN总线驱动文件 can_bus.c
c
复制代码
#include "can_bus.h"
#include <string.h>
// 全局变量
CAN_HandleTypeDef hcan1;
osMessageQueueId_t can_rx_queue = NULL;
osMessageQueueId_t can_tx_queue = NULL;
static CanStatistics_t can_stats = {0};
static uint32_t last_heartbeat_time = 0;
// 默认过滤器配置
const CanFilterConfig_t g_default_filters[] = {
// 过滤器0: 接收标准ID 0x100-0x10F (传感器数据)
{
.filter_id_high = 0x100 << 5,
.filter_id_low = 0,
.filter_mask_id_high = 0x10F << 5,
.filter_mask_id_low = 0,
.filter_fifo = CAN_FILTER_FIFO0,
.filter_bank = 0,
.filter_mode = CAN_FILTERMODE_IDMASK,
.filter_scale = CAN_FILTERSCALE_32BIT,
.filter_activation = ENABLE
},
// 过滤器1: 接收标准ID 0x200-0x20F (控制命令)
{
.filter_id_high = 0x200 << 5,
.filter_id_low = 0,
.filter_mask_id_high = 0x20F << 5,
.filter_mask_id_low = 0,
.filter_fifo = CAN_FILTER_FIFO0,
.filter_bank = 1,
.filter_mode = CAN_FILTERMODE_IDMASK,
.filter_scale = CAN_FILTERSCALE_32BIT,
.filter_activation = ENABLE
},
// 过滤器2: 接收扩展ID 0x18000000-0x1800FFFF (日志数据)
{
.filter_id_high = (0x18000000 >> 13) & 0xFFFF,
.filter_id_low = ((0x18000000 << 3) & 0xFFF8) | 0x04,
.filter_mask_id_high = (0x1800FFFF >> 13) & 0xFFFF,
.filter_mask_id_low = ((0x1800FFFF << 3) & 0xFFF8) | 0x04,
.filter_fifo = CAN_FILTER_FIFO1,
.filter_bank = 2,
.filter_mode = CAN_FILTERMODE_IDMASK,
.filter_scale = CAN_FILTERSCALE_32BIT,
.filter_activation = ENABLE
}
};
const uint8_t g_default_filter_count = sizeof(g_default_filters) / sizeof(g_default_filters[0]);
// CAN初始化
ErrorCode_t CAN_Init(void)
{
DEBUG_PRINT("Initializing CAN bus...");
// 创建消息队列
can_rx_queue = osMessageQueueNew(CAN_RX_QUEUE_SIZE, sizeof(CanMessage_t), NULL);
can_tx_queue = osMessageQueueNew(CAN_TX_QUEUE_SIZE, sizeof(CanMessage_t), NULL);
if (can_rx_queue == NULL || can_tx_queue == NULL) {
DEBUG_PRINT("Failed to create CAN queues");
return ERROR_RTOS_TASK_CREATE_FAILED;
}
// 初始化CAN外设
hcan1.Instance = CAN_INTERFACE;
hcan1.Init.Prescaler = CAN_CalculateBaudrate(SYSTEM_CLOCK_FREQ, CAN_BAUDRATE);
hcan1.Init.Mode = CAN_MODE;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_13TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = ENABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
// 初始化CAN
if (HAL_CAN_Init(&hcan1) != HAL_OK) {
DEBUG_PRINT("CAN hardware initialization failed");
return ERROR_CAN_INIT_FAILED;
}
// 配置过滤器
ErrorCode_t filter_error = CAN_ConfigureFilters();
if (filter_error != ERROR_NONE) {
DEBUG_PRINT("CAN filter configuration failed");
return filter_error;
}
// 清空统计信息
CAN_ClearStatistics();
DEBUG_PRINT("CAN bus initialized successfully");
return ERROR_NONE;
}
// 启动CAN总线
ErrorCode_t CAN_Start(void)
{
DEBUG_PRINT("Starting CAN bus...");
// 启动CAN
if (HAL_CAN_Start(&hcan1) != HAL_OK) {
DEBUG_PRINT("Failed to start CAN bus");
return ERROR_CAN_INIT_FAILED;
}
// 使能接收中断
if (HAL_CAN_ActivateNotification(&hcan1,
CAN_IT_RX_FIFO0_MSG_PENDING |
CAN_IT_RX_FIFO1_MSG_PENDING |
CAN_IT_TX_MAILBOX_EMPTY |
CAN_IT_ERROR) != HAL_OK) {
DEBUG_PRINT("Failed to activate CAN notifications");
return ERROR_CAN_INIT_FAILED;
}
DEBUG_PRINT("CAN bus started successfully");
return ERROR_NONE;
}
// 停止CAN总线
ErrorCode_t CAN_Stop(void)
{
DEBUG_PRINT("Stopping CAN bus...");
// 停止CAN
if (HAL_CAN_Stop(&hcan1) != HAL_OK) {
DEBUG_PRINT("Failed to stop CAN bus");
return ERROR_CAN_INIT_FAILED;
}
// 禁用所有中断
HAL_CAN_DeactivateNotification(&hcan1, CAN_IT_ALL);
DEBUG_PRINT("CAN bus stopped");
return ERROR_NONE;
}
// 重置CAN总线
ErrorCode_t CAN_Reset(void)
{
DEBUG_PRINT("Resetting CAN bus...");
// 停止CAN
CAN_Stop();
// 延迟
osDelay(10);
// 重新初始化
ErrorCode_t error = CAN_Init();
if (error != ERROR_NONE) {
return error;
}
// 重新启动
error = CAN_Start();
if (error != ERROR_NONE) {
return error;
}
DEBUG_PRINT("CAN bus reset successfully");
return ERROR_NONE;
}
// 配置CAN过滤器
ErrorCode_t CAN_ConfigureFilters(void)
{
DEBUG_PRINT("Configuring CAN filters...");
CAN_FilterTypeDef filter_config;
for (uint8_t i = 0; i < g_default_filter_count; i++) {
const CanFilterConfig_t *filter = &g_default_filters[i];
filter_config.FilterBank = filter->filter_bank;
filter_config.FilterMode = filter->filter_mode;
filter_config.FilterScale = filter->filter_scale;
filter_config.FilterIdHigh = filter->filter_id_high;
filter_config.FilterIdLow = filter->filter_id_low;
filter_config.FilterMaskIdHigh = filter->filter_mask_id_high;
filter_config.FilterMaskIdLow = filter->filter_mask_id_low;
filter_config.FilterFIFOAssignment = filter->filter_fifo;
filter_config.FilterActivation = filter->filter_activation;
filter_config.SlaveStartFilterBank = 14; // 从过滤器组14开始
if (HAL_CAN_ConfigFilter(&hcan1, &filter_config) != HAL_OK) {
DEBUG_PRINT("Failed to configure filter bank %d", i);
return ERROR_CAN_FILTER_FAILED;
}
}
DEBUG_PRINT("CAN filters configured successfully");
return ERROR_NONE;
}
// 发送CAN消息
ErrorCode_t CAN_SendMessage(CanMessage_t *msg)
{
if (msg == NULL || !CAN_ValidateMessage(msg)) {
DEBUG_PRINT("Invalid CAN message");
return ERROR_CAN_TX_FAILED;
}
if (CAN_IsBusOff()) {
DEBUG_PRINT("CAN bus is in bus-off state");
ErrorCode_t error = CAN_RecoverFromBusOff();
if (error != ERROR_NONE) {
return error;
}
}
// 准备CAN Tx消息
CAN_TxHeaderTypeDef tx_header;
uint32_t tx_mailbox;
tx_header.StdId = (msg->format == 0) ? msg->id : 0;
tx_header.ExtId = (msg->format == 1) ? msg->id : 0;
tx_header.IDE = (msg->format == 0) ? CAN_ID_STD : CAN_ID_EXT;
tx_header.RTR = (msg->type == 0) ? CAN_RTR_DATA : CAN_RTR_REMOTE;
tx_header.DLC = msg->length;
tx_header.TransmitGlobalTime = DISABLE;
// 发送消息
HAL_StatusTypeDef status = HAL_CAN_AddTxMessage(&hcan1, &tx_header, msg->data, &tx_mailbox);
if (status == HAL_OK) {
can_stats.tx_total++;
DEBUG_PRINT("CAN message sent: ID=0x%08X, Len=%d", msg->id, msg->length);
return ERROR_NONE;
} else {
can_stats.tx_error++;
DEBUG_PRINT("Failed to send CAN message: status=%d", status);
return ERROR_CAN_TX_FAILED;
}
}
// 接收CAN消息(阻塞式)
ErrorCode_t CAN_ReceiveMessage(CanMessage_t *msg, uint32_t timeout)
{
if (msg == NULL) {
return ERROR_CAN_RX_FAILED;
}
// 从队列接收消息
if (osMessageQueueGet(can_rx_queue, msg, NULL, timeout) == osOK) {
can_stats.rx_total++;
return ERROR_NONE;
}
return ERROR_CAN_RX_FAILED;
}
// 处理接收FIFO
void CAN_ProcessRxFifo(CAN_HandleTypeDef *hcan, uint32_t fifo)
{
CanMessage_t rx_msg;
CAN_RxHeaderTypeDef rx_header;
// 读取所有待处理消息
while (HAL_CAN_GetRxFifoFillLevel(hcan, fifo) > 0) {
// 从FIFO读取消息
if (HAL_CAN_GetRxMessage(hcan, fifo, &rx_header, rx_msg.data) == HAL_OK) {
// 填充消息结构
rx_msg.id = (rx_header.IDE == CAN_ID_STD) ? rx_header.StdId : rx_header.ExtId;
rx_msg.length = rx_header.DLC;
rx_msg.format = (rx_header.IDE == CAN_ID_STD) ? 0 : 1;
rx_msg.type = (rx_header.RTR == CAN_RTR_DATA) ? 0 : 1;
rx_msg.timestamp = HAL_GetTick();
// 添加到接收队列
if (osMessageQueuePut(can_rx_queue, &rx_msg, 0, 0) != osOK) {
// 队列满,丢弃最旧的消息
CanMessage_t dummy;
osMessageQueueGet(can_rx_queue, &dummy, NULL, 0);
osMessageQueuePut(can_rx_queue, &rx_msg, 0, 0);
DEBUG_PRINT("CAN RX queue overflow, message dropped");
}
}
}
}
// 错误回调
void CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
uint32_t error_code = HAL_CAN_GetError(hcan);
if (error_code & HAL_CAN_ERROR_EWG) {
can_stats.bus_error++;
DEBUG_PRINT("CAN error: Error warning");
}
if (error_code & HAL_CAN_ERROR_EPV) {
can_stats.bus_error++;
DEBUG_PRINT("CAN error: Error passive");
}
if (error_code & HAL_CAN_ERROR_BOF) {
can_stats.bus_error++;
DEBUG_PRINT("CAN error: Bus-off");
}
if (error_code & HAL_CAN_ERROR_STF) {
can_stats.arbitration_lost++;
DEBUG_PRINT("CAN error: Stuff error");
}
if (error_code & HAL_CAN_ERROR_FOR) {
can_stats.bus_error++;
DEBUG_PRINT("CAN error: Form error");
}
if (error_code & HAL_CAN_ERROR_ACK) {
can_stats.tx_error++;
DEBUG_PRINT("CAN error: Acknowledgment error");
}
if (error_code & HAL_CAN_ERROR_BR) {
can_stats.bus_error++;
DEBUG_PRINT("CAN error: Bit recessive error");
}
if (error_code & HAL_CAN_ERROR_BD) {
can_stats.bus_error++;
DEBUG_PRINT("CAN error: Bit dominant error");
}
if (error_code & HAL_CAN_ERROR_CRC) {
can_stats.bus_error++;
DEBUG_PRINT("CAN error: CRC error");
}
can_stats.last_error_code = error_code;
can_stats.last_error_timestamp = HAL_GetTick();
}
// 获取统计信息
CanStatistics_t* CAN_GetStatistics(void)
{
return &can_stats;
}
// 清空统计信息
void CAN_ClearStatistics(void)
{
memset(&can_stats, 0, sizeof(CanStatistics_t));
}
// 检查总线是否关闭
bool CAN_IsBusOff(void)
{
return (HAL_CAN_GetError(&hcan1) & HAL_CAN_ERROR_BOF) != 0;
}
// 从总线关闭状态恢复
ErrorCode_t CAN_RecoverFromBusOff(void)
{
DEBUG_PRINT("Recovering from CAN bus-off state...");
// 停止CAN
HAL_CAN_Stop(&hcan1);
// 延迟
osDelay(100);
// 重新初始化CAN
ErrorCode_t error = CAN_Init();
if (error != ERROR_NONE) {
return error;
}
// 重新启动CAN
error = CAN_Start();
if (error != ERROR_NONE) {
return error;
}
DEBUG_PRINT("CAN bus recovered from bus-off state");
return ERROR_NONE;
}
// 发送心跳消息
void CAN_SendHeartbeat(void)
{
uint32_t current_time = HAL_GetTick();
if (current_time - last_heartbeat_time >= CAN_HEARTBEAT_INTERVAL) {
CanMessage_t heartbeat_msg;
heartbeat_msg.id = CAN_ID_SYS_HEARTBEAT;
heartbeat_msg.length = 4;
heartbeat_msg.format = 0; // 标准帧
heartbeat_msg.type = 0; // 数据帧
heartbeat_msg.timestamp = current_time;
// 填充心跳数据
memcpy(heartbeat_msg.data, ¤t_time, 4);
CAN_SendMessage(&heartbeat_msg);
last_heartbeat_time = current_time;
}
}
// 计算波特率预分频值
uint32_t CAN_CalculateBaudrate(uint32_t clock_freq, uint32_t baudrate)
{
// CAN时钟频率 = APB1频率
// STM32F407: APB1最大频率42MHz
uint32_t time_quanta = 1 + 13 + 2; // 1(SJW) + 13(BS1) + 2(BS2)
uint32_t prescaler = clock_freq / (baudrate * time_quanta);
return prescaler;
}
// 计算CRC16校验
uint16_t CAN_CalculateCRC16(uint8_t *data, uint8_t length)
{
uint16_t crc = 0xFFFF;
for (uint8_t i = 0; i < length; i++) {
crc ^= data[i];
for (uint8_t j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
// 验证消息有效性
bool CAN_ValidateMessage(CanMessage_t *msg)
{
if (msg == NULL) {
return false;
}
if (msg->length > 8) {
return false;
}
if (msg->format == 0) { // 标准帧
if (msg->id > 0x7FF) {
return false;
}
} else { // 扩展帧
if (msg->id > 0x1FFFFFFF) {
return false;
}
}
return true;
}
// HAL CAN中断回调
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_ProcessRxFifo(hcan, CAN_RX_FIFO0);
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_ProcessRxFifo(hcan, CAN_RX_FIFO1);
}
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
// 发送完成处理
}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
{
// 发送完成处理
}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)
{
// 发送完成处理
}
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
CAN_ErrorCallback(hcan);
}
6. W5500网络驱动文件 w5500_net.h
c
复制代码
#ifndef __W5500_NET_H
#define __W5500_NET_H
#include "network_config.h"
#include "system_config.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif
// SPI句柄
extern SPI_HandleTypeDef hspi2;
// 网络队列句柄
extern osMessageQueueId_t net_tx_queue;
extern osMessageQueueId_t net_rx_queue;
// W5500寄存器地址
#define W5500_MR 0x0000 // 模式寄存器
#define W5500_GAR 0x0001 // 网关地址寄存器
#define W5500_SUBR 0x0005 // 子网掩码寄存器
#define W5500_SHAR 0x0009 // 源硬件地址寄存器
#define W5500_SIPR 0x000F // 源IP地址寄存器
#define W5500_RTR 0x0017 // 重试时间寄存器
#define W5500_RCR 0x0019 // 重试计数寄存器
// Socket寄存器偏移
#define SOCKET_BASE 0x0400
#define SOCKET_REG_SIZE 0x0100
#define SOCKET_MR 0x0000 // Socket模式寄存器
#define SOCKET_CR 0x0001 // Socket命令寄存器
#define SOCKET_IR 0x0002 // Socket中断寄存器
#define SOCKET_SR 0x0003 // Socket状态寄存器
#define SOCKET_PORT 0x0004 // 端口号寄存器
#define SOCKET_DHAR 0x0006 // 目标硬件地址寄存器
#define SOCKET_DIPR 0x000C // 目标IP地址寄存器
#define SOCKET_DPORT 0x0010 // 目标端口寄存器
#define SOCKET_TX_FSR 0x0020 // 发送空闲空间
#define SOCKET_TX_RD 0x0022 // 发送读指针
#define SOCKET_TX_WR 0x0024 // 发送写指针
#define SOCKET_RX_RSR 0x0026 // 接收数据大小
#define SOCKET_RX_RD 0x0028 // 接收读指针
#define SOCKET_RX_WR 0x002A // 接收写指针
// Socket命令
#define SOCKET_CMD_OPEN 0x01
#define SOCKET_CMD_LISTEN 0x02
#define SOCKET_CMD_CONNECT 0x04
#define SOCKET_CMD_DISCON 0x08
#define SOCKET_CMD_CLOSE 0x10
#define SOCKET_CMD_SEND 0x20
#define SOCKET_CMD_SEND_MAC 0x21
#define SOCKET_CMD_SEND_KEEP 0x22
#define SOCKET_CMD_RECV 0x40
// Socket状态
#define SOCKET_CLOSED 0x00
#define SOCKET_INIT 0x13
#define SOCKET_LISTEN 0x14
#define SOCKET_ESTABLISHED 0x17
#define SOCKET_CLOSE_WAIT 0x1C
#define SOCKET_UDP 0x22
#define SOCKET_MACRAW 0x42
// 函数声明
ErrorCode_t W5500_Init(void);
ErrorCode_t W5500_ConfigureNetwork(void);
ErrorCode_t W5500_TCPConnect(void);
ErrorCode_t W5500_TCPDisconnect(void);
ErrorCode_t W5500_TCPSend(uint8_t *data, uint16_t length);
ErrorCode_t W5500_TCPReceive(uint8_t *buffer, uint16_t *length);
bool W5500_IsConnected(void);
NetworkStatus_t* W5500_GetStatus(void);
void W5500_UpdateStatus(void);
ErrorCode_t W5500_SendPacket(PacketHeader_t *header, uint8_t *data);
ErrorCode_t W5500_ProcessTxQueue(void);
ErrorCode_t W5500_ProcessRxQueue(void);
void W5500_HandleConnection(void);
void W5500_Reset(void);
// SPI通信函数
uint8_t W5500_ReadByte(uint16_t address);
void W5500_WriteByte(uint16_t address, uint8_t data);
uint16_t W5500_ReadWord(uint16_t address);
void W5500_WriteWord(uint16_t address, uint16_t data);
void W5500_ReadBuffer(uint16_t address, uint8_t *buffer, uint16_t length);
void W5500_WriteBuffer(uint16_t address, uint8_t *buffer, uint16_t length);
// Socket操作函数
uint8_t W5500_GetSocketStatus(uint8_t socket);
ErrorCode_t W5500_SocketOpen(uint8_t socket, uint8_t protocol);
ErrorCode_t W5500_SocketClose(uint8_t socket);
ErrorCode_t W5500_SocketConnect(uint8_t socket, uint8_t *ip, uint16_t port);
ErrorCode_t W5500_SocketSend(uint8_t socket, uint8_t *data, uint16_t length);
ErrorCode_t W5500_SocketReceive(uint8_t socket, uint8_t *buffer, uint16_t *length);
#ifdef __cplusplus
}
#endif
#endif /* __W5500_NET_H */
7. W5500网络驱动文件 w5500_net.c
c
复制代码
#include "w5500_net.h"
#include <string.h>
// 全局变量
SPI_HandleTypeDef hspi2;
osMessageQueueId_t net_tx_queue = NULL;
osMessageQueueId_t net_rx_queue = NULL;
static NetworkStatus_t net_status = {0};
static NetworkConfig_t net_config;
static uint8_t socket = 0; // 使用Socket 0
// 默认网络配置
const NetworkConfig_t g_default_network_config = {
.mac = {0x00, 0x08, 0xDC, 0x01, 0x02, 0x03},
.ip = {192, 168, 1, 100},
.subnet = {255, 255, 255, 0},
.gateway = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.server_ip = "192.168.1.50",
.server_port = 5000,
.client_port = 6000,
.protocol = PROTOCOL_CUSTOM_BINARY,
.packet_size = 256,
.send_interval = 100,
.auto_reconnect = true,
.reconnect_interval = 5000
};
// W5500初始化
ErrorCode_t W5500_Init(void)
{
DEBUG_PRINT("Initializing W5500...");
// 创建网络队列
net_tx_queue = osMessageQueueNew(PACKET_QUEUE_SIZE, sizeof(PacketHeader_t) + PACKET_MAX_SIZE, NULL);
net_rx_queue = osMessageQueueNew(PACKET_QUEUE_SIZE, sizeof(PacketHeader_t) + PACKET_MAX_SIZE, NULL);
if (net_tx_queue == NULL || net_rx_queue == NULL) {
DEBUG_PRINT("Failed to create network queues");
return ERROR_RTOS_TASK_CREATE_FAILED;
}
// 初始化SPI
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK) {
DEBUG_PRINT("SPI initialization failed");
return ERROR_W5500_INIT_FAILED;
}
// 配置CS引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = W5500_SPI_CS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(W5500_SPI_CS_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_SET);
// 延迟以确保W5500上电完成
osDelay(100);
// 测试W5500通信
W5500_WriteByte(W5500_MR, 0x80); // 软件复位
osDelay(10);
W5500_WriteByte(W5500_MR, 0x00); // 清除复位
// 读取版本寄存器(应为0x04)
uint8_t version = W5500_ReadByte(0x0039);
if (version != 0x04) {
DEBUG_PRINT("W5500 version mismatch: 0x%02X", version);
return ERROR_W5500_INIT_FAILED;
}
// 加载默认配置
memcpy(&net_config, &g_default_network_config, sizeof(NetworkConfig_t));
// 配置网络
ErrorCode_t error = W5500_ConfigureNetwork();
if (error != ERROR_NONE) {
return error;
}
// 初始化状态
memcpy(net_status.mac, net_config.mac, 6);
memcpy(net_status.ip, net_config.ip, 4);
memcpy(net_status.subnet, net_config.subnet, 4);
memcpy(net_status.gateway, net_config.gateway, 4);
memcpy(net_status.dns, net_config.dns, 4);
net_status.dhcp_enabled = false;
net_status.link_status = true;
net_status.tcp_connected = false;
DEBUG_PRINT("W5500 initialized successfully");
DEBUG_PRINT("MAC: %02X:%02X:%02X:%02X:%02X:%02X",
net_config.mac[0], net_config.mac[1], net_config.mac[2],
net_config.mac[3], net_config.mac[4], net_config.mac[5]);
DEBUG_PRINT("IP: %d.%d.%d.%d",
net_config.ip[0], net_config.ip[1], net_config.ip[2], net_config.ip[3]);
return ERROR_NONE;
}
// 配置网络参数
ErrorCode_t W5500_ConfigureNetwork(void)
{
DEBUG_PRINT("Configuring W5500 network...");
// 设置MAC地址
W5500_WriteBuffer(W5500_SHAR, net_config.mac, 6);
// 设置IP地址
W5500_WriteBuffer(W5500_SIPR, net_config.ip, 4);
// 设置子网掩码
W5500_WriteBuffer(W5500_SUBR, net_config.subnet, 4);
// 设置网关
W5500_WriteBuffer(W5500_GAR, net_config.gateway, 4);
// 设置重试参数
W5500_WriteWord(W5500_RTR, 2000); // 重试时间2000ms
W5500_WriteByte(W5500_RCR, 8); // 重试次数8次
DEBUG_PRINT("W5500 network configured");
return ERROR_NONE;
}
// TCP连接
ErrorCode_t W5500_TCPConnect(void)
{
DEBUG_PRINT("Establishing TCP connection...");
// 打开Socket
ErrorCode_t error = W5500_SocketOpen(socket, 0x01); // TCP模式
if (error != ERROR_NONE) {
return error;
}
// 设置本地端口
W5500_WriteWord(SOCKET_BASE + socket * SOCKET_REG_SIZE + SOCKET_PORT, net_config.client_port);
// 解析服务器IP
uint8_t server_ip[4];
if (sscanf(net_config.server_ip, "%hhu.%hhu.%hhu.%hhu",
&server_ip[0], &server_ip[1], &server_ip[2], &server_ip[3]) != 4) {
DEBUG_PRINT("Invalid server IP address: %s", net_config.server_ip);
return ERROR_W5500_TCP_CONNECT_FAILED;
}
// 连接服务器
error = W5500_SocketConnect(socket, server_ip, net_config.server_port);
if (error != ERROR_NONE) {
return error;
}
// 等待连接建立
uint32_t timeout = HAL_GetTick();
while (W5500_GetSocketStatus(socket) != SOCKET_ESTABLISHED) {
if (HAL_GetTick() - timeout > 5000) {
DEBUG_PRINT("TCP connection timeout");
W5500_SocketClose(socket);
return ERROR_W5500_TCP_CONNECT_FAILED;
}
osDelay(10);
}
net_status.tcp_connected = true;
net_status.connect_count++;
net_status.last_connect_time = HAL_GetTick();
DEBUG_PRINT("TCP connection established");
return ERROR_NONE;
}
// TCP断开连接
ErrorCode_t W5500_TCPDisconnect(void)
{
DEBUG_PRINT("Closing TCP connection...");
ErrorCode_t error = W5500_SocketClose(socket);
if (error != ERROR_NONE) {
return error;
}
net_status.tcp_connected = false;
net_status.disconnect_count++;
DEBUG_PRINT("TCP connection closed");
return ERROR_NONE;
}
// TCP发送数据
ErrorCode_t W5500_TCPSend(uint8_t *data, uint16_t length)
{
if (data == NULL || length == 0) {
return ERROR_W5500_TCP_SEND_FAILED;
}
if (!W5500_IsConnected()) {
DEBUG_PRINT("TCP not connected, cannot send data");
return ERROR_W5500_TCP_SEND_FAILED;
}
ErrorCode_t error = W5500_SocketSend(socket, data, length);
if (error == ERROR_NONE) {
net_status.tx_bytes += length;
net_status.tx_packets++;
} else {
net_status.last_error_time = HAL_GetTick();
}
return error;
}
// TCP接收数据
ErrorCode_t W5500_TCPReceive(uint8_t *buffer, uint16_t *length)
{
if (buffer == NULL || length == NULL) {
return ERROR_W5500_TCP_SEND_FAILED;
}
if (!W5500_IsConnected()) {
*length = 0;
return ERROR_W5500_TCP_SEND_FAILED;
}
ErrorCode_t error = W5500_SocketReceive(socket, buffer, length);
if (error == ERROR_NONE && *length > 0) {
net_status.rx_bytes += *length;
net_status.rx_packets++;
}
return error;
}
// 检查连接状态
bool W5500_IsConnected(void)
{
return net_status.tcp_connected &&
(W5500_GetSocketStatus(socket) == SOCKET_ESTABLISHED);
}
// 获取网络状态
NetworkStatus_t* W5500_GetStatus(void)
{
return &net_status;
}
// 更新网络状态
void W5500_UpdateStatus(void)
{
// 更新链路状态(简化版本,实际需要检测PHY)
net_status.link_status = true;
// 更新TCP连接状态
if (net_status.tcp_connected) {
uint8_t status = W5500_GetSocketStatus(socket);
if (status != SOCKET_ESTABLISHED && status != SOCKET_CLOSE_WAIT) {
net_status.tcp_connected = false;
DEBUG_PRINT("TCP connection lost, status=0x%02X", status);
}
}
}
// 发送数据包
ErrorCode_t W5500_SendPacket(PacketHeader_t *header, uint8_t *data)
{
if (header == NULL) {
return ERROR_W5500_TCP_SEND_FAILED;
}
// 构建数据包
uint8_t packet[PACKET_MAX_SIZE];
uint16_t packet_size = PACKET_HEADER_SIZE + header->length;
if (packet_size > PACKET_MAX_SIZE) {
DEBUG_PRINT("Packet too large: %d > %d", packet_size, PACKET_MAX_SIZE);
return ERROR_W5500_TCP_SEND_FAILED;
}
// 复制包头
memcpy(packet, header, PACKET_HEADER_SIZE);
// 复制数据
if (data != NULL && header->length > 0) {
memcpy(packet + PACKET_HEADER_SIZE, data, header->length);
}
// 计算校验和
header->checksum = 0;
for (uint16_t i = 0; i < packet_size; i++) {
header->checksum += packet[i];
}
// 更新包头中的校验和
memcpy(packet, header, PACKET_HEADER_SIZE);
// 发送数据包
return W5500_TCPSend(packet, packet_size);
}
// 处理发送队列
ErrorCode_t W5500_ProcessTxQueue(void)
{
uint8_t packet[PACKET_MAX_SIZE];
// 尝试从队列获取数据包
if (osMessageQueueGet(net_tx_queue, packet, NULL, 0) == osOK) {
PacketHeader_t *header = (PacketHeader_t *)packet;
// 发送数据包
ErrorCode_t error = W5500_SendPacket(header, packet + PACKET_HEADER_SIZE);
if (error != ERROR_NONE) {
DEBUG_PRINT("Failed to send packet from queue");
return error;
}
}
return ERROR_NONE;
}
// 处理接收队列
ErrorCode_t W5500_ProcessRxQueue(void)
{
uint8_t buffer[TCP_RECV_BUFFER_SIZE];
uint16_t length = 0;
// 接收数据
ErrorCode_t error = W5500_TCPReceive(buffer, &length);
if (error == ERROR_NONE && length > 0) {
// 这里可以添加接收数据处理逻辑
DEBUG_PRINT("Received %d bytes from TCP", length);
// 将接收到的数据放入接收队列
if (osMessageQueuePut(net_rx_queue, buffer, 0, 0) != osOK) {
DEBUG_PRINT("Net RX queue full, data dropped");
}
}
return error;
}
// 处理连接
void W5500_HandleConnection(void)
{
static uint32_t last_reconnect_time = 0;
uint32_t current_time = HAL_GetTick();
// 更新状态
W5500_UpdateStatus();
if (!W5500_IsConnected()) {
// 尝试重新连接
if (net_config.auto_reconnect &&
(current_time - last_reconnect_time >= net_config.reconnect_interval)) {
DEBUG_PRINT("Attempting to reconnect...");
ErrorCode_t error = W5500_TCPConnect();
if (error == ERROR_NONE) {
DEBUG_PRINT("Reconnected successfully");
} else {
DEBUG_PRINT("Reconnect failed: %d", error);
last_reconnect_time = current_time;
}
}
} else {
// 发送保活数据(如果需要)
static uint32_t last_keepalive_time = 0;
if (current_time - last_keepalive_time >= TCP_KEEPALIVE_INTERVAL * 1000) {
// 可以发送心跳包
last_keepalive_time = current_time;
}
}
}
// 重置W5500
void W5500_Reset(void)
{
DEBUG_PRINT("Resetting W5500...");
// 软件复位
W5500_WriteByte(W5500_MR, 0x80);
osDelay(100);
W5500_WriteByte(W5500_MR, 0x00);
osDelay(100);
// 重新配置网络
W5500_ConfigureNetwork();
// 重置状态
net_status.tcp_connected = false;
DEBUG_PRINT("W5500 reset complete");
}
// SPI读取单个字节
uint8_t W5500_ReadByte(uint16_t address)
{
uint8_t control_byte = (address >> 8) & 0xF8; // 块选择
uint8_t addr_low = address & 0xFF;
uint8_t tx_data[4] = {control_byte, addr_low, 0x00, 0x00};
uint8_t rx_data[4];
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi2, tx_data, rx_data, 4, W5500_SPI_TIMEOUT);
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_SET);
return rx_data[3];
}
// SPI写入单个字节
void W5500_WriteByte(uint16_t address, uint8_t data)
{
uint8_t control_byte = ((address >> 8) & 0xF8) | 0x04; // 块选择 + 写命令
uint8_t addr_low = address & 0xFF;
uint8_t tx_data[4] = {control_byte, addr_low, 0x00, data};
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi2, tx_data, 4, W5500_SPI_TIMEOUT);
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_SET);
}
// 读取16位数据
uint16_t W5500_ReadWord(uint16_t address)
{
uint16_t value = 0;
value = W5500_ReadByte(address) << 8;
value |= W5500_ReadByte(address + 1);
return value;
}
// 写入16位数据
void W5500_WriteWord(uint16_t address, uint16_t data)
{
W5500_WriteByte(address, (data >> 8) & 0xFF);
W5500_WriteByte(address + 1, data & 0xFF);
}
// 读取缓冲区
void W5500_ReadBuffer(uint16_t address, uint8_t *buffer, uint16_t length)
{
uint8_t control_byte = (address >> 8) & 0xF8; // 块选择
uint8_t addr_low = address & 0xFF;
uint8_t tx_cmd[3] = {control_byte, addr_low, 0x00};
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi2, tx_cmd, 3, W5500_SPI_TIMEOUT);
HAL_SPI_Receive(&hspi2, buffer, length, W5500_SPI_TIMEOUT);
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_SET);
}
// 写入缓冲区
void W5500_WriteBuffer(uint16_t address, uint8_t *buffer, uint16_t length)
{
uint8_t control_byte = ((address >> 8) & 0xF8) | 0x04; // 块选择 + 写命令
uint8_t addr_low = address & 0xFF;
uint8_t tx_cmd[3] = {control_byte, addr_low, 0x00};
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi2, tx_cmd, 3, W5500_SPI_TIMEOUT);
HAL_SPI_Transmit(&hspi2, buffer, length, W5500_SPI_TIMEOUT);
HAL_GPIO_WritePin(W5500_SPI_CS_PORT, W5500_SPI_CS_PIN, GPIO_PIN_SET);
}
// 获取Socket状态
uint8_t W5500_GetSocketStatus(uint8_t socket)
{
uint16_t reg_addr = SOCKET_BASE + socket * SOCKET_REG_SIZE + SOCKET_SR;
return W5500_ReadByte(reg_addr);
}
// 打开Socket
ErrorCode_t W5500_SocketOpen(uint8_t socket, uint8_t protocol)
{
uint16_t reg_addr = SOCKET_BASE + socket * SOCKET_REG_SIZE;
// 设置Socket模式
W5500_WriteByte(reg_addr + SOCKET_MR, protocol);
// 发送打开命令
W5500_WriteByte(reg_addr + SOCKET_CR, SOCKET_CMD_OPEN);
// 等待命令完成
osDelay(1);
while (W5500_ReadByte(reg_addr + SOCKET_CR) != 0) {
osDelay(1);
}
// 检查Socket状态
uint8_t status = W5500_GetSocketStatus(socket);
if (status == SOCKET_CLOSED) {
DEBUG_PRINT("Failed to open socket %d", socket);
return ERROR_W5500_CONFIG_FAILED;
}
return ERROR_NONE;
}
// 关闭Socket
ErrorCode_t W5500_SocketClose(uint8_t socket)
{
uint16_t reg_addr = SOCKET_BASE + socket * SOCKET_REG_SIZE;
// 发送关闭命令
W5500_WriteByte(reg_addr + SOCKET_CR, SOCKET_CMD_CLOSE);
// 等待命令完成
osDelay(1);
while (W5500_ReadByte(reg_addr + SOCKET_CR) != 0) {
osDelay(1);
}
// 等待Socket关闭
uint32_t timeout = HAL_GetTick();
while (W5500_GetSocketStatus(socket) != SOCKET_CLOSED) {
if (HAL_GetTick() - timeout > 1000) {
DEBUG_PRINT("Socket close timeout");
return ERROR_W5500_CONFIG_FAILED;
}
osDelay(10);
}
return ERROR_NONE;
}
// Socket连接
ErrorCode_t W5500_SocketConnect(uint8_t socket, uint8_t *ip, uint16_t port)
{
uint16_t reg_addr = SOCKET_BASE + socket * SOCKET_REG_SIZE;
// 设置目标IP和端口
W5500_WriteBuffer(reg_addr + SOCKET_DIPR, ip, 4);
W5500_WriteWord(reg_addr + SOCKET_DPORT, port);
// 发送连接命令
W5500_WriteByte(reg_addr + SOCKET_CR, SOCKET_CMD_CONNECT);
// 等待命令完成
osDelay(1);
while (W5500_ReadByte(reg_addr + SOCKET_CR) != 0) {
osDelay(1);
}
return ERROR_NONE;
}
// Socket发送数据
ErrorCode_t W5500_SocketSend(uint8_t socket, uint8_t *data, uint16_t length)
{
uint16_t reg_addr = SOCKET_BASE + socket * SOCKET_REG_SIZE;
// 检查发送缓冲区空间
uint16_t free_size = W5500_ReadWord(reg_addr + SOCKET_TX_FSR);
if (free_size < length) {
DEBUG_PRINT("TX buffer full: %d < %d", free_size, length);
return ERROR_W5500_TCP_SEND_FAILED;
}
// 获取当前写指针
uint16_t write_ptr = W5500_ReadWord(reg_addr + SOCKET_TX_WR);
// 写入数据到TX缓冲区
uint16_t tx_buffer_addr = 0x8000 + socket * 0x0800; // 每个Socket 2KB TX缓冲区
uint16_t tx_offset = write_ptr + tx_buffer_addr;
W5500_WriteBuffer(tx_offset, data, length);
// 更新写指针
write_ptr += length;
W5500_WriteWord(reg_addr + SOCKET_TX_WR, write_ptr);
// 发送命令
W5500_WriteByte(reg_addr + SOCKET_CR, SOCKET_CMD_SEND);
// 等待命令完成
osDelay(1);
while (W5500_ReadByte(reg_addr + SOCKET_CR) != 0) {
osDelay(1);
}
return ERROR_NONE;
}
// Socket接收数据
ErrorCode_t W5500_SocketReceive(uint8_t socket, uint8_t *buffer, uint16_t *length)
{
uint16_t reg_addr = SOCKET_BASE + socket * SOCKET_REG_SIZE;
// 检查接收数据大小
uint16_t data_size = W5500_ReadWord(reg_addr + SOCKET_RX_RSR);
if (data_size == 0) {
*length = 0;
return ERROR_NONE;
}
// 限制接收大小
if (data_size > *length) {
data_size = *length;
}
// 获取当前读指针
uint16_t read_ptr = W5500_ReadWord(reg_addr + SOCKET_RX_RD);
// 从RX缓冲区读取数据
uint16_t rx_buffer_addr = 0xC000 + socket * 0x0800; // 每个Socket 2KB RX缓冲区
uint16_t rx_offset = read_ptr + rx_buffer_addr;
W5500_ReadBuffer(rx_offset, buffer, data_size);
// 更新读指针
read_ptr += data_size;
W5500_WriteWord(reg_addr + SOCKET_RX_RD, read_ptr);
// 发送接收完成命令
W5500_WriteByte(reg_addr + SOCKET_CR, SOCKET_CMD_RECV);
// 等待命令完成
osDelay(1);
while (W5500_ReadByte(reg_addr + SOCKET_CR) != 0) {
osDelay(1);
}
*length = data_size;
return ERROR_NONE;
}
8. SD卡存储驱动文件 sd_storage.h
c
复制代码
#ifndef __SD_STORAGE_H
#define __SD_STORAGE_H
#include "system_config.h"
#include "ff.h"
#include "diskio.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif
// SD卡配置
#define SD_SPI SPI1
#define SD_SPI_CS_PIN GPIO_PIN_2
#define SD_SPI_CS_PORT GPIOC
#define SD_SPI_TIMEOUT 1000
#define SD_CARD_DETECT_PIN GPIO_PIN_3
#define SD_CARD_DETECT_PORT GPIOC
// 文件系统配置
#define MAX_FILES 10
#define MAX_FILENAME_LENGTH 32
#define MAX_PATH_LENGTH 128
#define FILE_BUFFER_SIZE 512
#define LOG_FILE_SIZE_LIMIT (10 * 1024 * 1024) // 10MB
#define BACKUP_FILE_COUNT 5
// 文件类型定义
typedef enum {
FILE_TYPE_DATA = 0, // 数据文件
FILE_TYPE_LOG, // 日志文件
FILE_TYPE_CONFIG, // 配置文件
FILE_TYPE_TEMP // 临时文件
} FileType_t;
// 文件信息结构
typedef struct {
char filename[MAX_FILENAME_LENGTH];
FileType_t type;
uint32_t size;
uint32_t timestamp;
bool is_open;
FIL file_handle;
} FileInfo_t;
// 存储统计信息
typedef struct {
uint32_t total_space; // 总空间 (KB)
uint32_t free_space; // 剩余空间 (KB)
uint32_t files_written; // 写入文件数
uint32_t bytes_written; // 写入字节数
uint32_t write_errors; // 写入错误
uint32_t last_error; // 最后错误代码
bool is_mounted; // 挂载状态
bool card_present; // 卡存在状态
} StorageStatus_t;
// 数据记录结构
typedef struct {
uint32_t timestamp;
uint16_t data_type;
uint16_t data_length;
uint8_t data[256];
} DataRecord_t;
// 函数声明
ErrorCode_t SD_Storage_Init(void);
ErrorCode_t SD_Storage_Mount(void);
ErrorCode_t SD_Storage_Unmount(void);
bool SD_Storage_IsCardPresent(void);
bool SD_Storage_IsMounted(void);
StorageStatus_t* SD_Storage_GetStatus(void);
void SD_Storage_UpdateStatus(void);
// 文件操作
ErrorCode_t SD_Storage_OpenFile(const char *filename, FileType_t type, FileInfo_t *file_info);
ErrorCode_t SD_Storage_CloseFile(FileInfo_t *file_info);
ErrorCode_t SD_Storage_WriteData(FileInfo_t *file_info, uint8_t *data, uint32_t size);
ErrorCode_t SD_Storage_ReadData(FileInfo_t *file_info, uint8_t *buffer, uint32_t size, uint32_t *bytes_read);
ErrorCode_t SD_Storage_Seek(FileInfo_t *file_info, uint32_t offset);
ErrorCode_t SD_Storage_Truncate(FileInfo_t *file_info);
// 日志文件操作
ErrorCode_t SD_Storage_WriteLog(const char *message);
ErrorCode_t SD_Storage_WriteDataRecord(DataRecord_t *record);
ErrorCode_t SD_Storage_RotateLogs(void);
// 目录操作
ErrorCode_t SD_Storage_CreateDirectory(const char *path);
ErrorCode_t SD_Storage_ListFiles(const char *path, char **file_list, uint32_t *count);
ErrorCode_t SD_Storage_DeleteFile(const char *filename);
ErrorCode_t SD_Storage_Format(void);
// 工具函数
uint32_t SD_Storage_GetFreeSpace(void);
uint32_t SD_Storage_GetTotalSpace(void);
ErrorCode_t SD_Storage_CheckIntegrity(void);
void SD_Storage_CleanupOldFiles(void);
// FATFS回调函数
DSTATUS disk_initialize(BYTE pdrv);
DSTATUS disk_status(BYTE pdrv);
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count);
DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count);
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff);
#ifdef __cplusplus
}
#endif
#endif /* __SD_STORAGE_H */
9. SD卡存储驱动文件 sd_storage.c
c
复制代码
#include "sd_storage.h"
#include <string.h>
#include <stdio.h>
// 全局变量
static FATFS fatfs;
static StorageStatus_t storage_status = {0};
static char current_log_file[MAX_PATH_LENGTH] = "";
// SD卡初始化
ErrorCode_t SD_Storage_Init(void)
{
DEBUG_PRINT("Initializing SD card storage...");
// 初始化SPI
SPI_HandleTypeDef hspi1;
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; // 低速初始通信
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
DEBUG_PRINT("SD SPI initialization failed");
return ERROR_SD_INIT_FAILED;
}
// 配置CS引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = SD_SPI_CS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SD_SPI_CS_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(SD_SPI_CS_PORT, SD_SPI_CS_PIN, GPIO_PIN_SET);
// 配置卡检测引脚
GPIO_InitStruct.Pin = SD_CARD_DETECT_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(SD_CARD_DETECT_PORT, &GPIO_InitStruct);
// 初始化存储状态
memset(&storage_status, 0, sizeof(StorageStatus_t));
storage_status.card_present = SD_Storage_IsCardPresent();
// 尝试挂载文件系统
if (storage_status.card_present) {
ErrorCode_t mount_error = SD_Storage_Mount();
if (mount_error != ERROR_NONE) {
DEBUG_PRINT("SD card mount failed: %d", mount_error);
return mount_error;
}
} else {
DEBUG_PRINT("SD card not present");
return ERROR_SD_INIT_FAILED;
}
// 创建必要的目录
SD_Storage_CreateDirectory("/data");
SD_Storage_CreateDirectory("/logs");
SD_Storage_CreateDirectory("/config");
// 初始化当前日志文件
time_t rawtime;
struct tm *timeinfo;
char timestamp[20];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", timeinfo);
snprintf(current_log_file, sizeof(current_log_file), "/logs/data_%s.csv", timestamp);
DEBUG_PRINT("SD card storage initialized successfully");
DEBUG_PRINT("Log file: %s", current_log_file);
return ERROR_NONE;
}
// 挂载文件系统
ErrorCode_t SD_Storage_Mount(void)
{
FRESULT fr;
// 挂载文件系统
fr = f_mount(&fatfs, "", 1); // 立即挂载
if (fr != FR_OK) {
DEBUG_PRINT("Failed to mount filesystem: %d", fr);
storage_status.is_mounted = false;
return ERROR_SD_MOUNT_FAILED;
}
storage_status.is_mounted = true;
// 更新存储空间信息
DWORD free_clusters, total_clusters;
FATFS *fs;
fr = f_getfree("", &free_clusters, &fs);
if (fr == FR_OK) {
storage_status.total_space = (fs->csize * total_clusters) / 2; // KB
storage_status.free_space = (fs->csize * free_clusters) / 2; // KB
}
DEBUG_PRINT("Filesystem mounted, free space: %lu KB", storage_status.free_space);
return ERROR_NONE;
}
// 卸载文件系统
ErrorCode_t SD_Storage_Unmount(void)
{
FRESULT fr = f_mount(NULL, "", 0); // 卸载
if (fr != FR_OK) {
DEBUG_PRINT("Failed to unmount filesystem: %d", fr);
return ERROR_SD_MOUNT_FAILED;
}
storage_status.is_mounted = false;
DEBUG_PRINT("Filesystem unmounted");
return ERROR_NONE;
}
// 检查SD卡是否存在
bool SD_Storage_IsCardPresent(void)
{
// 卡检测引脚为低电平时表示卡存在
return (HAL_GPIO_ReadPin(SD_CARD_DETECT_PORT, SD_CARD_DETECT_PIN) == GPIO_PIN_RESET);
}
// 检查是否已挂载
bool SD_Storage_IsMounted(void)
{
return storage_status.is_mounted;
}
// 获取存储状态
StorageStatus_t* SD_Storage_GetStatus(void)
{
return &storage_status;
}
// 更新存储状态
void SD_Storage_UpdateStatus(void)
{
// 更新卡存在状态
bool card_present = SD_Storage_IsCardPresent();
if (card_present != storage_status.card_present) {
storage_status.card_present = card_present;
if (card_present) {
DEBUG_PRINT("SD card inserted");
SD_Storage_Mount();
} else {
DEBUG_PRINT("SD card removed");
SD_Storage_Unmount();
}
}
// 如果已挂载,更新空间信息
if (storage_status.is_mounted) {
DWORD free_clusters, total_clusters;
FATFS *fs;
FRESULT fr = f_getfree("", &free_clusters, &fs);
if (fr == FR_OK) {
storage_status.total_space = (fs->csize * total_clusters) / 2;
storage_status.free_space = (fs->csize * free_clusters) / 2;
}
}
}
// 打开文件
ErrorCode_t SD_Storage_OpenFile(const char *filename, FileType_t type, FileInfo_t *file_info)
{
if (filename == NULL || file_info == NULL) {
return ERROR_SD_FILE_OPEN_FAILED;
}
if (!storage_status.is_mounted) {
DEBUG_PRINT("Filesystem not mounted");
return ERROR_SD_MOUNT_FAILED;
}
// 设置打开模式
BYTE mode = FA_WRITE | FA_READ | FA_OPEN_ALWAYS;
if (type == FILE_TYPE_LOG || type == FILE_TYPE_DATA) {
mode = FA_WRITE | FA_READ | FA_OPEN_APPEND;
}
// 打开文件
FRESULT fr = f_open(&file_info->file_handle, filename, mode);
if (fr != FR_OK) {
DEBUG_PRINT("Failed to open file %s: %d", filename, fr);
storage_status.last_error = fr;
storage_status.write_errors++;
return ERROR_SD_FILE_OPEN_FAILED;
}
// 填充文件信息
strncpy(file_info->filename, filename, MAX_FILENAME_LENGTH - 1);
file_info->type = type;
file_info->is_open = true;
// 获取文件大小
file_info->size = f_size(&file_info->file_handle);
file_info->timestamp = HAL_GetTick();
DEBUG_PRINT("File opened: %s, size: %lu", filename, file_info->size);
return ERROR_NONE;
}
// 关闭文件
ErrorCode_t SD_Storage_CloseFile(FileInfo_t *file_info)
{
if (file_info == NULL || !file_info->is_open) {
return ERROR_NONE;
}
FRESULT fr = f_close(&file_info->file_handle);
if (fr != FR_OK) {
DEBUG_PRINT("Failed to close file %s: %d", file_info->filename, fr);
storage_status.last_error = fr;
return ERROR_SD_FILE_WRITE_FAILED;
}
file_info->is_open = false;
DEBUG_PRINT("File closed: %s", file_info->filename);
return ERROR_NONE;
}
// 写入数据
ErrorCode_t SD_Storage_WriteData(FileInfo_t *file_info, uint8_t *data, uint32_t size)
{
if (file_info == NULL || data == NULL || size == 0) {
return ERROR_SD_FILE_WRITE_FAILED;
}
if (!file_info->is_open) {
DEBUG_PRINT("File not open: %s", file_info->filename);
return ERROR_SD_FILE_WRITE_FAILED;
}
// 检查剩余空间
if (storage_status.free_space * 1024 < size) {
DEBUG_PRINT("Insufficient disk space: %lu < %lu",
storage_status.free_space * 1024, size);
return ERROR_SD_FULL;
}
UINT bytes_written;
FRESULT fr = f_write(&file_info->file_handle, data, size, &bytes_written);
if (fr != FR_OK || bytes_written != size) {
DEBUG_PRINT("Failed to write to file %s: %d, written: %u",
file_info->filename, fr, bytes_written);
storage_status.last_error = fr;
storage_status.write_errors++;
return ERROR_SD_FILE_WRITE_FAILED;
}
// 更新文件大小和统计
file_info->size += bytes_written;
storage_status.bytes_written += bytes_written;
storage_status.files_written++;
// 同步文件(确保数据写入物理介质)
fr = f_sync(&file_info->file_handle);
if (fr != FR_OK) {
DEBUG_PRINT("Failed to sync file %s: %d", file_info->filename, fr);
// 不返回错误,因为数据已经写入缓冲区
}
return ERROR_NONE;
}
// 写入日志
ErrorCode_t SD_Storage_WriteLog(const char *message)
{
if (message == NULL) {
return ERROR_SD_FILE_WRITE_FAILED;
}
// 检查是否需要轮转日志
if (strlen(current_log_file) > 0) {
FILINFO fno;
FRESULT fr = f_stat(current_log_file, &fno);
if (fr == FR_OK && fno.fsize > LOG_FILE_SIZE_LIMIT) {
SD_Storage_RotateLogs();
}
}
// 打开或创建日志文件
FileInfo_t log_file;
ErrorCode_t error = SD_Storage_OpenFile(current_log_file, FILE_TYPE_LOG, &log_file);
if (error != ERROR_NONE) {
return error;
}
// 添加时间戳
char log_entry[256];
uint32_t timestamp = HAL_GetTick();
snprintf(log_entry, sizeof(log_entry), "[%lu] %s\r\n", timestamp, message);
// 写入日志
error = SD_Storage_WriteData(&log_file, (uint8_t *)log_entry, strlen(log_entry));
// 关闭文件
SD_Storage_CloseFile(&log_file);
return error;
}
// 写入数据记录
ErrorCode_t SD_Storage_WriteDataRecord(DataRecord_t *record)
{
if (record == NULL || record->data_length == 0) {
return ERROR_SD_FILE_WRITE_FAILED;
}
// 创建CSV格式的数据行
char csv_line[512];
int pos = 0;
// 时间戳
pos += snprintf(csv_line + pos, sizeof(csv_line) - pos, "%lu,", record->timestamp);
// 数据类型
pos += snprintf(csv_line + pos, sizeof(csv_line) - pos, "%u,", record->data_type);
// 数据(十六进制格式)
for (uint16_t i = 0; i < record->data_length; i++) {
pos += snprintf(csv_line + pos, sizeof(csv_line) - pos, "%02X", record->data[i]);
}
// 换行
pos += snprintf(csv_line + pos, sizeof(csv_line) - pos, "\r\n");
// 写入日志文件
return SD_Storage_WriteLog(csv_line);
}
// 轮转日志文件
ErrorCode_t SD_Storage_RotateLogs(void)
{
DEBUG_PRINT("Rotating log files...");
// 关闭当前日志文件
if (strlen(current_log_file) > 0) {
// 这里应该关闭已打开的日志文件
}
// 生成新的日志文件名
time_t rawtime;
struct tm *timeinfo;
char timestamp[20];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", timeinfo);
snprintf(current_log_file, sizeof(current_log_file), "/logs/data_%s.csv", timestamp);
// 清理旧文件
SD_Storage_CleanupOldFiles();
DEBUG_PRINT("New log file: %s", current_log_file);
return ERROR_NONE;
}
// 创建目录
ErrorCode_t SD_Storage_CreateDirectory(const char *path)
{
if (path == NULL) {
return ERROR_SD_FILE_OPEN_FAILED;
}
if (!storage_status.is_mounted) {
return ERROR_SD_MOUNT_FAILED;
}
FRESULT fr = f_mkdir(path);
if (fr != FR_OK && fr != FR_EXIST) {
DEBUG_PRINT("Failed to create directory %s: %d", path, fr);
return ERROR_SD_FILE_OPEN_FAILED;
}
return ERROR_NONE;
}
// 获取剩余空间
uint32_t SD_Storage_GetFreeSpace(void)
{
return storage_status.free_space;
}
// 清理旧文件
void SD_Storage_CleanupOldFiles(void)
{
DIR dir;
FILINFO fno;
FRESULT fr;
// 打开日志目录
fr = f_opendir(&dir, "/logs");
if (fr != FR_OK) {
return;
}
// 读取所有文件
uint32_t file_count = 0;
char *files[100];
while (f_readdir(&dir, &fno) == FR_OK && fno.fname[0] != 0) {
if (!(fno.fattrib & AM_DIR)) {
// 统计文件数量
file_count++;
// 这里可以添加文件删除逻辑
// 例如:删除超过7天的文件或保留最多10个文件
}
}
f_closedir(&dir);
// 如果文件太多,删除最旧的文件
if (file_count > BACKUP_FILE_COUNT) {
// 这里需要实现文件排序和删除逻辑
}
}
10. 数据处理文件 data_processor.h
c
复制代码
#ifndef __DATA_PROCESSOR_H
#define __DATA_PROCESSOR_H
#include "can_config.h"
#include "network_config.h"
#include "sd_storage.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif
// 数据处理配置
#define DATA_QUEUE_SIZE 100
#define MAX_PROCESSING_TIME_MS 10
#define DATA_COMPRESSION_RATIO 0.5f
#define MAX_CACHE_SIZE (10 * 1024) // 10KB
// 数据类型定义
typedef enum {
DATA_TYPE_RAW_CAN = 0, // 原始CAN数据
DATA_TYPE_SENSOR, // 传感器数据
DATA_TYPE_SYSTEM_STATUS, // 系统状态
DATA_TYPE_EVENT_LOG, // 事件日志
DATA_TYPE_CONFIG, // 配置数据
DATA_TYPE_DIAGNOSTIC // 诊断数据
} DataType_t;
// 数据处理状态
typedef enum {
PROCESS_STATE_IDLE = 0,
PROCESS_STATE_READY,
PROCESS_STATE_PROCESSING,
PROCESS_STATE_COMPRESSING,
PROCESS_STATE_SENDING,
PROCESS_STATE_ERROR
} ProcessState_t;
// 数据包缓存
typedef struct {
uint8_t *buffer;
uint32_t size;
uint32_t capacity;
uint32_t write_index;
uint32_t read_index;
osMutexId_t mutex;
} DataBuffer_t;
// 处理器统计信息
typedef struct {
uint32_t total_packets;
uint32_t processed_packets;
uint32_t sent_packets;
uint32_t stored_packets;
uint32_t dropped_packets;
uint32_t compression_saved;
uint32_t processing_time_max;
uint32_t processing_time_avg;
uint32_t last_error;
} ProcessorStats_t;
// 函数声明
ErrorCode_t DataProcessor_Init(void);
ErrorCode_t DataProcessor_Start(void);
ErrorCode_t DataProcessor_Stop(void);
ErrorCode_t DataProcessor_ProcessCanMessage(CanMessage_t *msg);
ErrorCode_t DataProcessor_ProcessSensorData(SensorData_t *sensor_data);
ErrorCode_t DataProcessor_BatchProcess(void);
ErrorCode_t DataProcessor_SendToNetwork(DataBuffer_t *buffer);
ErrorCode_t DataProcessor_StoreToSD(DataBuffer_t *buffer);
ProcessorStats_t* DataProcessor_GetStats(void);
void DataProcessor_ClearStats(void);
ProcessState_t DataProcessor_GetState(void);
uint32_t DataProcessor_GetQueueSize(void);
// 数据缓冲操作
ErrorCode_t DataBuffer_Init(DataBuffer_t *buffer, uint32_t capacity);
ErrorCode_t DataBuffer_Write(DataBuffer_t *buffer, uint8_t *data, uint32_t size);
ErrorCode_t DataBuffer_Read(DataBuffer_t *buffer, uint8_t *data, uint32_t *size);
ErrorCode_t DataBuffer_Clear(DataBuffer_t *buffer);
uint32_t DataBuffer_GetFreeSpace(DataBuffer_t *buffer);
uint32_t DataBuffer_GetUsedSpace(DataBuffer_t *buffer);
void DataBuffer_Destroy(DataBuffer_t *buffer);
// 数据处理函数
ErrorCode_t DataProcessor_CompressData(uint8_t *input, uint32_t input_size,
uint8_t *output, uint32_t *output_size);
ErrorCode_t DataProcessor_FormatToJSON(uint8_t *buffer, uint32_t *size, DataType_t type);
ErrorCode_t DataProcessor_FormatToBinary(uint8_t *buffer, uint32_t *size, DataType_t type);
ErrorCode_t DataProcessor_AddTimestamp(uint8_t *buffer, uint32_t *size);
ErrorCode_t DataProcessor_CalculateChecksum(uint8_t *data, uint32_t size, uint16_t *checksum);
#ifdef __cplusplus
}
#endif
#endif /* __DATA_PROCESSOR_H */
11. 看门狗驱动文件 watchdog.h
c
复制代码
#ifndef __WATCHDOG_H
#define __WATCHDOG_H
#include "system_config.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif
// 看门狗配置
#define WATCHDOG_TIMEOUT_MS 10000 // 10秒超时
#define WATCHDOG_REFRESH_INTERVAL 1000 // 1秒刷新一次
#define WATCHDOG_TASK_COUNT 5 // 监控的任务数量
// 任务监控结构
typedef struct {
char task_name[16];
osThreadId_t task_id;
uint32_t last_alive_time;
uint32_t check_interval;
uint32_t max_miss_count;
uint32_t miss_count;
bool is_enabled;
} TaskMonitor_t;
// 看门狗状态
typedef enum {
WATCHDOG_DISABLED = 0,
WATCHDOG_ENABLED,
WATCHDOG_TRIGGERED,
WATCHDOG_RECOVERING
} WatchdogState_t;
// 看门狗统计
typedef struct {
WatchdogState_t state;
uint32_t reset_count;
uint32_t last_reset_time;
uint32_t last_refresh_time;
uint32_t task_timeout_count;
uint32_t recovery_count;
uint32_t max_recovery_time;
} WatchdogStats_t;
// 函数声明
ErrorCode_t Watchdog_Init(void);
ErrorCode_t Watchdog_Start(void);
ErrorCode_t Watchdog_Stop(void);
ErrorCode_t Watchdog_Refresh(void);
WatchdogState_t Watchdog_GetState(void);
WatchdogStats_t* Watchdog_GetStats(void);
// 任务监控
ErrorCode_t Watchdog_RegisterTask(const char *task_name, osThreadId_t task_id,
uint32_t check_interval, uint32_t max_miss_count);
ErrorCode_t Watchdog_UnregisterTask(const char *task_name);
ErrorCode_t Watchdog_TaskAlive(const char *task_name);
void Watchdog_CheckTasks(void);
// 系统监控
void Watchdog_MonitorSystemResources(void);
bool Watchdog_CheckSystemHealth(void);
ErrorCode_t Watchdog_RecoverSystem(void);
void Watchdog_SystemReset(void);
// 独立看门狗(IWDG)操作
ErrorCode_t IWDG_Init(uint32_t timeout_ms);
ErrorCode_t IWDG_Refresh(void);
ErrorCode_t IWDG_Start(void);
ErrorCode_t IWDG_Stop(void);
// 窗口看门狗(WWDG)操作
ErrorCode_t WWDG_Init(uint32_t timeout_ms);
ErrorCode_t WWDG_Refresh(void);
#ifdef __cplusplus
}
#endif
#endif /* __WATCHDOG_H */
12. FreeRTOS任务管理文件 rtos_tasks.h
c
复制代码
#ifndef __RTOS_TASKS_H
#define __RTOS_TASKS_H
#include "system_config.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif
// 任务句柄声明
extern osThreadId_t canRxTaskHandle;
extern osThreadId_t canTxTaskHandle;
extern osThreadId_t dataProcessTaskHandle;
extern osThreadId_t networkTaskHandle;
extern osThreadId_t storageTaskHandle;
extern osThreadId_t watchdogTaskHandle;
extern osThreadId_t systemMonitorTaskHandle;
// 队列句柄声明
extern osMessageQueueId_t canDataQueue;
extern osMessageQueueId_t processedDataQueue;
extern osMessageQueueId_t networkDataQueue;
extern osMessageQueueId_t storageDataQueue;
// 信号量句柄声明
extern osSemaphoreId_t canSemaphore;
extern osSemaphoreId_t networkSemaphore;
extern osSemaphoreId_t storageSemaphore;
extern osSemaphoreId_t systemSemaphore;
// 互斥锁句柄声明
extern osMutexId_t canMutex;
extern osMutexId_t networkMutex;
extern osMutexId_t storageMutex;
// 事件组句柄声明
extern osEventFlagsId_t systemEvents;
// 系统事件定义
#define EVENT_CAN_DATA_READY (1UL << 0)
#define EVENT_NETWORK_CONNECTED (1UL << 1)
#define EVENT_STORAGE_READY (1UL << 2)
#define EVENT_SYSTEM_ERROR (1UL << 3)
#define EVENT_SYSTEM_RECOVERY (1UL << 4)
#define EVENT_CONFIG_CHANGED (1UL << 5)
// 任务函数声明
void CAN_Rx_Task(void *argument);
void CAN_Tx_Task(void *argument);
void Data_Process_Task(void *argument);
void Network_Task(void *argument);
void Storage_Task(void *argument);
void Watchdog_Task(void *argument);
void System_Monitor_Task(void *argument);
// 任务管理函数
ErrorCode_t RTOS_Tasks_Init(void);
ErrorCode_t RTOS_Tasks_Start(void);
ErrorCode_t RTOS_Tasks_Stop(void);
ErrorCode_t RTOS_Tasks_Suspend(void);
ErrorCode_t RTOS_Tasks_Resume(void);
void RTOS_Tasks_PrintStatus(void);
uint32_t RTOS_Tasks_GetCpuUsage(void);
uint32_t RTOS_Tasks_GetStackUsage(osThreadId_t task_handle);
// 资源管理
ErrorCode_t RTOS_CreateQueues(void);
ErrorCode_t RTOS_CreateSemaphores(void);
ErrorCode_t RTOS_CreateMutexes(void);
ErrorCode_t RTOS_CreateEvents(void);
void RTOS_CleanupResources(void);
// 调试功能
void RTOS_EnableTrace(void);
void RTOS_PrintTaskInfo(void);
void RTOS_PrintQueueInfo(void);
void RTOS_PrintHeapInfo(void);
#ifdef __cplusplus
}
#endif
#endif /* __RTOS_TASKS_H */
13. FreeRTOS任务管理文件 rtos_tasks.c
c
复制代码
#include "rtos_tasks.h"
#include "can_bus.h"
#include "w5500_net.h"
#include "sd_storage.h"
#include "data_processor.h"
#include "watchdog.h"
// 任务句柄定义
osThreadId_t canRxTaskHandle;
osThreadId_t canTxTaskHandle;
osThreadId_t dataProcessTaskHandle;
osThreadId_t networkTaskHandle;
osThreadId_t storageTaskHandle;
osThreadId_t watchdogTaskHandle;
osThreadId_t systemMonitorTaskHandle;
// 队列句柄定义
osMessageQueueId_t canDataQueue;
osMessageQueueId_t processedDataQueue;
osMessageQueueId_t networkDataQueue;
osMessageQueueId_t storageDataQueue;
// 信号量句柄定义
osSemaphoreId_t canSemaphore;
osSemaphoreId_t networkSemaphore;
osSemaphoreId_t storageSemaphore;
osSemaphoreId_t systemSemaphore;
// 互斥锁句柄定义
osMutexId_t canMutex;
osMutexId_t networkMutex;
osMutexId_t storageMutex;
// 事件组句柄定义
osEventFlagsId_t systemEvents;
// 任务属性定义
static const osThreadAttr_t canRxTask_attributes = {
.name = "CAN_Rx_Task",
.stack_size = TASK_STACK_MEDIUM,
.priority = TASK_PRIORITY_HIGH,
};
static const osThreadAttr_t canTxTask_attributes = {
.name = "CAN_Tx_Task",
.stack_size = TASK_STACK_MEDIUM,
.priority = TASK_PRIORITY_NORMAL,
};
static const osThreadAttr_t dataProcessTask_attributes = {
.name = "Data_Process_Task",
.stack_size = TASK_STACK_LARGE,
.priority = TASK_PRIORITY_ABOVE_NORMAL,
};
static const osThreadAttr_t networkTask_attributes = {
.name = "Network_Task",
.stack_size = TASK_STACK_LARGE,
.priority = TASK_PRIORITY_NORMAL,
};
static const osThreadAttr_t storageTask_attributes = {
.name = "Storage_Task",
.stack_size = TASK_STACK_LARGE,
.priority = TASK_PRIORITY_NORMAL,
};
static const osThreadAttr_t watchdogTask_attributes = {
.name = "Watchdog_Task",
.stack_size = TASK_STACK_SMALL,
.priority = TASK_PRIORITY_REALTIME,
};
static const osThreadAttr_t systemMonitorTask_attributes = {
.name = "System_Monitor_Task",
.stack_size = TASK_STACK_MEDIUM,
.priority = TASK_PRIORITY_LOW,
};
// CAN接收任务
void CAN_Rx_Task(void *argument)
{
DEBUG_PRINT("CAN Rx Task started");
CanMessage_t rx_msg;
uint32_t last_process_time = 0;
// 注册任务到看门狗
Watchdog_RegisterTask("CAN_Rx", osThreadGetId(), 1000, 3);
while (1) {
// 刷新看门狗
Watchdog_TaskAlive("CAN_Rx");
// 接收CAN消息
ErrorCode_t error = CAN_ReceiveMessage(&rx_msg, 100); // 100ms超时
if (error == ERROR_NONE) {
// 将消息放入处理队列
if (osMessageQueuePut(canDataQueue, &rx_msg, 0, 0) != osOK) {
DEBUG_PRINT("CAN data queue full, message dropped");
}
// 设置数据就绪事件
osEventFlagsSet(systemEvents, EVENT_CAN_DATA_READY);
}
// 处理其他任务或进入低功耗模式
osDelay(1);
}
}
// CAN发送任务
void CAN_Tx_Task(void *argument)
{
DEBUG_PRINT("CAN Tx Task started");
// 注册任务到看门狗
Watchdog_RegisterTask("CAN_Tx", osThreadGetId(), 2000, 3);
while (1) {
// 刷新看门狗
Watchdog_TaskAlive("CAN_Tx");
// 发送心跳消息
CAN_SendHeartbeat();
// 这里可以添加其他发送逻辑
osDelay(500);
}
}
// 数据处理任务
void Data_Process_Task(void *argument)
{
DEBUG_PRINT("Data Process Task started");
CanMessage_t rx_msg;
DataRecord_t data_record;
uint32_t process_count = 0;
// 注册任务到看门狗
Watchdog_RegisterTask("Data_Process", osThreadGetId(), 1000, 3);
while (1) {
// 刷新看门狗
Watchdog_TaskAlive("Data_Process");
// 从队列获取CAN数据
if (osMessageQueueGet(canDataQueue, &rx_msg, NULL, 0) == osOK) {
// 处理CAN消息
DataProcessor_ProcessCanMessage(&rx_msg);
process_count++;
// 每处理10条消息记录一次
if (process_count % 10 == 0) {
DEBUG_PRINT("Processed %lu CAN messages", process_count);
}
}
// 批量处理数据
DataProcessor_BatchProcess();
// 短暂延时,让其他任务运行
osDelay(5);
}
}
// 网络任务
void Network_Task(void *argument)
{
DEBUG_PRINT("Network Task started");
uint32_t last_connect_time = 0;
bool network_initialized = false;
// 注册任务到看门狗
Watchdog_RegisterTask("Network", osThreadGetId(), 1000, 3);
// 初始化网络
ErrorCode_t error = W5500_Init();
if (error != ERROR_NONE) {
DEBUG_PRINT("Network initialization failed: %d", error);
osEventFlagsSet(systemEvents, EVENT_SYSTEM_ERROR);
} else {
network_initialized = true;
}
while (1) {
// 刷新看门狗
Watchdog_TaskAlive("Network");
if (network_initialized) {
// 处理网络连接
W5500_HandleConnection();
// 处理发送队列
W5500_ProcessTxQueue();
// 处理接收队列
W5500_ProcessRxQueue();
// 更新网络状态
W5500_UpdateStatus();
}
osDelay(100);
}
}
// 存储任务
void Storage_Task(void *argument)
{
DEBUG_PRINT("Storage Task started");
DataRecord_t data_record;
uint32_t last_cleanup_time = 0;
// 注册任务到看门狗
Watchdog_RegisterTask("Storage", osThreadGetId(), 2000, 3);
// 初始化存储
ErrorCode_t error = SD_Storage_Init();
if (error != ERROR_NONE) {
DEBUG_PRINT("Storage initialization failed: %d", error);
osEventFlagsSet(systemEvents, EVENT_SYSTEM_ERROR);
} else {
osEventFlagsSet(systemEvents, EVENT_STORAGE_READY);
}
while (1) {
// 刷新看门狗
Watchdog_TaskAlive("Storage");
// 更新存储状态
SD_Storage_UpdateStatus();
// 定期清理旧文件(每10分钟)
uint32_t current_time = HAL_GetTick();
if (current_time - last_cleanup_time > 10 * 60 * 1000) {
SD_Storage_CleanupOldFiles();
last_cleanup_time = current_time;
}
// 检查存储空间
if (SD_Storage_GetFreeSpace() < 1024) { // 少于1MB
DEBUG_PRINT("Low disk space: %lu KB", SD_Storage_GetFreeSpace());
osEventFlagsSet(systemEvents, EVENT_SYSTEM_ERROR);
}
osDelay(1000);
}
}
// 看门狗任务
void Watchdog_Task(void *argument)
{
DEBUG_PRINT("Watchdog Task started");
// 初始化看门狗
ErrorCode_t error = Watchdog_Init();
if (error != ERROR_NONE) {
DEBUG_PRINT("Watchdog initialization failed: %d", error);
}
// 启动看门狗
error = Watchdog_Start();
if (error != ERROR_NONE) {
DEBUG_PRINT("Failed to start watchdog: %d", error);
}
while (1) {
// 检查任务状态
Watchdog_CheckTasks();
// 监控系统资源
Watchdog_MonitorSystemResources();
// 检查系统健康状态
if (!Watchdog_CheckSystemHealth()) {
DEBUG_PRINT("System health check failed");
osEventFlagsSet(systemEvents, EVENT_SYSTEM_ERROR);
// 尝试恢复系统
error = Watchdog_RecoverSystem();
if (error != ERROR_NONE) {
DEBUG_PRINT("System recovery failed, resetting...");
Watchdog_SystemReset();
}
}
// 刷新看门狗
Watchdog_Refresh();
osDelay(1000);
}
}
// 系统监控任务
void System_Monitor_Task(void *argument)
{
DEBUG_PRINT("System Monitor Task started");
uint32_t last_status_time = 0;
SystemStatus_t system_status;
// 注册任务到看门狗
Watchdog_RegisterTask("SysMonitor", osThreadGetId(), 5000, 3);
while (1) {
// 刷新看门狗
Watchdog_TaskAlive("SysMonitor");
// 监控系统事件
uint32_t events = osEventFlagsWait(systemEvents,
EVENT_SYSTEM_ERROR | EVENT_SYSTEM_RECOVERY,
osFlagsWaitAny, 0);
if (events & EVENT_SYSTEM_ERROR) {
DEBUG_PRINT("System error event detected");
// 处理系统错误
osEventFlagsClear(systemEvents, EVENT_SYSTEM_ERROR);
}
if (events & EVENT_SYSTEM_RECOVERY) {
DEBUG_PRINT("System recovery event detected");
// 处理系统恢复
osEventFlagsClear(systemEvents, EVENT_SYSTEM_RECOVERY);
}
// 定期打印系统状态(每30秒)
uint32_t current_time = HAL_GetTick();
if (current_time - last_status_time > 30000) {
RTOS_Tasks_PrintStatus();
// 打印CAN统计
CanStatistics_t *can_stats = CAN_GetStatistics();
DEBUG_PRINT("CAN Stats: RX=%lu, TX=%lu, Errors=%lu",
can_stats->rx_total, can_stats->tx_total, can_stats->bus_error);
// 打印网络状态
NetworkStatus_t *net_status = W5500_GetStatus();
DEBUG_PRINT("Network: %s, TX=%lu, RX=%lu",
net_status->tcp_connected ? "Connected" : "Disconnected",
net_status->tx_bytes, net_status->rx_bytes);
// 打印存储状态
StorageStatus_t *storage_status = SD_Storage_GetStatus();
DEBUG_PRINT("Storage: %s, Free=%lu KB",
storage_status->is_mounted ? "Mounted" : "Unmounted",
storage_status->free_space);
last_status_time = current_time;
}
osDelay(1000);
}
}
// 初始化RTOS任务
ErrorCode_t RTOS_Tasks_Init(void)
{
DEBUG_PRINT("Initializing RTOS tasks...");
// 创建资源
if (RTOS_CreateQueues() != ERROR_NONE ||
RTOS_CreateSemaphores() != ERROR_NONE ||
RTOS_CreateMutexes() != ERROR_NONE ||
RTOS_CreateEvents() != ERROR_NONE) {
return ERROR_RTOS_TASK_CREATE_FAILED;
}
// 创建任务
canRxTaskHandle = osThreadNew(CAN_Rx_Task, NULL, &canRxTask_attributes);
canTxTaskHandle = osThreadNew(CAN_Tx_Task, NULL, &canTxTask_attributes);
dataProcessTaskHandle = osThreadNew(Data_Process_Task, NULL, &dataProcessTask_attributes);
networkTaskHandle = osThreadNew(Network_Task, NULL, &networkTask_attributes);
storageTaskHandle = osThreadNew(Storage_Task, NULL, &storageTask_attributes);
watchdogTaskHandle = osThreadNew(Watchdog_Task, NULL, &watchdogTask_attributes);
systemMonitorTaskHandle = osThreadNew(System_Monitor_Task, NULL, &systemMonitorTask_attributes);
// 检查任务创建是否成功
if (canRxTaskHandle == NULL || canTxTaskHandle == NULL ||
dataProcessTaskHandle == NULL || networkTaskHandle == NULL ||
storageTaskHandle == NULL || watchdogTaskHandle == NULL ||
systemMonitorTaskHandle == NULL) {
DEBUG_PRINT("Failed to create one or more RTOS tasks");
return ERROR_RTOS_TASK_CREATE_FAILED;
}
DEBUG_PRINT("RTOS tasks initialized successfully");
return ERROR_NONE;
}
// 创建队列
ErrorCode_t RTOS_CreateQueues(void)
{
canDataQueue = osMessageQueueNew(DATA_QUEUE_SIZE, sizeof(CanMessage_t), NULL);
processedDataQueue = osMessageQueueNew(DATA_QUEUE_SIZE, sizeof(DataRecord_t), NULL);
networkDataQueue = osMessageQueueNew(PACKET_QUEUE_SIZE, sizeof(PacketHeader_t) + PACKET_MAX_SIZE, NULL);
storageDataQueue = osMessageQueueNew(DATA_QUEUE_SIZE, sizeof(DataRecord_t), NULL);
if (canDataQueue == NULL || processedDataQueue == NULL ||
networkDataQueue == NULL || storageDataQueue == NULL) {
return ERROR_RTOS_TASK_CREATE_FAILED;
}
return ERROR_NONE;
}
// 打印任务状态
void RTOS_Tasks_PrintStatus(void)
{
DEBUG_PRINT("=== System Status ===");
DEBUG_PRINT("Uptime: %lu ms", HAL_GetTick());
DEBUG_PRINT("CPU Usage: %lu%%", RTOS_Tasks_GetCpuUsage());
// 这里可以添加更多状态信息
}
14. 主函数文件 main.c
c
复制代码
#include "main.h"
#include "rtos_tasks.h"
#include "system_config.h"
#include <stdio.h>
// 系统句柄
RTC_HandleTypeDef hrtc;
UART_HandleTypeDef huart3;
// 系统状态
static SystemStatus_t system_status;
// 错误处理函数
void Error_Handler(void)
{
DEBUG_PRINT("!!! FATAL ERROR !!!");
// 关闭所有外设
CAN_Stop();
W5500_TCPDisconnect();
SD_Storage_Unmount();
// 记录错误
system_status.last_error = ERROR_WATCHDOG_TIMEOUT;
system_status.system_state = SYS_STATE_FATAL;
// 进入错误状态循环
while (1) {
// 闪烁LED指示错误
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(100);
}
}
// 系统时钟配置
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
// 配置主PLL
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = HSE_VALUE / 1000000;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
Error_Handler();
}
// 配置外设时钟
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
Error_Handler();
}
}
// RTC配置
static void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK) {
Error_Handler();
}
// 设置初始时间
sTime.Hours = 0;
sTime.Minutes = 0;
sTime.Seconds = 0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) {
Error_Handler();
}
// 设置初始日期
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 1;
sDate.Year = 0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) {
Error_Handler();
}
}
// UART配置
static void MX_USART3_UART_Init(void)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = DEBUG_BAUDRATE;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK) {
Error_Handler();
}
}
// GPIO配置
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
// 用户LED (PC13)
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// CAN引脚 (PD0, PD1)
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
// SPI1引脚 (SD卡) - PA5, PA6, PA7
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// SPI2引脚 (W5500) - PB13, PB14, PB15
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
// 系统初始化
void System_Init(void)
{
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化外设
MX_GPIO_Init();
MX_RTC_Init();
MX_USART3_UART_Init();
// 初始化系统状态
memset(&system_status, 0, sizeof(SystemStatus_t));
system_status.system_state = SYS_STATE_INIT;
// 点亮LED表示系统正在启动
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
DEBUG_PRINT("\r\n========================================");
DEBUG_PRINT("CAN Bus Data Acquisition System");
DEBUG_PRINT("Version: %s", FIRMWARE_VERSION);
DEBUG_PRINT("Hardware: %s", HARDWARE_VERSION);
DEBUG_PRINT("Build: %s %s", __DATE__, __TIME__);
DEBUG_PRINT("System Clock: %lu MHz", SYSTEM_CLOCK_FREQ / 1000000);
DEBUG_PRINT("========================================\r\n");
}
// 硬件初始化
void Hardware_Init(void)
{
DEBUG_PRINT("Initializing hardware...");
// 初始化CAN总线
ErrorCode_t error = CAN_Init();
if (error != ERROR_NONE) {
DEBUG_PRINT("CAN initialization failed: %d", error);
system_status.last_error = error;
} else {
error = CAN_Start();
if (error != ERROR_NONE) {
DEBUG_PRINT("CAN start failed: %d", error);
}
}
// 其他硬件初始化会在各自的RTOS任务中进行
DEBUG_PRINT("Hardware initialization complete");
}
// 系统主循环
void System_Main_Loop(void)
{
uint32_t last_status_time = 0;
DEBUG_PRINT("Starting system main loop...");
// 初始化RTOS任务
ErrorCode_t error = RTOS_Tasks_Init();
if (error != ERROR_NONE) {
DEBUG_PRINT("RTOS tasks initialization failed: %d", error);
Error_Handler();
}
// 启动调度器
DEBUG_PRINT("Starting FreeRTOS scheduler...");
osKernelStart();
// 这里不会执行,因为调度器已经启动
while (1) {
// 如果调度器停止,会执行到这里
Error_Handler();
}
}
// 主函数
int main(void)
{
// 系统初始化
System_Init();
// 硬件初始化
Hardware_Init();
// 进入系统主循环(启动RTOS)
System_Main_Loop();
// 永远不会到达这里
return 0;
}
// 重写fputc以支持printf
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
15. 使用说明
硬件连接
c
复制代码
STM32F407引脚分配:
- PD0, PD1 -> CAN1 (CAN_H, CAN_L)
- PA5, PA6, PA7 -> SPI1 (SD卡: SCK, MISO, MOSI)
- PB13, PB14, PB15 -> SPI2 (W5500: SCK, MISO, MOSI)
- PC2 -> SD卡 CS
- PB12 -> W5500 CS
- PC3 -> SD卡检测
- PC13 -> 用户LED
- PA2, PA3 -> USART2 (调试串口)
- VBAT -> 3V电池(用于RTC)
编译和配置
- 使用STM32CubeMX生成基础工程
- 添加FreeRTOS和FATFS中间件
- 配置正确的时钟和引脚
- 将上述文件添加到工程中
- 配置FreeRTOS堆大小(至少30KB)
系统启动流程
- 系统初始化(时钟、GPIO、外设)
- 硬件初始化(CAN、网络、存储)
- 创建RTOS任务和资源
- 启动FreeRTOS调度器
- 各任务开始并行运行
任务功能说明
- CAN_Rx_Task:接收CAN总线数据,放入处理队列
- CAN_Tx_Task:发送CAN消息(心跳、命令等)
- Data_Process_Task:处理CAN数据,格式化打包
- Network_Task:管理网络连接,发送接收数据
- Storage_Task:管理SD卡存储,数据记录
- Watchdog_Task:监控系统健康,处理异常
- System_Monitor_Task:系统状态监控和日志
数据流
text
复制代码
CAN总线 → CAN接收任务 → 数据处理队列 → 数据处理任务
↓
网络发送队列 → 网络任务 → TCP服务器
↓
存储队列 → 存储任务 → SD卡文件系统
扩展功能建议
- 添加Modbus TCP支持:在W5500驱动中添加Modbus协议栈
- 实现数据加密:在数据处理中添加AES加密
- 添加Web配置界面:通过W5500实现HTTP服务器
- 实现OTA升级:通过网络进行固件更新
- 添加GPS模块:记录地理位置信息
- 实现数据压缩:在存储前压缩数据以节省空间