1. Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
  2. Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
  3. Не писать свой вопрос в первую попавшуюся тему - вместо этого создать новую тему.
  4. За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения.
  5. Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
  6. Перед тем как что-то написать - читать здесь и здесь, а студентам - обязательно здесь.
  7. Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.

CRC Modbus, Autonocs TM4, Delphi

RS-485, ProfiBUS, 4-20 mA, Wi-Fi, GSM и так далее
Ответить

Автор темы
grizzly
Сообщения: 1
Зарегистрирован: 12 июн 2015, 12:04
Имя: Расулов Ф.С.
Страна: Россия
город/регион: Курган

CRC Modbus, Autonocs TM4, Delphi

Сообщение grizzly »

Добрый день всем! Пишу программу на delphi, которая общается по протоколу Modbus. Вроде все получается, пока не столкнулся с любопытным моментом... Привожу алгоритм расчета crc

Код: Выделить всё

CONST crctab: ARRAY[0..255] OF WORD = (
    $0000, $C0C1, $C181, $0140, $C301, $03C0, $0280, $C241,
    $C601, $06C0, $0780, $C741, $0500, $C5C1, $C481, $0440,
    $CC01, $0CC0, $0D80, $CD41, $0F00, $CFC1, $CE81, $0E40,
    $0A00, $CAC1, $CB81, $0B40, $C901, $09C0, $0880, $C841,
    $D801, $18C0, $1980, $D941, $1B00, $DBC1, $DA81, $1A40,
    $1E00, $DEC1, $DF81, $1F40, $DD01, $1DC0, $1C80, $DC41,
    $1400, $D4C1, $D581, $1540, $D701, $17C0, $1680, $D641,
    $D201, $12C0, $1380, $D341, $1100, $D1C1, $D081, $1040,
    $F001, $30C0, $3180, $F141, $3300, $F3C1, $F281, $3240,
    $3600, $F6C1, $F781, $3740, $F501, $35C0, $3480, $F441,
    $3C00, $FCC1, $FD81, $3D40, $FF01, $3FC0, $3E80, $FE41,
    $FA01, $3AC0, $3B80, $FB41, $3900, $F9C1, $F881, $3840,
    $2800, $E8C1, $E981, $2940, $EB01, $2BC0, $2A80, $EA41,
    $EE01, $2EC0, $2F80, $EF41, $2D00, $EDC1, $EC81, $2C40,
    $E401, $24C0, $2580, $E541, $2700, $E7C1, $E681, $2640,
    $2200, $E2C1, $E381, $2340, $E101, $21C0, $2080, $E041,
    $A001, $60C0, $6180, $A141, $6300, $A3C1, $A281, $6240,
    $6600, $A6C1, $A781, $6740, $A501, $65C0, $6480, $A441,
    $6C00, $ACC1, $AD81, $6D40, $AF01, $6FC0, $6E80, $AE41,
    $AA01, $6AC0, $6B80, $AB41, $6900, $A9C1, $A881, $6840,
    $7800, $B8C1, $B981, $7940, $BB01, $7BC0, $7A80, $BA41,
    $BE01, $7EC0, $7F80, $BF41, $7D00, $BDC1, $BC81, $7C40,
    $B401, $74C0, $7580, $B541, $7700, $B7C1, $B681, $7640,
    $7200, $B2C1, $B381, $7340, $B101, $71C0, $7080, $B041,
    $5000, $90C1, $9181, $5140, $9301, $53C0, $5280, $9241,
    $9601, $56C0, $5780, $9741, $5500, $95C1, $9481, $5440,
    $9C01, $5CC0, $5D80, $9D41, $5F00, $9FC1, $9E81, $5E40,
    $5A00, $9AC1, $9B81, $5B40, $9901, $59C0, $5880, $9841,
    $8801, $48C0, $4980, $8941, $4B00, $8BC1, $8A81, $4A40,
    $4E00, $8EC1, $8F81, $4F40, $8D01, $4DC0, $4C80, $8C41,
    $4400, $84C1, $8581, $4540, $8701, $47C0, $4680, $8641,
    $8201, $42C0, $4380, $8341, $4100, $81C1, $8081, $4040 );
function crc16(twoSym:array of Word; size:Word):Word;
var
 i:Integer;
 crc:Word;
begin
  crc:=$FFFF;
 for i:=0 to ((size div 2)-1) do
  begin
    crc:=  (crc shr 8) xor CrcTab[(crc and $FF) xor twoSym[i]];
  end;
   Result:=(crc shr 8) or (crc shl 8);
end;

function ByteToDecInt(Value: String): Integer;
const hex:array['A'..'F'] of Word=(10,11,12,13,14,15);
var
 Int,i:Integer;
begin
If value<>'' then
 begin
   Int:=0;
       for i := 1 to Length(Value) do
        if Value[i] < 'A' then Int := Int * 16 + ORD(Value[i]) - 48
        else Int := Int * 16 + HEX[Value[i]];
   Result:=int;
 end;
end;

function crccontrol(paket:string):boolean;
var
bx: array[1..50] of Word;
i,j:integer;
crc:Word;
crckont:string;
begin
 If paket<>'' then
 begin
   j:=1;
     for i := 1 to Length(paket) do
     begin
       bx[i]:=ByteToDecInt(paket[j]+paket[j+1]);
       j:=j+2;
     end;
     crc:= crc16(bx, Length(paket)-4);
 bx[20]:=crc;
 bx[21]:=ByteToDecInt(paket[Length(paket)-3]+paket[Length(paket)-2]+paket[Length(paket)-1]+paket[Length(paket)]);

If bx[20]=bx[21] then
 Result:=true
else
 Result:=false;
 end;
end;

В общем суть такая, отправляю код на чтение данных с регистров типа "010300000001CRC", CRC рассчитывается по данному алгоритму - пакет уходит, приходит ответ - расшифровываю показания - все гуд. Чтения данных датчиков типа "010403E80001CRC", получаю ответ - все гуд. Пытаюсь задать температуру "010603E803E8(0904)" CRC рассчиталось как 0904. Получаю ответ "0106000003E8(095C)" и тут при проверке CRC возникает ошибка! 095С не верное CRC... Пробую отправить другой пакет "0106000003E8(4F18)" получаю ответ "0106000003E8(4F5С)" - что тоже вызывает ошибку проверки CRC... При этом - устройство получает команду, выполняет ее, т.е. мой расчет crc верен, иначе бы устройство не среагировало на команду... Узнаю об этом считывая регистр мощности - "010300010001CRC"... В чем может быть собака зарыта??? У меня дым из головы уже...
Ответить

Вернуться в «Интерфейсы, протоколы, связь»