Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Проблема, коллеги. Или, к слову о передаче данных.


Автор: Гость_Alexei 26.12.2003, 09:50
Итак, есть устройство (микроконтроллер ADAM, но это не суть важно), подключенное к последовательному порту, нужно связаться с ним и получить данные. Все это проходит нормально, это я сделал. Но есть досадная неприятность - когда пытаешься коннектиться к выключенному контроллеру, то программа зависает в бесконечном ожидании. Я узнал, что это нужно копать в направлении такого элемента функции CreateFile, как OVRELAPPED. Каким-то образом надо это организовать, чтобы при попытке соединения к выключенному контроллеру выдавалось сообщение и программа не завешивалась бы. Поискал я инфы по Сети и на этом форуме всплывала похожая проблема. Я столько вариантов перепробовал, но ничего не работает. Или наоборот, сообщение выдается даже и в том случае, когда устройство включено. Так все-таки, объясните, пожалуйста, кто может, как делается такая проверка. А то никаких представлений теперь нету.
Вот один из вариантов:

if(hComm==INVALID_HANDLE_ VALUE)
{
ShowMessage("ERROR");
}

Это я вставлял и перед настройкой параметров порта, и после команды WriteFile пробовал - не работает. Хотя в найденном материале оно так и использовалось.

Автор: shedon 26.12.2003, 11:37
Функция SetCommTimeouts устанавлмвает время ожидание. По умалчанию установленно 0, т.е. бесконечное, и программа будет зависать до получения данных.

P.S. Советую всю работу с портами производить из отдельного потока, чтобы программа не зависала.

Автор: Unregistered 27.12.2003, 03:49
А как это делается-то? Где бы инфы почитать?

Автор: shedon 27.12.2003, 08:13
Цитата
А как это делается-то?

Как делается, что ?
Поток создать можно так
Код

// Объявляем функцию нашего потока
UINT WorkThreadАгтс(LPVOID pParam);

CMyClass::MyFync()
{
    // Запускаем поток
    CWinThread *pThread =  AfxBeginThread(WorkThreadEFMD, this, THREAD_PRIORITY_NORMAL);
    ASSERT_VALID(pThread);
}

UINT WorkThreadFunc(LPVOID pParam)
{
   // Получаем указатель на класс CMyClass
   CMyClass *pMyClass = (CMyClass*)pParam;

//...

   MessageBox(NULL, "Thread begin", "Thread", MB_OK);
   return 0;
}


Цитата
Где бы инфы почитать?

Читай MSDN

Автор: Unregistered 28.12.2003, 05:05
Если еще сюда заглянешь, то вопрос. А ты уверен, что это сработает в моем случае? Что-то я не пойму вообще, как это использовать. И где тут обращение к Сом-порту. Или это надо делать после CreateFile?

Автор: shedon 29.12.2003, 09:03
Цитата

Если еще сюда заглянешь, то вопрос. А ты уверен, что это сработает в моем случае? Что-то я не пойму вообще, как это использовать. И где тут обращение к Сом-порту. Или это надо делать после CreateFile?


Я же сказал, что работать с портами надо в отдельном потоке(в программе всегда есть хотя бы один интерфейсный поток который обрабатывает сообщения, нажатие кнопок и т.д. если создавать долгие процессы в интерфейсном потоке то программа не будет, в это время, откликаться на сообщения пользователя и системы, т.е. зависнет!!! и поэтому мы создаём параллельный поток для работы с портами), в MyFync я создаю поток из которого запускается функция WorkThreadFunc(), а в ней мы уже можем работать с портом.

Для работы с портами в функцию WorkThreadFunc()
Код

// Открываем порт
HANDLE m_hCommCreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (m_hComm== INVALID_HANDLE_VALUE)
{
 TRACE(_T("Failed to open up the comms port\n"));
 return 0;
}
 //Get the current state prior to changing it
 DCB dcb;
 GetState(dcb);

 //Setup the baud rate
 dcb.BaudRate = 9600;
 //Setup the Parity
 dcb.Parity = 0;   //NOPARITY
 //Setup the data bits
 dcb.ByteSize = 8;
 //Setup the stop bits
dcb.StopBits = 0;  //ONE STOPBIT
 //Setup the flow control
 dcb.fDsrSensitivity = FALSE;
// NoFlowControl
 dcb.fOutxCtsFlow = FALSE;
 dcb.fOutxDsrFlow = FALSE;
 dcb.fOutX = FALSE;
 dcb.fInX = FALSE;
 SetState(dcb);

// Устанавливаем время ожидания
 COMMTIMEOUTS timeouts;
 timeouts.ReadIntervalTimeout = 500;
 timeouts.ReadTotalTimeoutConstant = 1000;
 timeouts.ReadTotalTimeoutMultiplier = 500;
 if (!SetCommTimeouts(m_hComm, timeouts))
 {
   TRACE(_T("Failed in call to SetCommTimeouts\n"));
   return 0;
 }

// Запись в порт
 DWORD dwBytesWritten = 0;
 const void* lpBuf = "Write to Port";
 if (!WriteFile(m_hComm, lpBuf, strlen(lpBuf ), &dwBytesWritten, NULL))
 {
   TRACE(_T("Failed in call to WriteFile\n"));
   return 0;
 }

// Чтение из порта
 DWORD dwBytesRead = 0;
 BOOL bSuccess = ReadFile(m_hComm, lpBuf, strlen(lpBuf ), &dwBytesRead, NULL);
 if (!bSuccess)
 {
   if (GetLastError() != ERROR_IO_PENDING)
   {
     TRACE(_T("Failed in call to ReadFile\n"));
     return 0;
   }
 }

// Закрываем порт
   BOOL bSuccess = CloseHandle(m_hComm);
   m_hComm = INVALID_HANDLE_VALUE;
   if (!bSuccess)
     TRACE(_T("Failed to close up the comms port, GetLastError:%d\n"), GetLastError());

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)