
Сообщение от
polubencev
Вот смотрите, через modscan64 пытаешься ТРМ считать, не получается. Там адреса с 4хххх. Например через Овен ОРС, указываешь 4105 все идет
modscan64 платная программа и даже воспроизвести эксперимент не каждый сможет.
Для изучения работы с Modbus читал уставку в ТРМ212 самописным тестовым кодом на FreePascal с использованием библиотеки работы с COM-портом Synaser
Обратите внимание, что после приёма значения из порта, для адекватного вывода на печать приходилось выполнять обмен байт в принятом 16 или 32 разрядном числе.
Кроме того, число типа Float занимает 2 регистра и не может быть типом MW, скорее уж MD - DWORD.
Код:
MB_ReadUInt16(ser, ModBusSetting_Addr, trm212SP, uiR);
Writeln(uiR);
Sleep(100);
MB_ReadSignedInt16(ser, ModBusSetting_Addr, trm212SP, siR);
Writeln(siR);
Sleep(100);
MB_ReadFloat32(ser, ModBusSetting_Addr, trm212SP_, fR);
Writeln(fR: 0: 1);
Sleep(100);
MB_ReadChar8(ser, ModBusSetting_Addr, trm212DEV, cR);
Writeln(cR);
Sleep(100);
MB_ReadChar8(ser, ModBusSetting_Addr, trm212VER, cR);
Writeln(cR);
Сама функция чтения была обёрткой над вызовом функции 03
Код:
function MB_ReadUInt16(var SerialPort: TBlockSerial; DevAddr, RegNo: word;
var R: UInt16): integer;
begin
Result := MB_ReadRegesters(SerialPort, DevAddr, RegNo, 1, R);
R := Swap(R);
end;
function MB_ReadFloat32(var SerialPort: TBlockSerial; DevAddr, RegNo: word;
var R: Float32): integer;
var
t: TDWordConvert;
begin
Result := MB_ReadRegesters(SerialPort, DevAddr, RegNo, 2, t);
t.dw := Swap(t.dw);
t.w0 := Swap(t.w0);
t.w1 := Swap(t.w1);
R := t.f32;
end;
Вызов функции 03
Код:
function MB_ReadRegesters(var SerialPort: TBlockSerial;
DevAddr, RegNo, RegCount: word; var ResBuffer): integer;
var
Buffer: TBuffer;
crc16: word;
i: integer;
ReadLen: word;
begin
if not SerialPort.InstanceActive then
begin
//ComException('can not read from a closed port.');
exit;
end;
if (DevAddr > 247) then
begin
if DevAddr > 40000 then
DevAddr := DevAddr - 40001
else
exit;
end;
{
Запрос
00 - адрес устройства
01 - функция
02 - адрес первого из группы считываемых регистров hi
03 - то же, lo
04 - количество считываемых регистров hi
05 - то же, lo
06 - crc16 lo
07 - то же hi
}
Buffer[0] := lo(DevAddr);
Buffer[1] := $03;
Buffer[2] := hi(RegNo);
Buffer[3] := lo(RegNo);
Buffer[4] := hi(RegCount);
Buffer[5] := lo(RegCount);
crc16 := Crc16InitValue;
for i := 0 to 5 do
Crc16 := UpdateCrc16(Buffer[i], crc16);
Buffer[6] := lo(crc16);
Buffer[7] := hi(crc16);
SerialPort.SendBuffer(@Buffer, 8);
SerialPort.RecvBufferEx(@Buffer, RegCount * 2 + 5, Timeout_1s div 10);
{
Ответ в корректном случае
00 - адрес устройства
01 - функция
02 - количество байт в ответных данных
03 - данные lo
04 - данные hi
05 - CRC16 lo
06 - CRC16 hi
В случае ошибки
или таймаут
или устройство пришлёт
00 - адрес устройства
01 - (=$83) код функции с установленным старшим битом
02 - код ошибки (exception code)
03 - lo crc16
04 - hi crc16
}
if Buffer[01] = $83 then
begin
ReadLen := 5;
end
else
begin
ReadLen := Buffer[2] + 3;
end;
Crc16 := Crc16InitValue;
for i := 0 to ReadLen - 1 do
Crc16 := UpdateCrc16(Buffer[i], crc16);
if Crc16 <> Buffer[ReadLen] + 256 * Buffer[succ(ReadLen)] then
begin
//ошибка приёма пакета - не правильный crc16
end
else
begin
//writeln('CRC16 Ok');
end;
if RegCount * 2 = Buffer[02] then
begin
move(Buffer[3], TBuffer(ResBuffer), RegCount * 2);
end
else
begin
//ошибка приёма пакета - не правильное количество принятых байт
end;
Result := SerialPort.LastError;
end;
При этом, адреса регистров задавались в 16-ричной системе счисления
Код:
{LvoP. Оперативные параметры (только чтение: Modbus-функция 0x03)}
trm212STAT = $0000; {binary}
trm212PV1 = $0001; {Signed Int16}
trm212PV2 = $0002; {Signed Int16}
trm212LUPV = $0003; {Signed Int16}
trm212SP = $0004; {Signed Int16} {запись: Modbus-функция 0x10}
trm212SET_P = $0005; {Signed Int16}
trm212O = $0006; {Int16}
{LvoP. Рабочие параметры прибора (чтение: Modbus-функция 0x03), запись: Modbus-функция 0x10}
trm212r_L = $0007; {Int16}
trm212r_out = $0008; {Signed Int16}
trm212R_S = $0009; {Int16}
trm212AT = $000A; {Int16}
{LvoP. Оперативные параметры прибора только чтение: Modbus-функция 0x03)}
trm212DEV = $1000; {Char[8]}
trm212VER = $1004; {Char[8]}
trm212STAT_ = $1008; {binary}
trm212PV1_ = $1009; {Float32}
trm212PV2_ = $100B; {Float32}
trm212LUPV_ = $100D; {Float32}
trm212SP_ = $100F; {Float32}
trm212SET_P_ = $1011; {Float32}
trm212O_ = $1013; {Float32}