Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
slavka_online
1 / 1 / 0
Регистрация: 06.11.2012
Сообщений: 102
#1

Как правильно создать ModBus ASCII запрос? - C++

26.01.2016, 12:38. Просмотров 441. Ответов 7
Метки qt (Все метки)

Адрес - 26
Код функции 03h
начало - 0000
Количество -0004

расчет LRC
C++ (Qt)
1
2
3
4
5
6
7
8
9
char calculateLRC( char b[], int n){
          char lrc = 0x00;
         for (int i = 1; i < n; i++)
         {
             lrc = ( char)((lrc + b[i]) & 0xFF);
         }
         lrc = ( char)(((lrc ^ 0xff) + 1) & 0xFF);
         return lrc;
 }
как я понял мне нужно передать что то вроде этого ":260300000004<LRC>0D0A"

но как это организовать в коде я не могу понять, вроде бы надо брать по одному символу, получать его hex представление и отправлять
но как в таком виде считать контрольную сумму и как получить hex представление
если (int)'2' возвращает 50 вместо 0х32

Добавлено через 1 час 22 минуты
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
 std::string cmd = ":260300000004";
    QByteArray buffer;
    for (int i = 0; i < cmd.length(); i++)
         buffer += cmd[i];
 
    char lrc = calculateLRC(buffer);
 
    buffer += lrc;
    buffer += 0x0D;
    buffer += 0x0A;
 
    int res = serialport->write(buffer);
    ui->textBrowser->setText(QString::number(res));
попробовал вот так, но прибор не отвечает мне
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.01.2016, 12:38     Как правильно создать ModBus ASCII запрос?
Посмотрите здесь:
C++ Builder Как отправить запрос и получить правильно СОМ-порт
C++ Как правильно проверить на запрос подключения к серверу (select)
C++ Builder Как правильно создать окно MCI?
Как правильно создать двумерный массив? C++
C++ Как правильно создать динамическим массивом
Как правильно создать свою DLL ? C++
C++ Как правильно создать глобальную переменную?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
26.01.2016, 19:30     Как правильно создать ModBus ASCII запрос? #2
slavka_online, в приведенном коде cmd - в строковом представлении, а отсылать нужно в бинарном.
Но исходя из того что вы создали Как из числа 0Fh получить "0F" ? вы это уже поняли.

Для начала попробуйте отослать устройству вот такой пакет:
C++
1
2
3
4
5
6
7
8
    QByteArray buffer;
    buffer.append(":\x26", 2);
    buffer.append("\x03\x00", 2);
    buffer.append("\x00\x00", 2);
    buffer.append("\x04\x00", 2);
    buffer.append(calculateLRC(buffer));
    buffer.append("\x0d\x0a", 2);
    qDebug() << buffer.toHex();
Ответит оно вам?

Цитата Сообщение от slavka_online Посмотреть сообщение
нужно передать что то вроде этого ":260300000004<LRC>0D0A"
кстати, если "количество" это 2 байта, то вы пропустили один нулевой байт перед LRC.

И по поповоду LRC: мне кажется подозрительным что его подсчет идет с 1-го индекса вместо 0-го.

Добавлено через 19 минут
slavka_online, ну а вообще с пакетом обычно работают через определенную структуру:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// ...
 
// заботимся о выравнивании структур
// погуглите как это делается для вашего
// компилятора, если мои макросы не подходят
#if defined(_MSC_VER)
// если у нас MSVC
#pragma pack(push)
#pragma pack(1)
#define GCCSTRUCTPACKED
#else
// если GCC
#define GCCSTRUCTPACKED __attribute__((packed))
#endif
 
// определяем стуктуру отражающую пакет
struct YOUR_AWESOME_PACKAGE {
    unsigned char cmd[2];   // 2 байта
    unsigned short funtion; // 2 байта
    unsigned short begin;   // 2 байта
    unsigned short amount;  // 2 байта
} GCCSTRUCTPACKED;
 
// возвращаем выравнивае структур как это было раньше
#undef GCCSTRUCTPACKED
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
 
// ...
 
    // теперь в коде функции формируем пакет
    QByteArray buffer;
    // резервируем память под пакет
    buffer.resize(sizeof(YOUR_AWESOME_PACKAGE));
    // получаем указатель на выделенную память
    YOUR_AWESOME_PACKAGE * pack = reinterpret_cast<YOUR_AWESOME_PACKAGE *>(buffer.data());
    // заполняем пакет
    pack->cmd[0] = ':';
    pack->cmd[1] = 0x26;
    pack->funtion = 3; // если byteoreder не соответсвует нашему
    pack->begin   = 0; // то приводим его к "общему знаменателю"
    pack->amount  = 4; // для этих переменнх
    buffer.append(calculateLRC(buffer));
    buffer.append("\x0d\x0a", 2);
    qDebug() << buffer.toHex();
 
    // здесь в buffer "лежит" сформированный пакет, который
    // можно отправлять устройству
 
// ...
Добавлено через 6 минут
И да, вы уверены что пакет должен быть именно в ASCII (не заметил сразу)?

Добавлено через 23 минуты
Ну а если данные пакета (т.е. от номера функции по количество включительно) должны быть в ASCII, то можно поступить так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    // формируем данные
    QByteArray data; {
        QDataStream stream(&data, QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);
        stream << (unsigned char) 0x26;
        stream << (unsigned short) 3; // номер функции
        stream << (unsigned short) 0; // начало
        stream << (unsigned short) 4; // количество
    }
 
    // формируем пакет полностью
    QByteArray buffer;
    buffer.append(':');
    buffer.append(data);
    buffer.append(calculateLRC(buffer));
    buffer.append("\x0d\x0a");
 
    // "3a26030000000400d30d0a"
    qDebug() << buffer.toHex();
 
    // здесь в buffer "лежит" сформированный пакет, который
    // можно отправлять устройству
slavka_online
1 / 1 / 0
Регистрация: 06.11.2012
Сообщений: 102
26.01.2016, 21:29  [ТС]     Как правильно создать ModBus ASCII запрос? #3
Спасибо большое за подробный ответ, то что нужно

Добавлено через 16 минут
LRC считается не сначала потому что ":" не входит в расчет, а вы уверены что 0D0A должны явно входить в конец запроса? как я понял это код символов переноса строки \r\n

Добавлено через 3 минуты
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 QByteArray buffer;
 
    QByteArray buffer2;
    buffer2 += (char)0x1A;
    buffer2 += (char)0x03;
    buffer2 += (char)0x00;
    buffer2 += (char)0x00;
    buffer2 += (char)0x00;
    buffer2 += (char)0x04;
    unsigned char lrc = calculateLRC(buffer2);
    //buffer2 += lrc;
 
QString str = ":";
for (int i = 0; i <buffer2.size(); i++){
 
    str += QString::number((int)buffer2[i], 16).rightJustified(2, '0').toUpper();
 
}
    str+= QString::number(lrc, 16).rightJustified(2, '0').toUpper();
    //str = ":1A0300000004DF";
for (int i = 0; i < str.length(); i++)
     buffer +=  str.at(i);
 
    buffer += 0x0D;
    buffer += 0x0A;
    //":1A0300000004DF\r\n"
    qDebug() << buffer;
Корявым способом я получил, что хотел
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
26.01.2016, 21:51     Как правильно создать ModBus ASCII запрос? #4
slavka_online, ну уж очень корявый код. Поглядите на мой последний вариант кода с QDataStream.
slavka_online
1 / 1 / 0
Регистрация: 06.11.2012
Сообщений: 102
26.01.2016, 21:52  [ТС]     Как правильно создать ModBus ASCII запрос? #5
завтра опробую его в деле
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
26.01.2016, 22:08     Как правильно создать ModBus ASCII запрос? #6
slavka_online, по поводу 0d0a, трудно сказать должно или не должно - зависит от Вашего устройства.
slavka_online
1 / 1 / 0
Регистрация: 06.11.2012
Сообщений: 102
27.01.2016, 15:30  [ТС]     Как правильно создать ModBus ASCII запрос? #7
Вашим способом уходит только 11байт из нужных 17
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.01.2016, 16:48     Как правильно создать ModBus ASCII запрос?
Еще ссылки по теме:
Как правильно создать шаблон функции C++
C++ WinAPI Как правильно создать панель GROUPBOX?
C++ Как правильно создать динамический массив из функции
Как правильно создать строку, используя swprintf? C++
C++ Как правильно создать функцию и затем вызвать ее

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
27.01.2016, 16:48     Как правильно создать ModBus ASCII запрос? #8
slavka_online, тогда вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    // формируем данные
    QByteArray data; {
        QDataStream stream(&data, QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::LittleEndian);
        stream << (unsigned short) 3; // номер функции
        stream << (unsigned short) 0; // начало
        stream << (unsigned short) 4; // количество
    }
 
    // формируем пакет полностью
    QByteArray buffer;
    buffer.append(":\x26");
    buffer.append(data.toHex());
    buffer.append(calculateLRC(buffer));
    buffer.append("\r\n");
 
    // 3a26303330303030303030343030930d0a
    qDebug() << buffer.toHex();
 
    // здесь в buffer "лежит" сформированный пакет, который
    // можно отправлять устройству
Yandex
Объявления
27.01.2016, 16:48     Как правильно создать ModBus ASCII запрос?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru