Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > ОС и железо
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 17.03.2010, 19:56
юрамеханик юрамеханик вне форума
Прохожий
 
Регистрация: 17.03.2010
Сообщения: 1
Репутация: 10
По умолчанию ошибка при чтении данных с Com порта, просто проверте небольшой код на ошибки

Всем доброго времени суток.
Опишу все вкратце
Задача такова: на порт приходят приерно раз в секунду несколько байтов данных
использую с++ builder 6 (пробовал этот же проект в 2010 , ситуация та же),
пользуюсь функциями из SDK(правильно ли оперирую терминами , поправьте если что)
код собран из примеров http://msdn.microsoft.com/en-us/library/ms810467.aspx
может важно а может нет - на компьютере нет com порта!! , для эмуляции всего процесса используется программа VSPD которая создает два порта и программа PROTEUS которая эмулирует устройство
на эти вещи не грешу - изначально делал в NONOVERLAPPED режиме и данные читались без проблем
НО как оказалось, это дубовый способ, ибо я жду прерывания (раз в секунду же) , а если ничего не приходит (сломалось устройство оторвался провод...) то функция WaitCommEvent будет ждать ждать ждать...
причем если делать чтение в отделном потоке а потом его пытатся завершить то виснет и основной поток

поэтому решил делать в OVERLAPPED режиме(ну и тоже в отделном потоке) ,
но тут возникает непонятная проблема - вроде все как показано на ссылке выше, НО функция чтения ReadFile возвращает false а функция GetLastError возвращает 998 ошибку (error_noaccess)

порядок действий в коде ниже таков:
создаем хендл для чтения (типа открываем файл с именем "COM7" скажем)
устнавливаем настройки (может тут где проблема) bcb структура , временные интервалы для чтения, тип прерывания,OVERLAPPED структура
далее в цикле WaitCommEvent возвращает ERROR_IO_PENDING и начинаем ждать функцией WaitForSingleObject когда они прибудут
данные прибыли , функция возвратила WAIT_OBJECT_0 и мы ждем функцией GetOverlappedResult когда будут прочитан байт
вот тут самое интересное - функция возвращает true
и numbytes_ok содержит "4" ,хотя во-первых я посылаю 6 байт(5 и символ перевода строки)
а во-вторых GetOverlappedResult выполняется после каждого принятого байта
причем читается всего 5 байтов!!
вызываем функцию ReadFile , она возвращает FALSE а GetLastError возвращает ошибку 998(error_noaccess)
numbytes_ok после этого равна 0
и причем numbytes_ok = 4 устанавливается после первого же принятого байта (точнее после первого захода в WAIT_OBJECT_0 из пяти между секундными интервалами)
какие либо перестановки в коде ничего толком не дали,
если все элементы не принадлежащие потоку засунуть в метод и вызывать через Synchronize то ситуация все та же

в общем наверно где-то допустил тупую ошибку и прошу беглым взглядом проверить сведущих людей данный код
заранее спасибо!
Код:
                  DCB dcb;
                _COMSTAT ComState;
                DWORD numbytes_ok;
                DWORD dwEvtMask;
               
               HANDLE hCom = CreateFile(      portName,
                                GENERIC_READ | GENERIC_WRITE,
                                0,   
                                NULL, 
                                OPEN_EXISTING,
                                 FILE_FLAG_OVERLAPPED,
                                0 
                               );


                READ = GetCommState(hCom, &dcb);
                dcb.BaudRate = 9600;
                dcb.ByteSize = 8;
                dcb.Parity = NOPARITY;
                dcb.StopBits = ONESTOPBIT;
                READ = SetCommState( hCom, &dcb );

                COMMTIMEOUTS CT;
                GetCommTimeouts( hCom, &CT) ;
                CT.ReadIntervalTimeout = 1;
                CT.ReadTotalTimeoutMultiplier = MAXDWORD;
                CT.ReadTotalTimeoutConstant = MAXDWORD;
                SetCommTimeouts( hCom, &CT );

                 if (!SetCommMask(hCom,EV_RXCHAR))
                        Form1->Memo1->Lines->Add("error setting communications mask; abort");

                int STATUS_CHECK_TIMEOUT =1300 ;  // Milliseconds
                DWORD      dwCommEvent;
                BOOL      fWaitingOnStat = FALSE;
                OVERLAPPED osStatus ;
                osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
                if (osStatus.hEvent == NULL)
                        Form1->Memo1->Lines->Add("error creating event; abort");
                if(READ)Form1->Memo1->Lines->Append("ОК");

                char *buf_in;
                while (!Thr->Terminated && READ)
                 {
                        if (!fWaitingOnStat && !Thr->Terminated)
                        {
                                if (!WaitCommEvent(hCom, &dwCommEvent, &osStatus))
                                {
                                        if (GetLastError() == ERROR_IO_PENDING)
                                        {
                                                Form1->Memo1->Lines->Add("ERROR_IO_PENDING");
                                                fWaitingOnStat = TRUE;
                                               // Form1->Memo1->Lines->Add(AnsiString(numbytes_ok)+" "+ "0");
                                        }
                                        else
                                        {
                                                Form1->Memo1->Lines->Add(" error in WaitCommEvent; abort");
                                                break;
                                        }
                                }
                                else
                                {
                                        Form1->Memo1->Lines->Add("WaitCommEvent returned immediately");
                                }

                        }
                        // Check on overlapped operation.
                        if (fWaitingOnStat && READ)
                        {
                                switch(WaitForSingleObject(osStatus.hEvent, STATUS_CHECK_TIMEOUT))
                                {
                                        case WAIT_OBJECT_0:

                                                if (!GetOverlappedResult(hCom, &osStatus, &numbytes_ok, TRUE))
                                                {
                                                        Form1->Memo1->Lines->Add("An error occurred in the overlapped operation");
                                                }
                                                else
                                                {
 /////////////////////////////////////////////////////////////////////////////////READING
                                                        if(ReadFile(hCom, buf_in, 1, &numbytes_ok, &osStatus))
                                                        {
                                                                Form1->Memo1->Lines->Add(buf_in);
                                                        }
                                                        else
                                                        {
                                                                Form1->Memo1->Lines->Add(GetLastError());
                                                        }
                                                        Form1->Memo1->Lines->Add(numbytes_ok);

                                                }
                                                fWaitingOnStat = FALSE;
                                                break;

                                        case WAIT_TIMEOUT:
                                                Form1->Memo1->Lines->Add("WAIT_TIMEOUT");
                                                break;

                                        default:

                                                Form1->Memo1->Lines->Add("CloseHandle");
                                                CloseHandle(osStatus.hEvent);
                                }
                        }
                }
Ответить с цитированием
  #2  
Старый 30.04.2010, 11:23
Dukus Dukus вне форума
Прохожий
 
Регистрация: 23.04.2010
Сообщения: 4
Репутация: 10
По умолчанию

Это же на С/С++ написано? А этот форум посвящен Delphi.
Ответить с цитированием
  #3  
Старый 01.05.2010, 08:27
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Переводи
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 00:22.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter