基于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, ¤t_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
六、工程配置建议
-
编译器优化
# IAR编译选项 -Ohs # 最高优化级别 -DUSE_FREEMODBUS=1 -DUIP_CONF_BUFFER_SIZE=1024 -
内存分配策略
#define MEM_HEAP_SIZE 2048 static uint8_t mem_heap[MEM_HEAP_SIZE]; mem_init(mem_heap, MEM_HEAP_SIZE); -
调试接口
#define MODBUS_DEBUG 1 #if MODBUS_DEBUG #define mb_printf(...) printf(__VA_ARGS__) #else #define mb_printf(...) #endif
浙公网安备 33010602011771号