小弟不才,才接触西门子3个多月,由于公司要求全线用西门子的电控,临时学习的,刚好又用到一个SMC电缸的控制,本人嫌接线麻烦又是走开环控制,故采用了MODBUS的方式来控制。
再论坛上找了好多MODBUS通讯的写法,都不适合开关量,数据量同时轮询。自己尝试研究了半个月写出来的。写的不好大家可以指点下,这个程序已经试运行过可以用的
SCL代码
//===========================================================================================================================
//1、上升沿信号 R_TRIG
IF #V.Output.位状态.X_电缸使能 AND NOT #V.Output.X_通讯错误 THEN
#R_TRIG[0](CLK := #V.input.X_电缸动作 AND NOT #电缸Output读取.位状态.X_运行中 AND #IN号 = #V.input.X_IN号);
#R_TRIG[1](CLK := #V.input.X_故障清除 AND NOT #电缸Output读取.位状态.X_运行中);
#R_TRIG[2](CLK := #V.input.X_回原点 AND NOT #电缸Output读取.位状态.X_运行中);
#R_TRIG[4](CLK := #V.input.X_通讯重启 AND NOT #电缸Output读取.位状态.X_运行中);
#R_TRIG[5](CLK := #V.input.X_电缸动作);
END_IF;
//--------------------------------------------------------------------------------------------------------------------------
//2、通讯参数设置
IF #FirstScan OR (#R_TRIG[4].Q AND #V.Output.X_通讯错误) THEN
#Modbus_Comm_Load.MODE := 4;
#Modbus_Comm_Load.REQ := 1;
#V.Output.X_通讯错误 := 0;
#i := 0;
END_IF;
#Modbus_Comm_Load("PORT" := #PORT,
BAUD := 38400,
RESP_TO := 1000,
MB_DB := #Modbus_Master主站.MB_DB);
//3、通讯启动
IF NOT #V.Output.X_通讯错误 AND #Modbus_Comm_Load.DONE OR (#TON_TIME.Q AND NOT #Modbus_Master主站.BUSY) THEN
#Modbus_Master主站.REQ := TRUE;
#启动延时 := FALSE;
IF #Modbus_Comm_Load.REQ = 1 THEN
#Modbus_Comm_Load.REQ := 0;
END_IF;
END_IF;
//--------------------------------------------------------------------------------------------------------------------------
//4、MODBUS通讯主站参数地址
#Modbus_Master主站.MB_ADDR := #Request[#i].站号;
#Modbus_Master主站.MODE := #Request[#i].方式;
#Modbus_Master主站.DATA_ADDR := #Request[#i].地址;
#Modbus_Master主站.DATA_LEN := #Request[#i].长度;
#Modbus_Master主站(DATA_PTR := #Request[#i].传送数据);
IF #Modbus_Master主站.ERROR THEN
#V.Output.X_通讯错误代码 := #Modbus_Master主站.STATUS;
#V.Output.X_通讯错误 := TRUE;
#V.InOut.动作号 := 0;
END_IF;
//通讯结束后延时时间30ms启动下次轮询
#TON_TIME(IN := #启动延时,
PT := t#30ms);
//=================================================================================================================================
FOR #A := 0 TO 2 DO//判断 X_电缸动作、X_故障清除、X_回原点上沿条件
IF #R_TRIG[#A].Q THEN
#V.InOut.动作号 := 500;
#Request[5].传送数据[#A] := 1;
EXIT;
END_IF;
END_FOR;
//----------------------------------------------------------------------------------------------------------------------------------
IF #R_TRIG[5].Q THEN
#电缸Output读取.位状态.X_动作到位 := 0;
END_IF;
//IN号判读
IF #IN号 <> #V.input.X_IN号 AND NOT #电缸Output读取.位状态.X_运行中 AND #V.InOut.动作号>0 THEN
#V.InOut.动作号 := 400;
END_IF;
//5、动作流程树
IF #Modbus_Master主站.DONE THEN
#Modbus_Master主站.REQ := FALSE;
#启动延时 := 1;
//-----------------------------------------------------------------------------------------------------------------------
//#i:= 值代表含义
//0 开启电缸通讯的地址写入地址位
//1 电缸使能通讯地址
//2 电缸位状态读取
//3 电缸字状态读取
//4 IN号修改写入
//5 X_电缸动作、X_故障清除、X_回原点状态条件写入
//------------------------------------------------------------------------------------------------------------------------
IF NOT #V.input.X_模式选择 AND NOT #电缸Output读取.位状态.X_运行中 THEN//电缸动作相应参数设置判断
FOR #B := 0 TO 3 DO
IF "电缸Static".参数待写区[#B] <> #电缸参数[#B] THEN
"电缸Static".参数待写区[#B] := #电缸参数[#B];
FOR #A := 0 TO 31 DO
POKE(area := 16#84,
dbNumber := #DB地址,
byteOffset := 2692 + (#B * 42) + #A,
value := PEEK(area := 16#84, dbNumber := 7, byteOffset := 0 + (#B * 32) + #A));
END_FOR;
#i := 6 + #B;
#V.InOut.动作号 := 100;
EXIT;
ELSE
IF #V.InOut.动作号 = 100 THEN
#V.InOut.动作号 := 200;
#i := 2;
END_IF;
END_IF;
END_FOR;
END_IF;
//------------------------------------------------------------------------------------------------------------------------
CASE #V.InOut.动作号 OF
0:
IF #i = 0 THEN//开启电缸通讯的地址写入地址位
#i := 1;
ELSIF #i = 1 THEN//电缸使能通讯地址
#i := 2;
#V.InOut.动作号 := 200;
END_IF;
200://电缸位状态读取
FOR #B := 0 TO 1 DO
POKE(area := 16#84,
dbNumber := #DB地址,
byteOffset := 2414 + #B,
value := PEEK(area := 16#84, dbNumber := #DB地址, byteOffset := 2524 + #B));
END_FOR;
#V.InOut.动作号 := 300;
#i := 3;
300://电缸字状态读取
FOR #B := 0 TO 14 DO
POKE(area := 16#84,
dbNumber := #DB地址,
byteOffset := 2416 + #B,
value := PEEK(area := 16#84, dbNumber := #DB地址, byteOffset := 2566 + #B));
END_FOR;
#V.InOut.动作号 := 200;
#i := 2;
400://IN位修改参数写入
#IN号 := #V.input.X_IN号;
POKE(area := 16#84,
dbNumber := #DB地址,
byteOffset := 2608,
value := PEEK(area := 16#84, dbNumber := #DB地址, byteOffset := 2412));
#i := 4;
#V.InOut.动作号 := 410;
410://IN写入后判断是否连续动作
IF NOT #V.input.X_电缸动作 THEN
#V.InOut.动作号 := 200;
#i := 2;
END_IF;
500:// X_电缸动作、X_故障清除、X_回原点状态条件写入
#i := 5;
#V.InOut.动作号 := 510;
510:// X_电缸动作、X_故障清除、X_回原点状态条件判断若有处于开启状态进行复位
IF #Request[5].传送数据[0] OR #Request[5].传送数据[1] OR #Request[5].传送数据[2] THEN
#Request[5].传送数据[0] := FALSE;
#Request[5].传送数据[1] := FALSE;
#Request[5].传送数据[2] := FALSE;
ELSE
#i := 2;
#V.InOut.动作号 := 200;
END_IF;
END_CASE;
END_IF;
//电缸状态读取后输出
#V.Output.位状态 := #电缸Output读取.位状态;
#V.Output.字状态 := #电缸Output读取.字状态;
SMC电缸MODBUS通讯控制.zip