Многострадальный COM1

Тема в разделе "WASM.WIN32", создана пользователем Freecod, 9 окт 2007.

  1. Freecod

    Freecod New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2006
    Сообщения:
    136
    Back in ...
    Вообщем, одна программа и отсылает, и принимает данные на COM1.
    Вроде инициализирую, устанавливаю маску событий без проблем (правда GetCommMask вернул 0),
    Читаю (ожидаю) данные в потоке.
    Отсылаю по кнопке. Но вот тут и косяки. WriteFile не хочет слать, возвращает 0...
    По организации COM вообще делал почти наугад, так что может поудачнее можно?
    Код (Text):
    1. .386
    2. .model flat, stdcall
    3. option casemap :none  
    4.  
    5. include \masm32\include\windows.inc
    6. include \masm32\include\user32.inc
    7. include \masm32\include\kernel32.inc
    8. includelib \masm32\lib\user32.lib
    9. includelib \masm32\lib\kernel32.lib
    10.  
    11. WndProc  PROTO :DWORD,:DWORD,:DWORD,:DWORD
    12. GetMsg   PROTO
    13. SendMsg  PROTO
    14.  
    15. .data
    16.     dlgname     db "MAIN",0
    17.     szTitle     db "Window Sizer",0
    18.     szerr       db "Error",0
    19.     texst       db "Text",0
    20.     errmes      db "Error open COM1",0
    21.     lineErr     db "Line now bisy", 0
    22.     com         db "COM1",0
    23.     over        OVERLAPPED <>
    24.     dcb         DCB <>
    25.     endprog     db 0
    26.     data        db 300 dup (0)
    27.     buffer      db 300 dup (0)
    28. .data?
    29.     hInstance   dd ?
    30.     hWnd        dd ?
    31.     flag        db ?
    32.     dwSignal    dd ?
    33.     hList       dd ?
    34.     hBox        dd ?
    35.     hCom        dd ?
    36. .code
    37. start:
    38.     invoke GetModuleHandle, NULL
    39.     mov hInstance, eax        
    40.     invoke DialogBoxParam,hInstance,ADDR dlgname,0,ADDR WndProc,0
    41.     call CloseCom
    42.     invoke ExitProcess,eax
    43.  
    44. WndProc proc hWin:DWORD,
    45.              uMsg:DWORD,
    46.              wParam:DWORD,
    47.              lParam:DWORD
    48.              
    49.     .if uMsg == WM_INITDIALOG
    50.         mov eax, hWin
    51.         mov hWnd, eax
    52.         invoke LoadIcon,hInstance,100
    53.         invoke SendMessage,hWin,WM_SETICON,1,eax
    54.         invoke GetDlgItem,hWin,1000                    
    55.         mov hList,eax  
    56.         invoke GetDlgItem,hWin,2000                    
    57.         mov hBox,eax
    58.         invoke SetFocus, hBox
    59.         call InitCom   
    60.         invoke CreateThread,0,0,GetMsg, 0, 0, 0
    61.     .elseif uMsg == WM_COMMAND
    62.         mov eax, wParam
    63.         .if wParam == 100  ; кнопка Send
    64.             invoke GetDlgItemText, hWin, 2000, ADDR buffer, 300
    65.             call SendMsg
    66.         .endif 
    67.         and eax,0FFFFh
    68.         .if eax == 1000   ; Listbox
    69.             mov eax,wParam
    70.             shr eax,16
    71.             .if eax == LBN_DBLCLK
    72.                 invoke SendMessage,hList,LB_GETCURSEL,0,0
    73.                 invoke SendMessage,hList,LB_GETTEXT,eax,ADDR buffer
    74.                 invoke MessageBox,hWnd,ADDR buffer,ADDR texst,MB_OK
    75.             .endif
    76.         .endif 
    77.     .elseif uMsg == WM_CLOSE
    78.         invoke EndDialog,hWin,0
    79.     .endif
    80.     xor eax,eax
    81.     ret
    82. WndProc endp
    83.  
    84. InitCom proc
    85.     invoke CreateFile,addr com, GENERIC_READ or GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL
    86.     mov hCom, eax
    87.     .if hCom == INVALID_HANDLE_VALUE
    88.         invoke MessageBox,hWnd,addr errmes,addr szerr,MB_OK
    89.         ret
    90.     .endif
    91.     invoke GetCommState, hCom, addr dcb
    92.     mov dcb.BaudRate, CBR_2400
    93.     mov dcb.ByteSize, 8
    94.     mov dcb.StopBits, ONESTOPBIT
    95.     mov dcb.Parity, ODDPARITY
    96.     invoke SetCommState,hCom, addr dcb
    97.     invoke GetCommMask, hCom, dwSignal
    98.     invoke SetCommMask, hCom, EV_RXCHAR
    99.     ;invoke CreateEvent, NULL, FALSE, FALSE, NULL
    100.     ;mov over.hEvent, eax
    101.     xor eax, eax
    102.     ret
    103. InitCom endp
    104.  
    105. GetMsg proc
    106.             local bytes:BYTE
    107. loopget:
    108.     invoke WaitCommEvent,hCom, addr dwSignal, NULL
    109.     mov flag, 1 ; флаг использования порта (получаем данные)
    110.     invoke ReadFile,hCom, addr data, sizeof data, addr bytes,  NULL
    111.     mov flag, 0 ; освободили линию
    112.     invoke SendMessage,hList,LB_ADDSTRING,NULL,addr data  ;and add it to the list box
    113.     jmp loopget
    114.     ret
    115. GetMsg endp
    116.  
    117. SendMsg proc
    118.             local bytes:BYTE           
    119.     .if flag == 0
    120.         invoke WriteFile, hCom, addr buffer, sizeof buffer, addr bytes, NULL
    121.     .elseif
    122.         invoke MessageBox,hWnd,addr lineErr,addr szerr,MB_OK
    123.     .endif
    124.     ret
    125. SendMsg endp
    126. CloseCom proc
    127.     invoke CloseHandle, over.hEvent
    128.     invoke CloseHandle, hCom
    129.     mov hCom, 0
    130.     ret
    131. CloseCom endp
    132. end start
     
  2. hybrid

    hybrid New Member

    Публикаций:
    0
    Регистрация:
    2 авг 2007
    Сообщения:
    42
    Вот тебе пример, ищи ошибку у себя. Пример на Си, но там все просто:
    Код (Text):
    1. //инициализация
    2. BOOL serial_init(LPCTSTR lpCommPort)
    3. {
    4.          m_hComm = CreateFile(lpCommPort,
    5.         GENERIC_READ | GENERIC_WRITE, 0, NULL,
    6.         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    7.  
    8.     if (m_hComm == INVALID_HANDLE_VALUE)
    9.     {
    10.         return FALSE;
    11.     }
    12.  
    13.     DCB dcb;
    14.  
    15.     if( !GetCommState(m_hComm, &dcb) ){
    16.         return FALSE;
    17.     }
    18.         //Здесь можно просто заполнить DCB
    19.     if( !BuildCommDCB(_T("baud=9600 parity=N data=8 stop=2"), &dcb))
    20.         {
    21.         return FALSE;
    22.     }
    23.     if(!SetCommState(m_hComm, &dcb))
    24.         {
    25.         return FALSE;
    26.     }
    27.  
    28.     if(!SetCommMask(m_hComm, EV_BREAK | EV_RXCHAR)){
    29.         return FALSE;
    30.     }
    31.     if(!SetupComm(m_hComm, 1024, 1024)){//буфера на прием/передачу
    32.         return FALSE;
    33.     }
    34.     return TRUE;
    35. }
    36. //Запись в порт
    37. BOOL  write_port(LPBYTE buf, DWORD len)
    38. {
    39.         COMSTAT cs;
    40.     DWORD dwBytes, dwBytesSent = 0, dwError;
    41.     DWORD dwBytesToWrite;
    42.     dwBytesToWrite = len;
    43.     CString str, szString;
    44.    
    45.     OVERLAPPED osWrite;
    46.     osWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    47.  
    48.         if( !WriteFile(m_hComm, buf, len, &dwBytes, &osWrite ) )
    49.         {
    50.                  if(GetLastError() == ERROR_IO_PENDING)
    51.                  {
    52.                        while(!GetOverlappedResult(m_hComm,&osWrite,&dwBytes,TRUE))
    53.                        {
    54.                                 dwError = GetLastError();
    55.                 if(dwError == ERROR_IO_INCOMPLETE)
    56.                 {
    57.                     dwBytesSent += dwBytes;
    58.                     continue;
    59.                 }
    60.                 else
    61.                 {
    62.                     ClearCommError(m_hComm,&dwError,&cs);
    63.                     break;
    64.                 }
    65.  
    66.                         }
    67.                   }
    68.                   dwBytesSent += dwBytes;
    69.          if( dwBytesSent != dwBytesToWrite )
    70.                  {
    71.                           ///error timeout
    72.                   }
    73.                   else
    74.                   {
    75.                           //ok
    76.                    }
    77.          }
    78.          else
    79.          {
    80.                ClearCommError(m_hComm, &dwError, &cs );
    81.                return FALSE;
    82.           }
    83.      }
    84.      return TRUE;
    85. }
    что-то типа того... на самом деле в MSDN был где-то пример даже нормальной работы с COM-портом.
     
  3. Freecod

    Freecod New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2006
    Сообщения:
    136
    Блииин...
    Дайте простой пример без оверлапа, плиз.
    Кстати, WriteFile возвращает true только если кабель соединён с другим компом?
    Вот на Си, но в линию всё равно нихрена не пишется...
    Код (Text):
    1. #define WIN32_LEAN_AND_MEAN
    2.  
    3. #include <windows.h>
    4. #include <commdlg.h>
    5. #include <commctrl.h>
    6. #include <SHELLAPI.H>
    7. #include "resource.h"
    8.  
    9. // prototype des fonctions
    10.  
    11. BOOL CALLBACK DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam);
    12. void InitCom();
    13. void SetEventCom();
    14. void CloseCOM();
    15. void ComError();
    16. // declaration variables globales
    17.  
    18. HWND hList;
    19. HANDLE hCom;
    20. HWND hWin;
    21. HINSTANCE Hinstance;
    22. char data[MAX_PATH];
    23. DCB dcb;
    24. OVERLAPPED over;
    25. DWORD dwSignal;
    26. BYTE end = 0;
    27. DWORD bytes;
    28. /////////////////////////////////////////////////////////////////////////////////////////
    29.  
    30. DWORD WINAPI MainCom(void)
    31. {
    32.     while (end!=1)
    33.     {
    34.         if ( WaitCommEvent(hCom, &dwSignal,NULL))
    35.             {
    36.                     ReadFile (hCom, data, sizeof data, &bytes,  NULL);
    37.             }
    38.     }
    39.     return true;
    40. }
    41.  
    42. void SendMSG()
    43. {
    44.         WriteFile (hCom, data, sizeof data, &bytes, NULL);
    45.         //MessageBox(hWin,"Error write data in COM1 - Line is busy","Error",MB_OK);
    46. }
    47.  
    48. int APIENTRY WinMain(HINSTANCE hInstance,
    49.                      HINSTANCE hPrevInstance,
    50.                      LPSTR lpCmdLine,
    51.                      int nShowCmd )
    52. {      
    53.     Hinstance = hInstance;
    54.     DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DlgProc,NULL);      
    55.     return 0;
    56. }
    57.  
    58.  
    59. BOOL CALLBACK DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam)
    60. {
    61.     switch (uMsg)
    62.     {
    63.     case WM_CLOSE:
    64.         EndDialog(hWnd,0);
    65.         break;
    66.        
    67.     case WM_INITDIALOG:
    68.         hWin = hWnd;
    69.         InitCom();
    70.         SetEventCom();
    71.         DWORD dwThreadId;
    72.         CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MainCom,NULL,0,&dwThreadId);
    73.         break;
    74.  
    75.     case WM_COMMAND:
    76.         switch(LOWORD(wParam))
    77.         {      
    78.         case IDC_BUTTON_SEND:
    79.             SendMSG();         
    80.             break; 
    81.         }
    82.  
    83.         case WM_NOTIFY:
    84.             LPNMHDR nmhdr;
    85.             nmhdr = (LPNMHDR)lParam;   
    86.             break;
    87.            
    88.         default:
    89.             return FALSE;
    90.     }
    91.     return TRUE;
    92. }
    93.  
    94. void InitCom() 
    95. {  
    96.     hCom = CreateFile ("COM1", GENERIC_READ | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    97.     if (hCom == INVALID_HANDLE_VALUE)
    98.     {
    99.         MessageBox(hWin,"Error open COM1","Error",MB_OK);
    100.         ComError ();
    101.     }
    102.     if (!GetCommState(hCom, &dcb))
    103.     {
    104.         MessageBox(hWin,"Error get COM1 state","Error",MB_OK);
    105.         ComError ();
    106.     }
    107.     dcb.BaudRate = CBR_2400;
    108.     dcb.ByteSize = 8;
    109.     dcb.StopBits = ONESTOPBIT;
    110.     dcb.Parity = ODDPARITY;
    111.     if (!SetCommState(hCom, &dcb))
    112.     {
    113.         MessageBox(hWin,"Error set COM1 state","Error",MB_OK);
    114.         ComError ();
    115.     }
    116. }
    117.  
    118. void SetEventCom ()
    119. {
    120.     if (!SetCommMask (hCom, EV_RXCHAR))
    121.         ComError ();
    122.     over.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    123.     if (!over.hEvent)
    124.         ComError ();
    125. }
    126.  
    127. void CloseCOM ()
    128. {
    129.     if (over.hEvent)
    130.     {
    131.         CloseHandle (over.hEvent);
    132.     }
    133.     if (hCom)
    134.     {
    135.         CloseHandle (hCom);
    136.         hCom = NULL;
    137.     }
    138. }
    139.  
    140. void ComError ()
    141. {
    142.     CloseCOM ();
    143.     EndDialog(hWin,0);
    144.     TerminateProcess (Hinstance, NULL);
    145. }
     
  4. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    нет такого.
     
  5. hybrid

    hybrid New Member

    Публикаций:
    0
    Регистрация:
    2 авг 2007
    Сообщения:
    42
    t00x прав... а чем тебе оверлап не нравится?
     
  6. Freecod

    Freecod New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2006
    Сообщения:
    136
    Нахрена нагромождать проверки, когда мне нужно просто прочитать и просто кинуть данные.
     
  7. hybrid

    hybrid New Member

    Публикаций:
    0
    Регистрация:
    2 авг 2007
    Сообщения:
    42
    хотя бы затем, чтобы понять что ты вообще читаешь и что происходит на порту.
     
  8. Freecod

    Freecod New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2006
    Сообщения:
    136
    Обрисую ситуацию - есть пример, есть описание чтения\записи, есть сделанная по этому делу программа. Выходные данные - сделанная по всем правилам программа не работает. Вопрос - WTF!?
    А асинхронное чтение\запись ничего к этому не даст, кроме замутной проверки выполнения.
    Вообщем, медленно к чему-то прихожу. WriteFile уже не завершается с ошибкой, а подвешивает прогу. Уже прогресс)
     
  9. hybrid

    hybrid New Member

    Публикаций:
    0
    Регистрация:
    2 авг 2007
    Сообщения:
    42
    а он работает?
    -что и следовало ожидать...
     
  10. MikDay

    MikDay New Member

    Публикаций:
    0
    Регистрация:
    5 май 2005
    Сообщения:
    32
    Адрес:
    Minsk
    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
     
  11. Freecod

    Freecod New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2006
    Сообщения:
    136
    Всё и веселее веселее =)
    Что то странное творится. Первый вызов ReadFile читает из линии 8 байт! из длинной строки. А второй дочитывает всё, что осталось... Да и действует он не как асинхронная функция... Возращяет единицу, уже после чтения данных, т.е. не возвращяет управление сразу назад. Без оверлапа вообще нифига не читает...
    MikDay: структура была другой, не было некоторых пунктов, я это пофиксил, но разницы не заметно.
    PS. Это клиент. От сервера косяки не зависят, проверенно.
    Код (Text):
    1. .386
    2. .model flat, stdcall
    3. option casemap :none  
    4.  
    5. include \masm32\include\windows.inc
    6. include \masm32\include\user32.inc
    7. include \masm32\include\kernel32.inc
    8. includelib \masm32\lib\user32.lib
    9. includelib \masm32\lib\kernel32.lib
    10.  
    11. WndProc  PROTO :DWORD,:DWORD,:DWORD,:DWORD
    12. GetMsg   PROTO
    13. SendMsg  PROTO
    14.  
    15. .data
    16.     dlgname     db "MAIN",0
    17.     szTitle     db "Window Sizer",0
    18.     szerr       db "Error",0
    19.     texst       db "Text",0
    20.     errmes      db "Error open COM1",0
    21.     lineErr     db "Line now bisy", 0
    22.     com         db "COM1",0
    23.     over        OVERLAPPED <>
    24.     dcb         DCB <>
    25.     endprog     db 0
    26.     bytes       dd 0
    27.     data        db 300 dup (0)
    28. .data?
    29.     hInstance   dd ?
    30.     hWnd        dd ?
    31.     flag        db ?
    32.     dwSignal    dd ?
    33.         hList       dd ?
    34.     hBox        dd ?
    35.     hCom        dd ?
    36.    
    37. .code
    38. start:
    39.     invoke GetModuleHandle, NULL
    40.     mov hInstance, eax        
    41.     invoke DialogBoxParam,hInstance,ADDR dlgname,0,ADDR WndProc,0
    42.     invoke ExitProcess,eax
    43.    
    44.  
    45. WndProc proc hWin:DWORD,
    46.              uMsg:DWORD,
    47.              wParam:DWORD,
    48.              lParam:DWORD
    49.              
    50.     pusha
    51.     .if uMsg == WM_INITDIALOG
    52.         mov eax, hWin
    53.         mov hWnd, eax
    54.         invoke LoadIcon,hInstance,100
    55.         invoke SendMessage,hWin,WM_SETICON,1,eax
    56.         invoke GetDlgItem,hWin,1000                    
    57.         mov hList,eax  
    58.         call InitCom   
    59.     .elseif uMsg == WM_COMMAND
    60.         mov eax, wParam
    61.         .if wParam == 100  ; кнопка Send
    62.             invoke WaitCommEvent,hCom, addr dwSignal, NULL
    63.             invoke ReadFile,hCom, addr data, 200, addr bytes,  addr over
    64.             mov eax, offset data
    65.             add eax, 8
    66.             invoke ReadFile,hCom, eax, 200, addr bytes,  addr over
    67.             invoke Sleep, 3000
    68.             invoke MessageBox,0,addr data,addr szerr,MB_OK
    69.             invoke SendMessage,hList,LB_ADDSTRING,NULL,addr data  ;and add it to the list box
    70.         .endif 
    71.        
    72.         and eax,0FFFFh
    73.         .if eax == 1000   ; Listbox
    74.             mov eax,wParam
    75.             shr eax,16
    76.             .if eax == LBN_DBLCLK
    77.                 invoke SendMessage,hList,LB_GETCURSEL,0,0
    78.                 invoke SendMessage,hList,LB_GETTEXT,eax,ADDR data
    79.                 invoke MessageBox,hWnd,ADDR data,ADDR texst,MB_OK
    80.             .endif
    81.             .endif 
    82.     .elseif uMsg == WM_CLOSE
    83.         invoke EndDialog,hWin,0
    84.     .endif
    85.     popa
    86.     xor eax,eax
    87.     ret
    88. WndProc endp
    89.  
    90. InitCom proc
    91.     invoke CreateFile,addr com, GENERIC_READ or GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL
    92.     mov hCom, eax
    93.     .if hCom == INVALID_HANDLE_VALUE
    94.         invoke MessageBox,hWnd,addr errmes,addr szerr,MB_OK
    95.         ret
    96.     .endif
    97.     invoke GetCommState, hCom, addr dcb
    98.     mov dcb.BaudRate, CBR_2400
    99.     mov dcb.ByteSize, 8
    100.     mov dcb.StopBits, ONESTOPBIT
    101.     mov dcb.Parity, ODDPARITY
    102.     invoke SetCommState,hCom, addr dcb
    103.     invoke GetCommMask, hCom, dwSignal
    104.     invoke SetCommMask, hCom, EV_RXCHAR  ; EV_DSR EV_RXCHAR EV_CTS
    105.     ;invoke CreateEvent, NULL, FALSE, FALSE, NULL
    106.     ;mov over.hEvent, eax
    107.     xor eax, eax
    108.     ret
    109. InitCom endp
    110.  
    111. CloseCom proc
    112.     invoke CloseHandle, over.hEvent
    113.     invoke CloseHandle, hCom
    114.     mov hCom, 0
    115.     ret
    116. CloseCom endp
    117. end start
     
  12. Freecod

    Freecod New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2006
    Сообщения:
    136
    Найдена ось зла, корень зол и красная угроза =)
    COM - неразделяемый ресурс, и когда мы висим в ожидании на WaitCommEvent в программе 2в1 из первого поста, мы ничего не можем закатать через WriteFile! Собстно, новая проблема - как на время освободить себе COM? Записать, и пусть он дальше себе ожидает. Ведь можно мониторить линию только приема\только передачи, но при этом сам ком ведь так же занят? Как быть? Есть свежие идеи?

    ######
    Вообщем, и это уже не проблема. Грохаю поток чтения, пишу и снова поток запускаю. Но COM так просто не сдаётся. Латинские символы и цифры передаются без проблем, а вот из русских букв вычитается 80h (EF = 6F, из 'п' получаем 'o')... Прямо не знаю что за нах...
     
  13. explosion

    explosion Member

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    34
    убедись что не настроен прием/передача на 7 бит. Это еще кстати зависит от девайса которому посылаешь