2013-04-02 73 views
5

我正在通過USB連接將數據作爲串行端口與PL2303驅動程序一起讀取。它在做一個open並且當我設置他們的TTY選項和非阻塞時成功返回。當我嘗試關閉連接時,它會掛起。在這種狀態下,它讀取「 」而不是字符。關閉串行端口連接時程序掛起

我可以用cutecom連接到設備上,完美無瑕。這是奇怪的部分:

  1. 如果我第一次通過cutecom(一個串行監視器)連接到設備,我的程序將連接和關閉後每次都完全罰款。它讀取字符,因爲我期望他們閱讀。 (否)。
  2. 如果我斷開並重新連接硬件,我的程序將再次掛起,直到我運行cutecom。

因爲它在我使用cutecom後工作,它讓我覺得我在我的初始連接或連接設置中缺少一些東西。這是我用來連接:

baud_rate = 38400; 
fd = open (device_path, O_RDONLY | O_NOCTTY); 

在我set_tty_options功能:

struct termios tty_options; 

memset (&tty_options, 0, sizeof(tty_options)); 
tcgetattr (fd, &tty_options); 

cfsetispeed(&tty_options, baud_rate);       // set baud rate 
tty_options.c_cflag = (tty_options.c_cflag & ~CSIZE) | CS8; // 8 bit msgs 
tty_options.c_cflag |= (CLOCAL | CREAD);      // enable reading 

tty_options.c_cflag &= ~(PARENB | PARODD);     // shut off parity 
tty_options.c_cflag |= parity; 
tty_options.c_cflag &= ~CSTOPB; 
tty_options.c_cflag &= ~CRTSCTS; 

if (tcsetattr (fd, TCSANOW, &tty_options) != 0) 
{ 
    printf("error %d from tcsetattr\n", errno); 
    return TTY_ERROR; 
} 

set_blocking功能:

if (tcgetattr (fd, &tty) != 0) 
{ 
    printf("error %d from tggetattr", errno); 
    return FAILURE; 
} 

// 0 or 1 byte is enough to return from read 
tty.c_cc[VMIN] = should_block ? 1 : 0; 
tty.c_cc[VTIME] = 5;   // 0.5 seconds read timeout 

if (tcsetattr (fd, TCSANOW, &tty) != 0) 
{ 
    printf("error %d setting term attributes", errno); 
    return FAILURE; 
} 
+0

我看到2代碼的問題。首先是'set_tty_options'函數似乎沒有完全初始化'tty_options'結構。這可以解釋爲「如果我先運行X,我的程序會運行,但如果單獨運行,則會掛起/失敗。」這是程序的典型症狀,不能正確或完全初始化其環境。其次,'set_blocking'函數對於規範輸入是僞造的。 'c_cc [VMIN]'和'c_cc [VTIME]'只能用於**非規範**(又名原始)輸入。對於規範輸入的非阻塞'read()',使用'fcntl()'來設置它。 – sawdust

回答

0

這是我最終做的。我通過基本上覆制和粘貼來自cutecom's源代碼的部分來解決這個問題。

  1. 打開當...

    int fd, n; 
    fd = open (device_path, O_RDONLY | O_NOCTTY | O_NDELAY); 
    
    ... error check fd ... 
    
    n = fcntl(ail_info->ail_serial_fd, F_GETFL, 0); 
    fcntl(fd, F_SETFL, n & ~O_NDELAY); 
    
  2. ,因爲我是做你不能設置波特率。您必須使用已定義的B38400;

    baud = B38400;

  3. 然後,我添加wallyk的答案。

    tty_settings.c_lflag = 0;

編輯:按鋸末評論,我發現了一個更好的辦法將它設置爲原始輸入。

tty_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 

它的工作原理。

+0

*「然後,我添加了wallyk的答案。tty_settings.c_lflag = 0;」* - 您還沒有正確配置串口。什麼是'c_oflag'設置?請注意,對於每個POSIX,不建議對'termios'結構成員進行硬分配。你應該調用'tcgetattr()',然後啓用或禁用每個屬性字段(就像你爲'c_cflag'所做的那樣)。請參閱[串行編程指南POSIX操作系統](http://www.easysw.com/~mike/serial/serial.html)。您正在使用POSIX呼叫,請遵循其規則。 – sawdust

1

我想你想添加| O_SYNC到開旗堅持在同步I/O上。我懷疑這是造成問題,但。

不過,我想你想忽略中斷信號,它就像你正在被報告爲NULL字符:

tty_settings.c_iflag &= ~IGNBRK;   // ignore break signal 

而且,你要確保輸入處理完全關閉,讓收到退格的,^ C,^ \,等不觸發任何反應:

tty_settings.c_lflag = 0;    // no signaling chars, no echo, 
             // no canonical processing 

看起來你已經在使用my set_blocking() function,所以應該沒問題。