Modbus RTU:动态配置


在树中插入 Modbus COM 端口设备时,只能对参数进行静态分配。

如果分配必须是动态的,那么完整的处理必须在 IEC 代码中实现

请注意,I/O 管理器不会同步动态配置中的不同进程。

这可能会导致变量的更新行为与静态配置不同,尤其是在从多个任务访问时。

  • 创建标准项目并选择 CODESYS Control Win V3作为设备。
  • 通过网络扫描连接目标系统。

图1

  • 打开库管理器并添加 Network库。 IoDrvModbus SysCom SysTypes2 Interfaces

图2

  • 修改 PLC_PRG 如下:

声明

VAR
    xComPortOpen         : BOOL;
    xComPortError        : BOOL;
    rtsResult            : RTS_IEC_RESULT;
    stComPortSettings    : SysCom.ComSettings;
    hComPort             : RTS_IEC_HANDLE;

    awReadBuffer         : ARRAY[0..31] OF WORD;        //note: adjsut to your requirements, max. is 128 Modbus Registers
    awWriteBuffer        : ARRAY[0..31] OF WORD;

    xExec                : BOOL;
    fbModbusRequest      : IoDrvModbus.ModbusRequest2;
    eComError            : IoDrvModbus.MB_ErrorCodes;
END_VAR

实现

IF(NOT xComPortOpen AND NOT xComPortError) THEN
    stComPortSettings.sPort := 3;
    stComPortSettings.byStopBits := 1;
    stComPortSettings.byParity := 0;            //EVEN:=2, ODD:=1 or NONE:=0*
    stComPortSettings.ulBaudRate := 19200;    //1200, 2400, 4800, ..., 115000 bps
    stComPortSettings.ulTimeout := 0;
    stComPortSettings.ulBufferSize := 256;    //Equals max size of Modbus packet

    hComPort := SysCom.SysComOpen2( pSettings := ADR(stComPortSettings), pSettingsEx := 0, pResult := ADR(rtsResult));

    xComPortError := (hComPort = RTS_INVALID_HANDLE OR rtsResult <> 0);
    xComPortOpen := NOT xComPortError;
END_IF

IF(xComPortOpen) THEN
    //apply new command
    fbModbusRequest.modbusCommand.uiFunctionCode := 23;        //Reda/Write Multiple Register
    fbModbusRequest.modbusCommand.uiReadOffset := 0;
    fbModbusRequest.modbusCommand.uiReadLen := 2;
    fbModbusRequest.modbusCommand.uiWriteOffset := 0;
    fbModbusRequest.modbusCommand.uiWriteLen := 2;

    fbModbusRequest.pRecvData := ADR(awReadBuffer);
    fbModbusRequest.pSendData := ADR(awWriteBuffer);   

    fbModbusRequest.tResponseTimeout := T#500MS;

    //note: if different tasks access the IO-Buffers then use some intermediate buffers
    //      that are thread safe (use e.g mutex or semaphore) before calling the FB
    fbModbusRequest(
        hComPort := hComPort,
        xExecute := xExec,
        usiSlaveAddr := 2,
        byModbusError => eComError);

    IF(fbModbusRequest.xDone) THEN
        //here you get valid data
        IF(awWriteBuffer[0] = awReadBuffer[0]) THEN
            ;
        END_IF
    ELSIF(fbModbusRequest.xError) THEN
        IF(eComError = MB_ErrorCodes.RESPONSE_TIMEOUT) THEN        //no cable plugged, wrong Com-Port settings ?
            ;
        END_IF
    END_IF
END_IF

  • 启动项目并测试功能。