2013-04-02 34 views
5

Tôi đang đọc dữ liệu qua kết nối USB làm cổng nối tiếp với trình điều khiển PL2303. Nó trả về thành công khi thực hiện một số open và khi tôi đặt chúng tùy chọn TTY và không chặn. Khi tôi cố gắng đóng kết nối, nó bị treo. Trong trạng thái này nó đọc " " thay vì ký tự.Chương trình bị treo khi đóng kết nối cổng nối tiếp

Tôi có thể kết nối với thiết bị hoàn toàn tốt bằng cutecom. Đây là phần lạ:

  1. Nếu lần đầu tiên tôi kết nối với thiết bị qua cutecom (màn hình nối tiếp), chương trình của tôi sẽ kết nối và đóng hoàn toàn tốt đẹp mỗi lần sau đó. Nó đọc các ký tự như tôi mong đợi chúng được đọc. (Không ).
  2. Nếu tôi ngắt kết nối và kết nối lại phần cứng, chương trình của tôi sẽ treo lại cho đến khi tôi chạy cutecom.

Vì nó hoạt động sau khi tôi sử dụng cutecom, nó làm cho tôi nghĩ rằng tôi thiếu một cái gì đó trong kết nối ban đầu của tôi, hoặc cài đặt kết nối. Đây là những gì tôi sử dụng để kết nối:

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

Trong set_tty_options chức năng của tôi:

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; 
} 

Trong set_blocking chức năng:

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

Tôi thấy 2 vấn đề với mã của bạn. Đầu tiên là hàm 'set_tty_options' dường như không khởi tạo hoàn toàn cấu trúc' tty_options'. Điều đó có thể giải thích "chương trình của tôi hoạt động nếu tôi chạy X trước, nhưng bị treo/thất bại nếu chạy solo." Đó là triệu chứng cổ điển của một chương trình không đúng hoặc khởi tạo hoàn toàn môi trường của nó. Thứ hai, hàm 'set_blocking' đó là không có thật cho đầu vào chuẩn. 'c_cc [VMIN]' và 'c_cc [VTIME]' chỉ nên được sử dụng cho đầu vào ** không chính tắc ** (aka nguyên). Đối với một 'read()' không chặn của đầu vào chuẩn, sử dụng 'fcntl()' để thiết lập điều đó. – sawdust

Trả lời

0

Đây là những gì tôi đã kết thúc. Tôi đã tìm ra điều này bằng cách sao chép và dán các phần cơ bản từ mã nguồn cutecom's.

  1. Khi mở ...

    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. Bạn không thể thiết lập tốc độ truyền như tôi đang làm. Bạn phải sử dụng định nghĩa B38400;

    baud = B38400;

  3. Sau đó, tôi đã thêm câu trả lời wallyk của.

    tty_settings.c_lflag = 0;

Edit: Theo nhận xét của mùn cưa, tôi tìm thấy một cách tốt hơn để thiết lập này để nhập liệu.

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

Và nó hoạt động.

+0

* "Sau đó, tôi đã thêm câu trả lời của wallyk. Tty_settings.c_lflag = 0;" * - Bạn vẫn chưa cấu hình đúng cổng nối tiếp. 'C_oflag' được đặt là gì? Lưu ý rằng việc gán cứng cho các thành phần 'termios' struct không được khuyến nghị cho mỗi POSIX. Bạn nên gọi 'tcgetattr()', và sau đó kích hoạt hoặc vô hiệu hóa từng trường thuộc tính (như bạn làm với 'c_cflag'). Xem [Hướng dẫn lập trình nối tiếp cho Hệ điều hành POSIX] (http://www.easysw.com/~mike/serial/serial.html). Bạn đang sử dụng các cuộc gọi POSIX, vì vậy hãy thực hiện theo các quy tắc của họ. – sawdust

1

Tôi nghĩ rằng bạn muốn thêm | O_SYNC đến cờ mở để nhấn mạnh trên đồng bộ i/o. Tôi nghi ngờ đó là gây ra một vấn đề mặc dù.

Tuy nhiên, tôi nghĩ rằng bạn muốn bỏ qua các tín hiệu phá vỡ, được báo cáo là một nhân vật NUL như bạn đang nhận được:

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

Ngoài ra, bạn muốn chắc chắn việc xử lý đầu vào là hoàn toàn tắt, để nhận được backspace,^C,^\, vv không gây ra bất kỳ phản ứng:

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

Dường như bạn đang sử dụng my set_blocking() function, do đó sẽ không sao.

Các vấn đề liên quan