查看: 584|回复: 8
收起左侧

[资料分享] TCP开放式通讯

邀请回答

马上注册,享受更多特权

您需要 登录 才可以下载或查看,没有帐号?立即注册   

x
使用plc位am401系列,用来做物联网连接中介,整套系统连接多台不同设备。其中比较好玩的连接的对象为工控机,通讯协议为自定义开发。报文的固定有起始帧头+帧尾部校验,发送的数据将16进制数据1:1同等等比位字符。整体通讯连接流程和思路如下。
展示内容位5
//枚举结构体
TYPE ENUM_TCP_Client :
(
        nInitial := 0,(*        复位信号        *)
        nConnect := 1,(*        连接服务器        *)
        nWhetherConnect := 2,(*        判断是否连接成功        *)
        nDetermineAction  := 3,(*        判断动作        *)
        nSend := 4,(*        发送数据        *)
        nWhetherSend := 5,(*        判断是否发送成功        *)
        nReceive := 6,(*        接收数据        *)
        nWhetherReceive := 7,(*        判断时候接收成功        *)
        nClose := 8(*        动作完成        *)
);
END_TYPE



(*        设备的输出初始设定        *)
TON_D2700(IN := TRUE, PT := T#10ms, Q => , ET => );
R_TRIG_D2700(CLK := TON_D2700.Q, Q => );
IF R_TRIG_D2700.Q THEN
        // 用于D27号设备,中科赛宁设备的socket初始化通讯参数
        IF TcpClient[27].strIpAddrDst = '' THEN
                // 开机默认设定IP地址'192.168.1.88'
                TcpClient[27].strIpAddrDst := '192.168.0.109';
        END_IF

        IF TcpClient[27].uiPortDst = NULL THEN
                // 开机默认设定端口号8000
                TcpClient[27].uiPortDst := 8001;
        END_IF

        IF        TcpClient[27].udiTimeOut = NULL THEN
                // 开机默认设定超时连接时间
                TcpClient[27].udiTimeOut := 500000;
        END_IF

        IF (TcpReceive[27].uiSize <= 0 )OR (TcpReceive[27].uiSize > 50) THEN
                // 开机默认设定接收数据长度
                TcpReceive[27].uiSize := 50;
                FOR var_D2703 := 0 TO UINT_TO_INT(TcpReceive[27].uiSize - 1) BY 1 DO
                        Group2_Receive_BUF[7, var_D2703] := 0; // 清楚接受缓存区的数据
                END_FOR
        END_IF

        IF (TcpSend[27].uiSize <= 0) OR (TcpSend[27].uiSize > 50) THEN
                // 开机默认设定数据发送长度
                TcpSend[27].uiSize := 50;;
        END_IF
        Step_D2701 := 0; // 执行功能块的复位功能
        TcpClient[27].bR_W_Mode := 0; // 数据读取模式
        TcpClient[27].bCDExecute := FALSE; // 初始化读取和发送数据的地址空间
END_IF

(*        客户端执行流程        *)
CASE Step_D2701  OF
        ENUM_TCP_Client.nInitial : // 复位信号
                TcpClient[27].xEnable := FALSE; // 关闭连接使能
                TcpSend[27].xExecute := FALSE; // 关闭发送数据
                TcpReceive[27].xEnable := FALSE; // 关闭接收数据
                IF NOT TcpClient[27].xError AND NOT TcpClient[27].xActive AND NOT TcpSend[27].xError THEN
                        Step_D2701 := ENUM_TCP_Client.nConnect;
                ELSE
                        Step_D2701 := 0; // 执行功能块的复位功能
                END_IF
        ENUM_TCP_Client.nConnect : // 连接服务器
                TcpClient[27].xEnable := TRUE; // 打开连接使能
                Step_D2701 := ENUM_TCP_Client.nWhetherConnect;
        ENUM_TCP_Client.nWhetherConnect : // 判断是否连接成功
                IF TcpClient[27].xActive AND (NOT TcpClient[27].xError)  THEN //
                        TcpClient[27].bConnectDone := TRUE; // Client连接功能块功能完成
                        Step_D2701 := ENUM_TCP_Client.nDetermineAction;
                END_IF
                IF TcpClient[27].xError THEN
                        TcpClient[27].bConnectDone := FALSE; // 客户端连接失败
                        Step_D2701 := ENUM_TCP_Client.nInitial; // connect连接错误,重启复位操作
                END_IF
        ENUM_TCP_Client.nDetermineAction : // 判断动作
                IF TcpClient[27].xError OR flag_D2701  OR  (NOT TcpClient[27].xActive) THEN
                        (* 1、客户端连接出错;2、数据发送出错;3、服务器掉线 *)
                        Step_D2701 := ENUM_TCP_Client.nInitial;
                        TcpClient[27].bCDExecute := FALSE;
                ELSE
                        TcpClient[27].bCDExecute := TRUE;
                END_IF
END_CASE

IF TcpClient[27].bCDExecute  THEN
        // 数据读取模式
        IF (NOT TcpClient[27].bR_W_Mode)AND(0 <= Step_D2702)AND(Step_D2702 <= 1)THEN
                Step_D2702 := 1; // 开启发送读取功能
        Step_D2703 := 0; // 关闭发送写入功能
        ELSIF TcpClient[27].bR_W_Mode AND (0 <= Step_D2703)AND(Step_D2703 <= 1) THEN
        // 数据写入模式
                Step_D2702 := 0; // 关闭发送读取功能
        Step_D2703 := 1; // 开启发送写入功能
        END_IF
ELSE
        Step_D2702 := 0; // 关闭发送读取功能
        Step_D2703 := 0; // 关闭发送写入功能
END_IF

CASE Step_D2702 OF
    1 ://读取初始化,从第0组数据开始
        var_D2700 := 0;
        Step_D2702 := 10;
    2 ://循环读取数据
        var_D2700 := var_D2700 + 1;
                IF var_D2700 > 21 THEN
                        var_D2700 := 0;
                END_IF
                Step_D2702 := 10;
    10 ://发送数据buffer填充
        var_D2701 := 0;
        FOR var_D2701 := 0 TO 19 BY 1 DO
            IF var_D2701 < 7 THEN
                Group2_Send_BUF[7, var_D2701] := Format_D2700[var_D2701];
            ELSIF 7 <= var_D2701 AND  var_D2701 < 12 THEN
                Group2_Send_BUF[7, var_D2701] := D27_SendData[var_D2700, var_D2701 - 7];
            ELSIF 12 <= var_D2701 AND  var_D2701 < 17 THEN
                 Group2_Send_BUF[7, var_D2701] := D27_SendData[var_D2700, var_D2701 - 12];
            ELSIF 17 <= var_D2701 AND  var_D2701 < 20 THEN
                 Group2_Send_BUF[7, var_D2701] := Format_D2701[var_D2701 - 17];
            END_IF
        END_FOR
        Step_D2702 := 20;
        20 : // 数据发送
                TcpSend[27].xExecute := TRUE; // 数据发送使能
                TcpReceive[27].xEnable := FALSE; // 数据接受使能
                // var_D2702 := 0; // 发送失败次数
                Step_D2702 := 30;
        30 : // 判定发送成功or失败
                // 数据发送失败
                IF TcpSend[27].xError AND (NOT TcpSend[27].xDone) THEN
                        IF var_D2702 < 3 THEN
                                TcpSend[27].xExecute := FALSE;
                                var_D2702 := var_D2702 + 1;
                                Step_D2702 := 20;
                        ELSE
                                flag_D2701 := 1; // 3次发送失败标志,重启功能块
                                var_D2702 := 0; // 发送失败次数清零
                                Step_D2702 := 0; // 跳转退出发送区
                        END_IF;
                END_IF;
                // 数据发送成功
                IF TcpSend[27].xDone AND TcpSend[27].xExecute THEN
                        var_D2702 := 0; // 发送失败次数清零
                        TcpSend[27].xExecute := FALSE;
                        TcpReceive[27].xEnable := TRUE;
                        Step_D2702 := 40;
                END_IF;
        40 : // 数据接受处理
                IF TcpReceive[27].xReady THEN
                        calcData_D2701 := 0;
                        FOR var_D2704:=6 TO 9 BY 1 DO
                                Buffer_D27[var_D2704-6] := Group2_Receive_BUF[7, var_D2704];
                        END_FOR;
                        Step_D2702 := 50;
                END_IF
        50 :
        IF  Buffer_D27[2] < 56 THEN
        //当前正数情况下计算结果
            FOR var_D2704:=6 TO 9 BY 1 DO       
                FOR var_D2705:=0 TO 15 BY 1 DO
                    IF Buffer_D27[var_D2704-6] = HexStr_D2700[var_D2705]  THEN
                        //Buffer_D27[var_D2704] := var_D2705;
                        IF var_D2704<= 7 THEN
                            calcData_D2701 := calcData_D2701+ LREAL_TO_INT(EXPT(16,(7-var_D2704))*var_D2705);
                        ELSE
                            calcData_D2701 := calcData_D2701+ LREAL_TO_INT(EXPT(16,(11-var_D2704))*var_D2705);
                        END_IF;
                    END_IF;
                END_FOR
            END_FOR
        else
        //当前负数情况下的计算结果
           // Buffer_D27[2]:= DWORD_TO_BYTE(PUTBIT(X:= Buffer_D27[2], N:= 3, B:= FALSE));
                        FOR var_D2704:=6 TO 9 BY 1 DO       
                FOR var_D2705:=0 TO 15 BY 1 DO
                    IF Buffer_D27[var_D2704-6] = HexStr_D2700[var_D2705]  THEN
                        //Buffer_D27[var_D2704] := var_D2705;
                        IF var_D2704<= 7 THEN
                            calcData_D2701 := calcData_D2701+ LREAL_TO_INT(EXPT(16,(7-var_D2704))*var_D2705);
                        ELSIF var_D2704 = 8THEN
                            calcData_D2701 := calcData_D2701+ LREAL_TO_INT(EXPT(16,(11-var_D2704))*(var_D2705-8));
                                                ELSE
                                                        calcData_D2701 := calcData_D2701+ LREAL_TO_INT(EXPT(16,(11-var_D2704))*var_D2705);
                        END_IF;
                    END_IF;
                END_FOR
            END_FOR
                        calcData_D2701:=calcData_D2701-32767-1;
        END_IF;
                Step_D2702 := 60;
        60 :// 接受数据转换完成,清楚buffer
                D27_ReciveData[var_D2700] := calcData_D2701;
                FOR var_D2703 := 0 TO UINT_TO_INT(TcpReceive[27].uiSize - 1) BY 1 DO
                        Group2_Receive_BUF[7, var_D2703] := 0; // 清楚接受缓存区的数据
                END_FOR
                Step_D2702 := 2;
    ELSE
    // Statement section else;
END_CASE;
//写入数据处理过程
CASE Step_D2703 OF
        1 :
                IF TcpClient[27].BWData >0 THEN
                //写入值为正值
                        VAR_D2712 := TcpClient[27].BWData;
                        FOR var_D2710:=0 TO 3 BY 1 DO
                                var_D2711 := VAR_D2712 MOD 16;
                                VAR_D2712 := VAR_D2712 / 16;
                                IF var_D2711 = 0 THEN
                                        Buffer_D27[var_D2710+4] := HexStr_D2700[0];
                                ELSE
                                        Buffer_D27[var_D2710+4] := HexStr_D2700[var_D2711];
                                END_IF
                        END_FOR;
                ELSE
                //写入值为负值
                        VAR_D2713 := TcpClient[27].BWData+65536;//将数据转换为正数
                        FOR var_D2710:=0 TO 3 BY 1 DO
                                var_D2714 := var_D2713 MOD 16;
                                var_D2713 := var_D2713 / 16;
                                IF var_D2713 = 0 THEN
                                        Buffer_D27[var_D2710+4] := HexStr_D2700[0];
                                ELSE
                                        Buffer_D27[var_D2710+4] := HexStr_D2700[var_D2714];
                                END_IF                               
                        END_FOR
                END_IF;
                Step_D2703 := 10;
        10://发送数据buffer填充
       FOR var_D2710 :=0 TO 22 BY 1 DO
                   IF var_D2710 <= 6 THEN
                                   Group2_Send_BUF[7,var_D2710] := Format_D2702[var_D2710];//发送数据报文:功能报文帧
                   ELSIF (6 < var_D2710 AND var_D2710 <= 11) THEN
                                   Group2_Send_BUF[7,var_D2710]:= D27_SendData[TcpClient[27].BW_Addr+11, var_D2710 - 7];//发送数据报文:起始地址帧
                   ELSIF (11 < var_D2710 AND var_D2710 <=16)THEN
                                   Group2_Send_BUF[7,var_D2710] := D27_SendData[TcpClient[27].BW_Addr+11, var_D2710-12];//发送数据报文:结束地址帧
                   ELSIF (16 < var_D2710 AND var_D2710 <= 17)THEN
                           Group2_Send_BUF[7,var_D2710] := Buffer_D27[var_D2710-10];//将写入值的高低交换写入填充
                   ELSIF (17 < var_D2710 AND var_D2710 <= 19)THEN
                           Group2_Send_BUF[7,var_D2710] := Buffer_D27[var_D2710-10];//将写入值的高低交换写入填充
                   END_IF

       END_FOR;
ELSE
        ;
END_CASE









点评

感谢分享!!  发表于 2023-3-6 10:10
整体通讯流程,沿用的是我以前使用twincat3的思路,过程不一定百分百都是对每个人适用。  发表于 2023-3-6 09:22
感谢分享  发表于 2023-3-6 09:21




上一篇:HMC_MoveCam中主轴延时启动功能是如何实现的?
下一篇:塔塔木门流水线程序:OMRON nj系列加NB触摸屏

已有 0 人打赏作者

回复 邀请回答送花

使用道具 举报

微光 2023-3-6 11:13:51 | 显示全部楼层
直接复制源码,O(∩_∩)O谢谢。
回复 送花

使用道具 举报

不败如来 2023-3-9 15:35:55 | 显示全部楼层
微光 发表于 2023-3-6 11:13
直接复制源码,O(∩_∩)O谢谢。

这个code流程是用来测试用的,用的时候需要修改内容哦!

点评

好的哦,谢谢提醒  发表于 2023-3-16 11:16
回复 送花

使用道具 举报

通用市场兄弟 2023-6-15 10:13:09 | 显示全部楼层
TCP_Client功能块其它的接头是哪里来的比如TcpClient[27].BWData。期待回复
回复 送花

使用道具 举报

不败如来 2023-8-15 16:48:54 | 显示全部楼层
通用市场兄弟 发表于 2023-6-15 10:13
TCP_Client功能块其它的接头是哪里来的比如TcpClient[27].BWData。期待回复

说明:27表示我链接的第27台设备。TcpClient[27].BWData:这个表示写入数据,此处数据的来源是上位机修改数据。我需要对上数据给我的数值进行转换,由于链接设备的协议是自定义的,需要通过转换格式和形式的方式进行转换。
回复 送花

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册   

本版积分规则

有技术问题,就上汇川技术社区

INOVANCE汇川技术 公众号

扫码下载掌上汇川APP

全国服务热线:8:30-17:30

4000-300124

苏州地址:江苏省苏州市吴中区越溪友翔路16号

深圳地址:深圳市龙华新区观澜街道高新技术产业园汇川技术总部大厦

Copyright © 2003-2100 汇川技术 Powered by Discuz! X3.4 ( 苏ICP备12002088号 )
快速回复 返回列表 返回顶部