2013-04-08 15 views
5

Próbuję odczytać i zapisać dane z płyty FPGA. Sama płyta została dostarczona wraz ze sterownikiem, który tworzy urządzenie terminalowe o nazwie ttyUSB0 za każdym razem, gdy płyta jest podłączona. W układzie FPGA zaimplementowano asynchroniczny odbiornik i nadajnik, i wydaje się, że działają.Jak prawidłowo skonfigurować komunikację szeregową w systemie Linux?

Jednak wydaje się, że problem dotyczy strony C rzeczy. Używam niektórych wektorów testowych do testowania, czy FPGA wyprowadza odpowiednie informacje. Zauważyłem kilka rzeczy rzeczy:

  1. Urządzenie czasami nie otwiera się prawidłowo
  2. Terminal atrybuty czasami nie być pobierane lub ustaw.
  3. Odczyt jest czasami nieblokujący i nie odzyskuje właściwej wartości.

Poniżej przedstawiono sposób konfigurowania opcji deskryptorów terminali i plików. Wiele z tego pochodzi stąd: http://slackware.osuosl.org/slackware-3.3/docs/mini/Serial-Port-Programming

Wszelkie rady lub komentarze na temat przyczyn niepowodzenia programu mogą być bardzo pomocne.

#include <stdio.h> // Standard input/output definitions 
#include <string.h> // String function definitions 
#include <unistd.h> // UNIX standard function definitions 
#include <fcntl.h> // File control definitions 
#include <errno.h> // Error number definitions 
#include <termios.h> // POSIX terminal control definitions 

int open_port(void){ 

    int fd; // File descriptor for the port 
    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); 

    if (fd == -1){ 
     fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno)); 
     exit(EXIT_FAILURE); 
    } 

    return (fd); 
} 

int main(void){ 

    int fd = 0;    // File descriptor 
    struct termios options; // Terminal options 

    fd = open_port(); // Open tty device for RD and WR 

    fcntl(fd, F_SETFL);   // Configure port reading 
    tcgetattr(fd, &options);  // Get the current options for the port 
    cfsetispeed(&options, B230400); // Set the baud rates to 230400 
    cfsetospeed(&options, B230400); 

    options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode 
    options.c_cflag &= ~PARENB;    // No parity bit 
    options.c_cflag &= ~CSTOPB;    // 1 stop bit 
    options.c_cflag &= ~CSIZE;    // Mask data size 
    options.c_cflag |= CS8;    // Select 8 data bits 
    options.c_cflag &= ~CRTSCTS;   // Disable hardware flow control 

    // Enable data to be processed as raw input 
    options.c_lflag &= ~(ICANON | ECHO | ISIG); 

    // Set the new attributes 
    tcsetattr(fd, TCSANOW, &options); 

    //////////////////////////////////// 
    // Simple read and write code here// 
    //////////////////////////////////// 

    // Close file descriptor & exit 
    close(fd) 
    return EXIT_SUCCESS 
} 

UPDATE I zostały zmodyfikowane mój kod na podstawie pierwszej odpowiedzi. To jest to, co mam teraz:

#include <errno.h>  // Error number definitions 
#include <stdint.h>  // C99 fixed data types 
#include <stdio.h>  // Standard input/output definitions 
#include <stdlib.h>  // C standard library 
#include <string.h>  // String function definitions 
#include <unistd.h>  // UNIX standard function definitions 
#include <fcntl.h>  // File control definitions 
#include <termios.h> // POSIX terminal control definitions 

// Open usb-serial port for reading & writing 
int open_port(void){ 

    int fd; // File descriptor for the port 
    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); 

    if (fd == -1){ 
     fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno)); 
     exit(EXIT_FAILURE); 
    } 

    return fd; 
} 

int main(void){ 

    int    fd = 0;  // File descriptor 
    struct termios options; // Terminal options 
    int    rc;   // Return value 

    fd = open_port();   // Open tty device for RD and WR 

    // Get the current options for the port 
    if((rc = tcgetattr(fd, &options)) < 0){ 
     fprintf(stderr, "failed to get attr: %d, %s\n", fd, strerror(errno)); 
     exit(EXIT_FAILURE); 
    } 

    // Set the baud rates to 230400 
    cfsetispeed(&options, B230400); 

    // Set the baud rates to 230400 
    cfsetospeed(&options, B230400); 

    cfmakeraw(&options); 
    options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode 
    options.c_cflag &= ~CSTOPB;   // 1 stop bit 
    options.c_cflag &= ~CRTSCTS;   // Disable hardware flow control 
    options.c_cc[VMIN] = 1; 
    options.c_cc[VTIME] = 2; 

    // Set the new attributes 
    if((rc = tcsetattr(fd, TCSANOW, &options)) < 0){ 
     fprintf(stderr, "failed to set attr: %d, %s\n", fd, strerror(errno)); 
     exit(EXIT_FAILURE); 
    } 

    //////////////////////////////// 
     // Simple Read/Write Code Here// 
     //////////////////////////////// 

    // Close file descriptor & exit 
    close(fd); 
    return EXIT_SUCCESS; 
} 

Właśnie w celu wyjaśnienia, odbiornik i nadajnik używanie 8 bitów danych, 1 bit stopu, bez bitu parzystości.

Odpowiedz

5

Wolę Serial Programming Guide for POSIX Operating Systems.

Należy usunąć instrukcję fcntl(mainfd, F_SETFL), ponieważ nie jest ona wymagana i niepoprawnie zaimplementowana (F_GETFL nie wykonano przed trzecim brakującym argumentem).

Spróbuj użyć cfmakeraw do trybu ustawiania niekanoniczne, ponieważ kod inicjalizacji jest niekompletna:

options->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP 
     | INLCR | IGNCR | ICRNL | IXON); 
options->c_oflag &= ~OPOST; 

dla trybu niekanonicznej, trzeba także określić

options.c_cc[VMIN] = 1; 
options.c_cc[VTIME] = 2; 

1 i 2 są tylko sugerowane wartości.

Dodaj testowanie statusu zwrotu po wszystkich wywołań systemowych.

rc = tcgetattr(mainfd, &options); 
if (rc < 0) { 
    printf("failed to get attr: %d, %s\n", mainfd, strerror(errno)); 
    exit (-3); 
} 

Spróbuj przetestować za pomocą wolniejszych prędkości transmisji (na przykład 115200 lub nawet 9600).

+0

Dzięki, dam ci to i zaktualizuję. – sj755

+0

Zrobiłem aktualizację i opublikowałem mój obecny kod. Z jakiegoś powodu program nie jest w stanie odczytać niczego z tablicy, po prostu czeka na funkcję odczytu. jakieś pomysły? – sj755

+1

Nie potrzebujesz 'c_cflag & = ~ PARENB', ponieważ' cfmakeraw() 'obsłuży to. Prawdopodobnie potrzebujesz 'c_cflag & = ~ CSTOPB' i' c_cflag & = ~ CRTSCTS' który został usunięty! Każda z nich może zabić czytanie. – sawdust

Powiązane problemy