CODESYS 2.3
Modbus RTU Slave 实现(Syscomlib libaray)
PLC PRG(MAIN PROGRAM)
SM320_STATUS:=%IX4.0;
IF NOT sm320_status THEN
CASE i_state OF
0:CS.dwBaudRate:=19200;
cs.byParity:=2;
cs.byStopBits:=1;
cs.cByteSize:=8;
cs.dwBufferSize:=0;
COM_OPEN:=SysComOpen(COM_PORT_EXT_RS4XX + COM_PORT_EXT_ADDR0+ COM_PORT_EXT_UPPER );
IF COM_OPEN <> INV ALID_HANDLE AND COM_OPEN <> 0 THEN
(* For the module SM230/A *)
SysComSetMode(COM_OPEN, COM_MODE_RS485_ENABLE);
(* Configure the COM-Port, Baudrate, Port, ... *)
SettingsOK := SysComSetSettingsEx(COM_OPEN,ADR(cs));
IF SettingsOK THEN
i_state:=10;
ELSE
i_state:=99;
END_IF;
END_IF;
10:
(*read data*)
IF COM_OPEN <> INV ALID_HANDLE AND COM_OPEN <> 0 THEN
read_act:=SysComRead(com_open,ADR(input_byte),SIZEOF(input_byte),0);
input_byte1:=input_byte;
IF read_act<>INV ALID_HANDLE THEN
(* ton1(in:=flag_rec,pt:=t#5ms);
IF ton1.Q THEN*)
frame_process();
IF send_do THEN
i_State := 20;
ELSE
i_state:=15;
(* END_IF;*)
END_IF;
ELSE
i_state:=99;
END_IF;
END_IF;
15:
i_State := 10;
20: (*write data*)
IF COM_OPEN <> INV ALID_HANDLE AND COM_OPEN <> 0 AND send_do=TRUE THEN
read_act1:=SysComWrite(COM_OPEN, ADR(output_byte),write_len,0);
i_State := 10;
send_do:=FALSE;
FOR i:=1 TO 10 DO
input_byte[1]:=0;
END_FOR;
ELSE
i_state:=99;
END_IF;
99:SysComClose(com_open);
com_open := 0;
i_State := 0;
END_CASE;
END_IF;
(*IF crc_cal THEN
crc_checka( lengthcrc:= length_checka,
inbyte:=test_crc,
CRC16CVT=>crc_outa );
END_IF;*)
Frame process: (sub program)
IF (( input_byte1[1]<16#FF) AND( input_byte1[1]>0)) AND( (input_byte1[2]=01) OR (input_byte1[2]=05) OR( input_byte1[2]=03 ) OR( input_byte1[2]=6 )OR(input_byte1[2]=16)) THEN
(*CRC16 check action *)
IF input_byte1[2]=03 OR input_byte1[2]=06 THEN
length_check:=6;
END_IF;
IF input_byte1[2]=16 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] );
(* CRC16 check OK then the process is going on ,judge the function code to response *)
IF ( crc_out = crc_temp<>0) AND (send_do =FALSE )THEN
CASE input_byte1[2] OF
03:
output_byte[1]:= input_byte1[1]; output_byte[2]:=03;
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]));
output_byte[3]:=INT_TO_BYTE((length_temp)*2);
FOR move_to_send:=address_temp TO address_temp+(length_temp)*2 DO
output_byte[4+move_to_send-address_temp]:=mw_area[move_to_send+address_temp+1];
END_FOR;
length_check1:=3+(length_temp)*2;
crc_check( lengthcrc:= length_check1,
inbyte:=output_byte,
CRC16CVT=>crc_out1 );
output_byte[4+(length_temp)*2]:= WORD_TO_BYTE(SHR((crc_out1 AND 16#FF00 ),8));
output_byte[5+(length_temp)*2]:= WORD_TO_BYTE(crc_out1 AND 16#FF );
write_len:= 5+(length_temp)*2;send_do:=TRUE;
16:
FOR move_to_send:=1 TO 6 DO
output_byte[move_to_send]:=input_byte1[move_to_send];
END_FOR;
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]);
FOR move_to_send:=address_temp TO address_temp+(length_temp)*2-1 DO
mw_area[move_to_send+address_temp+1]:=input_byte1[8+move_to_send-address_temp];
END_FOR;
length_check1:=6;
crc_check( lengthcrc:= length_check1,
inbyte:=output_byte,
CRC16CVT=>crc_out1 );
output_byte[7]:= WORD_TO_BYTE(SHR((crc_out1 AND 16#FF00 ),8));
output_byte[8]:= WORD_TO_BYTE(crc_out1 AND 16#FF );
write_len:= 8;send_do:=TRUE;
06:
FOR move_to_send:=1 TO 8 DO
output_byte[move_to_send]:=input_byte1[move_to_send];
END_FOR;
address_temp:=SHL(BYTE_TO_INT(input_byte1[3]),8)+
BYTE_TO_INT(input_byte1[4]);
mw_area[address_temp*2+1]:=input_byte1[5];mw_area[address_temp*2+2]:=input_byte1[6];
write_len:= 8;send_do:=TRUE;
END_CASE;
END_IF;
END_IF;
Crc_check: (Function block)
(*CRC16 check *)
crctmp := 16#FFFF;
FOR crci:= 0 TO (lengthcrc - 1) DO
crctmp:= crctmp XOR inbyte[crci];
FOR crcj:= 1 TO 8 DO
tempcrc:=1 AND crctmp;
crctmp :=SHR( crctmp ,1);
IF tempcrc = 1 THEN
crctmp:= crctmp XOR 16#A001 ;
END_IF;
END_FOR;
END_FOR;
lcrc := SHL((crctmp AND 16#FF) , 8);
hcrc:=SHR( (crctmp AND 16#FF00) , 8);
CRC16CVT:= lcrc OR hcrc;