С Новым годом! Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.84/25: Рейтинг темы: голосов - 25, средняя оценка - 4.84
1 / 1 / 1
Регистрация: 08.11.2014
Сообщений: 6

Передача одного байта по com-порту

27.05.2016, 14:48. Показов 4839. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ком порт в компьютере соединен перемычкой RX->TX;
C++
1
2
3
4
5
6
7
8
9
10
11
12
 
HANDLE COMport;  //дескриптор порта
 
OVERLAPPED overlapped; //будем использовать для операций чтения (см. поток ReadThread)
OVERLAPPED overlappedwr; //будем использовать для операций записи (см. поток WriteThread)
unsigned char
bufrd[10],
bufwr[10]; //приёмный и передающий буферы
 
freq,time1,time2;
freqD=0.;
resD=0.;
открываю ком порт:
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
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
71
72
73
74
75
76
77
78
79
80
void COMOpen(UnicodeString strochka)
{
 unsigned char *str = AnsiString(strochka).c_str();
 String portname;       //имя порта (например, "COM1", "COM2" и т.д.)
 DCB dcb;                //структура для общей инициализации порта DCB
 COMMTIMEOUTS timeouts;  //структура для установки таймаутов
 //открыть порт, для асинхронных операций обязательно нужно указать флаг FILE_FLAG_OVERLAPPED
 COMport = CreateFile(str,GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
 //здесь:
 // - portname.c_str() - имя порта в качестве имени файла, c_str() преобразует строку типа String в строку в виде массива типа char, иначе функция не примет
 // - GENERIC_READ | GENERIC_WRITE - доступ к порту на чтение/записть
 // - 0 - порт не может быть общедоступным (shared)
 // - NULL - дескриптор порта не наследуется, используется дескриптор безопасности по умолчанию
 // - OPEN_EXISTING - порт должен открываться как уже существующий файл
 // - FILE_FLAG_OVERLAPPED - этот флаг указывает на использование асинхронных операций
 // - NULL - указатель на файл шаблона не используется при работе с портами
 if(COMport == INVALID_HANDLE_VALUE)            //если ошибка открытия порта
  {
       ShowMessage("Ошибка открытия порта");
   return;
  }
 //инициализация порта
 dcb.DCBlength = sizeof(DCB);  //в первое поле структуры DCB необходимо занести её длину, она будет использоваться функциями настройки порта для контроля корректности структуры
 //считать структуру DCB из порта
 if(!GetCommState(COMport, &dcb)) //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
        ShowMessage("Ошибка открытия порта 0");
       COMClose();
   return;
  }
 //инициализация структуры DCB
 dcb.BaudRate = 9600;       //задаём скорость передачи 9600 бод
 dcb.fBinary = TRUE;                                    //включаем двоичный режим обмена
 dcb.fOutxCtsFlow = FALSE;                              //выключаем режим слежения за сигналом CTS
 dcb.fOutxDsrFlow = FALSE;                              //выключаем режим слежения за сигналом DSR
 dcb.fDtrControl = DTR_CONTROL_DISABLE;                 //отключаем использование линии DTR
 dcb.fDsrSensitivity = FALSE;                           //отключаем восприимчивость драйвера к состоянию линии DSR
 dcb.fNull = FALSE;                                     //разрешить приём нулевых байтов
 dcb.fRtsControl = RTS_CONTROL_DISABLE;                 //отключаем использование линии RTS
 dcb.fAbortOnError = FALSE;                             //отключаем остановку всех операций чтения/записи при ошибке
 dcb.ByteSize = 8;                                      //задаём 8 бит в байте
 dcb.Parity = 1;                                        //проверка нечётности
 dcb.StopBits = 2;                                      //задаём 2 стоп-бит
 //загрузить структуру DCB в порт
 if(!SetCommState(COMport, &dcb)) //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
       ShowMessage("Ошибка открытия порта 1");
   COMClose();
   return;
  }
 
 //установить таймауты
 timeouts.ReadIntervalTimeout = 0;   //таймаут между двумя символами
 timeouts.ReadTotalTimeoutMultiplier = 0; //общий таймаут операции чтения
 timeouts.ReadTotalTimeoutConstant = 0;         //константа для общего таймаута операции чтения
 timeouts.WriteTotalTimeoutMultiplier = 0;      //общий таймаут операции записи
 timeouts.WriteTotalTimeoutConstant = 0;        //константа для общего таймаута операции записи
 
 //записать структуру таймаутов в порт
 if(!SetCommTimeouts(COMport, &timeouts)) //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
       ShowMessage("Ошибка открытия порта 2");
   COMClose();
   return;
  }
 //установить размеры очередей приёма и передачи
 SetupComm(COMport,2000,2000);
 PurgeComm(COMport, PURGE_RXCLEAR); //очистить принимающий буфер порта
}
//---------------------------------------------------------------------------
//функция закрытия порта
void COMClose()
{
 if(COMport)
 {
    CloseHandle(COMport); //закрыть порт
    COMport = 0;
 }
}
//---------------------------------------------------------------------------
после этого по нажатию на кнопку :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
overlappedwr.hEvent = CreateEvent(NULL, true, true, NULL); //создать событие
overlapped.hEvent = CreateEvent(NULL, true, true, NULL); //создать событие
 
DWORD btr, temp, mask, signal; //переменная temp используется в качестве заглушки
 
bufwr[0]=0x1;
SetCommMask(COMport, EV_RXCHAR); //установить маску на срабатывание по событию приёма байта в порт
WriteFile(COMport, bufwr, 1, &temp, &overlappedwr); //записать байты в порт (перекрываемая
WaitForSingleObject(overlappedwr.hEvent, INFINITE); //приостановить поток, пока не завершится
 
QueryPerformanceFrequency(&freq);
freqD = (double)freq.QuadPart/1000000;   
QueryPerformanceCounter(&time1);   // засекаю таймер
 
WaitCommEvent(COMport, &mask, &overlapped); //ожидать события приёма байта (это и есть перекрываемая операция)
ReadFile(COMport, bufrd, 1, &temp, &overlapped); //прочитать байты из порта в буфер программы
WaitForSingleObject(overlapped.hEvent, INFINITE); //приостановить поток, пока не завершится
 
QueryPerformanceCounter(&time2);   // останавливаю таймер
resD = (time2.QuadPart - time1.QuadPart)/freqD;
Получаю время пересылки 1 байта в resD порядка 6400 мкс. Но ведь при скорости в 9600 бод\сек получаем: 1 байт=(8 информац.бит + стартовый + 2 стоповых + бит четности )/9600 = 0,00125 сек = 1250 мкс.
Подскажите почему так? И как получить байт за 1250 мкс. Спасибо
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.05.2016, 14:48
Ответы с готовыми решениями:

Передача по COM-порту
Доборого времени суток! имеется задачка по Паскалю: Реализация программы на паскале со втавками ASM для ком-порта. Необходимо передавать...

Передача char по com порту
учусь работать с com портом, может кто-нибудь написать простой пример передачи битовой структуры. вот так я заполняю структуру: ...

Передача данных по com порту
Добрый день! Написал программу открытия и передачи данных по com порту. Проблема в следующем. Если я пишу передачу в теле открытия ком...

10
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
27.05.2016, 16:11
Цитата Сообщение от mejau Посмотреть сообщение
Подскажите почему так?
для начала я бы попробовал передавать не один байт а скажем 1000 и посмотреть на время
0
1 / 1 / 1
Регистрация: 08.11.2014
Сообщений: 6
27.05.2016, 16:45  [ТС]
Интересует именно передача и приём 1 байта.(существует устройство с 1 байтовым обменом, требующее ответа в течение 4 мс)
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
27.05.2016, 16:59
mejau, для потока данных у меня получались показатели близкие к расчетным. Увеличить скорость есть возможность?
0
1 / 1 / 1
Регистрация: 08.11.2014
Сообщений: 6
27.05.2016, 17:37  [ТС]
vxg, спасибо за ответы, опытным путём выяснил, что только 1-й байт читается долго, последующие уже по ~ 1,2 мс, как и должно быть.Сейчас думаю над возможностью считывать этот байт прямо из регистров(если это как-то возможно в windows-е).
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
27.05.2016, 17:56
mejau, попробуйте работать с портом обычным образом - как с файлом - без событий
0
1 / 1 / 1
Регистрация: 08.11.2014
Сообщений: 6
28.05.2016, 08:51  [ТС]
Даже если зациклить
C++
1
ReadFile(COMport, bufrd, 1, &temp, &overlapped); //прочитать байты из порта в буфер программы
до тех пор пока не придет 1 байт, то всё равно время получаю +- 6мс.
Видимо, по какой-то причине, время "переноса" этого байта из регистра ком-порта в программный буфер затягивается до 6мс
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
28.05.2016, 09:24
Цитата Сообщение от mejau Посмотреть сообщение
Видимо, по какой-то причине, время "переноса" этого байта из регистра ком-порта в программный буфер затягивается до 6мс
к сожалению ардуино осталось на работе, в пн смогу смоделировать на нем ваш случай. а не может ли это быть временем реакции прибора?
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
30.05.2016, 13:14
mejau, попробовал сегодня - у меня упирается во время порядка 4 мс на передачу прием одного байта. может вам изменить протокол? или это невозможно?
0
1 / 1 / 1
Регистрация: 08.11.2014
Сообщений: 6
07.06.2016, 09:02  [ТС]
Лучший ответ Сообщение было отмечено vxg как решение

Решение

vxg, спасибо за помощь, победил проблему уменьшением объема FIFO буфера в настройках ком порта windows(поставил по 1 байту). При этом не нашел как программно управлять этим параметром.
if you set the receive buffer to 1, the UART will interrupt the processor to transfer a single byte to CPU memory whenever a byte is received.
Т.е. аппаратные прерывания будут теперь приходить по каждому байту, а не по заполнению этого буфера.
1
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
07.06.2016, 13:42
mejau, у меня такой фокус не влияет на результат, может я фиксирую отклик arduino
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.06.2016, 13:42
Помогаю со студенческими работами здесь

Передача данных по LPT порту
Всем привет! Передо мной стоит задача: Необходимо передать файл по средствам парралельного порта с одного компьютера, на другой. (2...

Передача данных по ком-порту
Добрый вечер. Мне необходимо разобраться с работой блоков передачи данных по ком порту в симулинк. Что можете посоветовать, возможно книги,...

Передача строк и символов по COM -порту
Ребят, подскажите пож. создаю строку char chOne = "1"; Отправляю по COM-порту и в терминале получаю "1C0". Откуда...

Работа SPI передача более 1 байта
Где посмотреть сколько тактов тратит аппаратный SPI меги на передачу одного байта при передаче двух и более байт ? все что я смог...

Прием и передача байта с включением двигателя
Помогите пожалуйста найти ошибку. Нужно передать 0xF на контроллер, сравнить и передать обратно, при этом включить двигатель и зажечь...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
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 Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru