Мой Kbyte.Ru
Рассылка Kbyte.Ru
Группы на Kbyte.Ru
Партнеры Kbyte.Ru
Реклама
Сделано руками
Сделано руками
> Статьи - Ярослав (comexe) Филипченко -

Delphi - Железо и устройства

Все статьи / Железо и устройства

Работа с протоколом Modbus RTU в среде Delphi 7

Автор: Ярослав (comexe) Филипченко | добавлено: 05.05.2014, 15:12 | просмотров: 8528 (1+) | комментариев: 15 | рейтинг: *x7

Введение

 

Данная статья является продолжением статьи, написанной год назад с той разницей, что программирование производится в среде компилятора Delphi 7. C предыдущей статьей Вы можете ознакомиться по адресу: http://kbyte.ru/ru/Programming/Articles.aspx?id=77&mode=art

 

С практической точки зрения будет рассматриваться тот же прибор компании ОВЕН МВ110-2А.

 

Написание кода

 

Существует несколько ньюансов программирования компилятора, настолько существенных, что код, в отличие от VB6 существенно усложняется. Сложность заключена в необходимости преобразования типов данных. К этому вопросу вернемся чуть позже, а для начала начнем формировать дейтаграмму для отправки в порт. Я нашел хороший табличный метод нахождения контрольной суммы:

 

 

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;

 

Как видно, всё просто. Возвращаемое значение этой функции Word. Запомним это.

 

Тип данных, который наиболее приближен к пользователю – это String. Компилятор же оперирует в основном символьными и численными типами: Integer, Byte, Word. Наша программа потребует несколько разных преобразований:

 

//вспомогательная функция преобразования типов String в Byte

 function StrToByte(p1:string):integer;

const hex:array['A'..'F'] of Word=(10,11,12,13,14,15);

var

 Int,i:Integer;

begin

   Int:=0;

       for i := 1 to Length(P1) do

        if P1[i] < 'A' then Int := Int * 16 + ORD(P1[i]) - 48

        else Int := Int * 16 + HEX[p1[i]];

   Result:=int;

end;

 

{делает из строки String массив Array of Char}

Procedure AssignFixedString( Var FixedStr: Array of Char; Const S: String);

Var

maxlen: Integer;

Begin

maxlen := succ(High( FixedStr ) - Low( FixedStr ));

FillChar( FixedStr, maxlen, ^@ ); { заполняем массив NULL-ами }

If Length(S) > maxlen Then

Move( S[1], FixedStr, maxlen )

Else

Move( S[1], FixedStr, Length(S));

End;

 

 

С преобразованием типов закончили. Теперь необходимо в закладку ActiveX среды Delphi7 добавить MSComm, поскольку работать придется через него. Обязательно установить в свойствах нужную скорость, InputMode = 0 – comInputModeText, NullDiscard = True. Всё, теперь пишем процедуру, например можно привязать к кнопке или же к таймеру:

 

Var

  crc: Word;

  i,j,k,l,m,n: Integer;

  b: array[1..100] of Word;

  frame, decoded, ansdec, dagramm :string;

  hexframe: array of byte;

  answer: string;

  ansarray:array[1..7] of char;

begin

  If edit1.text = '' Then

    ShowMessage('Поле данных пусто!')

  Else

    Begin

      j:=1;

     for i := 1 to Length(edit1.Text) do

     begin

       b[i]:=StrToByte(edit1.Text[j]+edit1.Text[j+1]);

       j:=j+2;

     end;

     crc:= crc16(b, Length(edit1.Text));

     frame :=edit1.Text + IntToHex(crc,4);//создали строковую переменную и прикрепили к ней ее CRC

SetLength(hexframe, Length(frame) div 2);//забиваем массив данными попарно:

  k := 1;

  for l := 0 to High(hexframe) do begin

    hexframe[l] := StrToInt( '$' + Copy(frame, k, 2) );//преобразовали строку frame в массив данных hexframe

    k := k + 2;

  end;

for m := low(hexframe) to high(hexframe) do

decoded:=decoded +' '+IntToHex (Ord(hexframe [m]),2);

edit2.Text :=decoded;

mscomm1.PortOpen :=true;

mscomm1.Output :=hexframe; //шлем готовый массив в порт RS

answer:=mscomm1.input;  // принимаем данные из порта RS

mscomm1.PortOpen :=false;

{данные, полученные из mscomm32 имеют тип OleVariant

поэтому их нельзя просто взять и преобразовать в массив для дальнейшей обработки. Мы

воспользовались функцией:}

assignfixedstring(ansarray,answer);

 label2.Caption :=inttostr(length(answer));

  for n := low(ansarray) to high(ansarray) do

dagramm := dagramm+' '+IntToHex(ord(ansarray[n]),2);//дешифруем полученный массив в строку

    if  length(answer)=6 then ansdec := inttostr(ord(ansarray[4]))

   else if  length(answer)=7 then ansdec := inttostr((ord(ansarray[4])*256)+ord(ansarray[5]))

    else ansdec :='n/a';

 edit3.Text :=dagramm;

 label5.Caption := ansdec+ '°C';

    End;

end;

 

Где edit1.text это строка для ввода пользователем дейтаграммы Modbus RTU в шестнадцатиричном формате. Для нашего прибора вводим 100300010001. Edit2.text показывает вид отправляемой дейтаграммы. Edit3.text – показывает вид принятого ответа от прибора. Label5.Caption показывает преобразованный в пользовательский вид ответ от прибора.

 

Как видим, писать программу для работы с протоколом Modbus RTU под Delphi7 совсем несложно. К этому добавляются дополнительные возможности компилятора, гибкость среды, удобство развертывания. Комментарии интересующихся приветствуются.

+ Добавить в избранное
    ? Помощь
Об авторе

Ярослав (comexe) Филипченко

Инженер по промышленной автоматизации

См. также:
Профиль автора
Ярослав (comexe) Филипченко
Последние комментарии (всего: 15)

Добавлять комментарии могут только зарегистрированные пользователи сайта.
Если у Вас уже есть учетная запись на Kbyte.Ru, пройдите процедуру авторизации OpenID.
Если Вы еще не зарегистрированы на Kbyte.Ru - зарегистрируйтесь.

не получается прочитать по данному примеру с Модуль ввода сигналов тензодатчиков МВ110-224.1ТД. Смотрю программой программой (serial port monitor) данные отправляются корректно через преобразователь moxa 1250.
Запрос шлю как 1003003E0002 в ответ ничего все по нулям. Не подскажите в чем проблема. Заранее благодарен за любую помощь т.к сам новичек в делфи 7
Похоже, что неправильно сформирован запрос. Ответ хоть какой-то приходит?
Если ответа нет, но данные отправляются корректно, значит неверно указан адрес МВ110
Здравствуйте Ярослав. Будьте любезны отправьте проект в delphi 7 на эту почту syrmax@gmail.com. Заранее благодарю.
Вроде отправил. Гуголевский спам пару раз зарубил отправку письма. Если письмо не пришло, попробуй грузануть с облака: https://cloud.mail.ru/public/a237be6624dd%2FMV110-2A%20Delphi.rar
Все комментарии (всего: 15)
Авторизация
 
OpenID
Зарегистрируйся и получи 10% скидку на добавление своего сайта в каталоги! Подробнее »
Поиск по сайту
Реклама
Счетчики