С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/259: Рейтинг темы: голосов - 259, средняя оценка - 4.59
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37

Чтение/запись с COM - порта

07.05.2021, 00:53. Показов 47852. Ответов 11

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток. Занимаюсь практикой от предприятия в институте. Задание по реализации симметричного шифрования при передаче данных через USB. Особо не парился с шифрованием, так как задание не про него толком. Взял шифр цезаря по введенному ключу. Что-то написал сам, где то содрал, в итоге имею код, который должен шифровать данные и отправлять их на ком-порт. Затем он считывает их обратно (когда микроконтроллер с ними закончил) и дешифрует. На первый взгляд, отправка и чтение с портом работает. Однако столкнулся с некоторыми трудностями. При отправке на порт, в терминале от всего сообщения отправляется только первая буква, хотя указал же строку целую (DWORD dwSize = sizeof(data); а в dwSize записывается всего 1 байт, хотя например в строке их 24), вот код параметров и цикл отправки:
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
    DCB dcbSerialParams = { 0 };
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams))
    {
        cout << "Ошибка начала работы\n";
    }
    dcbSerialParams.BaudRate = CBR_9600;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    if (!SetCommState(hSerial, &dcbSerialParams))
    {
        cout << "Ошибка настройки состояния последовательного порта\n";
    }
   f_cin.open("practice_encoded.txt"); //файлик с закодированной инфой
   if (f_cin.is_open())
    {
        while (!f_cin.eof())
        {
            text = "";
            getline(f_cin, text);
            char data[] = "";  // строка для передачи
            for (int i = 0; i < text.length(); i++) {
                data[i] = text[i];
            }
            DWORD dwSize = sizeof(data);   // размер этой строки
            DWORD dwBytesWritten;    // количество переданных байт
            BOOL iRet = WriteFile(hSerial, data, dwSize, &dwBytesWritten, NULL);
            cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;
            cout << data << endl;
        }
    }
    else
        cout << "Ошибка открытия файла!\n";
    f_cin.close();
Вполне вероятно, я просто не вижу очевидного, у меня такое бывает постоянно.
Есть ещё и трабл с чтением, но там я хотя бы догадываюсь где лажа. Подскажите, как тут справиться.

Добавлено через 30 минут
Пока все писал, внезапно осенило, что я через sizeof пытаюсь размер массива получить (простите ).
Тут разобрался. Но вот до сих пор думаю и не понимаю, что делать с чтением. Как сделать так, чтобы читало всю строку, которую получаю, а не посимвольно. При чтении посимвольно, он мне каждый раз добивает из символа строку из 10 элементов (не знаю зачем, причем всегда буквами М, а в конце какой то смайлик маленький, вобщем белиберда какая-то). Как получить длину полученного через порт сообщения?

Функция чтения:
C++
1
2
3
4
5
6
7
8
9
void ReadCOM()
{
    DWORD iSize;
    char sReceivedString[] = "";
    BOOL iRet = ReadFile(hSerial, &sReceivedString, 1, &iSize, 0);  // получаем 1 байт
    if (iSize > 0)   // если что-то принято, выводим
        cout << iSize << " Bytes in string. " << iSize << " Bytes received. " << endl;
    cout << sReceivedString;
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
07.05.2021, 00:53
Ответы с готовыми решениями:

Чтение из COM-порта
Здравствуйте! Никак не могу правильно прочитать данные из COM-порта. Мой процессор отправляет в компорт в бесконечном цикле (каждые...

Побайтовое чтение COM порта
Доброго времени суток. Обычно из COM порта читают передавая в функцию чтения указатель на буфер и сколько байтов прочитать. Как...

Чтение из LPT порта
LPT порт в режиме EPP. С некоторой частотой на него приходит последовательность импульсов, которые надо прочитать. Читать в бесконечном...

11
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
07.05.2021, 08:28
Цитата Сообщение от TongueLizard Посмотреть сообщение
всю строку, которую получаю, а не посимвольно.
так сигнатура вашей функции такая
C++
1
2
3
4
5
6
7
   function ReadFile(
    hFile: THandle; // Указатель на открытый файл
    var Buffer;     // Указатель на буфер, куда поместится прочитанный блок
    nNumberOfBytesToRead: DWORD;    // количество прочитанных байтов !!!
    var lpNumberOfBytesRead: DWORD; // указатель на число прочитанных данных 
    lpOverlapped: POverlapped       // указатель на структуру OVERLAPPED
   ): BOOL; stdcall;
и возвращает функция TRUE, если всё норм...
3-й параметр задайте, какой хотите, а не 1
Если хотите Прочитать всю строку - надо знать её размер, чтобы его задать 3-м параметром (банально перейти в конец файла, отнять начало = знать размер), т.к
Функция читает из файла блок данных начиная с текущей позиции. После прочтения блока, позиция переносится в конец прочитанного блока.
ИЛИ
? может вам стоит попробовать
ReadFileEx function

It reports its completion status asynchronously, calling the specified completion routine when reading is completed or canceled and the calling thread is in an alertable wait state.
оттуда же есть линк на пример Named Pipe Server, но вам, наверно, больше подойдёт пример Named Pipe Client...
p.s.
Вообще, при чтении блоками - банальный подход - зацикливать в while...
p.p.s.
подчеркнула 2 возможных варианта достижения вашей цели... если речь всё-таки о клиенте
1
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,531
Записей в блоге: 1
07.05.2021, 09:43
Как же пригорает от такого!
ТС, зачем ты пытаешься в сложные программы, если пока что не освоился с массивами обычными?
C++
1
char data[] = "";  // строка для передачи
Вот это какого размера массив?
ТС, ты решил, что если не знаешь заранее размера, то его можно не указывать при инициализации?
А кто тебе дал право это решать?
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 16:47  [ТС]
Добавлено через 5 минут
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Вот это какого размера массив?
ТС, ты решил, что если не знаешь заранее размера, то его можно не указывать при инициализации?
А кто тебе дал право это решать?
Я не понимаю сути вашего вопроса. И, пожалуйста, успокойтесь. Я создал тему в разделе с++ для начинающих.
С каких пор нельзя создавать массивы без объявления размера?
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
зачем ты пытаешься в сложные программы, если пока что не освоился с массивами обычными?
Дали задание - сделай что хочешь, но сдай его. Тупейший вопрос. Как могу, так делаю. Конструктивно критикуй и предлагай или не балаболь

Добавлено через 1 час 8 минут
Цитата Сообщение от JeyCi Посмотреть сообщение
3-й параметр задайте, какой хотите, а не 1
Если хотите Прочитать всю строку - надо знать её размер, чтобы его задать 3-м параметром (банально перейти в конец файла, отнять начало = знать размер), т.к
Да я знаю ее параметры, в том то и дело. Я хотел чтобы считывало сразу все сообщение. Но я не знаю его длины, она может быть любой. Вот и думал, может есть какой то вариант. А цикл у меня и так есть, я просто саму функцию указал. Ладно, я понял, спасибо
0
Эксперт .NET
 Аватар для Rius
13058 / 7623 / 1665
Регистрация: 25.05.2015
Сообщений: 23,165
Записей в блоге: 14
07.05.2021, 18:03
Цитата Сообщение от TongueLizard Посмотреть сообщение
Я хотел чтобы считывало сразу все сообщение. Но я не знаю его длины, она может быть любой. Вот и думал, может есть какой то вариант.
Можно попробовать считать, например, 100 байт. Если вылетел таймаут, значит либо ничего не пришло, либо пришло меньше, но посылка всё-таки завершилась. Если же считано успешно, снова читаем 100 байт.
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 20:10  [ТС]
Цитата Сообщение от Rius Посмотреть сообщение
Можно попробовать считать, например, 100 байт. Если вылетел таймаут, значит либо ничего не пришло, либо пришло меньше, но посылка всё-таки завершилась. Если же считано успешно, снова читаем 100 байт.
А вот насчет того, что я писал в начале, при получении 1 байта, он допиливает его буквами М и в конце какой-то значок бывает, типа смайлика или знака пики в картах.
Вот я отправляю слово "grep", а в консоли при получении у меня пишет:
gMMMMMMMMM(какой-то символ)
rMMMMMMMMM(какой-то символ)
eMMMMMMMMM(какой-то символ)
pMMMMMMMMM(какой-то символ)

Я вот даже понять не могу почему, и всегда до 10 символов именно. Я решил поставить 10 байт принять, он мне выдает какое то исключении и стопорит программу, потом можно продолжить и все передает, но факт остается фактом.
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 20:21  [ТС]
Цитата Сообщение от TongueLizard Посмотреть сообщение
gMMMMMMMMM(какой-то символ)
rMMMMMMMMM(какой-то символ)
eMMMMMMMMM(какой-то символ)
pMMMMMMMMM(какой-то символ)
Скрин
Изображения
 
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 20:36  [ТС]
Цитата Сообщение от Rius Посмотреть сообщение
Можно попробовать считать, например, 100 байт. Если вылетел таймаут, значит либо ничего не пришло, либо пришло меньше, но посылка всё-таки завершилась. Если же считано успешно, снова читаем 100 байт.
Если получаем сообщение меньше указанного в параметрах, выходит вот такое:
Миниатюры
Чтение/запись с COM - порта  
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.05.2021, 21:04
Цитата Сообщение от TongueLizard Посмотреть сообщение
С каких пор нельзя создавать массивы без объявления размера?
Всегда было нельзя.

Ваш массив
Цитата Сообщение от TongueLizard Посмотреть сообщение
C++
1
char data[] = "";
имеет размер 1. Размер выведен из инициализатора.
Соответственно записывать в него больше чем 1 char вы никак не можете.

Добавлено через 3 минуты
Цитата Сообщение от TongueLizard Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
 text = "";
 getline(f_cin, text);
 char data[] = ""; // строка для передачи
 for (int i = 0; i < text.length(); i++) {
   data[i] = text[i];
 }
 DWORD dwSize = sizeof(data); // размер этой строки
 DWORD dwBytesWritten; // количество переданных байт
 BOOL iRet = WriteFile(hSerial, data, dwSize, &dwBytesWritten, NULL);
C++
1
2
3
4
5
 text = "";
 getline(f_cin, text);
 DWORD dwSize = text.length(); // размер этой строки
 DWORD dwBytesWritten; // количество переданных байт
 BOOL iRet = WriteFile(hSerial, text.c_str(), dwSize, &dwBytesWritten, NULL);
Добавлено через 4 минуты
Цитата Сообщение от TongueLizard Посмотреть сообщение
я через sizeof пытаюсь размер массива получить
Именно это sizeof и делает. "Получает" размер в байтах. Если этот массив типа char, то вы как раз и получите таким образом размер массива. Другое дело, что у вас массив задан размера 1.

Добавлено через 11 минут
Цитата Сообщение от TongueLizard Посмотреть сообщение
Как получить длину полученного через порт сообщения?
А сообщение-то в протоколе каком-то наверняка? Так вот в этом протоколе и должно быть задано каким образом получать длину сообщения. На уровне функции чтения этой информации нет. В общем случае подход такой:
1) Вы читаете фиксированными блоками (любого размера) байты из порта;
2) Анализируете эти байты на предмет служебной информации об остальных данных;
3) Продолжаете чтение в соответствии с этой информацией;
4) По ходу чтения складываете полученные байты в некий контейнер или заранее выделенную память.

В простейшем случае никакой информации кроме самих данных в этих байтах может не быть, но тогда предполагается некое умолчание, которым должна руководствоваться читающая программа. Например, "читать до первого нуля - встреченный ноль означает конец сообщения", или "читать N байт", где N заранее известное значение.
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 21:14  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Соответственно записывать в него больше чем 1 char вы никак не можете.
Может это и странно, но у меня все записывается. Я просто добавил count который считает количество элементов массива в цикле, а потом во внешнем цикле передачи определяет, сколько байт передать. С этим проблем нет, у меня все передается сейчас отлично, без левых символов и в полном объеме.
А вот с приемом вопросы. Гляньте, пж, сообщение выше мое. Там вызывается исключение какое-то. А если по одному считывать, то дополняется до 10 буквами М и каким-то смайликом.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.05.2021, 21:19
Лучший ответ Сообщение было отмечено TongueLizard как решение

Решение

Цитата Сообщение от TongueLizard Посмотреть сообщение
А вот насчет того, что я писал в начале, при получении 1 байта, он допиливает его буквами М
Никто ничего не "допиливает". У вас есть массив размера 1. Вы читаете в него 1 байт. Дальше пытаетесь вывести его как С-строку на консоль. Си-строка это массив ограниченный нуль-символом. Т.к. в вашем массиве был всего один байт и вы в него записали какие-то данные из порта, то выводить его как Си-строку вы не можете. Потому что в этом массиве не осталось места для нуль-символа.
Далее происходит чистой воды Undefined Behavior:
Оператор << потока пытается выводить переданный ему массив как Си-строку, перебирая байты по очереди в поисках нуль-символа. Так как в массиве его нет, то неизбежно происходит выход за его пределы, читаются байты чужой памяти. Так вышло, что в этих байтах лежат коды символа M, а дальше таки попадается какой-то ноль и вывод прекращается. Все, что происходит с момента, когда оператор потока вашими стараниями вышел за пределы массива является неопределенным поведением.

Собственно выход тут простой,
1) читайте в массив бОльшего размера.
2) если вам необходимо выводить байты данных полученных из порта, то делайте это побайтно, лучше всего в 16-ричном виде (т.к. там совсем не обязательно будет текст)
3) выводите ровно столько байт, сколько было прочитано (для получения размера прочитанных данных есть специальная переменная)

Добавлено через 2 минуты
Цитата Сообщение от TongueLizard Посмотреть сообщение
Может это и странно, но у меня все записывается
Я думаю вам уже надо знать простую вещь про С\С++. Скомпилированная и корректно выполняющаяся программа не есть гарантия того, что в ней нет ошибок и что условно "завтра" она не сломается.
Так что слова "у меня все работает", при совершенно точном наличии ошибок в коде ничего особо не значат.

Добавлено через 2 минуты
Цитата Сообщение от TongueLizard Посмотреть сообщение
А вот с приемом вопросы.
На приеме точно такая же ошибка, как и на отправке. Просто в чуть иных условиях эта ошибка стреляет.
Исправлять надо обе ошибки, и на приеме и на записи.
1
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 23:16  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
2) если вам необходимо выводить байты данных полученных из порта, то делайте это побайтно, лучше всего в 16-ричном виде (т.к. там совсем не обязательно будет текст)
В итоге сделал чтение побайтно, массив символов длины 2 задал. После прочтения каждого байта в [0] эл массива, в [1] элемент массива ставил '/0' и все чудесно выводит.
Сделал цикл чтения, с break, если ничего не получили.
Спасибо большое за помощь
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.05.2021, 23:16
Помогаю со студенческими работами здесь

Определение паузы при чтение с COM порта
Пишу под OS Windows 7 visual studio c использованием MFC. Нужно добиться определения наличия паузы между принятием двух байт по COM...

Открыть текстовый файл в необходимом режиме (на чтение, на чтение и запись, на добавление)
Открыть текстовый файл в необходимом режиме (на чтение, на чтение и запись, на добавление). (В файле должно быть не менее 30 строк)....

Непрерывное чтение и обработка с com порта (последовательный порт) в Visual C++
Здравствуйте, я задумал одну идею с GPS приемником, но для того чтобы реализовать это мне необходимо читать и обработать данные с com порта...

[Файлы] Запись-чтение-запись. Почему не прокатывает?
Сначала записываю в файл &quot;а&quot; запись &quot;makulatura&quot;, потом читаю ее в строку h. Все ок. Но потом когда открываю файл &quot;a&quot; опять для...

Как обрабатывать результат буфера ком-порта(запись, чтение)?
Такой вопрос. Пишу программу, которая работает с гипертерминалом на другом компе. На прием, пишу например так char buf=&quot;hello&quot;;...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru