Консультация № 26003
07.09.2005, 16:05
0.00 руб.
0 2 2
Беда настигла да и всё. Может посоветуете чем. Работаю с СОМ портом через API функции. Когда данных приходит мало всё работает отлично. Когда данные начинают идти сплошным потоком программа виснит на чтении/записи. Уже почти всё варианты синхронизации перебрал ничего не помогает.Если замыкаю передачу на себя (соединяю приём с передачей) то программа виснит минуты через 3. Когда от устройства время меняется.

Приложение:
//////Записываю данныеDWORD SerialWrite(LPVOID lpBuf, DWORD dwCount, OVERLAPPED overlapped){ DWORD dwBytesWritten = 0; if (!Write(lpBuf, dwCount, overlapped)){ if (overlapped.hEvent == 0) return dwBytesWritten; if (WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0){ GetOverlappedResult(overlapped, dwBytesWritten, FALSE); dwBytesWritten = 1; } } else{ dwBytesWritten = 0; } return dwBytesWritten;}///Функция Write вызывает WriteFile и проверяет ошибки. Читаю //Чтение такое же. Только записываю по 3 байта, а читаю по ///одному. Может сдесь и вылитает но по идее не должна. Цикл ///обработки: while (_run) { dwWaitResult = WaitForSingleObject(this, 100); if (dwWaitResult == WAIT_TIMEOUT){ _run = FALSE; continue; } try{ if (Tx){ if (IsOpen()){ if (SerialWrite(sendBuffer, 3, overlapped)){ Rx = TRUE; Tx = FALSE; } else{ Tx = TRUE; Rx = FALSE; } } } else{ if (Rx){ if (GetBuffer(rBuffer)){ Tx = TRUE; } Rx = FALSE; } } } catch(CException* pEx){ CHAR error[255]; pEx->GetErrorMessage(error, 255); TRACE(_T("Handle Exception, Message:%s\\n"), error); pEx->Delete(); } }

Обсуждение

Неизвестный
07.09.2005, 16:36
общий
это ответ
Здравствуйте, Максим Гаврилов!
Хорошо бы код посмотреть. Важно, чтобы сохранялась последовательность чтения/записи, т.к. какая-то из операций при одновременном чтении и записи результат может вернуться одновременно, чтение может завершиться раньше или запись завершится раньше. Может тут проблема? Есть вариант попробовать порт завершения ввода-вывода (IOCompletionPort). Это - асинхронная фитча винды, которая на себя берет синхронизацию. Вряд ли помог, конечно, но готов обсудить код.
давно
Специалист
742
345
07.09.2005, 18:13
общий
это ответ
Здравствуйте, Максим Гаврилов!
вот тебе пример рабочей проги с ком портом.(просто некогда думать че к чему, да и полного кода нету, думаю сам разберешься)

Приложение:
#include <windows.h>#include "resource.h"// глобальные переменные// hCom - дескриптор нашего порта// hThread - дескриптор нитиHANDLE hCom = INVALID_HANDLE_VALUE, hThread;// счетчик отосланных\принитых байтDWORD n1;// буфферы для имени порта и данных посланных портchar *combuffer,*writebuffer;// структура с конфигурацией портаDCB dcb;// функция, созданная, чтобы все выводить в Edit boxvoid __stdcall WriteLog(HWND hw, char* str){ for(int i = 0; i < strlen(str); i++) SendDlgItemMessage((HWND)hw,IDC_EDIT3,WM_CHAR,str[i],0);}// Нить, в которой мы читаем данные из порта// Мы передаем ей в параметре хэндл нашего окна// это нужно для того, чтобы мы смоглиDWORD __stdcall ReadThread(LPVOID hwnd){ char newb; while(true){ // Читаю байт ReadFile(hCom,&newb,1,&n1,0); // Посылаю байт в поле IDC_EDIT3 на форме SendDlgItemMessage((HWND)hwnd,IDC_EDIT3,WM_CHAR,newb,0); }}// В этой функции мы будем обрабатывать сообщения прешедшие нашему окнуint __stdcall Dlg_Proc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam){ switch (wMsg){ case WM_CLOSE: // Когда нас просят закрыться, делаем это EndDialog(hwnd,1); break; case WM_COMMAND: // Это сообщение приходит когда кликают на наши любимые кнопочки switch (LOWORD(wParam)) { case IDC_BUTTON1: // Нажали на баттон для отправки данных // Выделяем под буфферы 64 и 128 байт writebuffer = (char*)malloc((size_t)128); // Заполняем их нулями memset(writebuffer,0,128); // Получаю текст в буффер GetDlgItemText(hwnd,IDC_EDIT1,writebuffer,128); // Если он есть(на кнопку не просто так нажали) и порт открыт if ((strlen(writebuffer)>0)&&(hCom != INVALID_HANDLE_VALUE)){ // То стираем текст в поле на форме SetDlgItemText(hwnd,IDC_EDIT1,NULL); writebuffer[strlen(writebuffer)] = ‘\r‘; writebuffer[strlen(writebuffer)] = ‘\0‘; // Красиво печатаем отправляемый нами текст в listbox WriteLog(hwnd,writebuffer); // Убиваем нить чтения данных TerminateThread(hThread,0); // Отправляем тект WriteFile(hCom,writebuffer,strlen(writebuffer),&n1,0); // Заново создаем нить hThread = CreateThread(0, 0, ReadThread, (LPVOID)hwnd, 0, 0); } break; case IDC_BUTTON2: // Нажали на баттон для открытия порта // Если порт ещё не открыт if (hCom == INVALID_HANDLE_VALUE){ // Выделяю память под буффер и обнуляю её combuffer = (char*)malloc((size_t)16); memset(combuffer,0,16); // Получаю имя порта GetDlgItemText(hwnd,IDC_EDIT2,combuffer,16); // Открываю порт hCom = CreateFile(combuffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); // Если порт создался нормально, то создаю нить чтения данных if (hCom == INVALID_HANDLE_VALUE) WriteLog(hwnd," *** Error!!!\r"); else { WriteLog(hwnd," *** Port successfully opened.\r"); hThread = CreateThread(0, 0, ReadThread, (LPVOID)hwnd, 0, 0); // получаю текущие настройки порта GetCommState(hCom, &dcb); // стандартные настройки потра dcb.BaudRate = CBR_57600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; // записываю настройки if (SetCommState(hCom, &dcb)) WriteLog(hwnd," *** Port successfully reconfigured.\r"); else WriteLog(hwnd," *** Error!!!\r"); } } else { // Если порт уже открыт, то предложим его закрыть if (MessageBox(hwnd,"Порт уже открыт. Закрыть его?","Порт уже открыт",MB_YESNO) == IDYES){ TerminateThread(hThread,0); CloseHandle(hCom); hCom = INVALID_HANDLE_VALUE; WriteLog(hwnd," *** Port successfully closed.\r"); } } break; } break; } return false;}int __stdcall WinMain(HINSTANCE hinst, HINSTANCE, PTSTR, int) { // Тут мы вызываем функцию, которая создает окно из ресурса. DialogBox(hinst,MAKEINTRESOURCE(IDD_DIALOG1),NULL,Dlg_Proc); return 0;}
Форма ответа