2013-04-02 17 views
5

Odczytuję dane przez połączenie USB jako port szeregowy ze sterownikiem PL2303. Zwraca on pomyślnie, wykonując numer open i po ustawieniu opcji TTY i braku blokowania. Kiedy próbuję zamknąć połączenie, zawiesza się. W tym stanie odczytuje " " zamiast znaków.Program zawiesza się podczas zamykania portu szeregowego

Mogę podłączyć urządzenie do urządzenia idealnie z wycinarką. Oto dziwna część:

  1. Jeśli po raz pierwszy połączę się z urządzeniem przez cutecom (monitor szeregowy), mój program połączy się i zamknie idealnie dokładnie za każdym razem. Czyta postacie tak, jak oczekuję, że zostaną przeczytane. (Nie ).
  2. Po odłączeniu i ponownym podłączeniu sprzętu mój program zawiesi się ponownie, dopóki nie uruchomię cutecom.

Ponieważ działa po tym, jak używam cutecom, to powoduje, że myślę, że brakuje mi czegoś w początkowym połączeniu lub ustawieniach połączenia. Oto co mogę użyć do podłączenia:

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

W moim set_tty_options funkcję:

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

W set_blocking funkcja:

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

Widzę 2 problemy z kodem. Po pierwsze, funkcja 'set_tty_options' nie wydaje się w pełni inicjować struktury' tty_options'. To może wyjaśnić, że "mój program działa, jeśli uruchomię X ​​jako pierwszy, ale zawiesza się/zawiedzie, jeśli uruchomi się solo". Jest to klasyczny objaw programu, który nie inicjuje poprawnie ani w pełni jego środowiska. Po drugie, funkcja 'set_blocking' jest fałszywa dla danych wejściowych kanonicznych. 'c_cc [VMIN]' i 'c_cc [VTIME]' powinny być używane tylko dla ** niekanonicznego ** (również surowego) wejścia. Aby nie blokować 'read()' wejścia kanonicznego, użyj 'fcntl()', aby to ustawić. – sawdust

Odpowiedz

0

Oto, co skończyło się robi. Wyjaśniałem to przez zasadniczo kopiowanie i wklejanie części z kodu źródłowego cutecom's.

  1. Podczas otwierania ...

    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. Nie można ustawić szybkość transmisji, jak robię. Musisz użyć zdefiniowanego B38400;

    baud = B38400;

  3. Potem dodał odpowiedź wallyk użytkownika.

    tty_settings.c_lflag = 0;

Edit: Zgodnie trociny komentarzu, znalazłem lepszy sposób ustawić to do wejścia surowego.

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

I działa.

+0

* "Następnie dodałem odpowiedź na stronie wikik.tty_settings.c_lflag = 0;" * - Nadal nie skonfigurowałeś poprawnie portu szeregowego. Do czego służy ustawienie 'c_oflag'? Zauważ, że trudne przypisanie do elementów strukturalnych 'termios' nie jest zalecane na POSIX. Powinieneś wywołać 'tcgetattr()', a następnie włączyć lub wyłączyć każde pole atrybutów (tak jak w przypadku 'c_cflag'). Zobacz [Serial Programming Guide for POSIX Operating Systems] (http://www.easysw.com/~mike/serial/serial.html). Korzystasz z połączeń POSIX, więc przestrzegaj ich zasad. – sawdust

1

myślę chcesz dodać | O_SYNC do otwartych flagi nalegać na synchronicznym wejściu/wyjściu. Wątpię, że to powoduje problem.

Myślę jednak, że chcesz, aby zignorować sygnał przerwania, który jest zgłoszony jako znak NUL jak otrzymujesz:

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

Również, chcesz mieć pewność, przetwarzanie wejście jest całkowicie wyłączony, tak że otrzymanie backspace^C^\, itd. nie powodują żadnych reakcji:

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

To wygląda już używasz my set_blocking() function, więc to powinno być w porządku.

Powiązane problemy