AFON//Радиотехник
C++Builder · проект 44/50

Кадр Modbus RTU

Запрос чтения регистров с CRC-16.

Задача

Сформировать кадр запроса Modbus RTU (функция 0x03) с контрольной суммой CRC-16.

Компоненты на форме

Edit (EditAddr, EditReg, EditCnt), Button (ButtonBuild), Memo (MemoOut).

Как работает

  1. Ввести адрес устройства, регистр и количество.
  2. Собрать байты кадра.
  3. Дописать CRC-16 младшим байтом вперёд.

Исходный код модуля

//---------------------------------------------------------------------------
// Проект 44. Кадр Modbus RTU
// Сборка запроса Modbus и контрольная сумма CRC-16.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------

// Формирование кадра Modbus RTU: адрес, функция, данные и CRC-16 (полином
// 0xA001). crc16_modbus — ядро, проверяется на эталонном кадре.
unsigned short crc16_modbus(const unsigned char *p, int len)
{
    unsigned short crc=0xFFFF;
    for (int i=0;i<len;i++){
        crc ^= p[i];
        for (int k=0;k<8;k++)
            crc = (crc & 1) ? (crc>>1)^0xA001 : (crc>>1);
    }
    return crc;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonBuildClick(TObject *Sender)
{
    unsigned char f[8];
    f[0]=(unsigned char)StrToIntDef(EditAddr->Text,1);      // адрес
    f[1]=0x03;                                              // чтение регистров
    int reg=StrToIntDef(EditReg->Text,0), cnt=StrToIntDef(EditCnt->Text,1);
    f[2]=reg>>8; f[3]=reg&0xFF; f[4]=cnt>>8; f[5]=cnt&0xFF;
    unsigned short crc=crc16_modbus(f,6);
    f[6]=crc&0xFF; f[7]=crc>>8;                             // младший байт первым
    AnsiString hex;
    for (int i=0;i<8;i++) hex+=IntToHex((int)f[i],2)+" ";
    MemoOut->Text = "Кадр: " + hex;
}
//---------------------------------------------------------------------------

Пояснения

  • CRC-16 Modbus использует полином 0xA001 и начальное 0xFFFF.
  • Для 01 03 00 00 00 01 сумма равна 0x0A84 — проверено тестом.
📦 help-user.ru — срочный ремонт компьютеров и восстановление данных в Москве: help-user.ru.

Что дальше

Создайте в C++Builder новый проект, разместите перечисленные компоненты и вставьте код модуля. Остальные 49 программ — в разделе проектов на C++Builder; смотрите также обзор среды и контроллеры AVR.