Back in ... Вообщем, одна программа и отсылает, и принимает данные на COM1. Вроде инициализирую, устанавливаю маску событий без проблем (правда GetCommMask вернул 0), Читаю (ожидаю) данные в потоке. Отсылаю по кнопке. Но вот тут и косяки. WriteFile не хочет слать, возвращает 0... По организации COM вообще делал почти наугад, так что может поудачнее можно? Код (Text): .386 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD GetMsg PROTO SendMsg PROTO .data dlgname db "MAIN",0 szTitle db "Window Sizer",0 szerr db "Error",0 texst db "Text",0 errmes db "Error open COM1",0 lineErr db "Line now bisy", 0 com db "COM1",0 over OVERLAPPED <> dcb DCB <> endprog db 0 data db 300 dup (0) buffer db 300 dup (0) .data? hInstance dd ? hWnd dd ? flag db ? dwSignal dd ? hList dd ? hBox dd ? hCom dd ? .code start: invoke GetModuleHandle, NULL mov hInstance, eax invoke DialogBoxParam,hInstance,ADDR dlgname,0,ADDR WndProc,0 call CloseCom invoke ExitProcess,eax WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD .if uMsg == WM_INITDIALOG mov eax, hWin mov hWnd, eax invoke LoadIcon,hInstance,100 invoke SendMessage,hWin,WM_SETICON,1,eax invoke GetDlgItem,hWin,1000 mov hList,eax invoke GetDlgItem,hWin,2000 mov hBox,eax invoke SetFocus, hBox call InitCom invoke CreateThread,0,0,GetMsg, 0, 0, 0 .elseif uMsg == WM_COMMAND mov eax, wParam .if wParam == 100 ; кнопка Send invoke GetDlgItemText, hWin, 2000, ADDR buffer, 300 call SendMsg .endif and eax,0FFFFh .if eax == 1000 ; Listbox mov eax,wParam shr eax,16 .if eax == LBN_DBLCLK invoke SendMessage,hList,LB_GETCURSEL,0,0 invoke SendMessage,hList,LB_GETTEXT,eax,ADDR buffer invoke MessageBox,hWnd,ADDR buffer,ADDR texst,MB_OK .endif .endif .elseif uMsg == WM_CLOSE invoke EndDialog,hWin,0 .endif xor eax,eax ret WndProc endp InitCom proc invoke CreateFile,addr com, GENERIC_READ or GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL mov hCom, eax .if hCom == INVALID_HANDLE_VALUE invoke MessageBox,hWnd,addr errmes,addr szerr,MB_OK ret .endif invoke GetCommState, hCom, addr dcb mov dcb.BaudRate, CBR_2400 mov dcb.ByteSize, 8 mov dcb.StopBits, ONESTOPBIT mov dcb.Parity, ODDPARITY invoke SetCommState,hCom, addr dcb invoke GetCommMask, hCom, dwSignal invoke SetCommMask, hCom, EV_RXCHAR ;invoke CreateEvent, NULL, FALSE, FALSE, NULL ;mov over.hEvent, eax xor eax, eax ret InitCom endp GetMsg proc local bytes:BYTE loopget: invoke WaitCommEvent,hCom, addr dwSignal, NULL mov flag, 1 ; флаг использования порта (получаем данные) invoke ReadFile,hCom, addr data, sizeof data, addr bytes, NULL mov flag, 0 ; освободили линию invoke SendMessage,hList,LB_ADDSTRING,NULL,addr data ;and add it to the list box jmp loopget ret GetMsg endp SendMsg proc local bytes:BYTE .if flag == 0 invoke WriteFile, hCom, addr buffer, sizeof buffer, addr bytes, NULL .elseif invoke MessageBox,hWnd,addr lineErr,addr szerr,MB_OK .endif ret SendMsg endp CloseCom proc invoke CloseHandle, over.hEvent invoke CloseHandle, hCom mov hCom, 0 ret CloseCom endp end start
Вот тебе пример, ищи ошибку у себя. Пример на Си, но там все просто: Код (Text): //инициализация BOOL serial_init(LPCTSTR lpCommPort) { m_hComm = CreateFile(lpCommPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (m_hComm == INVALID_HANDLE_VALUE) { return FALSE; } DCB dcb; if( !GetCommState(m_hComm, &dcb) ){ return FALSE; } //Здесь можно просто заполнить DCB if( !BuildCommDCB(_T("baud=9600 parity=N data=8 stop=2"), &dcb)) { return FALSE; } if(!SetCommState(m_hComm, &dcb)) { return FALSE; } if(!SetCommMask(m_hComm, EV_BREAK | EV_RXCHAR)){ return FALSE; } if(!SetupComm(m_hComm, 1024, 1024)){//буфера на прием/передачу return FALSE; } return TRUE; } //Запись в порт BOOL write_port(LPBYTE buf, DWORD len) { COMSTAT cs; DWORD dwBytes, dwBytesSent = 0, dwError; DWORD dwBytesToWrite; dwBytesToWrite = len; CString str, szString; OVERLAPPED osWrite; osWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if( !WriteFile(m_hComm, buf, len, &dwBytes, &osWrite ) ) { if(GetLastError() == ERROR_IO_PENDING) { while(!GetOverlappedResult(m_hComm,&osWrite,&dwBytes,TRUE)) { dwError = GetLastError(); if(dwError == ERROR_IO_INCOMPLETE) { dwBytesSent += dwBytes; continue; } else { ClearCommError(m_hComm,&dwError,&cs); break; } } } dwBytesSent += dwBytes; if( dwBytesSent != dwBytesToWrite ) { ///error timeout } else { //ok } } else { ClearCommError(m_hComm, &dwError, &cs ); return FALSE; } } return TRUE; } что-то типа того... на самом деле в MSDN был где-то пример даже нормальной работы с COM-портом.
Блииин... Дайте простой пример без оверлапа, плиз. Кстати, WriteFile возвращает true только если кабель соединён с другим компом? Вот на Си, но в линию всё равно нихрена не пишется... Код (Text): #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <commdlg.h> #include <commctrl.h> #include <SHELLAPI.H> #include "resource.h" // prototype des fonctions BOOL CALLBACK DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam); void InitCom(); void SetEventCom(); void CloseCOM(); void ComError(); // declaration variables globales HWND hList; HANDLE hCom; HWND hWin; HINSTANCE Hinstance; char data[MAX_PATH]; DCB dcb; OVERLAPPED over; DWORD dwSignal; BYTE end = 0; DWORD bytes; ///////////////////////////////////////////////////////////////////////////////////////// DWORD WINAPI MainCom(void) { while (end!=1) { if ( WaitCommEvent(hCom, &dwSignal,NULL)) { ReadFile (hCom, data, sizeof data, &bytes, NULL); } } return true; } void SendMSG() { WriteFile (hCom, data, sizeof data, &bytes, NULL); //MessageBox(hWin,"Error write data in COM1 - Line is busy","Error",MB_OK); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { Hinstance = hInstance; DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DlgProc,NULL); return 0; } BOOL CALLBACK DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam) { switch (uMsg) { case WM_CLOSE: EndDialog(hWnd,0); break; case WM_INITDIALOG: hWin = hWnd; InitCom(); SetEventCom(); DWORD dwThreadId; CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MainCom,NULL,0,&dwThreadId); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BUTTON_SEND: SendMSG(); break; } case WM_NOTIFY: LPNMHDR nmhdr; nmhdr = (LPNMHDR)lParam; break; default: return FALSE; } return TRUE; } void InitCom() { hCom = CreateFile ("COM1", GENERIC_READ | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (hCom == INVALID_HANDLE_VALUE) { MessageBox(hWin,"Error open COM1","Error",MB_OK); ComError (); } if (!GetCommState(hCom, &dcb)) { MessageBox(hWin,"Error get COM1 state","Error",MB_OK); ComError (); } dcb.BaudRate = CBR_2400; dcb.ByteSize = 8; dcb.StopBits = ONESTOPBIT; dcb.Parity = ODDPARITY; if (!SetCommState(hCom, &dcb)) { MessageBox(hWin,"Error set COM1 state","Error",MB_OK); ComError (); } } void SetEventCom () { if (!SetCommMask (hCom, EV_RXCHAR)) ComError (); over.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); if (!over.hEvent) ComError (); } void CloseCOM () { if (over.hEvent) { CloseHandle (over.hEvent); } if (hCom) { CloseHandle (hCom); hCom = NULL; } } void ComError () { CloseCOM (); EndDialog(hWin,0); TerminateProcess (Hinstance, NULL); }
Обрисую ситуацию - есть пример, есть описание чтения\записи, есть сделанная по этому делу программа. Выходные данные - сделанная по всем правилам программа не работает. Вопрос - WTF!? А асинхронное чтение\запись ничего к этому не даст, кроме замутной проверки выполнения. Вообщем, медленно к чему-то прихожу. WriteFile уже не завершается с ошибкой, а подвешивает прогу. Уже прогресс)
Freecod Проверь определение структуры DCB. Кажется в Windows.inc была ошибка: DCB STRUC DCBlength dd ? ;// sizeof(DCB) BaudRate dd ? ;// current baud rate fBinary dd ? ;// binary mode, no EOF check fParity dd ? ;// enable parity checking fOutxCtsFlow dd ? ;// CTS output flow control fOutxDsrFlow dd ? ;// DSR output flow control fDtrControl dd ? ;// DTR flow control type fDsrSensitivity dd ? ;// DSR sensitivity fTXContinueOnXoff dd ? ;// XOFF continues Tx fOutX dd ? ;// XON/XOFF out flow control fInX dd ? ;// XON/XOFF in flow control fErrorChar dd ? ;// enable error replacement fNull dd ? ;// enable null stripping fRtsControl dd ? ;// RTS flow control fAbortOnError dd ? ;// abort reads/writes on error fDummy2 dd ? ;// reserved wReserved dw ? ;// not currently used XonLim dw ? ;// transmit XON threshold XoffLim dw ? ;// transmit XOFF threshold ByteSize db ? ;// number of bits/byte, 4-8 Parity db ? ;// 0-4=no,odd,even,mark,space StopBits db ? ;// 0,1,2 = 1, 1.5, 2 XonChar db ? ;// Tx and Rx XON character XoffChar db ? ;// Tx and Rx XOFF character ErrorChar db ? ;// error replacement character EofChar db ? ;// end of input character EvtChar db ? ;// received event character wReserved1 dw ? ;// reserved; do not use DCB ENDS
Всё и веселее веселее =) Что то странное творится. Первый вызов ReadFile читает из линии 8 байт! из длинной строки. А второй дочитывает всё, что осталось... Да и действует он не как асинхронная функция... Возращяет единицу, уже после чтения данных, т.е. не возвращяет управление сразу назад. Без оверлапа вообще нифига не читает... MikDay: структура была другой, не было некоторых пунктов, я это пофиксил, но разницы не заметно. PS. Это клиент. От сервера косяки не зависят, проверенно. Код (Text): .386 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD GetMsg PROTO SendMsg PROTO .data dlgname db "MAIN",0 szTitle db "Window Sizer",0 szerr db "Error",0 texst db "Text",0 errmes db "Error open COM1",0 lineErr db "Line now bisy", 0 com db "COM1",0 over OVERLAPPED <> dcb DCB <> endprog db 0 bytes dd 0 data db 300 dup (0) .data? hInstance dd ? hWnd dd ? flag db ? dwSignal dd ? hList dd ? hBox dd ? hCom dd ? .code start: invoke GetModuleHandle, NULL mov hInstance, eax invoke DialogBoxParam,hInstance,ADDR dlgname,0,ADDR WndProc,0 invoke ExitProcess,eax WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD pusha .if uMsg == WM_INITDIALOG mov eax, hWin mov hWnd, eax invoke LoadIcon,hInstance,100 invoke SendMessage,hWin,WM_SETICON,1,eax invoke GetDlgItem,hWin,1000 mov hList,eax call InitCom .elseif uMsg == WM_COMMAND mov eax, wParam .if wParam == 100 ; кнопка Send invoke WaitCommEvent,hCom, addr dwSignal, NULL invoke ReadFile,hCom, addr data, 200, addr bytes, addr over mov eax, offset data add eax, 8 invoke ReadFile,hCom, eax, 200, addr bytes, addr over invoke Sleep, 3000 invoke MessageBox,0,addr data,addr szerr,MB_OK invoke SendMessage,hList,LB_ADDSTRING,NULL,addr data ;and add it to the list box .endif and eax,0FFFFh .if eax == 1000 ; Listbox mov eax,wParam shr eax,16 .if eax == LBN_DBLCLK invoke SendMessage,hList,LB_GETCURSEL,0,0 invoke SendMessage,hList,LB_GETTEXT,eax,ADDR data invoke MessageBox,hWnd,ADDR data,ADDR texst,MB_OK .endif .endif .elseif uMsg == WM_CLOSE invoke EndDialog,hWin,0 .endif popa xor eax,eax ret WndProc endp InitCom proc invoke CreateFile,addr com, GENERIC_READ or GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL mov hCom, eax .if hCom == INVALID_HANDLE_VALUE invoke MessageBox,hWnd,addr errmes,addr szerr,MB_OK ret .endif invoke GetCommState, hCom, addr dcb mov dcb.BaudRate, CBR_2400 mov dcb.ByteSize, 8 mov dcb.StopBits, ONESTOPBIT mov dcb.Parity, ODDPARITY invoke SetCommState,hCom, addr dcb invoke GetCommMask, hCom, dwSignal invoke SetCommMask, hCom, EV_RXCHAR ; EV_DSR EV_RXCHAR EV_CTS ;invoke CreateEvent, NULL, FALSE, FALSE, NULL ;mov over.hEvent, eax xor eax, eax ret InitCom endp CloseCom proc invoke CloseHandle, over.hEvent invoke CloseHandle, hCom mov hCom, 0 ret CloseCom endp end start
Найдена ось зла, корень зол и красная угроза =) COM - неразделяемый ресурс, и когда мы висим в ожидании на WaitCommEvent в программе 2в1 из первого поста, мы ничего не можем закатать через WriteFile! Собстно, новая проблема - как на время освободить себе COM? Записать, и пусть он дальше себе ожидает. Ведь можно мониторить линию только приема\только передачи, но при этом сам ком ведь так же занят? Как быть? Есть свежие идеи? ###### Вообщем, и это уже не проблема. Грохаю поток чтения, пишу и снова поток запускаю. Но COM так просто не сдаётся. Латинские символы и цифры передаются без проблем, а вот из русских букв вычитается 80h (EF = 6F, из 'п' получаем 'o')... Прямо не знаю что за нах...
убедись что не настроен прием/передача на 7 бит. Это еще кстати зависит от девайса которому посылаешь