2013-09-30 51 views
2

我正在使用筆記本電腦和Arduino進行通信的小型Linux服務器(在Beagleboard xM ARM計算機上運行的Ubuntu Server 13.04)。我似乎遇到的問題是關於Arduino和Beagleboard之間的通信。該程序將運行一段時間,大約30秒左右,然後停止。該程序將保持運行,但端口顯然凍結。Linux C串行程序凍結

我正在運行的程序目前只是一個測試程序,將掃描一定範圍內的伺服。用於設置端口功能的代碼被發現here

我的程序代碼如下,在單獨的線程中發現的代碼的異常:

#include <errno.h> 
    #include <termios.h> 
    #include <stdio.h> 
    #include <string.h> 
    #include <fcntl.h> 
    #include <unistd.h> 
    #include <iostream> 

    using namespace std; 

    ... 

    int main (int argc, const char* argv[]) { 
     cout << "TestIO running...\n"; 
     char* portname = "/dev/ttyACM0"; 
     // Open serial port 
     int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); 

     // Return error if port cannot be opened 
     if (fd < 0) 
     { 
       cout << "error " << errno << " opening " << portname << ": " << strerror (errno) << "\n"; 
       return -1; 
     } 

     set_interface_attribs (fd, B9600, 0); // set speed to 9600 bps, 8n1 (no parity) 
     set_blocking (fd, 0);     // set no blocking 

     // Read from serial port 
     //char inputBuffer[64]; 
     //int inputLength = read(fd, inputBuffer, sizeof inputBuffer); 

     double output = 575; 
     char outputString[255]; 
     char outputLength; 
     int incrimentor = 1; 
     char inChar; 
     for(;;) { 
       if (output >= 675) 
         incrimentor = -1; 
       else if (output <= 375) 
         incrimentor = 1; 
       output += incrimentor; 

       // Sweep wheels on car, set drive motor to 0 
       outputLength = sprintf(outputString, "%0.2f", output); 
       write(fd, outputString, outputLength); 
       write(fd, ",", 1); 
       write(fd, "0", 1); 
       write(fd, "\n", 1); 

       cout << outputString << "\n"; 

       // Sleep thread for 5000 uS (5 ms) 
       usleep(5000); 
     } 
     close(fd); 
     return 0; 
} 

在一個稍微不同的說明,當程序沒有響應,我必須強迫它退出代碼以關閉端口永遠不會到達,因此我不能再次運行程序來測試它。我很好奇,如果有人可能知道如何通過終端中運行的Linux命令關閉串口。

謝謝!

+0

它需要1毫秒〜輸出1和焦炭在9600波特。你正在睡5ms。每5ms輸出多少個字符?你使用什麼流量控制? –

+0

這是一個很好的觀點,目前我每送六個循環,未來我會送八加。然而,我試圖在循環之間延遲10ms,這仍然以相同的結果結束。我實際上沒有計算時間,但我認爲它可能會運行一段時間。這讓我相信有一個數據類型被溢出了,但我看了又找不到。至於流量控制,我目前沒有使用任何,這條線是異步的。 – SuperUser320

回答

0

參考有關如何退出掛程序你的第二個問題:

添加返回值的測試,所有的系統調用是一般的好主意!

請注意,read()/write()不需要讀入/寫出儘可能多的數據。

還有read()/write()如果進程收到信號則返回。

這裏特別附加測試結果可能會阻止呼叫(write()):

ssize_t writen(int fd, char * buffer, size_t size) 
{ 
    ssize_t written_total = 0; 
    ssize_t written = 0; 

    while (outputLength > written_total) 
    { 
    written = write(fd, buffer + written_total, size - written_total); 
    if (-1 == written) 
    { 
     if (EINTR == errno) 
     { 
     /* interupted by signal -> break and leave */ 
     break; 
     } 
     elseif ((EAGAIN == errno) || (EWOULDBLOCK == errno)) 
     { 
     continue; /* try again */ 
     } 

     /* another error occured -> log, break and leave */ 

     break; 
    } 

    written_total += written; 
    } 

    if (outputLength > written_total) 
    { 
    if (-1 = written) 
    { 
     /* handle error */ 
    } 
    else 
    { 
     /* notify of interruption */ 
    } 
    } 
    else 
    { 
    /* log succesfully transmission of all data */ 
    } 

    return written_total; 
} 

int main() 
{ 
    ... 

    do 
    { 
    if (outputLength != writen(fd, outputString, outputLength)) 
    { 
     fprintf(stderr, "writen(fd, outputString, outputLength) failed"); 
     break; 
    } 

    if (1 != writen(fd, ",", 1)) 
    { 
     fprintf(stderr, "writen(fd, ",", 1)) failed"); 
     break; 
    } 

    if (1 != writen(fd, "0", 1)) 
    { 
     fprintf(stderr, "writen(fd, "0", 1)) failed"); 
     break; 
    } 

    if (1 != writen(fd, "\n", 1)) 
    { 
     fprintf(stderr, "writen(fd, "\n", 1)) failed"); 
     break; 
    } 
    } while (0); 

    if (-1 == close(fd)) 
    { 
    perror("close() failed"); 
    } 

    ... 
} 

注意,該方案還需要有註冊的信號處理程序(SIGUSR1例如),什麼也不做,但是「吃」了信號。

然後從你可以通過執行容易的未塊中的程序的命令行:

$ kill <program-pid> -SIGUSR1 
+0

謝謝!似乎運作良好,我會upvote你的答案,但我沒有足夠的代表,所以謝謝!這會爲我節省很多時間。 – SuperUser320