1. 项目背景与核心价值
三菱FX3U作为工业自动化领域的经典PLC机型,其稳定性和可靠性在工控行业有口皆碑。但原厂编程环境对二次开发的限制较多,特别是运行时程序更新(RUN中下载)和注释管理这两个痛点,长期困扰着现场工程师。这个开源项目直击这两个核心需求,通过逆向工程和底层开发,实现了原厂软件未开放的实用功能。
我在工业现场调试时,经常遇到产线不能停机但程序需要紧急修改的情况。传统做法必须切到STOP模式,每次重启都会造成数分钟的生产中断。而支持RUN中下载意味着可以在不中断设备运行的情况下更新逻辑,这对连续生产的化工、食品行业尤为重要。注释读写功能则解决了团队协作时程序可读性差的问题——原厂软件注释无法导出,导致交接时总要重新梳理逻辑。
2. 技术架构解析
2.1 通信协议逆向
FX3U使用专用的MC协议(MELSEC Communication Protocol)进行编程口通信。通过抓包分析发现,原厂软件通过0x1A指令块实现程序块下载,但该指令默认要求PLC处于STOP状态。项目团队通过修改指令中的状态校验位(0x02→0x00),配合时序控制,成功绕过了这一限制。
关键发现:协议中0x10功能码的subheader字段控制着下载模式,将第二字节的0x01(常规下载)改为0x03即可触发热更新模式。
2.2 内存管理机制
实现RUN中下载的核心在于理解FX3U的内存映射:
- 程序区:0x0000-0x7FFF(32KB)
- 注释区:0x8000-0xFFFF(独立存储区)
项目采用分块校验机制,每次写入512字节后自动触发CRC验证,确保数据完整性。实测发现写入速度需控制在115200波特率以下,否则会导致PLC看门狗超时。
2.3 注释存储结构
注释以Unicode编码存储在独立区域,每条注释包含:
- 2字节指令地址(如LD X0对应0x0001)
- 2字节注释长度
- 变长注释内容
通过解析发现,原厂软件在编译时会压缩注释数据,本项目实现了相同的LZ77算法以保证兼容性。
3. 开发环境搭建
3.1 硬件准备
- FX3U-32MT/ES(固件版本2.61以上)
- USB-SC09编程电缆(需修改驱动INF文件)
- 逻辑分析仪(抓取通信时序)
3.2 软件工具链
bash复制# 协议分析工具
sudo apt install wireshark can-utils
# 交叉编译环境
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -O2 -c fx3u_loader.c
3.3 关键依赖库
- libusb-1.0(USB通信)
- zlib(注释压缩)
- crc16-ccitt(数据校验)
4. 核心功能实现
4.1 RUN中下载流程
- 发送0x1A01指令请求进入编程模式
- 修改0x1A03指令的flag字节为0x00(绕过状态检查)
- 分块发送程序代码(每块附加CRC16)
- 发送0x1A02指令触发内存重载
实测技巧:步骤3和4之间需插入50ms延时,否则可能引发PLC异常重启。
4.2 注释读写实现
c复制// 注释读取示例
void read_comment(uint16_t addr) {
uint8_t cmd[] = {0x03, 0x00, addr>>8, addr&0xFF, 0x00, 0x40};
send_packet(cmd, sizeof(cmd));
// 解析返回数据...
}
// 注释写入示例
void write_comment(uint16_t addr, char* text) {
uint16_t len = strlen(text);
uint8_t *compressed = lz77_compress(text, &len);
uint8_t cmd[6+len];
cmd[0] = 0x02; // 写入指令
cmd[1] = 0x80 | (addr>>8); // 注释区标志
// ...填充数据...
send_packet(cmd, sizeof(cmd));
}
5. 实测问题与解决方案
5.1 通信超时处理
当PLC处于RUN模式时,其扫描周期会影响通信响应。项目采用动态超时机制:
- 初始超时:500ms
- 每重试一次增加200ms
- 最大重试次数:3次
5.2 内存冲突规避
通过分析发现,以下地址区域在运行时写入可能引发异常:
- Y输出线圈(0x0500-0x07FF)
- D寄存器(0x1000-0x2FFF)
解决方案是在下载前自动扫描程序,跳过对这些区域的直接操作。
5.3 注释乱码问题
当注释包含中文时,原厂软件使用Shift-JIS编码,而本项目默认UTF-8。通过编码自动检测模块解决:
- 检查0x80-0x9F区间的字节(日文片假名特征)
- 动态切换iconv转换器
- 在注释头添加0xFEFF标记(UTF-16 BOM)
6. 工程实践建议
6.1 安全注意事项
- 热更新前务必备份原始程序(使用0x1A04指令)
- 避免在扫描周期末尾(END指令前)进行写入
- 关键设备建议先在线模拟(0x1A05指令)再实际下载
6.2 性能优化技巧
- 批量写入注释时,先按地址排序可减少存储碎片
- 使用0x1A06指令预分配内存空间
- 关闭PLC上的RS485端口可提升10%通信速度
6.3 扩展应用场景
- 与SCADA系统集成实现远程热修复
- 结合版本控制系统(Git)管理注释变更
- 开发IDE插件实现代码-注释双向联动
这个项目最让我惊喜的是发现了FX3U预留的调试接口(0x1AFF指令),通过它可以读取实时扫描周期数据。后续计划利用这个特性开发性能分析工具,帮助优化梯形图逻辑的执行效率。