PLC的开放式用户协议,TSAP(含S7300和S71200TCP连接实例)

0. 向导

只想看S7-300和S7-1200 TCP连接实例的朋友请直接点击这里

1. OUC

开放式用户协议,包括ISO,ISO-on-TCP,TCP/IP,UDP四种。西门子PLC中有多种不同的方式建立连接。

2. 在硬件组态中建立TCP通信

  • 打开硬件组图,网络视图
  • 添加新连接
  • 填入本地ID,关于本地ID:**针对1513实测过,ID的取值范围从16#01到16#999,但是16#01-16#99大概率被系统占用了,可用范围从16#100开始。西门子本身没有规定ID必须从多少开始,所以在允许范围类,随便填。一条TCP连接(或者一个通信设备之间)分配一个唯一的ID**
    • 主动连接:如果本地对象是客户端就勾选主动建立连接,如果做服务器可以不用勾选
    • 添加后关闭页面

  • 设置伙伴参数
    • 本地端口和伙伴端口可以不一致,也可以一致,本地端口甚至可以不用填写。端口设定范围从1-65535,也可以自由定义。一般约定从2000开始(ipv4)
    • 伙伴设备可以选择不指定

  • 网络视图的连接建立好之后就可以在程序中调用TSENDTRCV指令用作收发数据了。
    1
    2
    3
    4
    5
    6
    7
    8
    //ID就是在网络视图里面设置的ID
    "TSEND_DB".TSEND(REQ:="Tag_1",
    ID:=16#100,
    DATA:=_variant_inout_);

    "TRCV_DB".TRCV(EN_R:="Tag_2",
    ID:=16#100,
    DATA:=_variant_inout_);
  • 在硬件组态里面建立TCP连接的方式会在“系统资源”里面使用一条OUC资源,连接在线时也能在线看到连接详情

2. 参数化的方式建立TCP连接

  • 在这种方式中,不需要在硬件组态里面配置连接,它在资源占用上是动态化的,“系统资源”里面体现不出来,但是在线的时候看得到连接详情

  • TCON连接参数设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    "_ShareDB".FB110.tcon.I_req := NOT "_ShareDB".FB110.tdiscon.I_req;

    "_ShareDB".FB110.tcon.I_id := 16#100;//ID
    "_ShareDB".FB110.tcon.IO_connect.InterfaceID := 64;//Local~PROFINET_接口,hw_Interface

    //connect参数,ID,Type,连接方式
    "_ShareDB".FB110.tcon.IO_connect.ID := 16#100;//ID
    "_ShareDB".FB110.tcon.IO_connect.connType := 11;//11 TCP,19 UDP
    "_ShareDB".FB110.tcon.IO_connect.activeEst := 1;//=1:建立主动连接 =0:建立被动连接

    //伙伴端点IP地址
    "_ShareDB".FB110.tcon.IO_connect.reAddress[0] := 192;
    "_ShareDB".FB110.tcon.IO_connect.reAddress[1] := 168;
    "_ShareDB".FB110.tcon.IO_connect.reAddress[2] := 0;
    "_ShareDB".FB110.tcon.IO_connect.reAddress[3] := 241;

    //远程和本地端口
    "_ShareDB".FB110.tcon.IO_connect.rePort := 6688;//ipv4 0-65535
    "_ShareDB".FB110.tcon.IO_connect.LoPort := 2000;//ipv4 1-49151

    #TCON_Instance(REQ:="_ShareDB".FB110.tcon.I_req,
    ID:="_ShareDB".FB110.tcon.I_id,
    DONE=>"_ShareDB".FB110.tcon.O_done,
    BUSY=>"_ShareDB".FB110.tcon.O_busy,
    ERROR=>"_ShareDB".FB110.tcon.O_error,
    STATUS=>"_ShareDB".FB110.tcon.O_status,
    CONNECT:="_ShareDB".IO_connect);
  • 关于connect参数的数据类型

    • TCP_IP_v4结构如下:
    • 对于ISO-on-TCP,使用TCP_IP_RFC结构
    • 其他结构参见帮助
  • 发送指令,异步指令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //TSEND
    "_ShareDB".FB110.tsend.I_id := 16#100;
    "_ShareDB".FB110.tsend.I_len := 10;

    #TSEND_Instance(REQ:="_ShareDB".FB110.tsend.I_req,
    ID:="_ShareDB".FB110.tsend.I_id,
    LEN:="_ShareDB".FB110.tsend.I_len,//处理长度,1200=8.192kb,1500=65.536kb,CM1542=240bytes
    DONE=>"_ShareDB".FB110.tsend.O_done,
    BUSY=>"_ShareDB".FB110.tsend.O_busy,
    ERROR=>"_ShareDB".FB110.tsend.O_err,
    STATUS=>"_ShareDB".FB110.tsend.O_status,
    DATA:="_ShareDB".FB110.tsend.IO_data);//数据指针,发送端和接收端的数据格式要一致
  • 接收指令,TRCV为异步指令

    • ADHOC接口用于指定TCP协议下是否启动动态长度接收功能(对ISO-on-TCP或者FDL无效);ADHOC=0,按length指定的长度接收数据;ADHOC=1,至少会接收到一个可用字节数据
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      //TRCV
      "_ShareDB".FB110.trcv.I_R := TRUE;
      "_ShareDB".FB110.trcv.I_id := 16#100;
      "_ShareDB".FB110.trcv.I_len := 10;
      "_ShareDB".FB110.trcv.I_ADHOC := 0;

      #TRCV_Instance(EN_R:="_ShareDB".FB110.trcv.I_R,//使能接收
      ID:="_ShareDB".FB110.trcv.I_id,
      LEN:="_ShareDB".FB110.trcv.I_len,//ADHOC=0时指定长度
      ADHOC:="_ShareDB".FB110.trcv.I_ADHOC,//指定以固定长度接收或者动态长度接收
      NDR=>"_ShareDB".FB110.trcv.O_NDR,//作业过程标志位 =1,Done
      BUSY=>"_ShareDB".FB110.trcv.O_busy,
      ERROR=>"_ShareDB".FB110.trcv.O_err,
      STATUS=>"_ShareDB".FB110.trcv.O_status,
      RCVD_LEN=>"_ShareDB".FB110.trcv.O_len,
      DATA:="_ShareDB".FB110.trcv.IO_data);//接收到的数据,格式和发送端一致
  • 断开连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //TDISCON
    "_ShareDB".FB110.tdiscon.I_id := 16#100;

    #TDISCON_Instance(REQ:="_ShareDB".FB110.tdiscon.I_req,
    ID:="_ShareDB".FB110.tdiscon.I_id,//要终止作业的ID
    DONE=>"_ShareDB".FB110.tdiscon.O_done,
    BUSY=>"_ShareDB".FB110.tdiscon.O_busy,
    ERROR=>"_ShareDB".FB110.tdiscon.O_error,
    STATUS=>"_ShareDB".FB110.tdiscon.O_status);
  • 各个指令的”属性”-“组态”-“块参数”

    • 如图,这些块参数其实就是指令接口填写的内容,接口填写完成后这里会自动生成相应的变量符号名
  • 这个方法有个特点,所有的参数都可以动态化,动态配置,由程序更改,更好的实现自动化。但是它看不了也用不了TCON关于“属性”-“组态”-“连接参数”里面的静态设置。

3. 参数化但使用”属性”-“组态”-“连接参数”

  • 不同于第二种方法,这是一种介于第一种和第二种方法之间的方法,它既需要填写常量的ID,IP等等信息,但是又不会在“系统资源”里显示出来,属于参数化方法。
  • 依旧使用TCON,TSEND,TRCV,TDISCON等方法来做程序
  • 如图,TCON的参数不用在程序里填写,在“属性”-“组态”-“连接参数”里定义,定义为固定的设置

4. OUC相关指令以及它们的区别和应用场景


5. 关于TSAP的概念

  • TSAP(Transport Server Access Point 传输服务访问点)是用于ISO-on-TCP上的两个参数,有本地TSAP和伙伴TSAP。用2个字节表示

  • 本地TSAP和远程TSAP可以相同,因为通过不同的MAC地址建立的连接是唯一的,但如果要在两个站之间建立多个连接,则远程TSAP和本地TSAP必须不同。

  • TSAP是ISO传输连接中的相关概念,ISO传输连接的过程如下:

  • TSAP的结构

    • TSAP(ASC II)
    • TSAP-ID(Hex)(系统自动生成)
  • TSAP的含义


  • TSAP分配案例(如何填写TSAP)

    • 在S7协议下的规定
      • 对于S7-1500CPU:"SIMATIC-ACC"<nnn><mm>,nnn = 本地 ID,mm = 任何值
      • 对于S7-300/400:<xx>.<yz>,xx = 连接资源号,y = 机架号,z = 插槽号
      • 连接资源号由配置界面填入的连接资源(十六进制)确定


        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        请参见不同连接组态的以下 TSAP 示例
        两个 S7-1200 CPU(固件版本均为 V2.0)之间的连接:
        S7-1200 CPU“A”(固件版本为 V2.0,本地 ID 为 100):
        TSAP: SIMATIC-ACC10001
        S7-1200 CPU“B”(固件版本为 V2.0,本地 ID 为 5AE):
        TSAP: SIMATIC-ACC5AE01
        两个 S7-1200 CPU(固件版本分别为 V2.0V1.0)之间的连接:
        S7-1200 CPU(固件版本为 V2.0,本地 ID 为 1FF):
        TSAP: SIMATIC-ACC1FF01
        S7-1200 CPU,固件版本为 V1.0(机架 0,插槽 1,连接资源 03):
        TSAP03.01
        S7-1200 CPU(固件版本为 V2.0)与 S7-300/400 CPU 之间的连接:
        S7-1200 CPU,固件版本为 V2.0(机架 0,插槽 1,连接资源 12):
        TSAP12.01
        S7-300/400 CPU(机架 0,插槽 2,连接资源 11):
        TSAP11.02
  • 在ISO-on-TCP下的实例

    • PLC-PLC,ID由系统自动生成,TSAP可空
    • 本地ASC II - TSAP
    • 在本地CPU1513和远程CPU1516的ISO-on-TCP通信中,本地TSAP可填CPU1513,远程TSAP可填CPU1516。TSAP ID会根据TSAP填入的ASCii字符自动生成。

6. S7300 - S71200 TCP通信实例

  • 案例中,S7 300和S7 1200同处在一个项目下,300做服务器端,1200做客户端。TCP配置从程序中进行,不在硬件组态中设置。
  • 若需要不在同一个项目下的案例,其实只需要把伙伴端口设置为未指定。其他步骤殊途同归。
  • 配置300PLC参数和程序:
    • TCON:
      • 注意点1:指定出伙伴
      • 注意点2:子网为PN/IE_1,这条连接是在硬件组态中已经配好的,且是必要的。


- 注意点3:连接类型选择TCP
- 注意点4:连接ID,此处填写的是1,可以随便填,但是要保证伙伴和本地端口的连接ID是一致的,连接ID表示当前使用的TCP网络通道号。
- 注意点5:连接数据TCP_Server_Connection_DBTCP_Client_Connection_DB。这是两个系统生成的DB。由系统自动建立,分别位于300和1200的程序文件夹内。(当然也可以自己填写和建立)



- 注意点6:若你的连接配置页面出现了无可用连接参数界面。请注意检查一下你的Connect参数,或者干脆删除管脚的connect参数地址后重建。


- 客户端选择主动连接,如1200侧主动连接

- TCON配置好后,就可以自由配置TSENDTRCV了。注意一下连接ID保持一致,接收或者发送长度可以自定。TSEND发送 REQ需要用上升沿触发,为了方便,可以在SEND_REQ管脚做周期频率触发(5Hz/2Hz/10Hz/..)的信号

  • 配置1200PLC参数和程序:
    • TCON,细节注意点和300PLC配置TCON时一致
    • TSEND及TRCV配置

7. update 实际用例

  • 300侧
    开头一部分是用于出错重连逻辑;
    tcp_start点在OB100里面被初始化置1;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    //Establish TCP comm
    //TCON
    #IEC_Timer_0_Instance(IN := "_TcpComm2client".tcp_start,
    PT := T#1S,
    Q => "_TcpComm2client".TCON.REQ);

    IF "_TcpComm2client".TRCV.ERROR AND NOT #pulser[0] THEN
    "_TcpComm2client".tcp_start := false;
    END_IF;
    #pulser[0] := "_TcpComm2client".TRCV.ERROR;

    #IEC_Timer_0_Instance_1(IN := "_TcpComm2client".TRCV.ERROR,
    PT := T#50MS);
    IF #IEC_Timer_0_Instance_1.Q AND NOT #pulser[1] THEN
    "_TcpComm2client".tcp_start := TRUE;
    END_IF;
    #pulser[1] := #IEC_Timer_0_Instance_1.Q;

    //"_TcpComm2client".TCON.REQ := true;
    #TCON_Instance(REQ := "_TcpComm2client".TCON.REQ,
    ID := 1,
    DONE => "_TcpComm2client".TCON.DONE,
    BUSY => "_TcpComm2client".TCON.BUSY,
    ERROR => "_TcpComm2client".TCON.ERROR,
    STATUS => "_TcpComm2client".TCON.STATUS,
    CONNECT := P#DB6.DBX0.0 BYTE 64);

    IF "_TcpComm2client".TCON.REQ THEN

    //TRCV
    #TRCV_Instance(EN_R := NOT "_TcpComm2client".TRCV.EN_R,
    ID := 1,
    LEN := 8,
    NDR => "_TcpComm2client".TRCV.NDR,
    BUSY => "_TcpComm2client".TRCV.BUSY,
    ERROR => "_TcpComm2client".TRCV.ERROR,
    STATUS => "_TcpComm2client".TRCV.STATUS,
    RCVD_LEN => "_TcpComm2client".TRCV.RCVD_LEN,
    DATA := P#DB11.DBX0.0 BYTE 8);

    //TSEND
    "_TcpComm2client".TSEND.REQ := "1.0s";
    #TSEND_Instance(REQ := "_TcpComm2client".TSEND.REQ,
    ID := 1,
    LEN := 8,
    DONE => "_TcpComm2client".TSEND.DONE,
    BUSY => "_TcpComm2client".TSEND.BUSY,
    ERROR => "_TcpComm2client".TSEND.ERROR,
    STATUS => "_TcpComm2client".TSEND.STATUS,
    DATA := P#DB15.DBX0.0 BYTE 8);
    END_IF;

  • 1200侧
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    //Establish TCP comm
    //TCON
    #IEC_Timer_0_Instance(IN:=TRUE,
    PT:=T#2s,
    Q=>"_TcpComm2serve".TCON.REQ);

    //"_TcpComm2serve".TCON.REQ:=true;
    #TCON_Instance(REQ:="_TcpComm2serve".TCON.REQ,
    ID:=1,
    DONE=>"_TcpComm2serve".TCON.DONE,
    BUSY=>"_TcpComm2serve".TCON.BUSY,
    ERROR=>"_TcpComm2serve".TCON.ERROR,
    STATUS=>"_TcpComm2serve".TCON.STATUS,
    CONNECT:="_1200PLC_Connection_DB");

    IF "_TcpComm2serve".TCON.REQ THEN

    //TSEND
    "_TcpComm2serve".SEND.REQ := "Clock_1Hz";
    #TSEND_Instance(REQ := "_TcpComm2serve".SEND.REQ,
    ID := 1,
    LEN := 8,
    DONE => "_TcpComm2serve".SEND.DONE,
    BUSY => "_TcpComm2serve".SEND.BUSY,
    ERROR => "_TcpComm2serve".SEND.ERROR,
    STATUS => "_TcpComm2serve".SEND.STATUS,
    DATA := P#DB7.DBX0.0 BYTE 8);

    //TRCV
    #TRCV_Instance(EN_R := NOT "_TcpComm2serve".TRCV.EN_R,
    ID := 1,
    LEN := 8,
    NDR => "_TcpComm2serve".TRCV.NDR,
    BUSY => "_TcpComm2serve".TRCV.BUSY,
    ERROR => "_TcpComm2serve".TRCV.ERROR,
    STATUS => "_TcpComm2serve".TRCV.STATUS,
    RCVD_LEN => "_TcpComm2serve".TRCV.RCVD_LEN,
    DATA := P#DB8.DBX0.0 BYTE 8);
    END_IF;


PLC的开放式用户协议,TSAP(含S7300和S71200TCP连接实例)
http://example.com/2024/07/21/PLC的开放式用户协议,TSAP(含S7300和S71200TCP连接实例)/
作者
xiao cuncun
发布于
2024年7月21日
许可协议