MODULE modbusTCP_Master
! author: Liao Chen, mousechen17@163.com
!!!!!!! support discrete input coil
!!!!!!! support holding coil
!!!!!!! support 0x01 0x02 0x05 0x0F function
VAR socketdev sock_mod;
VAR rawbytes recv_raw;
VAR rawbytes send_raw;
PERS num write_coils{16}:=[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0];pers num read_coils{16}:=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];!!!!!! data need to be modified
PERS string slave_ip:="127.0.0.1";
PERS num slave_ID:=1;
PERS num regAdd:=0;
PROC main()
WHILE true DO
readMultiCoil\Input,regAdd,16,read_coils;
! 读取16个输入并存入read_coils数组
setDI1 16;
! 将modbus信号存入vdo信号,并通过crossconnection关联到对应DI
! 此处假设DI信号均为di1,di2.。。di16的命名
writeCoils 16;
! 将do1.。。do16真实信号的值存入write_coils数组
writeMultiCoil regAdd,16,write_coils;
! 写入modbus远程
waittime 0.05;
ENDWHILE
ENDPROC
PROC writeCoils(num count)
! 假设do信号名为do1...do16
VAR signaldo sig;
VAR string name;
FOR i FROM 1 TO count DO
name:="do"+valtostr(i);
AliasIO name,sig;
write_coils{i}:=doutput(sig); ENDFOR
ENDPROC
PROC setDI1(num count)
FOR i FROM 1 TO count DO
setDO_int "vdo"+ValToStr(i),read_coils{i}; ENDFOR
ENDPROC
PROC setDO_int(string name,num value)
VAR signaldo sig;
aliasIO name,sig;
setdo sig,value;
ENDPROC
PROC writeMultiCoil(num regAdd,num coilCount,num coils{*}) ! funNo: 0x0F: write multi Coil
! device send: 00 01 00 00 00 09 01 0F 0005 000A 02 CD 01
! ttl data len slaveID funNo add coil_count byte_len byte1 byte2
! robot feedback: 0000 0000 0006 01 0F 0005 000A
! ttl data len slaveID funNo add coil_num
VAR byte outByte{50}; VAR num byteCount:=1;
VAR num b{100}; b{1}:=0x00; b{2}:=0x00; b{3}:=0x00; b{4}:=0x00; ! b{5}:=0x00; ! b{6}:=0x06; b{7}:=slave_ID; b{8}:=0x0F;
ClearRawBytes send_raw;
FOR i FROM 1 TO 8 DO
PackRawBytes b{i},send_raw,i\IntX:=1; ENDFOR
PackRawBytes regAdd,send_raw\Network,9\IntX:=2;
PackRawBytes coilCount,send_raw\Network,11\IntX:=2;
FOR i FROM 1 TO coilCount DO
outByte{byteCount}:=outByte{byteCount}+coils{i}*pow(2,(i-1) mod 8); IF (i mod 8)=0 THEN
byteCount:=byteCount+1;
ENDIF
ENDFOR
Decr byteCount;
FOR i FROM 1 TO byteCount DO
PackRawBytes outByte{i},send_raw\Network,13+i\Hex1; ENDFOR
PackRawBytes byteCount,send_raw\Network,13\IntX:=1;
PackRawBytes 7+byteCount,send_raw\Network,5\IntX:=2;
sendAndReceive;
ENDPROC
PROC readMultiCoil(\switch Input,num regAdd,num coilCount,inout num coils{*}) ! funNo: 0x01: read multi Coil
! device send: 00 00 00 00 00 06 01 01 0002 0002
! ttl data len slaveID funNo add coil_num
! robot feedback: 0000 0000 0004 01 01 01 01
! ttl data len slaveID funNo rest_data_len data
! funNo: 0x02: read input multi Coil
! device send: 00 00 00 00 00 06 01 02 0002 0002
! ttl data len slaveID funNo add coil_num
! robot feedback: 0000 0000 0004 01 02 01 01
! ttl data len slaveID funNo rest_data_len data
VAR byte inValue;
VAR num byteCount:=1;
VAR num tmpValue;
VAR num b{100}; b{1}:=0x00; b{2}:=0x00; b{3}:=0x00; b{4}:=0x00; b{5}:=0x00; b{6}:=0x06; b{7}:=slave_ID; IF Present(input) THEN
b{8}:=0x02; ELSE
b{8}:=0x01; endif
ClearRawBytes send_raw;
FOR i FROM 1 TO 8 DO
PackRawBytes b{i},send_raw,i\IntX:=1; ENDFOR
PackRawBytes regAdd,send_raw\Network,9\IntX:=2;
PackRawBytes coilCount,send_raw\Network,11\IntX:=2;
sendAndReceive;
FOR i FROM 1 TO coilCount DO
IF (i mod 8)=1 THEN
UnPackRawBytes recv_raw\Network,9+byteCount,tmpValue\IntX:=USINT;
inValue:=tmpValue;
byteCount:=byteCount+1;
ENDIF
coils{i}:=bitand(inValue,1); inValue:=BitRSh(inValue,1);
ENDFOR
ENDPROC
PROC checkSocket()
if SocketGetStatus(sock_mod)<>SOCKET_CONNECTED THEN
SocketClose sock_mod;
SocketCreate sock_mod;
SocketConnect sock_mod,slave_ip,502\Time:=10;
endif
ENDPROC
PROC sendAndReceive()
checkSocket;
SocketSend sock_mod\RawData:=send_raw;
SocketReceive sock_mod\RawData:=recv_raw;
ENDPROC
ENDMODULE