8
votes

Définition de l'interruption du port série à Linux

J'essaie de définir l'interruption d'un port série à Ubuntu (dans le programme écrit en C), mais cela ne fonctionne pas. J'ai vérifié que la communication série fonctionne correctement sans interruption, je peux donc créer quelque chose de mal. Le code est le suivant:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <fcntl.h>
    #include <sys/signal.h>
    #include <errno.h>
    #include <termios.h>

    void signal_handler_IO (int status);   /* definition of signal handler */

    int n;
    int fd;
    int connected;
    struct termios termAttr;
    struct sigaction saio;

    int main(int argc, char *argv[])
    {
         fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
         if (fd == -1)
         {
            perror("open_port: Unable to open /dev/ttyO1\n");
            exit(1);
         }

         saio.sa_handler = signal_handler_IO;
         saio.sa_flags = 0;
         saio.sa_restorer = NULL; 
         sigaction(SIGIO,&saio,NULL);

         fcntl(fd, F_SETFL, FNDELAY);
         fcntl(fd, F_SETOWN, getpid());

         tcgetattr(fd,&termAttr);
         baudRate = B115200; 
         cfsetispeed(&termAttr,B115200);
         cfsetospeed(&termAttr,B115200);
         termAttr.c_cflag &= ~PARENB;
         termAttr.c_cflag &= ~CSTOPB;
         termAttr.c_cflag &= ~CSIZE;
         termAttr.c_cflag |= CS8;
         termAttr.c_cflag |= (CLOCAL | CREAD);
         termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
         termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
         termAttr.c_oflag &= ~OPOST;
         tcsetattr(fd,TCSANOW,&termAttr);
         printf("UART1 configured....\n");

         connected = 1;
         while(connected == 1){
               // some code
         }

         close(fd);
         exit(0);             
    }

    void signal_handler_IO (int status)
    {
         printf("received data from UART.\n");
    }


2 commentaires

1) Je n'installerais pas le gestionnaire de signal avant que l'initialisation des TTYS soit terminée. 2) Vous ne devez pas appeler printf () à partir d'un gestionnaire de signal; printf () est non reentrant.


Merci d'avoir répondu, mais à la suite de vos commentaires, "l'interruption" ne fonctionne toujours pas. Plus d'idées?


3 Réponses :


1
votes

Toute suggestion pour résoudre ce problème? En outre, comment le système raconte-t-il l'interruption avec le port série?

L'interruption de port série est écrite à l'intérieur de la partie de périphérique du pilote série du noyau Linux. L'interruption est traitée par le conducteur lui-même, de sorte que vous ne pouvez pas le contrôler.

Quel est le programme ci-dessus, vous notifiez-vous à travers un signal, lors d'une interruption de réception du dispositif de partie série est déclenché.

Le traitement du signal ci-dessus n'est pas lié aux interruptions, il est plus difficile de manipuler. Tout d'abord, vous vous inscrivez, votre programme, pour obtenir un signal lorsqu'une interruption d'Io est terminée, le gestionnaire de signal de votre programme affichera ensuite le message Printf.

Je pense que la manipulation du signal de votre programme n'est pas mise en œuvre correctement. Juste corriger les parties du signal de votre programme xxx


1 commentaires

Merci de votre réponse, mais le signal ("interruption") ne fonctionne toujours pas et j'ai déjà vérifié que le programme reçoit / transmet des données via le port correctement. Avez-vous une autre approche pour résoudre ce problème?



6
votes

J'ai trouvé qu'un morceau de code est manquant pour que le code d'origine fonctionne comme prévu. Le code ci-dessous fonctionne sur Linux compilé avec GCC. La ligne de code ajoutée est celle marquée avec / **
Une ligne a également été commentée: // baudred = b115200; code>. xxx pré>

La sortie du programme était la suivante: p>

./a.out 
UART1 configured....
received data from UART.
received data from UART.
received data from UART.
^C


3 commentaires

Merci beaucoup pour la réponse, cela a du sens maintenant.


Pourquoi votre sortie est-elle affichée 3 fois?


Y a-t-il un moyen d'afficher une fois?



4
votes

Le problème est que vous désactivez les signaux du descripteur de fichier en nettoyant le drapeau FASYNC code> avec f_setfl code>. Vous devez définir que si vous souhaitez obtenir des signaux:

fcntl(fd, F_SETFL, FNDELAY|FASYNC);


0 commentaires