📄 rtu_client.pl
字号:
use Win32::SerialPort 0.19;
use XML::Simple;
use crctable;
use strict;
###### Andrzej Sokulski WWW.MODBUS.PL#######
##################### reading configuration from xml file #################################
my $xmlfile = 'rtu_config.xml'; #Configuration file
my $xs1 = XML::Simple->new();
my $doc = $xs1->XMLin($xmlfile)
or die "Modbus client : problem with congig file: $xmlfile\n";
my $slave_add = $doc->{REGISTERS}->{SLAVEADDR};
my $start_add = $doc->{REGISTERS}->{STARTADDR} - 1;
my $quantity = $doc->{REGISTERS}->{QUANTITY};
my $polls_time = $doc->{REGISTERS}->{POLLSTIME};
my $nr_of_polls = $doc->{REGISTERS}->{NROFPOLLS};
my $data_format = $doc->{REGISTERS}->{DATAFORMAT};
my $com_port = $doc->{SERIALPORT}->{COMPORT};
my $baud = $doc->{SERIALPORT}->{BAUD};
my $parity = $doc->{SERIALPORT}->{PARITY};
my $stop_bits = $doc->{SERIALPORT}->{STOPBITS};
my $timeout = $doc->{SERIALPORT}->{TIMEOUT};
my $data_bits = $doc->{SERIALPORT}->{DATABITS};
my $pack_val = unpack("H*",pack("n",$start_add));
my $msg_count = 0;
my $pass;
$quantity < 256 or die "Nr of registers must be less or equal 255\n";
#################### end of configurations #############################################
#################### Modbus frame #######################################################
my @buffor = ();
$buffor[0] = chr($slave_add);
$buffor[1] = chr(3);
$buffor[2] = chr(hex (substr $pack_val, 0, 2));
$buffor[3] = chr(hex (substr $pack_val, 2, 2));
$buffor[4] = chr(0);
$buffor[5] = chr($quantity);
##################### end of Modbus frame ###############################################
##################### CRC ###############################################################
my $i;
my $index;
my $Length = 6;
my $crc_Low = 0xFF;
my $crc_High = 0xFF;
for ($i = 0; $i<$Length; $i++)
{
our @crc_table;
$index = ($crc_High ^ ord($buffor[$i]));
$crc_High = $crc_Low ^ $crc_table[$index] ;
$crc_Low = $crc_table[$index + 256];
}
$buffor[6] = chr($crc_High);;
$buffor[7] = chr($crc_Low);
##################### end of CRC ########################################################
##################### serial port configuration #########################################
my $serial_port = new Win32::SerialPort($com_port) or die "Can't start $com_port";
$serial_port->databits($data_bits) or die "$com_port data bits settings error\n";
$serial_port->baudrate($baud) or die "$com_port baud rate settings error\n";
$serial_port->parity($parity) or die "$com_port parity settings error\n";
$serial_port->stopbits($stop_bits) or die "$com_port stop bits settings error\n";
$serial_port->read_interval(10) or die "$com_port read interval settings error\n";
$serial_port->read_const_time($timeout) or die "$com_port timeout settings error\n";
$serial_port->error_msg(1); # use built-in error messages
$serial_port->user_msg(1);
$serial_port->write_settings or die "$com_port settings error\n";
sleep 1;
##################### end of serial port configuration ##################################
while ( $msg_count < $nr_of_polls){
my $data = join('',@buffor); #Modbus frame to scalar
$pass=$serial_port->write($data)
or warn "Modbus client : problem with send: $!\n";
my ($count, $data) = $serial_port->read($quantity*2 + 5 );
if ($count != $quantity*2 + 5){
if ($count == 0)
{print "Modbus timeout \n";}
else
{print "Wrong response from slave \n";}
}else{
my $i;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
print "\n $hour:$min:$sec >> [$msg_count] New data from slave nr $slave_add \n";
for ($i = 0; $i < (length( $data ) - 5)/2;$i++){
my $hex = substr $data, $i*2+3, 2;
if ($data_format eq "HEX"){
$hex = unpack "H*", $hex;
}
else {
$hex = unpack "n", $hex;
}
my $regadd = 400001 + $start_add + $i;
print " $regadd : [$hex] \n";
}
}
$msg_count++;
sleep $polls_time;
}
$serial_port->close;
undef $serial_port;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -