2017-01-10 3 views
0

S'il vous plaît me conseiller. Je voudrais que le code obtienne des données du port série tel que tty/USB0. Donc, besoin de faire ce code lire les données du protocole série comme indiqué ci-dessous.Pourquoi les données de "read" dans le tableau uint8_t ne peuvent pas être récupérées?

uint8_t recBlk; // receive blk from chunk 
ret = read(serial_fd, &recBlk, sizeof(recBlk)); 
printf("Block Num is %d\n", recBlk); 
fflush(stdout); 
if (ret != sizeof(recBlk)) { 
    perror("read"); 
    return -errno; 
} 

Cependant, je ne comprenais pas pourquoi ces lignes ci-dessous montrant ne fonctionne pas, mais l'erreur se produisant « lire: argument non valide »

Comment puis-je obtenir les données du tableau de fonction de lecture?

uint8_t recData[1024]; // receive data from chunk 
ret = read(serial_fd, (void *)&recData, sizeof(recData)); 
    printf("Data buffer is %c\n", &recData); 
    fflush(stdout); 
if (ret != sizeof(recData)) { 
    printf("Can't fetch the Data length!"); 
     perror("read"); 
     return -errno; 
} 

enter image description here

Ce code montrant ci-dessous est ma fonction d'exécution.

static int xmodem_receive(int serial_fd, char* filename, int _crc, int use_crc){ 
    int skip = 0; 
    uint8_t sdCRC = 'C'; // Request-To-Send 
    uint8_t sdACK = X_ACK; // 
    uint8_t eof = X_EOF; 
    uint8_t sdNAK = X_NAK; 
    uint8_t recSTX; // receive SOH from chunk 
    uint8_t recBlk; // receive blk from chunk 
    uint8_t recNegBlk; // receive blk negative from chunk 
    uint8_t recData[1024]; // receive data from chunk 
    uint16_t recChksum; 
  
    uint8_t expected_blkno; 
  
    FILE *fp; 
    int ret, fd; 
    struct stat stat; 
    // If we want to receive, We have to send NAK to Sendor. 
  
    if (use_crc) 
        use_crc = MAX_RETRY + 1; 
  
        /* Writing as binary */ 
    fp = fopen(filename, "wb"); 
    //Send NAK still read SOH that header of one data chunks 
    /* 
    CRC 16 
    Sending C 
    Sending NAK 
  
    */ 
    while(use_crc){ 
        char status; 
        printf("Waiting for sender ping ..."); 
        fflush(stdout); 
        // 
        if(_crc){ 
            printf("Send C ping....\n"); 
            ret = write(serial_fd, &sdCRC, sizeof(sdCRC)); 
        }else{ 
            // send NAK before read SOH 
            printf("Send NAK ping....\n"); 
            ret = write(serial_fd, &sdNAK, sizeof(sdNAK)); 
        }    // after sending NAK,receiving SOH from chunk 
        fflush(stdout); 
        ret = read(serial_fd, &recSTX, sizeof(recSTX)); 
  
  
        if(recSTX == X_STX){ 
            printf("STX is %c\n", &recSTX); 
            break; 
        }else{ 
            printf("Garabage payload %c\n", &recSTX); 
        } 
        fflush(stdout); 
        if (ret != sizeof(recSTX)) { 
                printf("Not working"); 
                fflush(stdout); 
                perror("read"); 
                return -errno; 
        } 
        use_crc--; 
    } 
  
    expected_blkno = 1; 
  
    while(ret != EOF){ 
        //So next, receiving blk 
        ret = read(serial_fd, &recBlk, sizeof(recBlk)); 
        printf("Block Num is %d\n", recBlk); 
        fflush(stdout); 
        if (ret != sizeof(recBlk)) { 
            perror("read"); 
            return -errno; 
        } 
        ret = read(serial_fd, &recNegBlk, sizeof(recNegBlk)); 
        printf("Negative Block Num is %d\n", recNegBlk); 
        fflush(stdout); 
        if (ret != sizeof(recNegBlk)) { 
            perror("read"); 
            return -errno; 
        } 
        ret = read(serial_fd, (void *)&recData, sizeof(recData)); 
        printf("Data buffer is %c\n", &recData); 
        fflush(stdout); 
        if (ret != sizeof(recData)) { 
            printf("Can't fetch the Data length!"); 
            perror("read"); 
            return -errno; 
        } 
        ret = read(serial_fd, &recChksum, sizeof(recChksum)); 
        printf("Check sum is %c", &recChksum); 
        fflush(stdout); 
        if (ret != sizeof(recChksum)) { 
            printf("Can't fetch the Check sum"); 
            perror("read"); 
            return -errno; 
        } 
        // data block number check 
        if(recBlk == 0xff - recNegBlk){ 
            printf("Can't fetch the Block !"); 
            perror("read"); 
  
            return -errno; 
        } 
        // data integrity check 
        if(recChksum == swap16(crc16(recData, sizeof(recData)))){ 
            perror("read"); 
            return -errno; 
        } 
        // check of appended "0xff" from end of data to  end of chunk in chunk 
        unsigned char *ptr = recData; 
        ptr += sizeof(recData); 
        while(*ptr == 0xff){ 
            ptr--; 
        } 
        fwrite(recData, (ptr - recData),1,fp); // write Datas bytes from our buffer 
        // set skip flag or end connect 
        ret = write(serial_fd, &eof, sizeof(uint8_t)); 
        if (ret != sizeof(eof) || ret != sizeof(X_STX)){ 
            return -errno; 
        }else{ 
            if(ret == X_STX){ 
                skip = 1; 
                printf("next chunk"); 
                fflush(stdout); 
                expected_blkno++; 
            }else if(ret == EOF){ 
                printf("EOF ..."); 
                ret = write(serial_fd, &sdACK, sizeof(sdACK)); 
                break; 
            }else{ 
                return -errno; 
            } 
        } 
  
    } 
    printf("done.\n"); 
    fclose(fp); 
    return 0; 
  
} 

Le réglage terminal est ici.

static int open_serial(const char *path, int baud) 
{ 
     int fd; 
     struct termios tty; 

     fd = open(path, O_RDWR | O_SYNC); 
     if (fd < 0) { 
       perror("open"); 
       return -errno; 
     } 

     memset(&tty, 0, sizeof(tty)); 
     if (tcgetattr(fd, &tty) != 0) { 
       perror("tcgetattr"); 
       return -errno; 
     } 

     cfsetospeed(&tty, baud); 
     cfsetispeed(&tty, baud); 

     tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;  // 8-bit chars 
     tty.c_iflag &= ~IGNBRK;       // disable break processing 
     tty.c_lflag = 0;        // no signaling chars, no echo, 
                 // no canonical processing 
     tty.c_oflag = 0;        // no remapping, no delays 
     tty.c_cc[VMIN] = 1;       // read doesn't block 
     tty.c_cc[VTIME] = 5;       // 0.5 seconds read timeout 

     tty.c_iflag &= ~(IXON | IXOFF | IXANY);   // shut off xon/xoff ctrl 

     tty.c_cflag |= (CLOCAL | CREAD);    // ignore modem controls, 
                 // enable reading 
     tty.c_cflag &= ~(PARENB | PARODD);    // shut off parity 
     tty.c_cflag &= ~CSTOPB; 
     tty.c_cflag &= ~CRTSCTS; 

     if (tcsetattr(fd, TCSANOW, &tty) != 0) { 
       perror("tcsetattr"); 
       return -errno; 
     } 

     return fd; 
} 
+0

Peut-être 'serial_fd' n'est pas valide. – user2079303

+0

Pourriez-vous me dire plus comment est-ce mauvais? serial_fd est obtenu à partir de open_serial ("/ dev/ttyUSB0", 115200) de la fonction principale. – NEWBIEEBIEE

+0

Je ne connais pas 'open_serial'. Est-ce une chose raspberrypi? Avez-vous vérifié la valeur de retour, pour s'assurer qu'il a réussi? – user2079303

Répondre

1

Le code qui produit le "erreur" est la suivante:

uint8_t recData[1024]; // receive data from chunk 
    ... 
     ret = read(serial_fd, (void *)&recData, sizeof(recData)); 
     printf("Data buffer is %c\n", &recData); 
     fflush(stdout); 
     if (ret != sizeof(recData)) { 
      printf("Can't fetch the Data length!"); 
      perror("read"); 
      return -errno; 
     } 

1.) La première question est de syntaxe C.
recData est l'adresse d'un tableau, et dans la lecture () et printf() appels, l'adresse de cette adresse est transmise en tant que second argument.
L'adresse de l'opération sur l'adresse du tableau est incorrecte.

2.) Le deuxième problème est l'évaluation de la valeur de retour.
La page de manuel décrit les valeurs de retour possibles du read() syscall.

2a.) La variable errno n'est valide que si la valeur de retour est -1.
Cependant perror() dans votre code serait appelé chaque fois que la valeur de retour n'est pas égale au nombre d'octets d'un tableau.
Par conséquent, le message "read: Invalid argument" est susceptible d'être faux.

2b.) Le read() syscall n'est pas requis pour satisfaire l'argument de longueur demandé.
Votre configuration termios spécifie une lecture minimale de 1 octet.
Ainsi, le read() syscall retournera avec au moins un octet, et seulement autant de données que celles reçues actuellement par le pilote du port série, jusqu'à atteindre le maximum de la longueur demandée.
Donc, chaque fois que la lecture complète de 1024 octets ne peut pas être accomplie (ce qui est susceptible d'être toujours), votre programme va avorter avec une erreur bidon.

+0

Merci, @sawdust. Je suis entièrement d'accord avec votre point de vue. – NEWBIEEBIEE