Modbus-RTU通讯轮询

已锁定

Hushuguo

  • 帖子

    385
  • 精华

    2
  • 被关注

    37

论坛等级:奇侠

注册时间:2004-04-17

普通 普通 如何晋级?

Modbus-RTU通讯轮询

7484

13

2019-01-28 08:54:09

最近论坛关于Modbus-RTU通讯轮询的讨论很火热,连版主都出来发程序,我也凑个热闹,发个Modbus-RTU通讯轮询的程序,此程序在S7-1200+CB1241上测试成功,和西门子G120、丹佛斯FC360、ABB ACS510上做过测试,理论上也可以用于S7-1500上,我后天也要回老家过年去了,大家娱乐一下,祝大家新年合家欢乐身体健康。



FUNCTION_BLOCK "Modbus通讯"

TITLE = Modbus-RTU通讯处理

{ S7_Optimized_Access := 'FALSE' }

AUTHOR : hushuguo

VERSION : 0.1

//用于西门子S7-1200/1500和Modbus-RTU从站通讯

//

   VAR_INPUT 

      PARITY { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt := 2;   // 奇偶校验 0无校验1奇校验2偶校验

      PORT { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : PORT;   // 通讯端口

      BAUD { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UDInt := 57600;   // 波特率

      OverTime { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt := 100;   // 从站等待超时

      Replace { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool := TRUE;   // 0:读错误保持接受数据不变;1:读错误则数据用零替代

   END_VAR


   VAR_OUTPUT 

      InitialError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // 初始化错误

      Error { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // 没有任务被选择

   END_VAR


   VAR_IN_OUT 

      Initial { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // 初始化

   END_VAR


   VAR 

      Task { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#MaxTask] of Struct   // 任务

         Enable { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // 启用该任务

         Error { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // 通讯错误

         Mode { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : USInt;   // 读写模式 0读取1写入

         Address { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt;   // 从站地址

         Registor { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UDInt;   // 从站寄存器地址

         Length { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt;   // 要通讯的数据长度

         Data { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1..#MaxLength] of Word;   // 数据区

      END_STRUCT;

      COMM_LOAD {InstructionName := 'Modbus_Comm_Load'; LibVersion := '3.1'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Modbus_Comm_Load;

      Master {InstructionName := 'Modbus_Master'; LibVersion := '3.2'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Modbus_Master;

      Index { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int := 1;   // 任务索引

      I { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;

      Req { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // 请求信号

      InitialDone { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // 初始化已完成

      P1 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;

      P2 { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;

   END_VAR


   VAR CONSTANT 

      MaxTask : Int := 8;   // 定义最大任务数量

      MaxLength : Int := 4;   // 定义最大数据长度

   END_VAR



BEGIN

(*

注意事项:

    1:通讯连接要正确

    2:奇偶校验、数据位、停止位、波特率等几个参数要保证在程序里、硬件组态、从站三处设置一致

    3:通讯端口填写通讯模块使用的端口,见硬件组态->属性->系统常数

    4:本程序里已强制为485通讯

    5:请认真看接口区里的个变量的注释

使用方法:

    首先将本程序导入项目并编译,由于块里使用了部分系统块,所以第一次编译会有错误,没关系,再编译一次就好,

    在程序里调用本块并生成背景数据块,然后修改背景数据块里的Task结构里的数据,本程序默认提供了8个任务,

    但需要使用者自己启用,并修改相关参数,具体见参数注释,任务数及数据长度不够请修改Constant里关于数量定义的变量

*)

IF NOT #InitialDone THEN

    #Initial := TRUE;

END_IF;

IF #Initial THEN //通讯模块初始化

    IF NOT #P1 THEN

        #Req := FALSE;

        #InitialDone := FALSE;

        #COMM_LOAD.MODE := 4;   //工作模式设为485通讯

    END_IF;

    IF #COMM_LOAD.DONE THEN

        #Initial := FALSE;

        #InitialDone := TRUE;

    END_IF;

ELSE

    IF #Master.ERROR AND #Task[#Index].Mode=0 AND #Replace THEN  //读错误则清掉之前接受的数据

        FOR #I := 1 TO #MaxLength DO

            #Task[#Index].Data[#I] := 0;

        END_FOR;

    END_IF;

    IF #Master.DONE OR #Master.ERROR THEN

        #Req := FALSE;

        #Task[#Index].Error := #Master.ERROR;

    ELSE

        #Req := TRUE;

    END_IF;

    IF (#Req AND NOT #P2) OR #Error THEN //开始通讯

        FOR #I := 1 TO #MaxTask DO

            #Index := #Index + 1;

            IF #Index > #MaxTask THEN

                #Index := #Index - #MaxTask;

            END_IF;

            IF #Task[#Index].Enable THEN

                EXIT;

            END_IF;

        END_FOR;

        #Error := #I > #MaxTask;

    END_IF;

END_IF;

#P1 := #Initial;

#P2 := #Req;

#COMM_LOAD(REQ := #Initial,

           "PORT" := #PORT,

           BAUD := #BAUD,

           PARITY := #PARITY,

           RESP_TO := #OverTime,

           ERROR => #InitialError,

           MB_DB := #Master.MB_DB);

#Master(REQ := #Req AND NOT #Error,

        MB_ADDR := #Task[#Index].Address,

        MODE := #Task[#Index].Mode,

        DATA_ADDR := #Task[#Index].Registor,

        DATA_LEN := #Task[#Index].Length,

        DATA_PTR := #Task[#Index].Data);

END_FUNCTION_BLOCK


Modbus-RTU通讯轮询 已锁定
编辑推荐: 关闭

请填写推广理由:

本版热门话题

SIMATIC S7-1200系列

共有15228条技术帖

相关推荐

热门标签

相关帖子推荐

guzhang

恭喜,你发布的帖子

评为精华帖!

快扫描右侧二维码晒一晒吧!

再发帖或跟帖交流2条,就能晋升VIP啦!开启更多专属权限!

  • 分享

  • 只看
    楼主

top
X 图片
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。