Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: RS232 под win
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
paskal
Нужно соединить компутер с устройством через RS232. Обмен такой. Устройство непрерывно шлет пакеты по 16 байт и принимает ответные пакеты. Скорость обмена 115200, частота отправки пакетов 50 Гц.
Под WinXP пользуюсь стандартными API. В билдере я открываю ком порт через CreateFile, дальше вешаю на таймер функцию которая проверяет сколько байт в приемном буфере, если не 0, то считывает буфер.
Проблема в том что считывается не 16 байт, а от 80 до 96. Т.е. получается что виндосовский таймер может работать с частотой 18 Гц и никак не чаще. Подскажите способ чтоб мне уложится в частоту 50 Гц.
Dog Pawlowa
Цитата(paskal @ Jul 21 2011, 15:22) *
Обмен такой.

Обмен бездарный. Сами придумали?
PhX
Цитата(Dog Pawlowa @ Jul 21 2011, 16:39) *
Обмен бездарный. Сами придумали?

Предложите, пожалуйста, или ткните ссылкой в правильный. Тоже очень нужно.
DpInRock
Опрашивайте порт в отдельном потоке. Никаких проблем не будет.
Сергей Борщ
QUOTE (paskal @ Jul 21 2011, 15:22) *
Подскажите способ чтоб мне уложится в частоту 50 Гц.
Работайте по таймауту, не используя таймер вообще. Посмотрите на SetCommTimeouts.
Палыч
Цитата(paskal @ Jul 21 2011, 16:22) *
получается что виндосовский таймер может работать с частотой 18 Гц и никак не чаще.
Вас не устраивает точность работы таймера? В Win несколько таймеров. Самый точный из них - мультимедийный (см. Multimedia Timer Functions: timeBeginPeriod, timeSetEvent, и др.). Однако при работе с ним нужно проявлять хотя бы элементарную осторожность: запуск из под этого таймера - в режиме "Real time".
ibiza11
Решалась подобная задача, писал на PureBasic. Открывал в приложении параллельный поток. В нем выполнялась функция приема из COM порта. Пользовался тупым сравнением прошедшего времени в мс. т.е. что то типо того :
Код
DateTime dt= DateTime.Now
                    while (true)
                    {
                        if (dt<=DateTime.Now)
                        {
                            //твоя операция
                             dt=DateTime.Now.AddMilliseconds(20);
                        }
                    }

на PureBasic это выглядит несколько иначе:
Код
dT.f=MeasureHiResIntervalStop()
MeasureHiResIntervalStart()
T.f=T+Abs(dT)
If T>=0.020
    T=0
;действие
EndIF
Dog Pawlowa
Цитата(PhX @ Jul 21 2011, 15:42) *
Предложите, пожалуйста, или ткните ссылкой в правильный. Тоже очень нужно.

Передавайте данные текстом, а поле текста обрамляйте STX/ETX, или просто после данных код перевода строки

Можно будет смотреть данные обычным гипертерминалом.
Тайм-аут не нужен вообще.

paskal
Цитата(Палыч @ Jul 21 2011, 16:48) *
Вас не устраивает точность работы таймера? В Win несколько таймеров. Самый точный из них - мультимедийный (см. Multimedia Timer Functions: timeBeginPeriod, timeSetEvent, и др.).

А есть в С++ билдере компоненты с этим таймером?
Цитата(Сергей Борщ @ Jul 21 2011, 16:47) *
Работайте по таймауту, не используя таймер вообще. Посмотрите на SetCommTimeouts.

Не совсем понял как это не использовать таймер. Если я без таймера буду непрерывно опрашивать приемник, то программа просто повиснет.
Если только добавлю таймаут, то это даст то что вместо 96 байт я приму 16. А остальные 80 потеряются. Т.е. проблема не решится

PS
изменить протокол нельзя, нам его дали сверху
гипертерминал вообще не катит, т.к. надо чтоб обмен был в обе стороны: принял пакет - ответил
Dog Pawlowa
Цитата(paskal @ Jul 21 2011, 16:51) *
изменить протокол нельзя, нам его дали сверху
гипертерминал вообще не катит, т.к. надо чтоб обмен был в обе стороны: принял пакет - ответил

Такой протокол может дать только препод sm.gif
Никакой логики - если принял-ответил, тогда почему устройство передает опять, не дожидаясь ответа?
Сергей Борщ
QUOTE (paskal @ Jul 21 2011, 16:51) *
Не совсем понял как это не использовать таймер. Если я без таймера буду непрерывно опрашивать приемник, то программа просто повиснет.
Не надо его опрашивать. Функция read() сама веренет управления после приема N байт или истечения таймаута. Можете использовать асинхронные события (используя структуру OVERLAPPED), тогда вообще ничего ждать не надо будет.
Палыч
Цитата(paskal @ Jul 21 2011, 17:51) *
А есть в С++ билдере компоненты с этим таймером?
Не знаю. Но, похоже, таймер Вам и не нужен... Я думал, что Вам нужно передавать строго через 20 мс... Для приёма использовать таймер - моветон. Рациональнее - вынести приём в отдельный поток.
paskal
Цитата(Палыч @ Jul 21 2011, 19:07) *
Для приёма использовать таймер - моветон. Рациональнее - вынести приём в отдельный поток.

Но ведь переключение между потоками по таймеру. В чем тогда выигрыш?
haker_fox
QUOTE (paskal @ Jul 21 2011, 21:22) *
Нужно соединить компутер с устройством через RS232. Обмен такой. Устройство непрерывно шлет пакеты по 16 байт и принимает ответные пакеты. Скорость обмена 115200, частота отправки пакетов 50 Гц.

Необходимо ждать наступления события - приема нескольких байт. Это можно сделать по прерываниям в МК, в Win - не знаю. Нужно смотреть, можно ли ждать события для последовательного порта.
Либо, действительно, настроить таймауты, чтобы система не повисла. С таймером бы не стал связываться. Как-то интуитивно не вяжется...
Палыч
Цитата(paskal @ Jul 21 2011, 20:14) *
Но ведь переключение между потоками по таймеру. В чем тогда выигрыш?
По истечению выделенного кванта времени переключаются чисто вычислительные потоки, которых, обычно, раз-два и обчёлся... Любое ожидание события (а, ввод-вывод без ожидания, обычно, не обходится) приводит к переключению потоков.
paskal
А нет ли примерчика приема через отдельный поток или работы в асинхронном режиме?
Dog Pawlowa
Цитата(paskal @ Jul 21 2011, 21:46) *
А нет ли примерчика приема через отдельный поток или работы в асинхронном режиме?

Нужно ли усложнять?
Если уж очень надо работать с задержками, при вызове read укажите количество байтов = 1 и считайте время от одного байта до другого.

типа

Код
...
for (;;)
{ ReadFile(port, in_buffer, 1, &numbytes,NULL );
   if (numbytes) break;
}
   current_time=GetCurrentTime();
   delay_between_bytes=current_time-last_byte_time;
   last_byte_time=current_time;
   if (delay_between_bytes>PAUSE_TIME)   // обнаружена пауза - сбросить индекс
...
Danis
Выкладываю пример создания и обработки событий мультимедийного таймера, заряжайте хоть на 1ms. Пример под Windows, на VC++ накидал. Под Builder немного по другому это выглядит, если будут сложности переправить, пишите.

На счет обработки COM порта, вот исчерпывающая информация и примеры.
Работа с COM-портом с помощью потоков
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.