Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
1

Работа с СОМ-портом

04.03.2014, 11:04. Показов 2521. Ответов 26
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пишу программу для работы с устройством через COM-порт. Я отсылаю устройству запрос так:
C++
1
WriteFile(hComPort, buff, buffSize, &bytesWritten, NULL);
и жду ответа от прибора. buff -- это массив типа BYTE.

Ситуация такая. Присылаю запрос номер 1, приходит только его часть. Затем посылаю любой другой запрос, и приходит остаток от запроса 1. Пробовал соединить два компьютера через COM-порты. Я присылаю что-то -- на том компьютере отображается переданная строка. Мне присылают, тоже приходит. Затем я снова отправляю строку тому компьютеру, и тут же мне приходит строка из элементов 20, хотя с того компьютера ничего не отсылали.

Буфер COM-порта очищаю после каждого чтения данных следующей функцией:
C++
1
PurgeComm(hComPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
В чем может быть дело? Если для ответа на мою тему нужны уточнения, спрашивайте.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.03.2014, 11:04
Ответы с готовыми решениями:

Работа с COM портом
Добрый день! Решил поработать с COM портом. в строке ...

Работа с com-портом
Всем привет. Нужно ловить из com-порта некоторые данные. По итогу, не получается даже открыть порт....

Работа с COM - портом
Не могу сделать чтобы, при работе с соm - портом возможно было выбирать как автоматические...

Работа с COM портом
Доброго времени суток, уважаемые форумчане! Помогите разобраться с COM портом. Хотя бы с чего...

26
Заблокирован
04.03.2014, 11:10 2
Что за устройство? Какой протокол? Случаем не над после каждой команды обрабатывать телетайповские ACK и NCK ?

Добавлено через 1 минуту
Цитата Сообщение от volodymir Посмотреть сообщение
Ситуация такая. Присылаю запрос номер 1, приходит только его часть.
куда присылаю? откуда приходит?
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:12  [ТС] 3
Устройство -- счетчик на воду. Протокол -- Modbus.
Даже если два компьютера соединить, то все равно лишние данные приходят, хотя с того компьютера ничего мне не присылали. Может, буфер очищать какой-нибудь или что? И влияет ли на это, что у меня работа без OVERLAPPED?
0
zzzZZZ...
527 / 358 / 94
Регистрация: 11.09.2013
Сообщений: 2,041
04.03.2014, 11:12 4
А сам протокол соблюдаете? Мб у вас кол-во стоп битов отличается там и там?
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:13  [ТС] 5
Присылаю на устройство, от него дальше жду ответ в отдельном потоке через WaitCommEvent.
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
04.03.2014, 11:13 6
Таймауты у тебя на прием - какие? Если истек таймаут приема, то функция ReadFile вернет ту часть ответа, которая к этому моменту успела дойти до приемника. Независимо от того, что ответ пришел еще не весь.
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:23  [ТС] 7
dzrkot, стоп-бит пробовал и 1, и 2 ставить -- нет разницы.

Добавлено через 9 минут
CheshireCat, таймауты так выставляю:
C++
1
2
3
4
5
6
7
8
9
10
11
COMMTIMEOUTS timeOuts;
 
GetCommTimeouts(hPort, &timeOuts);
 
timeOuts.ReadIntervalTimeout = MAXDWORD;
timeOuts.ReadTotalTimeoutMultiplier = 0;
timeOuts.ReadTotalTimeoutConstant = 0;
timeOuts.WriteTotalTimeoutMultiplier = 0;
timeOuts.WriteTotalTimeoutConstant = 0;
 
if (!SetCommTimeouts(hPort, &timeOuts))
0
Заблокирован
04.03.2014, 11:27 8
попробуй так:
COMMTIMEOUTS ctout;
ctout.ReadIntervalTimeout = 50;
ctout.ReadTotalTimeoutMultiplier = 5;
ctout.ReadTotalTimeoutConstant = 2000;
ctout.WriteTotalTimeoutConstant = 200;
ctout.WriteTotalTimeoutMultiplier = 5;
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:34  [ТС] 9
THE--MASTER, попробовал -- проблема та же. Порт/устройство/программа как будто помнят предыдущие данные и их повторно отсылают.
0
Заблокирован
04.03.2014, 11:35 10
Цитата Сообщение от volodymir Посмотреть сообщение
Присылаю запрос номер 1, приходит только его часть
Ты покажи код чтения из COM порта, ты скорее всего читаешь меньшее кол - во байт, чем должно быть по протоколу и у тебя в буфере остаются байты

Добавлено через 1 минуту
Цитата Сообщение от volodymir Посмотреть сообщение
Порт/устройство/программа как будто помнят предыдущие данные и их повторно отсылают.
их не помнят - они хранятся в буфере, если ты буфер не до конца считал - то в нём хранятся байты с предыдущего запроса, PurgeComm далеко не всегда правильно отрабатывает, особенно на USB - to COM
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:43  [ТС] 11
Вот код чтения из СОМ-порта:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
WaitCommEvent(hPort, &dwMask, NULL);
ClearCommError(hPort, &dwError, &comstat);
        
dwRead = comstat.cbInQue;
 
if (dwRead > 0)
{
    ReadFile(hPort, buf, dwRead, &dwRead, NULL);
 
    PurgeComm(hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
        
    for (int i = 0; i < (int)dwRead; i++)
        printf_s("Byte read #%d: %u\n", i, buf[i]);
}
0
Заблокирован
04.03.2014, 11:53 12
Цитата Сообщение от volodymir Посмотреть сообщение
ReadFile(hPort, buf, dwRead, &dwRead, NULL);
ты зачем одну и туже переменную суёшь dwRead ?
C++
1
2
3
4
5
6
7
BOOL WINAPI ReadFile(
  _In_         HANDLE hFile,
  _Out_        LPVOID lpBuffer,
  _In_         DWORD nNumberOfBytesToRead,
  _Out_opt_    LPDWORD lpNumberOfBytesRead,
  _Inout_opt_  LPOVERLAPPED lpOverlapped
);
nNumberOfBytesToRead - это сколько ты байт хочешь считать,
lpNumberOfBytesRead - это сколько байт фактический считалось.
Тебе нужно сравнивать эти переменные для определения корректности чтения

Дай мне результат байтов, который ты читаешь первым запросом и вторым, в котором у тебя остаток первого. А так же сообщи где во втором запросе у тебя кончаются байты первого
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 12:00  [ТС] 13
Исправил:
C++
1
2
DWORD dwRead = comstat.cbInQue, dwGot = 0;
ReadFile(hPort, buf, dwRead, &dwGot, NULL);
Цитата Сообщение от THE--MASTER Посмотреть сообщение
Дай мне результат байтов, который ты читаешь первым запросом и вторым
Прямо последовательность написать? Она пока на экран только выводится, а байты переводятся из шестнадцатиричной системы в десятичную.
0
Заблокирован
04.03.2014, 12:04 14
Цитата Сообщение от volodymir Посмотреть сообщение
Исправил:
ну и теперь сравни их, они одинаковые или же читается меньше, чем ты запрашиваешь? Кстате, сколько байт ты хотел прочитать?

Цитата Сообщение от volodymir Посмотреть сообщение
Прямо последовательность написать?
да, можешь скриншот консоли дать
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 12:22  [ТС] 15
Сравнил -- совпадают.

Внизу приложен скриншот. Я ввожу 1, приходит часть. Потом еще раз 1 -- приходит довесок. А должно единым блоком приходить. Если в третий раз введу любое число, то одним блоком придет уже целиковый блок от запроса 1 (как бы объединенные первая и вторая части).
Миниатюры
Работа с СОМ-портом  
0
Заблокирован
04.03.2014, 12:38 16
Цитата Сообщение от volodymir Посмотреть сообщение
DWORD dwRead = comstat.cbInQue, dwGot = 0;
ReadFile(hPort, buf, dwRead, &dwGot, NULL);
1. Попробуй захардкодь переменную dwRead = 60; - посмотри что получится
2. Попробуй поставить Sleep(5000); перед ReadFile - пусть для теста будет 5 секунд, будем твои таймауты наабум подбирать, раз ты не хочешь доки читать :-)

P.S.: у тебя DWORD dwRead = comstat.cbInQue здесь dwRead вообще чему равно?
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 12:50  [ТС] 17
Исправил. Теперь в коде стало так:
C++
1
2
3
4
DWORD dwGot = 0;
 
Sleep(5000);
ReadFile(hPort, buf, 60, &dwGot, NULL);
Результат (картинка). Так же дробно приходит ответ на запрос 1. Байты после 59 (нумерация с 0, 60 элементов) нулевые.
Миниатюры
Работа с СОМ-портом  
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 12:52  [ТС] 18
dwRead всего ответа должен быть равен 221. Когда дробно приходит, то сначала 14, а потом -- 207.
0
Заблокирован
04.03.2014, 12:54 19
Цитата Сообщение от volodymir Посмотреть сообщение
Так же дробно приходит ответ на запрос 1. Байты после 59 (нумерация с 0, 60 элементов) нулевые.
А с чего ты взял, что ответ дробно приходит? Я же задавал уже вопрос, сколько байт тебе конкретно нужно считывать в ответе??????
Цитата Сообщение от THE--MASTER Посмотреть сообщение
P.S.: у тебя DWORD dwRead = comstat.cbInQue здесь dwRead вообще чему равно?
!!!

У тебя после 59-го байта идут нули, т.к. твой приёмный буфер больше 60-и байт и ты его нулями инициализируешь наверное, а читаешь в него только 60 байт = тут всё правильно

Добавлено через 52 секунды
тогда пиши тут для теста так:
DWORD dwGot = 0;

Sleep(5000);
ReadFile(hPort, buf, 221, &dwGot, NULL);

P.S.: покажи инициализацию buf
0
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 13:03  [ТС] 20
Цитата Сообщение от THE--MASTER Посмотреть сообщение
сколько байт тебе конкретно нужно считывать в ответе?
Не для всех запросов оговорено, что должна быть такая-то длина ответа. Но в данном случае это, наверно, 221.

Инициализация buf:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
BYTE* buf = 0;
 
while (!terminated)
{
    if (!buf) buf = new BYTE[bufferSize];
    else
    {
        delete[] buf;
        buf = new BYTE[bufferSize];
    }
 
    // ...
}
Поставил 221, все равно сначала приходит 14, а потом уже целиком 221. Иногда нажимаешь 1, а приходит один байт 255. Иногда вообще не приходит ничего.
0
04.03.2014, 13:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.03.2014, 13:03
Помогаю со студенческими работами здесь

работа с ком портом?
Добрый день! Я ещё только учусь. Но мне очень бы хотелось научиться работать с ком портами в...

Работа с COM портом запись и чтение в один заход-как сделать?
Столкнулся с тем что оборудование которое прицеплено к компорту не отвечает если сразу же после...

работа с COM портом
здравствуйте всем,я в форумах в первие ,и просил бы не судить очень строго. помогите пожалуйста ,...

Работа с COM-портом в C++ (соединение с Arduino)
Доброго времени суток, уважаемые коллеги! Мне для проекта требуется соединить Arduino и компьютер...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru