|
邀请回答
马上注册,享受更多特权
您需要 登录 才可以下载或查看,没有帐号?立即注册
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
|
上一篇: HMC_MoveCam中主轴延时启动功能是如何实现的?下一篇: 塔塔木门流水线程序:OMRON nj系列加NB触摸屏
|