реклама на сайте
подробности

 
 
> Чтение данных из ком-порта в WINXP, избитая тема, но решения для Builder 6 нигде не нашел
skopus
сообщение May 4 2006, 11:27
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 65
Регистрация: 31-08-05
Из: Moscow
Пользователь №: 8 124



Задача стоит такая:
в устройство отправляется последовательность байт - команда на исполнение. После этого компьютер ждет кода ответа от устройства. Необходимо сделалать так, чтобы пока он ждет, можно было отправить код экстренной остановки, нажав на программную кнопку и, соответственно перестать ждать ответа.

Application->ProcessMessages(); не помогает :(
как же это делается?

нашел несколько статей по поводу того как это делается через потоки на Visual C++ 6.0
но на практике код не переносится, да и в многопоточном программировании у меня никакого опыта нет.
Всякие хитрые компоненты применять запрещено.

Помогите пожалуйста! Скоро уже защита :((

На микроконтроллере я бы сделал отправку байта по внешнему прерыванию от кнопки. Но на программном уровне в виндоус так похоже нельзя, да?

Сообщение отредактировал skopus - May 4 2006, 11:31
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Aleks17
сообщение May 4 2006, 12:24
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 238
Регистрация: 17-01-05
Из: Новосибирск
Пользователь №: 2 003



Я правда в Билдере нифига не понимаю - на Visual C++ пишу, но думаю принципы те же:

Вариант 1) Многопоточное приложение.

Вариант 2) Открываешь порт для асинхронных операций (FILE_FLAG_OVERLAPPED по-моему)

и организуешь процедуру таймера, внутри которой (а не в процедуре) проверяешь на получение данных.
Go to the top of the page
 
+Quote Post
skopus
сообщение May 4 2006, 14:07
Сообщение #3


Участник
*

Группа: Свой
Сообщений: 65
Регистрация: 31-08-05
Из: Moscow
Пользователь №: 8 124



Цитата(Aleks17 @ May 4 2006, 16:24) *
Я правда в Билдере нифига не понимаю - на Visual C++ пишу, но думаю принципы те же:

Вариант 1) Многопоточное приложение.

Вариант 2) Открываешь порт для асинхронных операций (FILE_FLAG_OVERLAPPED по-моему)

и организуешь процедуру таймера, внутри которой (а не в процедуре) проверяешь на получение данных.

вот посмотрите

Код
MComPort.Write(&lpBuf,1); // отправили байт в устройство
Timer1->Enabled=true; //включили таймер

           memset(&MComPort.Overlap,0,sizeof(MComPort.Overlap));                   //это для overlap
           MComPort.Overlap.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);  //MComPort.Overlap - сама структура оверлап
          
           MComPort.Read(SystemAnswer,1); //читаем байт в переменную SystemAnswer

//обработчик события таймера
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        if(WaitForSingleObject(MComPort.Overlap.hEvent,10000)==WAIT_OBJECT_0)
             {
              GetOverlappedResult(MComPort.handle,&MComPort.Overlap,&byte_counter,FALSE);
             }
        else {
              Application->MessageBoxA("Нет отзыва о выполнении движения","Внимание",MB_OK);
             }
}


мне кажется, что я сделал что-то не так...
Go to the top of the page
 
+Quote Post
Aleks17
сообщение May 5 2006, 05:25
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 238
Регистрация: 17-01-05
Из: Новосибирск
Пользователь №: 2 003



Цитата(skopus @ May 4 2006, 21:07) *
вот посмотрите

Код
MComPort.Write(&lpBuf,1); // отправили байт в устройство
Timer1->Enabled=true; //включили таймер

           memset(&MComPort.Overlap,0,sizeof(MComPort.Overlap));                   //это для overlap
           MComPort.Overlap.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);  //MComPort.Overlap - сама структура оверлап
          
           MComPort.Read(SystemAnswer,1); //читаем байт в переменную SystemAnswer

//обработчик события таймера
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        if(WaitForSingleObject(MComPort.Overlap.hEvent,10000)==WAIT_OBJECT_0)
             {
              GetOverlappedResult(MComPort.handle,&MComPort.Overlap,&byte_counter,FALSE);
             }
        else {
              Application->MessageBoxA("Нет отзыва о выполнении движения","Внимание",MB_OK);
             }
}


мне кажется, что я сделал что-то не так...


Ну в целом похоже. Только место для структуры помнится надо задавать до открытия порта (не помню точно). И Event смотреть не обязательно (да и создавать тоже) если GetOverlappedResult пользуешь, функция же возвращает ссостояние.
Go to the top of the page
 
+Quote Post
skopus
сообщение May 5 2006, 06:39
Сообщение #5


Участник
*

Группа: Свой
Сообщений: 65
Регистрация: 31-08-05
Из: Moscow
Пользователь №: 8 124



Цитата(Aleks17 @ May 5 2006, 09:25) *
Цитата(skopus @ May 4 2006, 21:07) *
вот посмотрите

Код
MComPort.Write(&lpBuf,1); // отправили байт в устройство
Timer1->Enabled=true; //включили таймер

           memset(&MComPort.Overlap,0,sizeof(MComPort.Overlap));                   //это для overlap
           MComPort.Overlap.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);  //MComPort.Overlap - сама структура оверлап
          
           MComPort.Read(SystemAnswer,1); //читаем байт в переменную SystemAnswer

//обработчик события таймера
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        if(WaitForSingleObject(MComPort.Overlap.hEvent,10000)==WAIT_OBJECT_0)
             {
              GetOverlappedResult(MComPort.handle,&MComPort.Overlap,&byte_counter,FALSE);
             }
        else {
              Application->MessageBoxA("Нет отзыва о выполнении движения","Внимание",MB_OK);
             }
}


мне кажется, что я сделал что-то не так...


Ну в целом похоже. Только место для структуры помнится надо задавать до открытия порта (не помню точно). И Event смотреть не обязательно (да и создавать тоже) если GetOverlappedResult пользуешь, функция же возвращает ссостояние.


но че-то это так и не заработало. Кнопку остановки так и нельзя нажать, пока программа ждет приема из КОМ-порта.
Ща попробую ожидание приема в отдельный поток вынести
Go to the top of the page
 
+Quote Post
Old1
сообщение May 5 2006, 08:14
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 697
Регистрация: 26-07-05
Из: Могилев
Пользователь №: 7 095



Цитата(skopus @ May 5 2006, 09:39) *
Цитата(Aleks17 @ May 5 2006, 09:25) *

Цитата(skopus @ May 4 2006, 21:07) *
вот посмотрите

Код
MComPort.Write(&lpBuf,1); // отправили байт в устройство
Timer1->Enabled=true; //включили таймер

           memset(&MComPort.Overlap,0,sizeof(MComPort.Overlap));                   //это для overlap
           MComPort.Overlap.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);  //MComPort.Overlap - сама структура оверлап
          
           MComPort.Read(SystemAnswer,1); //читаем байт в переменную SystemAnswer

//обработчик события таймера
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        if(WaitForSingleObject(MComPort.Overlap.hEvent,10000)==WAIT_OBJECT_0)
             {
              GetOverlappedResult(MComPort.handle,&MComPort.Overlap,&byte_counter,FALSE);
             }
        else {
              Application->MessageBoxA("Нет отзыва о выполнении движения","Внимание",MB_OK);
             }
}


мне кажется, что я сделал что-то не так...


Ну в целом похоже. Только место для структуры помнится надо задавать до открытия порта (не помню точно). И Event смотреть не обязательно (да и создавать тоже) если GetOverlappedResult пользуешь, функция же возвращает ссостояние.


но че-то это так и не заработало. Кнопку остановки так и нельзя нажать, пока программа ждет приема из КОМ-порта.
Ща попробую ожидание приема в отдельный поток вынести

Естественно через таймер не заработает, так как процедура-обработчик стоит на месте пока не сработает WaitForSingleObject, а так как таймер работает в главном потоке - то главный поток стоит.
Выход - организовать процедуру чтения в отдельном потоке - это позволит управлять главным потоком приложения (нажимать на кнопки), но надо иметь в виду, что пока таймаут у WaitForSingleObject не кончится (если еще байты от устройства не пришли во входной буфер ком-порта) поток чтения все равно не убъешь, только если закрыть приложение.
На C++Builder поток реализуется следующим образом:
Код
DWORD WINAPI ReadBites()//процедура потока
{
     if(WaitForSingleObject(MComPort.Overlap.hEvent,10000)==WAIT_OBJECT_0)
             {
                 GetOverlappedResult(MComPort.handle,&MComPort.Overlap,&byte_counter,FALSE);
             }
        else {
              Application->MessageBoxA("Нет отзыва о выполнении движения","Внимание",MB_OK);
             }
}

HANDLE ht=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ReadBites, NULL, 0, &ind);//запускаем поток
CloseHandle(ht);
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 18:30
Рейтинг@Mail.ru


Страница сгенерированна за 0.01435 секунд с 7
ELECTRONIX ©2004-2016