凌霸天
级别: 探索解密
精华主题: 0
发帖数量: 25 个
工控威望: 191 点
下载积分: 215 分
在线时间: 18(小时)
注册时间: 2024-12-16
最后登录: 2025-07-07
查看凌霸天的 主题 / 回贴
楼主  发表于: 4天前
现有一台1200PLC,20台200smart,1200作为主站,200smart作为从站,1200通过modbus rtu协议对20台从站轮询读写,正常情况只需要读轮询,但是只要有写的情况,需要优先去写操作,有没有前辈做过类似的实验或者实操的,分享一下经验
凌霸天
级别: 探索解密
精华主题: 0
发帖数量: 25 个
工控威望: 191 点
下载积分: 215 分
在线时间: 18(小时)
注册时间: 2024-12-16
最后登录: 2025-07-07
查看凌霸天的 主题 / 回贴
1楼  发表于: 4天前
// 主程序
IF #firstScan THEN
    // 初始化Modbus通信端口 (PORT=0, 波特率9600, 8N1)
    #commLoad(
              REQ := TRUE,
              "PORT" := 0,
              BAUD := 9600,
              PARITY := 2,    // 0=None, 1=Odd, 2=Even
              MB_DB := #mbMaster);
    #firstScan := FALSE;
    
    // 初始化错误状态
    FOR #i := 1 TO 20 DO
        #errorStatus[#i] := FALSE;
        #errorCount[#i] := 0;
    END_FOR;
END_IF;

// 处理写请求 (高优先级)
IF #writeRequest THEN
    #mode := 1; // 进入写模式
    #currentSlave := #writeSlaveID;
    
    // 执行写操作 (功能码6 - 写单个寄存器)
    #mbMaster(
              REQ := TRUE,
              MB_ADDR := #writeSlaveID,
              MODE := 1,       // 写模式
              DATA_ADDR := #writeAddress,
              DATA_LEN := 1,    // 写入1个寄存器
              DATA_PTR := (#writeValue),
              DONE => #tempDone,
              ERROR => #tempError);
    // 处理写结果
    IF #tempDone OR #tempError THEN
        #writeRequest := FALSE;
        IF #tempError THEN
            // 记录错误
            #errorStatus[#writeSlaveID] := TRUE;
            #errorCount[#writeSlaveID] := #errorCount[#writeSlaveID] + 1;
        ELSE
            // 清除错误状态(可选)
            #errorStatus[#writeSlaveID] := FALSE;
        END_IF;
        #mode := 0; // 返回读模式
    END_IF;
    
    // 正常轮询模式
ELSE
    // 检查从站错误状态
    IF #errorStatus[#currentSlave] THEN
        // 跳过错误从站,直接递增计数器
        #currentSlave := #currentSlave MOD 20 + 1;
        #pollCounter := #pollCounter + 1;
        RETURN;
    END_IF;
    
    // 执行读操作 (功能码3 - 读保持寄存器)
     #mbMaster(
    REQ := TRUE,
    MB_ADDR := #currentSlave,
    MODE := 0,       // 读模式
    DATA_ADDR := 40001, // 示例起始地址
    DATA_LEN := 10,   // 读取10个寄存器
    DATA_PTR := #datebuffer, // 指向数据缓冲区
    DONE => #tempDone,
    ERROR => #tempError);
    
    // 处理读结果
    IF #tempDone OR #tempError THEN
        IF #tempError THEN
            // 记录错误
            #errorStatus[#currentSlave] := TRUE;
            #errorCount[#currentSlave] := #errorCount[#currentSlave] + 1;
        END_IF;
        
        // 移动到下一个从站
        #currentSlave := #currentSlave MOD 20 + 1;
        #pollCounter := #pollCounter + 1;
    END_IF;
END_IF;