0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
1

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

07.05.2021, 00:53. Показов 3996. Ответов 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)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.05.2021, 00:53
Ответы с готовыми решениями:

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

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

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

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

11
49 / 147 / 33
Регистрация: 29.06.2019
Сообщений: 1,428
07.05.2021, 08:28 2
Цитата Сообщение от 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
3652 / 2989 / 828
Регистрация: 25.03.2012
Сообщений: 11,024
Записей в блоге: 1
07.05.2021, 09:43 3
Как же пригорает от такого!
ТС, зачем ты пытаешься в сложные программы, если пока что не освоился с массивами обычными?
C++
1
char data[] = "";  // строка для передачи
Вот это какого размера массив?
ТС, ты решил, что если не знаешь заранее размера, то его можно не указывать при инициализации?
А кто тебе дал право это решать?
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 16:47  [ТС] 4
Добавлено через 5 минут
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Вот это какого размера массив?
ТС, ты решил, что если не знаешь заранее размера, то его можно не указывать при инициализации?
А кто тебе дал право это решать?
Я не понимаю сути вашего вопроса. И, пожалуйста, успокойтесь. Я создал тему в разделе с++ для начинающих.
С каких пор нельзя создавать массивы без объявления размера?
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
зачем ты пытаешься в сложные программы, если пока что не освоился с массивами обычными?
Дали задание - сделай что хочешь, но сдай его. Тупейший вопрос. Как могу, так делаю. Конструктивно критикуй и предлагай или не балаболь

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

Я вот даже понять не могу почему, и всегда до 10 символов именно. Я решил поставить 10 байт принять, он мне выдает какое то исключении и стопорит программу, потом можно продолжить и все передает, но факт остается фактом.
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 20:21  [ТС] 7
Цитата Сообщение от TongueLizard Посмотреть сообщение
gMMMMMMMMM(какой-то символ)
rMMMMMMMMM(какой-то символ)
eMMMMMMMMM(какой-то символ)
pMMMMMMMMM(какой-то символ)
Скрин
Изображения
 
0
0 / 0 / 0
Регистрация: 23.12.2018
Сообщений: 37
07.05.2021, 20:36  [ТС] 8
Цитата Сообщение от Rius Посмотреть сообщение
Можно попробовать считать, например, 100 байт. Если вылетел таймаут, значит либо ничего не пришло, либо пришло меньше, но посылка всё-таки завершилась. Если же считано успешно, снова читаем 100 байт.
Если получаем сообщение меньше указанного в параметрах, выходит вот такое:
Миниатюры
Чтение/запись с COM - порта  
0
16079 / 8681 / 2120
Регистрация: 30.01.2014
Сообщений: 14,967
07.05.2021, 21:04 9
Цитата Сообщение от 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  [ТС] 10
Цитата Сообщение от DrOffset Посмотреть сообщение
Соответственно записывать в него больше чем 1 char вы никак не можете.
Может это и странно, но у меня все записывается. Я просто добавил count который считает количество элементов массива в цикле, а потом во внешнем цикле передачи определяет, сколько байт передать. С этим проблем нет, у меня все передается сейчас отлично, без левых символов и в полном объеме.
А вот с приемом вопросы. Гляньте, пж, сообщение выше мое. Там вызывается исключение какое-то. А если по одному считывать, то дополняется до 10 буквами М и каким-то смайликом.
0
16079 / 8681 / 2120
Регистрация: 30.01.2014
Сообщений: 14,967
07.05.2021, 21:19 11
Лучший ответ Сообщение было отмечено 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  [ТС] 12
Цитата Сообщение от DrOffset Посмотреть сообщение
2) если вам необходимо выводить байты данных полученных из порта, то делайте это побайтно, лучше всего в 16-ричном виде (т.к. там совсем не обязательно будет текст)
В итоге сделал чтение побайтно, массив символов длины 2 задал. После прочтения каждого байта в [0] эл массива, в [1] элемент массива ставил '/0' и все чудесно выводит.
Сделал цикл чтения, с break, если ничего не получили.
Спасибо большое за помощь
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.05.2021, 23:16
Помогаю со студенческими работами здесь

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

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

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

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

Чтение из COM порта, При чтении из порта зависает read()
Каждому рано или поздно приходится программировать com порт. Вот и мой черед пришол. Я ужу умею:...

Чтение из COM-порта
Ребят помогите глупому Пашке разобраться с багом в программе. Проблема в том, что программа висит...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru