STM32 平台 TRDP 轨道交通实时以太网络(C语言)
一、系统架构设计
1.1 硬件平台配置
主控芯片:STM32F407ZGT6(168MHz,1MB Flash,192KB RAM)
网络芯片:LAN8742A(RMII接口,10/100Mbps)
内存:外部SDRAM 8MB(用于协议栈缓存)
存储:SPI Flash 16MB(配置存储)
实时时钟:DS3231(I2C接口)
1.2 TRDP协议栈层次
应用层(列车控制逻辑)
↓
TRDP协议层(PD/MD处理)
↓
UDP/IP协议层
↓
以太网MAC层(STM32内置)
↓
PHY层(LAN8742A)
二、完整工程源码
2.1 TRDP协议栈核心头文件(trdp_types.h)
/**
* @file trdp_types.h
* @brief TRDP协议数据类型定义(基于IEC 61375-2-3)
*/
#ifndef __TRDP_TYPES_H
#define __TRDP_TYPES_H
#include <stdint.h>
#include <stdbool.h>
/* TRDP版本定义 */
#define TRDP_PROTOCOL_VERSION 0x0100 // 版本1.0
#define TRDP_DEFAULT_PORT 17224 // 默认UDP端口
#define TRDP_MAX_PD_DATA_SIZE 1436 // 最大PD数据长度
#define TRDP_MAX_MD_DATA_SIZE 65535 // 最大MD数据长度
#define TRDP_HEADER_SIZE 40 // PD头部大小
/* TRDP消息类型 */
typedef enum {
TRDP_MSG_PD = 0x5064, // 过程数据 (ASCII 'Pd')
TRDP_MSG_MD = 0x4D64, // 消息数据 (ASCII 'Md')
TRDP_MSG_REQ = 0x5271, // 请求消息 (ASCII 'Rq')
TRDP_MSG_REP = 0x5270 // 回复消息 (ASCII 'Rp')
} TRDP_MSG_TYPE;
/* TRDP通信模式 */
typedef enum {
TRDP_COMM_PD = 0, // 过程数据(周期性)
TRDP_COMM_MD = 1 // 消息数据(事件驱动)
} TRDP_COMM_MODE;
/* TRDP错误码 */
typedef enum {
TRDP_NO_ERROR = 0,
TRDP_ERR_INIT_FAILED = -1,
TRDP_ERR_SOCKET_FAILED = -2,
TRDP_ERR_TIMEOUT = -3,
TRDP_ERR_CRC = -4,
TRDP_ERR_INVALID_PARAM = -5,
TRDP_ERR_MEM_ALLOC = -6
} TRDP_ERR;
/* TRDP IP地址结构 */
typedef union {
uint8_t u8[4];
uint32_t u32;
} TRDP_IP_ADDR;
/* TRDP PD头部结构(40字节) */
typedef struct __attribute__((packed)) {
uint32_t sequence_counter; // 序列号
uint16_t protocol_version; // 协议版本
uint16_t msg_type; // 消息类型
uint32_t com_id; // 通信ID
uint32_t etb_topo_cnt; // ETB拓扑计数器
uint32_t op_trn_topo_cnt; // 操作列车拓扑计数器
uint32_t dataset_length; // 数据集长度
uint32_t reserved; // 保留字段
uint32_t reply_com_id; // 回复通信ID
uint32_t reply_ip_address; // 回复IP地址
uint32_t header_fcs; // 头部CRC32校验
} TRDP_PD_HEADER;
/* TRDP PD数据帧 */
typedef struct {
TRDP_PD_HEADER header;
uint8_t data[TRDP_MAX_PD_DATA_SIZE];
uint32_t fcs; // 数据CRC32校验
} TRDP_PD_FRAME;
/* TRDP会话句柄 */
typedef struct {
int socket_fd; // 套接字描述符
TRDP_IP_ADDR local_ip; // 本地IP
TRDP_IP_ADDR multicast_ip; // 组播IP
uint16_t port; // 端口号
bool is_initialized; // 初始化标志
uint32_t sequence_counter; // 序列号计数器
uint32_t last_send_time; // 上次发送时间
uint32_t last_recv_time; // 上次接收时间
void (*recv_callback)(uint32_t com_id, uint8_t* data, uint32_t len);
} TRDP_SESSION;
/* TRDP发布者配置 */
typedef struct {
uint32_t com_id; // 通信ID
TRDP_IP_ADDR dest_ip; // 目标IP
uint32_t cycle_time_us; // 发送周期(微秒)
uint32_t dataset_length; // 数据集长度
uint8_t* dataset; // 数据集指针
bool is_active; // 激活标志
} TRDP_PUBLISHER;
/* TRDP订阅者配置 */
typedef struct {
uint32_t com_id; // 通信ID
TRDP_IP_ADDR src_ip; // 源IP过滤
uint32_t timeout_us; // 超时时间(微秒)
uint32_t dataset_length; // 期望数据集长度
bool is_active; // 激活标志
uint32_t last_seq; // 上次序列号
uint32_t error_count; // 错误计数
} TRDP_SUBSCRIBER;
#endif /* __TRDP_TYPES_H */
2.2 TRDP协议栈实现(trdp_stack.c)
/**
* @file trdp_stack.c
* @brief TRDP协议栈核心实现(STM32平台)
*/
#include "trdp_stack.h"
#include "lwip/udp.h"
#include "lwip/netif.h"
#include "crc.h"
#include "stm32f4xx_hal.h"
/* 全局会话 */
static TRDP_SESSION g_session;
static TRDP_PUBLISHER g_publishers[16];
static TRDP_SUBSCRIBER g_subscribers[16];
static uint8_t g_pub_count = 0;
static uint8_t g_sub_count = 0;
/* CRC32计算表 */
static const uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
// ... 省略中间值,实际使用完整CRC32表
};
/* 初始化TRDP会话 */
TRDP_ERR trdp_init(TRDP_IP_ADDR local_ip, uint16_t port)
{
struct udp_pcb *pcb;
err_t err;
/* 1. 创建UDP控制块 */
pcb = udp_new();
if (pcb == NULL) {
return TRDP_ERR_SOCKET_FAILED;
}
/* 2. 绑定本地端口 */
err = udp_bind(pcb, IP_ADDR_ANY, port);
if (err != ERR_OK) {
udp_remove(pcb);
return TRDP_ERR_SOCKET_FAILED;
}
/* 3. 设置接收回调 */
udp_recv(pcb, trdp_recv_callback, NULL);
/* 4. 初始化会话结构 */
memset(&g_session, 0, sizeof(TRDP_SESSION));
g_session.socket_fd = (int)pcb;
g_session.local_ip = local_ip;
g_session.port = port;
g_session.is_initialized = true;
g_session.sequence_counter = 0;
g_session.last_send_time = HAL_GetTick();
g_session.last_recv_time = HAL_GetTick();
/* 5. 初始化发布者和订阅者列表 */
memset(g_publishers, 0, sizeof(g_publishers));
memset(g_subscribers, 0, sizeof(g_subscribers));
g_pub_count = 0;
g_sub_count = 0;
return TRDP_NO_ERROR;
}
/* 创建发布者 */
TRDP_ERR trdp_create_publisher(TRDP_PUBLISHER* pub)
{
if (g_pub_count >= 16) {
return TRDP_ERR_INVALID_PARAM;
}
/* 验证参数 */
if (pub->com_id == 0 || pub->dataset == NULL || pub->dataset_length == 0) {
return TRDP_ERR_INVALID_PARAM;
}
/* 添加到发布者列表 */
memcpy(&g_publishers[g_pub_count], pub, sizeof(TRDP_PUBLISHER));
g_publishers[g_pub_count].is_active = true;
g_pub_count++;
return TRDP_NO_ERROR;
}
/* 创建订阅者 */
TRDP_ERR trdp_create_subscriber(TRDP_SUBSCRIBER* sub)
{
if (g_sub_count >= 16) {
return TRDP_ERR_INVALID_PARAM;
}
/* 验证参数 */
if (sub->com_id == 0 || sub->dataset_length == 0) {
return TRDP_ERR_INVALID_PARAM;
}
/* 添加到订阅者列表 */
memcpy(&g_subscribers[g_sub_count], sub, sizeof(TRDP_SUBSCRIBER));
g_subscribers[g_sub_count].is_active = true;
g_subscribers[g_sub_count].last_seq = 0xFFFFFFFF;
g_sub_count++;
return TRDP_NO_ERROR;
}
/* 发送PD数据 */
TRDP_ERR trdp_send_pd(uint32_t com_id, uint8_t* data, uint32_t len)
{
TRDP_PD_FRAME frame;
struct udp_pcb *pcb = (struct udp_pcb *)g_session.socket_fd;
ip_addr_t dest_ip;
err_t err;
if (!g_session.is_initialized) {
return TRDP_ERR_INIT_FAILED;
}
/* 1. 查找对应的发布者 */
TRDP_PUBLISHER* pub = NULL;
for (int i = 0; i < g_pub_count; i++) {
if (g_publishers[i].com_id == com_id && g_publishers[i].is_active) {
pub = &g_publishers[i];
break;
}
}
if (pub == NULL) {
return TRDP_ERR_INVALID_PARAM;
}
/* 2. 构建PD头部 */
frame.header.sequence_counter = g_session.sequence_counter++;
frame.header.protocol_version = TRDP_PROTOCOL_VERSION;
frame.header.msg_type = TRDP_MSG_PD;
frame.header.com_id = com_id;
frame.header.etb_topo_cnt = 0; // 实际应用中从网络配置获取
frame.header.op_trn_topo_cnt = 0; // 实际应用中从网络配置获取
frame.header.dataset_length = len;
frame.header.reserved = 0;
frame.header.reply_com_id = 0;
frame.header.reply_ip_address = 0;
/* 3. 计算头部CRC32 */
frame.header.header_fcs = crc32_calc((uint8_t*)&frame.header,
TRDP_HEADER_SIZE - 4);
/* 4. 复制数据 */
if (len > TRDP_MAX_PD_DATA_SIZE) {
return TRDP_ERR_INVALID_PARAM;
}
memcpy(frame.data, data, len);
/* 5. 计算数据CRC32 */
frame.fcs = crc32_calc(frame.data, len);
/* 6. 发送UDP数据包 */
dest_ip.addr = pub->dest_ip.u32;
err = udp_sendto(pcb,
pbuf_alloc(PBUF_TRANSPORT,
TRDP_HEADER_SIZE + len + 4,
PBUF_RAM),
&dest_ip,
TRDP_DEFAULT_PORT);
if (err != ERR_OK) {
return TRDP_ERR_SOCKET_FAILED;
}
g_session.last_send_time = HAL_GetTick();
return TRDP_NO_ERROR;
}
/* UDP接收回调函数 */
void trdp_recv_callback(void *arg, struct udp_pcb *pcb,
struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
TRDP_PD_HEADER* header;
uint8_t* data;
uint32_t calc_crc;
uint32_t recv_crc;
if (p->tot_len < TRDP_HEADER_SIZE + 4) {
pbuf_free(p);
return;
}
/* 1. 解析头部 */
header = (TRDP_PD_HEADER*)p->payload;
/* 2. 验证协议版本 */
if (header->protocol_version != TRDP_PROTOCOL_VERSION) {
pbuf_free(p);
return;
}
/* 3. 验证消息类型 */
if (header->msg_type != TRDP_MSG_PD) {
pbuf_free(p);
return;
}
/* 4. 验证头部CRC */
calc_crc = crc32_calc((uint8_t*)header, TRDP_HEADER_SIZE - 4);
if (calc_crc != header->header_fcs) {
pbuf_free(p);
return;
}
/* 5. 获取数据指针 */
data = (uint8_t*)p->payload + TRDP_HEADER_SIZE;
/* 6. 验证数据CRC */
recv_crc = *((uint32_t*)(data + header->dataset_length));
calc_crc = crc32_calc(data, header->dataset_length);
if (calc_crc != recv_crc) {
pbuf_free(p);
return;
}
/* 7. 查找对应的订阅者 */
for (int i = 0; i < g_sub_count; i++) {
if (g_subscribers[i].com_id == header->com_id &&
g_subscribers[i].is_active) {
/* 检查序列号连续性 */
if (g_subscribers[i].last_seq != 0xFFFFFFFF) {
if (header->sequence_counter != g_subscribers[i].last_seq + 1) {
g_subscribers[i].error_count++;
}
}
g_subscribers[i].last_seq = header->sequence_counter;
/* 调用应用层回调 */
if (g_session.recv_callback) {
g_session.recv_callback(header->com_id, data,
header->dataset_length);
}
break;
}
}
g_session.last_recv_time = HAL_GetTick();
pbuf_free(p);
}
/* 设置接收回调函数 */
void trdp_set_recv_callback(void (*callback)(uint32_t com_id,
uint8_t* data,
uint32_t len))
{
g_session.recv_callback = callback;
}
/* 周期性处理任务(需在1ms任务中调用) */
void trdp_periodic_task(void)
{
uint32_t current_time = HAL_GetTick();
/* 检查订阅者超时 */
for (int i = 0; i < g_sub_count; i++) {
if (g_subscribers[i].is_active) {
if (current_time - g_session.last_recv_time >
g_subscribers[i].timeout_us / 1000) {
/* 超时处理 */
g_subscribers[i].error_count++;
}
}
}
/* 检查发布者周期发送 */
for (int i = 0; i < g_pub_count; i++) {
if (g_publishers[i].is_active) {
if (current_time - g_session.last_send_time >=
g_publishers[i].cycle_time_us / 1000) {
/* 发送周期性数据 */
trdp_send_pd(g_publishers[i].com_id,
g_publishers[i].dataset,
g_publishers[i].dataset_length);
}
}
}
}
/* 加入组播组 */
TRDP_ERR trdp_join_multicast(TRDP_IP_ADDR multicast_ip)
{
ip_addr_t group_ip;
struct netif *netif = netif_default;
if (!g_session.is_initialized) {
return TRDP_ERR_INIT_FAILED;
}
group_ip.addr = multicast_ip.u32;
/* 添加网络接口到组播组 */
if (netif != NULL) {
igmp_joingroup(netif, &group_ip);
g_session.multicast_ip = multicast_ip;
return TRDP_NO_ERROR;
}
return TRDP_ERR_SOCKET_FAILED;
}
2.3 CRC32校验实现(crc.c)
/**
* @file crc.c
* @brief CRC32校验算法(IEEE 802.3标准)
*/
#include "crc.h"
/* CRC32多项式:0x04C11DB7(反转后为0xEDB88320) */
#define CRC32_POLYNOMIAL 0xEDB88320
/* 计算CRC32 */
uint32_t crc32_calc(uint8_t* data, uint32_t len)
{
uint32_t crc = 0xFFFFFFFF;
uint32_t i, j;
for (i = 0; i < len; i++) {
crc ^= data[i];
for (j = 0; j < 8; j++) {
if (crc & 0x00000001) {
crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
} else {
crc >>= 1;
}
}
}
return ~crc;
}
/* 快速CRC32计算(使用查表法) */
uint32_t crc32_fast(uint8_t* data, uint32_t len)
{
uint32_t crc = 0xFFFFFFFF;
static const uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
// ... 完整256项表
};
for (uint32_t i = 0; i < len; i++) {
crc = (crc >> 8) ^ crc32_table[(crc ^ data[i]) & 0xFF];
}
return ~crc;
}
2.4 列车控制应用示例(train_control.c)
/**
* @file train_control.c
* @brief 列车控制应用层示例
*/
#include "train_control.h"
#include "trdp_stack.h"
/* 列车状态数据结构 */
typedef struct {
uint32_t vehicle_id; // 车辆ID
uint8_t door_status[8]; // 车门状态(每车8门)
uint8_t brake_status; // 制动状态
uint8_t traction_status; // 牵引状态
uint16_t speed; // 速度(0.1 km/h)
uint16_t line_voltage; // 网压(0.1 V)
uint16_t battery_voltage; // 蓄电池电压(0.1 V)
uint32_t mileage; // 里程(m)
uint8_t fault_codes[16]; // 故障代码
} TRAIN_STATUS;
/* 列车控制命令 */
typedef struct {
uint8_t door_control; // 车门控制
uint8_t brake_control; // 制动控制
uint8_t traction_control; // 牵引控制
uint16_t speed_limit; // 限速值
uint8_t emergency_brake; // 紧急制动
} TRAIN_COMMAND;
/* 全局列车状态 */
static TRAIN_STATUS g_train_status;
static TRAIN_COMMAND g_train_command;
/* TRDP通信ID定义(根据列车网络配置) */
#define COM_ID_TRAIN_STATUS 0x1001 // 列车状态发布
#define COM_ID_TRAIN_COMMAND 0x1002 // 列车命令接收
#define COM_ID_DOOR_STATUS 0x2001 // 车门状态发布
#define COM_ID_BRAKE_STATUS 0x2002 // 制动状态发布
/* 初始化列车网络 */
TRDP_ERR train_network_init(void)
{
TRDP_IP_ADDR local_ip = {.u8 = {192, 168, 10, 100}};
TRDP_IP_ADDR multicast_ip = {.u8 = {239, 192, 10, 1}};
TRDP_ERR err;
/* 1. 初始化TRDP协议栈 */
err = trdp_init(local_ip, TRDP_DEFAULT_PORT);
if (err != TRDP_NO_ERROR) {
return err;
}
/* 2. 加入组播组 */
err = trdp_join_multicast(multicast_ip);
if (err != TRDP_NO_ERROR) {
return err;
}
/* 3. 创建列车状态发布者 */
TRDP_PUBLISHER status_pub = {
.com_id = COM_ID_TRAIN_STATUS,
.dest_ip = multicast_ip,
.cycle_time_us = 100000, // 100ms周期
.dataset_length = sizeof(TRAIN_STATUS),
.dataset = (uint8_t*)&g_train_status,
.is_active = true
};
trdp_create_publisher(&status_pub);
/* 4. 创建列车命令订阅者 */
TRDP_SUBSCRIBER cmd_sub = {
.com_id = COM_ID_TRAIN_COMMAND,
.src_ip = {.u32 = 0}, // 接收所有源
.timeout_us = 500000, // 500ms超时
.dataset_length = sizeof(TRAIN_COMMAND),
.is_active = true
};
trdp_create_subscriber(&cmd_sub);
/* 5. 设置接收回调 */
trdp_set_recv_callback(train_data_received);
return TRDP_NO_ERROR;
}
/* 数据接收回调函数 */
void train_data_received(uint32_t com_id, uint8_t* data, uint32_t len)
{
switch (com_id) {
case COM_ID_TRAIN_COMMAND:
if (len == sizeof(TRAIN_COMMAND)) {
memcpy(&g_train_command, data, len);
process_train_command(&g_train_command);
}
break;
case COM_ID_DOOR_STATUS:
// 处理车门状态
break;
case COM_ID_BRAKE_STATUS:
// 处理制动状态
break;
default:
break;
}
}
/* 处理列车控制命令 */
void process_train_command(TRAIN_COMMAND* cmd)
{
/* 紧急制动处理 */
if (cmd->emergency_brake) {
emergency_brake_apply();
return;
}
/* 车门控制 */
if (cmd->door_control != 0) {
door_control(cmd->door_control);
}
/* 制动控制 */
if (cmd->brake_control != 0) {
brake_control(cmd->brake_control);
}
/* 牵引控制 */
if (cmd->traction_control != 0) {
traction_control(cmd->traction_control);
}
/* 限速设置 */
if (cmd->speed_limit != 0) {
set_speed_limit(cmd->speed_limit);
}
}
/* 更新列车状态 */
void update_train_status(void)
{
/* 读取传感器数据 */
g_train_status.speed = read_speed_sensor();
g_train_status.line_voltage = read_line_voltage();
g_train_status.battery_voltage = read_battery_voltage();
/* 读取车门状态 */
for (int i = 0; i < 8; i++) {
g_train_status.door_status[i] = read_door_status(i);
}
/* 读取制动系统状态 */
g_train_status.brake_status = read_brake_status();
g_train_status.traction_status = read_traction_status();
/* 更新里程 */
g_train_status.mileage += calculate_mileage_increment();
/* 检查故障 */
check_fault_conditions(&g_train_status);
}
/* 主任务循环 */
void train_main_task(void)
{
static uint32_t last_status_update = 0;
uint32_t current_time = HAL_GetTick();
/* 每100ms更新一次状态 */
if (current_time - last_status_update >= 100) {
update_train_status();
last_status_update = current_time;
}
/* 处理TRDP协议栈 */
trdp_periodic_task();
}
2.5 LWIP网络配置(lwipopts.h)
/**
* @file lwipopts.h
* @brief LWIP协议栈配置(针对TRDP优化)
*/
#ifndef __LWIPOPTS_H
#define __LWIPOPTS_H
/* 内存配置 */
#define MEM_ALIGNMENT 4
#define MEM_SIZE (16 * 1024) // 16KB内存池
/* 堆内存配置 */
#define LWIP_RAM_HEAP_POINTER ((uint8_t*)0xD0000000) // 外部SDRAM地址
#define LWIP_HEAP_SIZE (8 * 1024) // 8KB堆内存
/* UDP配置 */
#define LWIP_UDP 1
#define UDP_TTL 64
#define UDP_SEND_BUFSIZE 2048
#define UDP_RECV_BUFSIZE 2048
/* 组播配置 */
#define LWIP_IGMP 1 // 启用IGMP组播
#define LWIP_MULTICAST_TX_OPTIONS 1
/* 网络接口配置 */
#define NETIF_MAX_HWADDR_LEN 6
#define ETHARP_SUPPORT_VLAN 0
#define ETH_PAD_SIZE 0
/* 超时配置 */
#define TCP_MSL 60000 // 最大段生存期
#define TCP_FIN_WAIT_TIMEOUT 20000 // FIN_WAIT超时
/* 调试配置 */
#define LWIP_DEBUG 0
#define UDP_DEBUG LWIP_DBG_OFF
#endif /* __LWIPOPTS_H */
2.6 主程序(main.c)
/**
* @file main.c
* @brief STM32 TRDP主程序
*/
#include "stm32f4xx_hal.h"
#include "lwip/init.h"
#include "netif/ethernet.h"
#include "ethernetif.h"
#include "trdp_stack.h"
#include "train_control.h"
/* 全局变量 */
ETH_HandleTypeDef heth;
struct netif g_netif;
/* 系统时钟配置 */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/* 配置HSE振荡器 */
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 = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* 配置系统时钟 */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
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;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
/* 以太网初始化 */
void ethernet_init(void)
{
ip_addr_t ipaddr, netmask, gw;
/* 设置网络参数 */
IP4_ADDR(&ipaddr, 192, 168, 10, 100);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 192, 168, 10, 1);
/* 添加网络接口 */
netif_add(&g_netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);
netif_set_default(&g_netif);
netif_set_up(&g_netif);
}
/* 主函数 */
int main(void)
{
/* 1. 系统初始化 */
HAL_Init();
SystemClock_Config();
/* 2. 初始化外设 */
MX_GPIO_Init();
MX_ETH_Init();
MX_USART_Init();
/* 3. 初始化LWIP协议栈 */
lwip_init();
/* 4. 初始化以太网 */
ethernet_init();
/* 5. 初始化TRDP列车网络 */
if (train_network_init() != TRDP_NO_ERROR) {
Error_Handler();
}
/* 6. 初始化列车控制 */
train_control_init();
printf("TRDP Train Network Initialized Successfully!\r\n");
/* 7. 主循环 */
while (1) {
/* 处理以太网数据包 */
ethernetif_input(&g_netif);
/* 处理列车控制任务 */
train_main_task();
/* 系统监控 */
system_monitor();
/* 延时 */
HAL_Delay(1);
}
}
/* 系统监控 */
void system_monitor(void)
{
static uint32_t last_monitor_time = 0;
uint32_t current_time = HAL_GetTick();
if (current_time - last_monitor_time >= 1000) {
/* 打印运行状态 */
printf("System Running: Mem=%d, TRDP Rx=%lu, Tx=%lu\r\n",
lwip_get_free_heap(),
g_session.last_recv_time,
g_session.last_send_time);
last_monitor_time = current_time;
}
}
三、Keil工程配置
3.1 工程设置
Target:
- Device: STM32F407ZGT6
- Clock: 8MHz HSE → 168MHz PLL
- RAM: 192KB
- Flash: 1MB
C/C++:
- Define: USE_STDPERIPH_DRIVER, STM32F407xx
- Include Paths:
.\
..\Libraries\CMSIS\Include
..\Libraries\STM32F4xx_StdPeriph_Driver\inc
..\Libraries\lwip-1.4.1\src\include
..\User
..\User\trdp
Linker:
- IROM1: 0x08000000, 0x100000 (1MB Flash)
- IRAM1: 0x20000000, 0x30000 (192KB RAM)
3.2 内存分配文件(scatter file)
LR_IROM1 0x08000000 0x00100000 { ; load region size_region
ER_IROM1 0x08000000 0x00100000 { ; exec region size_region
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00030000 { ; RW data 192KB
.ANY (+RW +ZI)
}
RW_SDRAM 0xD0000000 0x00800000 { ; External SDRAM 8MB
.ANY (lwip_ram)
}
}
参考代码 TRDP用于轨道交通实时以太网络源代码 www.youwenfan.com/contentcnu/56391.html
四、测试与验证
4.1 测试工具
- Wireshark:抓包分析TRDP协议
- TRDP Spy:专用TRDP分析工具
- 列车网络仿真器:模拟列车控制指令
4.2 测试用例
/* 测试用例1:基本通信测试 */
void test_trdp_basic(void)
{
uint8_t test_data[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
/* 发送测试数据 */
TRDP_ERR err = trdp_send_pd(0x9999, test_data, 8);
if (err == TRDP_NO_ERROR) {
printf("Test data sent successfully!\r\n");
}
}
/* 测试用例2:列车状态发布测试 */
void test_train_status_publish(void)
{
TRAIN_STATUS status;
status.vehicle_id = 0x12345678;
status.speed = 600; // 60.0 km/h
status.line_voltage = 2500; // 250.0 V
status.battery_voltage = 1100; // 110.0 V
/* 发布列车状态 */
trdp_send_pd(COM_ID_TRAIN_STATUS, (uint8_t*)&status, sizeof(status));
}
4.3 预期输出
TRDP Train Network Initialized Successfully!
System Running: Mem=8192, TRDP Rx=1000, Tx=1000
Received TRDP Data: ComID=0x1002, Length=8
Processing Train Command: Emergency Brake=0, Speed Limit=80
五、安全与可靠性设计
5.1 安全机制
- 数据完整性:CRC32校验
- 序列号检查:防止数据丢失
- 超时检测:监控通信链路
- 冗余通信:双网冗余
5.2 故障处理
/* 通信故障处理 */
void trdp_fault_handler(void)
{
/* 1. 记录故障日志 */
log_fault("TRDP Communication Lost!");
/* 2. 切换到安全状态 */
enter_safe_state();
/* 3. 尝试重新初始化 */
if (trdp_init(g_session.local_ip, g_session.port) != TRDP_NO_ERROR) {
/* 硬件复位 */
NVIC_SystemReset();
}
}
浙公网安备 33010602011771号