2015-04-21 41 views
1

我創建了2個函數來讀取和寫入一個串行端口,我使用Visual Studio 2012,Windows 7,64位操作系統和使用RS-232串行線編碼C++。我連接的板子應該按下按鈕發送5個字符,TRG 1,代碼有效,但輸出並不總是正確的值。串行通信C++讀取文件()

char serialRead() 
{ 
    char input[5]; 
    DCB dcBus; 
    HANDLE hSerial; 
    DWORD bytesRead, eventMask; 
    COMMTIMEOUTS timeouts; 
    hSerial = CreateFile (L"\\\\.\\COM13", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 
    if (hSerial == INVALID_HANDLE_VALUE) 
    { 
     cout << "error opening handle\n"; 
    } 
    else 
    { 
     cout << "port opened\n"; 
    } 
    dcBus.DCBlength = sizeof(dcBus); 
    if ((GetCommState(hSerial, &dcBus) == 0)) 
    { 
     cout << "error getting comm state\n"; 
    } 
    dcBus.BaudRate = CBR_9600; 
    dcBus.ByteSize = DATABITS_8; 
    dcBus.Parity = NOPARITY; 
    dcBus.StopBits = ONESTOPBIT; 
    if ((GetCommState(hSerial, &dcBus) == 0)) 
    { 
     cout << "error setting comm state\n"; 
    } 
    if ((GetCommTimeouts(hSerial, &timeouts) == 0)) 
    { 
     cout << "error getting timeouts\n"; 
    } 
    timeouts.ReadIntervalTimeout = 10; 
    timeouts.ReadTotalTimeoutMultiplier = 1; 
    timeouts.ReadTotalTimeoutConstant = 500; 
    timeouts.WriteTotalTimeoutMultiplier = 1; 
    timeouts.WriteTotalTimeoutConstant = 500; 
    if (SetCommTimeouts(hSerial, &timeouts) == 0) 
    { 
     cout << "error setting timeouts\n"; 
    } 
    if (SetCommMask(hSerial, EV_RXCHAR) == 0) 
    { 
     cout << "error setting comm mask\n"; 
    } 
    if (WaitCommEvent(hSerial, &eventMask, NULL)) 
    { 
     if (ReadFile(hSerial, &input, 5, &bytesRead, NULL) !=0) 
     { 
      for (int i = 0; i < sizeof(input); i++) 
      { 
       cout << input[i]; 
      } 
      cout << endl; 
     } 
     else 
     { 
      cout << "error reading file\n"; 
     } 
    } 
    else 
    { 
     cout << "error waiting for comm event\n"; 
    } 
    switch (input[4]) 
    { 
    case '1' : 
     CloseHandle(hSerial); 
     return '1'; 
     break; 
    case '2' : 
     CloseHandle(hSerial); 
     return '2'; 
     break; 
    case '3' : 
     CloseHandle(hSerial); 
     return '3'; 
     break; 
    case '4' : 
     CloseHandle(hSerial); 
     return '4'; 
     break; 
    case '5': 
     CloseHandle(hSerial); 
     return '5'; 
     break; 
    default : 
     CloseHandle(hSerial); 
     return '9'; 
     break; 
    } 
} 

代碼運行成功,意思是端口配置正確並且數據正在傳輸。輸出會有所不同,大多數情況下輸出將打印整個「TRG 1」,但隨機(看起來),輸出將爲「TRG |} |}」或「T |} |} |} |}」即它將成爲字符串的一部分,每個缺失的字符將被替換爲「|}」而不是正確的字符。這是一個問題,因爲我希望能夠發送不同的觸發值並運行該變量的開關。

我是比較新的串行通信,而不是專家程序員,所以我想知道發生了什麼?

+3

檢查readFile()返回的bytesRead的值 – zdan

+0

@zdan我在ReadFile後面插入了'cout << sizeof(bytesRead)<< endl;',它每次都返回4,即使它返回「TRG 1」或「TRG |} |}」或「T |} |} |} |}」 – jschnitz1

+3

不,sizeof(bytesRead)告訴您包含bytesRead的DWORD的大小(當然是4)。只要做cout << bytesRead << endl; – zdan

回答

4

串行通信不是基於數據包的。這些信息並不包含在整個信息必須一次閱讀的包中;相反,它是一個流,所以你可以閱讀半條消息,一條完整消息,多條消息等。

正如zdan在評論中所說的,你需要檢查從ReadFile中讀取的字節數,並用它來組成5個字符的包,這是你的消息。 具體而言,只有第一對字符直到返回的字節數纔有效;其餘的都是垃圾。

+0

所以我需要添加一個循環來執行readfile 1個字節,直到5個字節被讀取?那麼每次都應該返回完整的字符流? – jschnitz1

+0

這個答案在解釋遇到的問題時起作用,找到了解決方案,將readfile函數限制爲從緩衝區一次讀取1個字節,直到找到正確數量的字符 – jschnitz1