PDA

Просмотр полной версии : сетевой протокол овен по Rs-485. рассчет Crc.



Танец Ветра
04.10.2010, 14:01
Устройство - МВ110-224.16ДН
Сетевой адрес устройства: 0х38 (56dec)
Запрос параметра: r.Cn (нигде, кстати, не указано, что для хеш-свертки этого параметра надо добавить пробел. нашли методом "научного тыка")
У нас формируется следующая последовательность байтов: 0x38, 0x10, 0x2D, 0x26
CRC этого пакета: 0x1A80 (используя тот же алгоритм, что и для хеш-свертки)
При кодировании в символы получается следующая последовательность: JOHGITIMHQOG (начало и конец пакета я опустил)

CRC, формируемый вашей программой "Конфигуратор М110" почему-то PNSN.
Мы не можем уяснить, с какого пакета вы берете CRC, чем они у нас отличаются?
Т.е. у нас пакет запроса выглядит как JOHGITIMHQOG, а ваш JOHGITIMPNSN. Как?
Почему HASH параметра совпадает, а CRC разнятся, если они вычисляются по одному и тому же алгоритму?

Может, есть бОлее новое описание протокола ОВЕН? Мы использовали это: http://www.owen.ru/uploads/type_prot_owen.zip

485я сеть подключена к компьютеру:
Компьютер -> RS-232 -> автомат.конвертор (232 <-> 485) -> 485 сеть -> модули. Вышеуказанный ваш конфигуратор отлично работает по этой сети, а моя программа (Delphi) ну никак. стали анализировать пакеты вашего программатора, и возникли вопросы по расчету CRC.

На всякий случай приведу листинг фунции, рассчитывающей HASH и CRC:

function oHASH(m: array of byte): word;
// функция расчета HASH-свертки по ОВЕНу
type Tword_s = record
case boolean of
True: (bw: word);
False: (bb: array [0..1] of byte);
end;

var i,j: integer; // cycle
tmp1, tmp2: byte;
tmp3: Tword_s;
begin
Result:=0;
for i:=0 to High(m) do
begin
tmp1:=m[i];
for j:=0 to 6 do
begin
tmp1:= tmp1 shl 1;
tmp3.bw:=Result;
tmp2:=tmp3.bb[1] xor tmp1;
if (tmp2 and $80)>0 then Result:=(Result shl 1) xor $8F57 else Result:=Result shl 1;
end;
end;
end;

Малышев Олег
05.10.2010, 09:21
протокол овен под виндовс программировать не нужно!!! используте Dll!!!
все грабли уже пройдены за вас!!! пример на дельфи приложен.

yugog
05.10.2010, 14:33
Пример расчета CRC на QT. Списан откуда-то с форума и подточен для QT. Я думаю будет полезен.
Еще можно глянуть здесь: http://code.google.com/p/mdvvconf/

QByteArray ModbusFunction::getCRC16Owen(QByteArray _data)
{
int i, j;
unsigned short crc;
crc = 0x0000;
for (i = 0; i < _data.size(); i++)
{
unsigned char b = _data[i];
for (j = 0; j < 8; ++j, b <<= 1)
{
if ((b ^ (crc >> 8)) & 0x80)
{
crc <<= 1;
crc ^= 0x8F57;
}
else
crc <<= 1;
}
}
unsigned char crcH = crc >> 8;
unsigned char crcL = crc & 255;
QByteArray res;
res.append(crcH);
res.append(crcL);
return res;
}

Танец Ветра
06.10.2010, 11:16
Вопрос решил использованием owen_io.dll
Однако, и там сходу на косяк нарвался. В описании функции чтения беззнакового целого написано:
function ReadUInt(adr_type,adr: DWORD;command:PChar;var value: DWORD;index:Integer): Integer;
Т.е. тип адресации сначала, а затем адрес. Более того, и в исходниках для Delphi - то же. После нескольких попыток установить связь с прибором, ненормативной лексики, и почти принятого решения отказаться от использования продукции ОВЕН, случайно обратил внимание, что в описании для других языков программирования сначала идет адрес, а потом тип адресации. Ознакомился с другими схожими функциями (ReadSInt, ReadFloat24 и т.д.) - адрес первый. Поменял местами адрес и тип адресации - и все заработало.
Будьте осторожны. Для себя я уже усвоил: на техническую документацию ОВЕНа 100% полагаться нельзя

Малышев Олег
06.10.2010, 14:55
действительно, есть такая ошибка. приносим свои извинения.

EFrol
18.10.2010, 19:48
будьте осторожны. для себя я уже усвоил: на техническую документацию овена 100% полагаться нельзя

абсолютно согласен!!! при досканальном изучении техдокументации на любое устройство или по 1 - 2 %% неточностей, опечаток, несоответсвий описанной функциональности к реализованной и т.д.
зайдешь с вопросом на форум, а боги его твердят "читайте документацию". :d

EFrol
19.10.2010, 14:02
На всякий случай пример функций на VB для расчета CRC пакета и хэш-кода для имени параметра. Про пробелы не забывайте! Должно быть 4-е символа, кроме "." (ее считать не надо).

Public Function Hash(Value As String, isName As Boolean) As Long
Dim iBit As Byte
Dim vByte As Long
Dim i As Integer

Hash = 0

For i = 1 To Len(Value)
If isName Then
vByte = ByteCode(UCase(Mid(Value, i, 1)))
If Mid(Value, i + 1, 1) = "." Then
vByte = vByte + 1
i = i + 1
End If
vByte = vByte * 2
Else
vByte = Asc(Mid(Value, i, 1))
End If

For iBit = 1 To IIf(isName, 7, 8)
If Int((vByte Xor Int(Hash / 256)) / 128) > 0 Then
Hash = (Hash * 2) Mod 65536
Hash = (Hash Xor 36695) Mod 65536
Else
Hash = (Hash * 2) Mod 65536
End If
vByte = (vByte * 2) Mod 256
Next
Next
End Function

Public Function ByteCode(vByte As String) As Byte
Select Case vByte
Case "0" To "9": ByteCode = Asc(vByte) - Asc("0")
Case "A" To "Z": ByteCode = Asc(vByte) - Asc("A") + 10
Case "-": ByteCode = 36
Case "_": ByteCode = 37
Case "/": ByteCode = 38
Case " ": ByteCode = 39
End Select
ByteCode = ByteCode * 2
End Function