logo资料库

modbus_tcp_server(codesys).doc

第1页 / 共13页
第2页 / 共13页
第3页 / 共13页
第4页 / 共13页
第5页 / 共13页
第6页 / 共13页
第7页 / 共13页
第8页 / 共13页
资料共13页,剩余部分请下载后查看
MODBUS TCP SERVER 在 LTI MOTION ONE 控制器上的实现 (Codesys) 一.概述 由于客户的成本需求,客户想选择第三方的触摸屏幕和 LTI 的 MOTION ONE 进行通讯 (以太网),通讯接口选择了控制器本体的以太网接口,由于 MODBUS TCP SERVER 通讯 软件功能块不是 CODESYS 内核自有的块,需要另外购买,所以我利用 CODESYS 内部原 有的底层功能块(SYSockets.LIB)开发了一个 MODBUS TCP SERVER DEMO 程序,这样 MOTION ONE 就可以和市面上几乎所有的触摸屏进行以太网通讯了。 以下是程序配置及源代码,经过和 MODSCAN 和威伦触摸屏的实际 MODBU-TCP 通讯, 验证了这个程序的功能,这个程序支持 01,03,05,06,15,16 MODBU-TCP 读写字,读 写位功能码。 VAR_GLOBAL VIRTUALPOS: LREAL; TEST_T:INT; can_encoder_pos:UDINT; input_byte:ARRAY[1..250] OF BYTE; input_byte1:ARRAY[1..250] OF BYTE; mw_area AT %MB1000:ARRAY[1..500] OF BYTE; : ARRAY[1..512] OF BOOL; mx_area output_byte: ARRAY[1..250]OF BYTE; mw_temp AT%MW1000: ARRAY[1..500] OF INT; write_len:INT; send_do: BOOL; mw_area_use AT %MW2000:ARRAY[1..500] OF INT; ton2: TON; test_trigger: BOOL; t1: TON; receive1_tmp:BYTE; flag:BOOL; test_lreal AT%MD1000 :LREAL; EN_READ: BOOL; en_camin: BOOL; EN_CAM: BOOL; addressPointer:POINTER TO SOCKADDRESS; address:SOCKADDRESS; ip:STRING:='192.168.39.100'; (*PLC IP ADDRESS*) send:STRING:='0001t'; receive:STRING; receive1:ARRAY[1..300] OF BYTE; port: WORD:=502; (*MODBUS——TCP 端口*) objectArray:ARRAY[0..6] OF REAL; tcp_connect_state:BOOL; tcp_connect_time1:TON;
tcp_connect_time2:TON; get_last: BOOL; protocol_id:INT; device_id:INT; send1:ARRAY[1..300] OF BYTE; torque_real AT%MD2012:REAL; acttorque: LREAL; actvelocity:LREAL; virtual_speed AT %MD2016:DINT; tttt AT %MD2000:ARRAY[1..100] OF DINT; Master_axis_ref:axis_ref; switch_master:INT; start_syn:BOOL; in_syn:BOOL; end_of_profile:BOOL; END_VAR PROGRAM TCP_socket_test VAR result: BOOL; socketId: DINT; terminate: BOOL; dwValue: DINT; bResult: BOOL; test_state: BOOL; send: STRING; error_now: BOOL; time_trigger: BOOL; SysSockGetLastError1:SysSockGetLastError; MasterSocketList:SOCKET_FD_SET; SlaveSocketList:SOCKET_FD_SET; SelectTimeOut:SOCKET_TIMEVAL; TCPindex: INT; diSize: DINT; TCPMax: DINT; tcp_state: INT;
SocketHandle:DINT; move_ref: INT; END_VAR PROGRAM :TCP_socket_test address.sin_addr:=SysSockInetAddr(ip); address.sin_family:=SOCKET_AF_INET; address.sin_port:=SysSockHtons(port); addressPointer:=ADR(address); IF terminate=FALSE THEN CASE tcp_state OF 0: socketId := SysSockCreate(SOCKET_AF_INET,SOCKET_STREAM,0); IF socketId <> SOCKET_INVALID THEN dwValue := 1; (*Set the option that we can reuse 'old' port addresses *) SysSockSetOption(socketId, SOCKET_SOL, SOCKET_SO_REUSEADDR, ADR(dwValue), SIZEOF (dwValue)); tcp_state := 10; END_IF 10:bResult := SysSockBind(socketId, ADR(address), SIZEOF(address)); IF bResult THEN tcp_state := 20; END_IF 20: bResult := SysSockListen(socketId, 255); IF bResult THEN MasterSocketList.fd_count := 1; MasterSocketList.fd_array[0] := socketId; tcp_state := 30; END_IF 30: SlaveSocketList:=MasterSocketList; := SelectTimeOut.tv_sec := 30; SelectTimeOut.tv_usec := 0; diSize ADR(SelectTimeOut)); IF diSize > 0 THEN tcp_state := 50; SysSockSelect(SOCKET_FD_SETSIZE, ADR(SlaveSocketList), 0, 0,
TCPindex := 0; END_IF 50: SocketHandle := SlaveSocketList.fd_array[TCPindex]; IF SocketHandle = socketId THEN diSize := SIZEOF(Address); SocketHandle:=SysSockAccept(socketId, ADR(Address), ADR(address)); IF SocketHandle <> SOCKET_INVALID THEN TCPMax := SocketHandle; MasterSocketList.fd_array[MasterSocketList.fd_count] := SocketHandle; MasterSocketList.fd_count := MasterSocketList.fd_count + 1; END_IF tcp_state := 100; END_IF 100: (* SysSockSend(socketId,ADR(send),SIZEOF(send),1);*) SysSockRecv(SocketHandle,ADR(receive1),SIZEOF(receive1),1); FOR move_ref:=7 TO receive1[6]+7 DO input_byte1[move_ref-6] :=receive1[move_ref]; END_FOR; protocol_id:=BYTE_TO_INT(receive1[4]); device_id:=BYTE_TO_INT(receive1[7]); IF protocol_id=0 AND (*modbus_tcp,protocol_id=0*) device_id>=0 AND receive1[1]<>0 THEN frame_process(); tcp_state := 120; END_IF; 120: IF send_do THEN send1[1]:=receive1[1];send1[2]:=receive1[2]; send1[3]:=0;send1[4]:=0; send1[5]:=0;send1[6]:=INT_TO_BYTE(write_len-2); FOR move_ref:=7 TO 7+(write_len-2) DO send1[move_ref]:=output_byte[move_ref-6]; END_FOR; SysSockSend(SocketHandle,ADR(send1),(write_len-1+6),1); receive1[1]:=0; send_do:=FALSE; END_IF;
tcp_state := 100; END_CASE; END_IF; IF terminate = TRUE THEN (* close socket *) SysSockClose(socketId); socketId := 0; tcp_state:=0; result := FALSE; END_IF PROGRAM frame_process VAR length_check:INT; crc_out:WORD; crc_temp:WORD; address_temp:INT; move_to_send:INT; byte_len:INT; mod_state:INT; length_temp: INT; length_check1: INT; crc_out1: WORD; write_area:ARRAY[1..250] OF BYTE; x:INT; control_temp: WORD; offset_temp:INT; END_VAR Frame_process IF (( input_byte1[1]<16#FF) AND( (input_byte1[2]=05) OR( input_byte1[2]=6 )OR(input_byte1[2]=16)OR(input_byte1[2]=15)) THEN input_byte1[1]>=0)) AND( OR( input_byte1[2]=03 (input_byte1[2]=01) OR ) *) OR input_byte1[2]=06 OR input_byte1[2]=01 OR (*CRC16 check action IF input_byte1[2]=03 input_byte1[2]=05 THEN length_check:=6; END_IF;
IF input_byte1[2]=16 OR input_byte1[2]=15 THEN length_check:=7+input_byte1[7]; END_IF; (* crc_check( lengthcrc:= length_check, inbyte:=input_byte1, CRC16CVT=>crc_out ); crc_temp:=SHL(BYTE_TO_WORD(input_byte1[length_check+1] ),8) OR BYTE_TO_WORD(input_byte1[length_check+2] );*) ( crc_out = crc_temp<>0) AND*) (send_do =FALSE )THEN (* CRC16 check OK then the process is going on ,judge the function code to response *) IF (* CASE input_byte1[2] OF 01:(*read the coils*) output_byte[1]:=17; output_byte[2]:=01; address_temp:=SHL(BYTE_TO_INT(input_byte1[3]),8) + ( BYTE_TO_INT(input_byte1[4])); length_temp:=SHL(BYTE_TO_INT(input_byte1[5]),8) +(BYTE_TO_INT(input_byte1[6])); mod_state:=length_temp MOD 8; IF mod_state<>0 THEN byte_len:=1+length_temp/8; ELSE byte_len:=length_temp/8; END_IF; output_byte[3]:=INT_TO_BYTE(byte_len); FOR move_to_send:=4 TO byte_len+3 DO IF mod_state=0 THEN output_byte[move_to_send].0:=mx_area[address_temp+1+(move_to_send-4)*8]; output_byte[move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send].2:=mx_area[address_temp+(move_to_send-4)*8+3]; output_byte[move_to_send].3:=mx_area[address_temp+(move_to_send-4)*8+4]; output_byte[move_to_send].4:=mx_area[address_temp+(move_to_send-4)*8+5]; output_byte[move_to_send].5:=mx_area[address_temp+(move_to_send-4)*8+6]; output_byte[move_to_send].6:=mx_area[address_temp+(move_to_send-4)*8+7]; output_byte[move_to_send].7:=mx_area[address_temp+(move_to_send-4)*8+8]; ELSE IF move_to_send=byte_len+3 THEN CASE mod_state OF 1:
output_byte[move_to_send].0:=mx_area[address_temp+(move_to_send-4)*8+1];output_byte [move_to_send]:=output_byte[move_to_send] AND 16#0001; 2: output_byte[move_to_send].0:=mx_area[address_temp+(move_to_send-4)*8+1];output_byte [move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send]:=output_byte[move_to_send] AND 16#0003; 3: output_byte[move_to_send].0:=mx_area[address_temp+(move_to_send-4)*8+1];output_byte [move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send].2:=mx_area[address_temp+(move_to_send-4)*8+3]; output_byte[move_to_send]:=output_byte[move_to_send] AND 16#0007; 4: output_byte[move_to_send].0:=mx_area[address_temp+(move_to_send-4)*8+1];output_byte [move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send].2:=mx_area[address_temp+(move_to_send-4)*8+3]; output_byte[move_to_send].3:=mx_area[address_temp+(move_to_send-4)*8+4]; output_byte[move_to_send]:=output_byte[move_to_send] AND 16#000F; 5: output_byte[move_to_send].0:=mx_area[address_temp+(move_to_send-4)*8+1];output_byte [move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send].2:=mx_area[address_temp+(move_to_send-4)*8+3]; output_byte[move_to_send].3:=mx_area[address_temp+(move_to_send-4)*8+4]; output_byte[move_to_send].4:=mx_area[address_temp+(move_to_send-4)*8+5]; output_byte[move_to_send]:=output_byte[move_to_send] AND 16#001F; 6:output_byte[move_to_send].0:=mx_area[address_temp+(move_to_send-4)*8+1];output_b yte[move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send].2:=mx_area[address_temp+(move_to_send-4)*8+3]; output_byte[move_to_send].3:=mx_area[address_temp+(move_to_send-4)*8+4]; output_byte[move_to_send].4:=mx_area[address_temp+(move_to_send-4)*8+5]; output_byte[move_to_send].5:=mx_area[address_temp+(move_to_send-4)*8+6]; output_byte[move_to_send]:=output_byte[move_to_send] AND
16#003F; 7:output_byte[move_to_send].0:=mx_area[address_temp+(move_to_send-4)*8+1];output_b yte[move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send].2:=mx_area[address_temp+(move_to_send-4)*8+3]; output_byte[move_to_send].3:=mx_area[address_temp+(move_to_send-4)*8+4]; output_byte[move_to_send].4:=mx_area[address_temp+(move_to_send-4)*8+5]; output_byte[move_to_send].5:=mx_area[address_temp+(move_to_send-4)*8+6]; output_byte[move_to_send].6:=mx_area[address_temp+(move_to_send-4)*8+7]; output_byte[move_to_send]:=output_byte[move_to_send] AND 16#007F; END_CASE; ELSE output_byte[move_to_send].0:=mx_area[address_temp+1+(move_to_send-4)*8]; output_byte[move_to_send].1:=mx_area[address_temp+(move_to_send-4)*8+2]; output_byte[move_to_send].2:=mx_area[address_temp+(move_to_send-4)*8+3]; output_byte[move_to_send].3:=mx_area[address_temp+(move_to_send-4)*8+4]; output_byte[move_to_send].4:=mx_area[address_temp+(move_to_send-4)*8+5]; output_byte[move_to_send].5:=mx_area[address_temp+(move_to_send-4)*8+6]; output_byte[move_to_send].6:=mx_area[address_temp+(move_to_send-4)*8+7]; output_byte[move_to_send].7:=mx_area[address_temp+(move_to_send-4)*8+8]; END_IF; END_IF; END_FOR; length_check1:=3+byte_len; (* crc_check( lengthcrc:= length_check1, inbyte:=output_byte, CRC16CVT=>crc_out1 ); output_byte[4+byte_len]:= WORD_TO_BYTE(SHR((crc_out1 AND 16#FF00 ),8)); output_byte[5+byte_len]:= WORD_TO_BYTE(crc_out1 AND 16#FF );*) write_len:= 5+byte_len;send_do:=TRUE; 15:(*force multi coils*) address_temp:=SHL(BYTE_TO_INT(input_byte1[3]),8) + ( BYTE_TO_INT(input_byte1[4]));
分享到:
收藏