2016-03-04 1 views
1

Ma Linux application C ne peut pas recevoir octets d'Arduinomon programme C Linux ne peut pas recevoir des données à partir Arduino via USB série

Salut à tous, je compte utiliser Arduino Mega 2560 en tant que programmeur pour AT89S52 (une famille de 8051 microprocesseur) . La carte Arduino se connecte au PC via un câble série USB. Au début, j'ai besoin d'écrire un programme dans mon Ubuntu pour communiquer avec la carte Arduino. Mon programme peut ouvrir une connexion et écrire des octets correctement sur Arduino (j'ai testé en allumant/éteignant la led), mais le problème est que le programme Linux ne peut pas recevoir de données d'Arduino. J'ai déjà cherché à travers de nombreux tutoriels et forums mais je n'arrive toujours pas à résoudre le problème, alors je poste une question ici et j'espère que quelqu'un pourra m'aider.

  • Ci-dessous mon functon utilisé pour ouvrir la connexion à un appareil

    AT89S_EID usbserial_open (char* dev_name, 
               UsbSerialDevice* dev_ptr, 
               int baudrate, 
               int config) { 
    speed_t io_baudrate = B9600; 
    
    if (dev_name == NULL || dev_ptr == NULL) 
    { 
        return AT89S_EID_ARG_NULL; 
    } 
    
    if (baudrate != US_BAUDRATE_9600 
        && baudrate != US_BAUDRATE_19200 
        && baudrate != US_BAUDRATE_115200) 
    { 
        return AT89S_EID_SERIAL_BAUDRATE_INVALID; 
    } 
    if (config != US_CONFIG_8N1 
        && config != US_CONFIG_7E1 
        && config != US_CONFIG_7O1) 
    { 
        return AT89S_EID_SERIAL_CONFIG_INVALID; 
    } 
    
    // store device name 
    strcpy(dev_ptr->name, dev_name); 
    
    // open device 
    dev_ptr->fd = open (dev_ptr->name, 
            O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); 
    if (dev_ptr->fd < 0) 
    { 
        return AT89S_EID_SERIAL_OPEN; 
    } 
    
    // get current termios settings 
    if (tcgetattr(dev_ptr->fd, &dev_ptr->tios) < 0) 
    { 
        return AT89S_EID_SERIAL_GET_ATTR; 
    } 
    
    // set input/output baudrdate 
    if (baudrate == US_BAUDRATE_9600) 
        io_baudrate = B9600; 
    else if (baudrate == US_BAUDRATE_19200) 
        io_baudrate = B19200; 
    else if (baudrate == US_BAUDRATE_115200) 
        io_baudrate = B115200; 
    
    if (cfsetispeed(&dev_ptr->tios, io_baudrate) != 0 
        || cfsetospeed(&dev_ptr->tios, io_baudrate) != 0) 
    { 
        return AT89S_EID_SERIAL_SET_IOSPEED; 
    } 
    
    // enable receiver, ignore status line 
    dev_ptr->tios.c_cflag |= (CREAD | CLOCAL); 
    // set config 
    if (config == US_CONFIG_8N1) 
    { 
        dev_ptr->tios.c_cflag &= ~PARENB; 
        dev_ptr->tios.c_cflag &= ~CSTOPB; 
        dev_ptr->tios.c_cflag &= ~CSIZE; 
        dev_ptr->tios.c_cflag |= CS8; 
    } 
    else if (config == US_CONFIG_7E1) 
    { 
        dev_ptr->tios.c_cflag |= PARENB; 
        dev_ptr->tios.c_cflag &= ~PARODD; 
        dev_ptr->tios.c_cflag &= ~CSTOPB; 
        dev_ptr->tios.c_cflag &= ~CSIZE; 
        dev_ptr->tios.c_cflag |= CS7; 
    } 
    else if (config == US_CONFIG_7O1) 
    { 
        dev_ptr->tios.c_cflag |= PARENB; 
        dev_ptr->tios.c_cflag |= PARODD; 
        dev_ptr->tios.c_cflag &= ~CSTOPB; 
        dev_ptr->tios.c_cflag &= ~CSIZE; 
        dev_ptr->tios.c_cflag |= CS7; 
    } 
    
    // no HW flow control 
    dev_ptr->tios.c_cflag &= ~CRTSCTS; 
    
    // no input processing (raw input) 
    dev_ptr->tios.c_iflag &= ~(IXON | IXOFF | IXANY); 
    // other input settings 
    dev_ptr->tios.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
    
    // no output processing (raw output) 
    dev_ptr->tios.c_oflag &= ~OPOST; 
    
    // control character settings 
    dev_ptr->tios.c_cc[VMIN] = 1; // wait for 1 minimum chacacter received 
    dev_ptr->tios.c_cc[VTIME] = 0; // no timeout when waiting for charater 
    
    // commit new settings 
    if (tcsetattr(dev_ptr->fd, TCSANOW, &dev_ptr->tios) < 0) 
    { 
        return AT89S_EID_SERIAL_SET_ATTR; 
    } 
    
    // wait for device reset & sync up 
    usleep(1500 * 1000); 
    return AT89S_EID_OK; 
    } /* usbserial_open */ 
    
  • Et cela est la fonction de réception:

    AT89S_EID usbserial_recv (UsbSerialDevice* dev_ptr, 
               unsigned char* data_ptr, 
               int data_len) { 
    int read_byte = 0; 
    char b[1]; 
    
    if (dev_ptr == NULL 
        || data_ptr == NULL) 
    { 
        return AT89S_EID_ARG_NULL; 
    } 
    
    // block reading 
    fcntl(dev_ptr->fd, F_SETFL, 0); 
    
    // start receiving data 
    while (read_byte < data_len) 
    { 
        if (read(dev_ptr->fd, b, 1) > 0) 
        { 
         data_ptr[read_byte++] = *b; 
        } 
        else 
        { 
         if (errno == EAGAIN) 
          continue; 
         else if (errno == ETIMEDOUT) 
          break; 
         else 
          return AT89S_EID_SERIAL_RECV; 
        } 
    } 
    
    return AT89S_EID_OK; 
    } /* usbserial_recv */ 
    

Alors désolé pour l'affichage d'un code long:)

Je travaille déjà dy cherché à travers de nombreux tutoriels et forums, mais ne peut toujours pas résoudre le problème. Je crois que le code Arduino fonctionne bien parce que j'ai utilisé d'autres outils pour le tester (par exemple: minicom)

+0

Vous aurez probablement besoin d'afficher le code qui utilise vos fonctions ici aussi. Avez-vous également débogué votre code? Ce qui se produit ? – nos

+0

Le problème est que je peux envoyer 256 octets à arduino correctement, mais ne peut pas recevoir plein de 256 octets de arduino (j'ai seulement reçu 1 octet). J'ai utilisé minicom pour tester mon code arduino et peut lire et recevoir des données complètes de 256 octets. –

+0

Droit - mais nous ne pouvons pas dire ce qui ne va pas avec ce code - il semble bien. Vous devriez donc l'exécuter vous-même dans un débogueur et voir ce qui se passe (est-ce qu'il bloque dans un appel read()? Est-ce que quelque chose vous donne une erreur? Que se passe-t-il après avoir reçu 1 octet? Ou il est possible qu'il y ait un bug dans le code qui appelle les fonctions que vous avez posté ici. – nos

Répondre

0

J'ai résolu mon problème. Il suffit d'ajouter la fonction flush lors de l'ouverture de la connexion à l'appareil, tout peut fonctionner correctement.

tcflush(fd, TCIOFLUSH);