基于uIP协议栈移植FreeModbus TCP的方案

一、系统架构设计

1. 硬件配置方案

模块 推荐参数 功能说明
主控芯片 STM32F407ZG (ARM Cortex-M4) 支持以太网MAC+PHY
网络接口 ENC28J60 (SPI接口) 10/100Mbps以太网控制器
存储 1MB Flash + 192KB RAM 协议栈及数据存储
电源管理 3.3V LDO稳压 低功耗设计

2. 协议栈架构

graph TD A[应用层] -->|Modbus TCP请求| B(Modbus协议栈) B -->|封装TCP数据| C(uIP协议栈) C -->|处理TCP连接| D[网络接口层] D -->|物理层传输| E[以太网控制器]

二、关键移植步骤

1. uIP协议栈初始化

// 初始化以太网MAC和PHY
void eth_init() {
    enc28j60_init(mymac);        // 初始化SPI接口
    enc28j60_phy_write(PHLCON, 0x476); // 配置PHY寄存器
    init_ip_arp_udp_tcp(mymac, myip, 80); // 初始化IP层
}

// 启动uIP协议栈
void uip_start() {
    uip_listen(HTONS(502));      // 监听Modbus TCP默认端口
    uip_set_appcall(uip_modbus_appcall); // 设置应用层回调
}

2. FreeModbus TCP适配

// 修改FreeModbus端口接口
BOOL xMBTCPPortInit(USHORT usTCPPort) {
    if(usTCPPort == 0) usTCPPort = 502; // 使用标准端口
    return TRUE;
}

// 数据接收处理
BOOL xMBTCPPortGetRequest(UCHAR **ppucMBTCPFrame, USHORT *usTCPLength) {
    *ppucMBTCPFrame = ucTCPRequestFrame;
    *usTCPLength = uip_len;
    return TRUE;
}

// 数据发送处理
BOOL xMBTCPPortSendResponse(const UCHAR *pucMBTCPFrame, USHORT usTCPLength) {
    memcpy(ucTCPResponseFrame, pucMBTCPFrame, usTCPLength);
    uip_send(ucTCPResponseFrame, usTCPLength);
    return TRUE;
}

3. Modbus TCP数据处理

// Modbus TCP事件处理
void uip_modbus_appcall() {
    if(uip_connected()) {
        mb_tcp_state = MB_TCP_CONNECTED;
    }
    
    if(uip_newdata()) {
        // 处理Modbus请求
        mb_tcp_request_len = uip_len;
        memcpy(mb_tcp_request_buf, uip_appdata, uip_len);
        xMBPortEventPost(EV_FRAME_RECEIVED); // 触发FreeModbus事件
    }
    
    if(uip_poll()) {
        if(mb_tcp_state == MB_TCP_READY) {
            uip_send(mb_tcp_response_buf, mb_tcp_response_len);
        }
    }
}

三、核心代码

1. MBAP头处理

// 构建MBAP头
void build_mbap_header(uint8_t *buffer, uint16_t trans_id, 
                      uint16_t protocol_id, uint16_t length, 
                      uint8_t unit_id) {
    buffer[0] = (trans_id >> 8) & 0xFF;
    buffer[1] = trans_id & 0xFF;
    buffer[2] = (protocol_id >> 8) & 0xFF;
    buffer[3] = protocol_id & 0xFF;
    buffer[4] = (length >> 8) & 0xFF;
    buffer[5] = length & 0xFF;
    buffer[6] = unit_id;
}

// 解析MBAP头
void parse_mbap_header(uint8_t *buffer, uint16_t *trans_id,
                      uint16_t *protocol_id, uint16_t *length,
                      uint8_t *unit_id) {
    *trans_id = (buffer[0] << 8) | buffer[1];
    *protocol_id = (buffer[2] << 8) | buffer[3];
    *length = (buffer[4] << 8) | buffer[5];
    *unit_id = buffer[6];
}

2. 数据帧处理流程

void process_modbus_tcp() {
    static uint8_t frame_buffer[MB_TCP_BUF_SIZE];
    
    // 接收数据
    uint16_t recv_len = xMBTCPPortGetRequest(&frame_buffer, &current_length);
    
    if(recv_len > 0) {
        // 解析MBAP头
        parse_mbap_header(frame_buffer, &trans_id, &proto_id, &pdu_length, &unit_id);
        
        // 处理PDU数据
        mb_error = eMBTCPReceive(frame_buffer + 7, pdu_length);
        
        // 构建响应
        build_mbap_header(response_buffer, trans_id, proto_id, 
                         2 + pdu_length, unit_id);
        memcpy(response_buffer + 7, mb_tcp_response, pdu_length + 2);
        
        // 发送响应
        xMBTCPPortSendResponse(response_buffer, 7 + pdu_length + 2);
    }
}

四、调试与验证

1. 抓包分析示例

No.     Time           Source                Destination           Protocol Length Info
  1 0.000000000    192.168.1.100         192.168.1.15          TCP      74     54321→502 [SYN] 
  2 0.000123456    192.168.1.15          192.168.1.100         TCP      74     502→54321 [SYN, ACK]
  3 0.000234567    192.168.1.100         192.168.1.15          TCP      66     54321→502 [ACK]
  4 0.001000000    192.168.1.100         192.168.1.15          Modbus   132    Read Coils (03)
  5 0.001111111    192.168.1.15          192.168.1.100         Modbus   126    Read Coils Response

2. 常见问题解决

问题现象 解决方案
无法建立TCP连接 检查IP地址配置和防火墙设置
数据包丢失 调整uIP的TCP重传参数
响应延迟大 优化中断处理优先级,减少任务阻塞
CRC校验失败 验证网络层和协议层CRC实现一致性

五、扩展功能

1. 多从站支持

// 多从站地址映射表
typedef struct {
    uint8_t slave_addr;
    uint16_t holding_start;
    uint16_t holding_size;
} mb_slave_config;

mb_slave_config slaves[] = {
    {1, 0x0000, 100},
    {2, 0x0100, 50}
};

// 处理多从站请求
void handle_multi_slave() {
    for(int i=0; i<sizeof(slaves)/sizeof(slaves[0]); i++) {
        if(current_slave == slaves[i].slave_addr) {
            // 处理对应从站数据
            break;
        }
    }
}

2. 安全增强方案

// 添加TLS加密支持
void enable_tls() {
    #include "mbedtls/config.h"
    mbedtls_ssl_init(&ssl_ctx);
    mbedtls_ssl_config_init(&conf);
    
    mbedtls_ssl_config_defaults(&conf,
        MBEDTLS_SSL_IS_SERVER,
        MBEDTLS_SSL_TRANSPORT_STREAM,
        MBEDTLS_SSL_PRESET_DEFAULT);
    
    mbedtls_ssl_setup(&ssl_ctx, &conf);
}

// 在uIP发送前加密数据
void uip_send_encrypted(uint8_t *data, uint16_t len) {
    uint8_t encrypted[2048];
    mbedtls_ssl_write(&ssl_ctx, data, len, encrypted, sizeof(encrypted));
    uip_send(encrypted, len);
}

参考代码 uip协议,modbusTCP协议,移植freemodbus TCP www.youwenfan.com/contentcnj/70744.html

六、工程配置建议

  1. 编译器优化

    # IAR编译选项
    -Ohs        # 最高优化级别
    -DUSE_FREEMODBUS=1
    -DUIP_CONF_BUFFER_SIZE=1024
    
  2. 内存分配策略

    #define MEM_HEAP_SIZE 2048
    static uint8_t mem_heap[MEM_HEAP_SIZE];
    mem_init(mem_heap, MEM_HEAP_SIZE);
    
  3. 调试接口

    #define MODBUS_DEBUG 1
    #if MODBUS_DEBUG
    #define mb_printf(...) printf(__VA_ARGS__)
    #else
    #define mb_printf(...)
    #endif
    
posted @ 2025-10-20 09:33  yijg9998  阅读(35)  评论(0)    收藏  举报