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, &ethernetif_init, &ethernet_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 测试工具

  1. Wireshark:抓包分析TRDP协议
  2. TRDP Spy:专用TRDP分析工具
  3. 列车网络仿真器:模拟列车控制指令

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 安全机制

  1. 数据完整性:CRC32校验
  2. 序列号检查:防止数据丢失
  3. 超时检测:监控通信链路
  4. 冗余通信:双网冗余

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();
    }
}
posted @ 2026-05-18 15:48  yijg9998  阅读(117)  评论(0)    收藏  举报