Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451

Qt + последовательный порт

24.12.2014, 12:04. Показов 3963. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Осваиваю чтение данных из последовательного порта, и возник такой вопрос.
Вот есть метод, который считывает данные:

C++ (Qt)
1
2
QByteArray data;
data.append(_port.readAll());
И на выходе я получаю массив байт.
С этим все понятно.
А в каком виде байты будут? Я без устройства, и поэтому мне приходится гадать, в каком виде каждый байт будет. Знаю точно, что пакет данных выглядит примерно так: (здесь и далее, в хексе)

00 22 11 F0 88 F0 F0 F0 F0 11 F0 77 EE F0 3C

Где первый байт, это байт синхронизации, и он всегда 00, а все остальное еще и кодированные байты, то есть их надо каким то образом декодировать. Подскажите, каким образом это делать? У меня есть таблица, где прописано, что байт 1 это допустим в кодированном виде байт 11. Из чего я могу сделать вывод, что операцию кодирования\декодирования надо будет делать через обычное сравнивание. А как мне каждый байт сравнить? Пробовал так:
C++ (Qt)
1
if (data.at(0) == 0xF0)
На что мне сразу предупреждение, что результат проверки всегда будет false:
предупреждение: comparison is always false due to limited range of data type [-Wtype-limits]
if (data.at(0) == 0xF0)
^

Вот, и я вообще запутался. Более того, изначально я не знаю, какой длины пакет. Тот пример, что я привел, это минимальный пакет - заголовок + контрольная сумма. В таком случае, я не знаю, весь ли пакет пришел, пока не расшифрую заголовок пакета.
И еще вопрос, касаемо контрольной суммы. Она всегда находится в конце пакета и составляет 4 байта. И так же в кодировке. Контрольная сумма CRC16, табличная. Нашел для Qt метод:
Кликните здесь для просмотра всего текста

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
quint16 crc16_modbus(const QByteArray &array)
{
 
    static const quint16 wCRCTable[] = {
    0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
    0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
    0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
    0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
    0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
    0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
    0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
    0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
    0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
    0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
    0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
    0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
    0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
    0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
    0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
    0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
    0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
    0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
    0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
    0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
    0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
    0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
    0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
    0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
    0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
    0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
    0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
    0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
    0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
    0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
    0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
    0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 };
 
    quint8 nTemp;
    quint16 wCRCWord = 0xFFFF;
 
 
    for (int i=0; i < array.length();++i)
    {
        nTemp = (quint8)array.at(i) ^ wCRCWord;
        wCRCWord >>= 8;
        wCRCWord ^= wCRCTable[nTemp];
    }
 
    return wCRCWord;
}

Я правильно понимаю, что мне надо в этот метод отправить пакет и на выходе я получу массив байтов с контрольной суммой?

Заранее извиняюсь за, возможно, столь примитивные вопросы, никогда прежде не занимался работой с байтами.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
24.12.2014, 12:04
Ответы с готовыми решениями:

Последовательный порт
Прежде всего откровенно признаюсь, что с winAPI я знакома в объёме давным давно просмотренной книжки Петзольда. Я пишу используя Qt, но в...

Последовательный порт
Пытаюсь разобраться с теорией по последовательным портам... Вот описание функции, тут меня интересует, что есть такое &quot;... в формате...

ArduinoIDE и последовательный порт
Такая проблема, во вкладке сервис нельзя поменять последовательный порт. Как решить такую проблему? Инструкция здесь не помогла. Точнее...

15
 Аватар для solar_wind
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
24.12.2014, 12:24
Воротислав,
1. Вы реально считаете, что на форуме кто либо не имея не то что вашего устройства, но и вообще не имея понятия о том, что это за устройство, сможет подсказать как расшифровать байтовый массив?
2. В функцию расчета CRC передаешь массив байт и получаешь целое 4-х байтовое число.

Добавлено через 2 минуты
Дальше это число можешь воспринимать как 4 байта и запихнуть их в байтовый массив, если тебе это нужно...
1
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
24.12.2014, 12:34  [ТС]
solar_wind,
1. я не уверен, но так ли важно знать что это за устройство, чтоб по протоколу разобрать по байтам пакет? То есть, если касаемо вида, в каком приходит пакет, то да, согласен. Могу сказать, что устройства находится на железнодорожных станциях и отвечают за какую либо часть, например за стрелки на путях. Или разрешающий сигнал. Больше информации не имею на данный момент. А что касаемо разбора пакета? То есть я пример реального пакета привел. Это он в кодированном наборе (кроме первого байта), кодировка Бауэра. Таблицу кодирования могу приложить, если таковая будет необходима.
2. Понял, благодарю.
0
 Аватар для solar_wind
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
24.12.2014, 12:40
Воротислав, Ну если есть таблица кодирования, то делаешь цикл по массиву и дальше сравниваешь байты. Желательно, что бы типы сравниваемых байтов соответствовали друг другу.
1
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
24.12.2014, 12:43  [ТС]
solar_wind, Вот именно с этого я и начал пост :-). Как правильно сравнить байты, не могу догнать. Может имеет смысл перевести QByteArray к другому виду? Например весь массив QByteArray в массив char*[] и там уже сравнивать? Если да, то как это сделать?
0
 Аватар для solar_wind
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
24.12.2014, 12:48
Лучший ответ Сообщение было отмечено Воротислав как решение

Решение

Воротислав, Зависит от того в каком виде у тебя таблица.
Можно получить указатель на char через функцию data.
Попробуй вот так:
C++ (Qt)
1
2
char f0=0xF0;
if (data.at(0) == f0) ...
1
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
24.12.2014, 12:51  [ТС]
solar_wind, таблица пока в виде doc-файла . Спасибо большое!
0
 Аватар для solar_wind
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
24.12.2014, 12:53
Цитата Сообщение от Воротислав Посмотреть сообщение
таблица пока в виде doc-файла
В каком виде она в документе это не так важно. Важно как она у тебя в памяти в программе будет отображена.
0
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
25.12.2014, 01:26  [ТС]
Чет я вообще перестал понимать.
В одной программульке формирую массив байт:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    QByteArray data;
    data[0] =0x00;
    data[1] =0x22;
    data[2] =0x11;
    data[3] =0xF0;
    data[4] =0x88;
    data[5] =0xF0;
    data[6] =0xF0;
    data[7] =0xF0;
    data[8] =0xF0;
    data[9] =0x11;
    data[10] =0xF0;
    data[11] =0x77;
    data[12] =0xEE;
    data[13] =0xF0;
    data[14] =0x3C;
    qDebug() << "data.size to send: " << data.size();
    qDebug() << "data.toHex to send: " << data.toHex();
data.size to send: 15
data.toHex to send: "002211f088f0f0f0f011f077eef03c"

отправляю в порт:
C++ (Qt)
1
serial->write(data.toHex());
В другой принимаю:

C++ (Qt)
1
2
3
4
    QByteArray data;
    data.append(_port->readAll());
    qDebug() << "Packet data: " << data;
    qDebug() << "Packet data.size(): " << data.size();
Packet data: "002211f088f0f0f0f011f077eef03c"
Packet data.size(): 30

Как так то? То есть то, что было одним байтом, стало двумя... А как мне получить то, что я отправил?
0
 Аватар для solar_wind
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
25.12.2014, 06:21
Ну для начала я бы посоветовал вам почитать что такое структуры данных и как различные данные представляются в памяти.
Изначально у вас был массив из 15 байт.
Далее вы, как я понимаю, использовали функцию data.toHex
Вы знаете что эта функция делает? Она просто преобразовывает шестнадцатеричное представление данных в текст.
Каждая латинская буква может быть закодирована одним байтом. Один байт в шестнадцатеричном виде представляется 2 символами. toHex превратила каждый из этих символов в букву/цифру и каждый из этих символов, который раньше характеризовал пол байта, теперь превратился в байт.
И это символьное представление ты уже передал в порт.
И абсолютно логично, что ты получил 30 байт.

Добавлено через 2 минуты
Воротислав, То есть вы получили точно то, что отправили. Но отправили вы не массив data.
1
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
25.12.2014, 08:48  [ТС]
solar_wind, благодарю! уже становится понятнее. Значит не правильно понял описание:
"QByteArray QByteArray::toHex () const

Возвращает копию массива, преобразованного в шестнадцатеричный вид. Шестнадцатеричное представление использует цифры 0-9 и буквы a-f."
Вот я и не мог предположить, что будет текст. И меня смущал тот факт, что после вызова
C++ (Qt)
1
2
3
QByteArray data;
data.append(_port->readAll());
qDebug() << "Data: " << data;
Отображался в дебаг панели пустая строка. Вот и начал мудрить. Сейчас отправил просто массив, не переводя в хекс, действительно размер принятого массива 15 байт составляет. Спасибо большое, буду дальше ковыряться. Вы не против, если будут вопросы, я продолжу сюда спрашивать?
0
 Аватар для solar_wind
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
25.12.2014, 08:54
Воротислав, qDebug наверное пытался отобразить текст отображая символьное представление кодов из массива. Или просто не понял, что ты от него хочешь. Если хочешь посмотреть реально, что в памяти, то память и смотри, дебагеры предоставляют такую возможность. Надо только адрес нужной ячейки памяти выяснить.

Добавлено через 20 секунд
Цитата Сообщение от Воротислав Посмотреть сообщение
Вы не против, если будут вопросы, я продолжу сюда спрашивать?
Спрашивай
0
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
25.12.2014, 12:16  [ТС]
solar_wind,
toHex превратила каждый из этих символов в букву/цифру и каждый из этих символов, который раньше характеризовал пол байта, теперь превратился в байт.
я правильно понимаю, что:
C++ (Qt)
1
data[14] =0x3C;
3 - это полубайт
С - это полубайт?
А можно ли как то байты, как правильно сказать, совмещать что ли?
Из этой конструкции:
C++ (Qt)
1
2
3
4
    data[11] =0x77;
    data[12] =0xEE;
    data[13] =0xF0;
    data[14] =0x3C;
мы видим, что это 4 байта. Как я уже упоминал, это закодированные байты. После декодирования они выглядит следующим образом:
7E0C
И по прежнему 4 байта, а мне надо из них сделать 2 байта. Я так предполагаю, что это надо делать в функции декодирования, она на данный момент выглядит так:

Кликните здесь для просмотра всего текста
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
QByteArray Packet::decoding(const QByteArray &data)
{
    QByteArray m_data = data;
    QByteArray m_result;
 
    if (m_data.at(0) == 00) {
        for (int i = 1; i < m_data.size(); i++) {
            m_result.append(fromBauer(m_data.at(i)));
        }
    }
 
    return m_result;
}
 
char Packet::fromBauer(const char &data)
{
    char ch0 = 0xF0;
    char ch1 = 0x11;
    char ch2 = 0x22;
    char ch3 = 0xC3;
    char ch4 = 0x44;
    char ch5 = 0xA5;
    char ch6 = 0x96;
    char ch7 = 0x77;
    char ch8 = 0x88;
    char ch9 = 0x69;
    char chA = 0x5A;
    char chB = 0xBB;
    char chC = 0x3C;
    char chD = 0xDD;
    char chE = 0xEE;
    char chF = 0x0F;
 
    char result;
    if (data == ch0)
        result = '0';
    else if (data == ch1)
        result = '1';
    else if (data == ch2)
        result = '2';
    else if (data == ch3)
        result = '3';
    else if (data == ch4)
        result = '4';
    else if (data == ch5)
        result = '5';
    else if (data == ch6)
        result = '6';
    else if (data == ch7)
        result = '7';
    else if (data == ch8)
        result = '8';
    else if (data == ch9)
        result = '9';
    else if (data == chA)
        result = 'A';
    else if (data == chB)
        result = 'B';
    else if (data == chC)
        result = 'C';
    else if (data == chD)
        result = 'D';
    else if (data == chE)
        result = 'E';
    else if (data == chF)
        result = 'F';
 
 
    return result;
}

То есть где то здесь, надо указать массиву, что грубо говоря, два чара - это один байт?
И еще вопрос, функция qFromLittleEndian поможет ли мне "развернуть" порядок байт?
После декодирования я получаю: 7E0C
А надо: с0е7
0
 Аватар для solar_wind
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
25.12.2014, 12:32
Воротислав,
То есть у тебя кодировщик тупо берет младшую половину каждого байта и из них получает нужные значения? Странное какое то кодирование......
Но вообще ты можешь совмещать все что угодно. Изучай битовые операции https://ru.wikipedia.org/wiki/... 0%F6%E8%E8

Не, ну конечно ты можешь и через преобразование в текст и обратно сделать, но это не очень хороший способ наверное....
1
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
25.12.2014, 12:43  [ТС]
solar_wind, младшую половину байта? я предполагал, что у меня весь байт кодирует...
C++ (Qt)
1
2
data[13] =0xF0;
char ch0 = 0xF0;
что я делаю не так? Или вы про то, что байт кодированный заменяется полубайтом?
C++ (Qt)
1
2
if (data == ch0)
        result = '0';
Вообще да, меня это тоже смутило. Спасибо вам. Буду дальше разбираться
0
 Аватар для Воротислав
127 / 105 / 27
Регистрация: 25.02.2010
Сообщений: 451
25.12.2014, 12:48  [ТС]
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.12.2014, 12:48
Помогаю со студенческими работами здесь

Последовательный порт в Windows 7
Спецам, привет! Влияет ли эта настройка на интернет? Есть ли польза от этой настройки, если поставить её на максимум? Подключение...

Отправка байт в последовательный порт
Доброго времени суток! Столкнулся со следующей проблемой. Есть необходимость отправить в SerialPort байт, в виде именно байта ( то...

Последовательный порт в Multisim 13 не работает
Здравствуйте, форумчане! Пробовал собрать последовательный порт в Multisim 13 из: 2х регистров данных; 2х счетчиков; 2х...

Cинхронный последовательный порт DSP
Подскажите: В цифровом сигнальном процессоре имеются синхронный последовательный порт для для подключения ЦАП, АЦП, модемов и других...

Последовательный порт, отправка информации
Доброго времени суток! Объясните пожалуйста и помогите советом и желательно простым языком, так как в С# я вот только-только начал...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
Программный отбор значений справочника
Maks 21.03.2026
Установка программного отбора значений справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru