Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
volodymir
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
1

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

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

Пишу программу для работы с устройством через 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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.03.2014, 11:04
Ответы с готовыми решениями:

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

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

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

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

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

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

Добавлено через 1 минуту
Цитата Сообщение от volodymir Посмотреть сообщение
Ситуация такая. Присылаю запрос номер 1, приходит только его часть.
куда присылаю? откуда приходит?
0
volodymir
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:12  [ТС] 3
Устройство -- счетчик на воду. Протокол -- Modbus.
Даже если два компьютера соединить, то все равно лишние данные приходят, хотя с того компьютера ничего мне не присылали. Может, буфер очищать какой-нибудь или что? И влияет ли на это, что у меня работа без OVERLAPPED?
0
dzrkot
zzzZZZ...
523 / 354 / 94
Регистрация: 11.09.2013
Сообщений: 2,039
04.03.2014, 11:12 4
А сам протокол соблюдаете? Мб у вас кол-во стоп битов отличается там и там?
0
volodymir
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:13  [ТС] 5
Присылаю на устройство, от него дальше жду ответ в отдельном потоке через WaitCommEvent.
0
CheshireCat
Эксперт С++
2913 / 1262 / 114
Регистрация: 27.05.2008
Сообщений: 3,464
04.03.2014, 11:13 6
Таймауты у тебя на прием - какие? Если истек таймаут приема, то функция ReadFile вернет ту часть ответа, которая к этому моменту успела дойти до приемника. Независимо от того, что ответ пришел еще не весь.
0
volodymir
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
THE--MASTER
Заблокирован
04.03.2014, 11:27 8
попробуй так:
COMMTIMEOUTS ctout;
ctout.ReadIntervalTimeout = 50;
ctout.ReadTotalTimeoutMultiplier = 5;
ctout.ReadTotalTimeoutConstant = 2000;
ctout.WriteTotalTimeoutConstant = 200;
ctout.WriteTotalTimeoutMultiplier = 5;
0
volodymir
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 11:34  [ТС] 9
THE--MASTER, попробовал -- проблема та же. Порт/устройство/программа как будто помнят предыдущие данные и их повторно отсылают.
0
THE--MASTER
Заблокирован
04.03.2014, 11:35 10
Цитата Сообщение от volodymir Посмотреть сообщение
Присылаю запрос номер 1, приходит только его часть
Ты покажи код чтения из COM порта, ты скорее всего читаешь меньшее кол - во байт, чем должно быть по протоколу и у тебя в буфере остаются байты

Добавлено через 1 минуту
Цитата Сообщение от volodymir Посмотреть сообщение
Порт/устройство/программа как будто помнят предыдущие данные и их повторно отсылают.
их не помнят - они хранятся в буфере, если ты буфер не до конца считал - то в нём хранятся байты с предыдущего запроса, PurgeComm далеко не всегда правильно отрабатывает, особенно на USB - to COM
0
volodymir
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
THE--MASTER
Заблокирован
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
volodymir
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
THE--MASTER
Заблокирован
04.03.2014, 12:04 14
Цитата Сообщение от volodymir Посмотреть сообщение
Исправил:
ну и теперь сравни их, они одинаковые или же читается меньше, чем ты запрашиваешь? Кстате, сколько байт ты хотел прочитать?

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

Внизу приложен скриншот. Я ввожу 1, приходит часть. Потом еще раз 1 -- приходит довесок. А должно единым блоком приходить. Если в третий раз введу любое число, то одним блоком придет уже целиковый блок от запроса 1 (как бы объединенные первая и вторая части).
0
Миниатюры
Работа с СОМ-портом  
THE--MASTER
Заблокирован
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
volodymir
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
Миниатюры
Работа с СОМ-портом  
volodymir
1 / 1 / 0
Регистрация: 20.02.2014
Сообщений: 23
04.03.2014, 12:52  [ТС] 18
dwRead всего ответа должен быть равен 221. Когда дробно приходит, то сначала 14, а потом -- 207.
0
THE--MASTER
Заблокирован
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
volodymir
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
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.03.2014, 13:03

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

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

управление через СОМ порт
Как сдельть сигнал на RTS,DTR по нажатию BUTTON1и2 соответственно. Причём при...


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

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

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