8

Ubuntu(Cで書かれたプログラム)でシリアルポートの割り込みを設定しようとしていますが、機能しません。シリアル通信が途切れることなく正常に動作することを確認しましたので、設定がおかしいのではないでしょうか。コードは次のとおりです。

    #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");
    }

したがって、別のデバイスが設定されたポートを介してメッセージを送信するときはいつでも、メッセージは「UARTからデータを受信しました」。表示されることはありません。

この問題を解決するための提案はありますか?また、システムはどのようにシリアルポートとの割り込みを関連付けますか?、signal.hについて読みましたが、その答えは見つかりませんでした。私はこのページから中断のアイデアを得ました:http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html

助けてくれてありがとう。前もって感謝します。

4

3 に答える 3

6

元のコードが期待どおりに機能するために、コードの一部が欠落していることがわかりました。以下のコードは、gccでコンパイルされたLinuxで動作しています。追加されたコード行は、1/**<<<<<<------This line made it work.**/
行でマークされた行もコメントアウトされています://baudRate = B115200;

#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());
     fcntl(fd, F_SETFL,  O_ASYNC ); /**<<<<<<------This line made it work.**/

     tcgetattr(fd,&termAttr);
     //baudRate = B115200;          /* Not needed */
     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");
}

プログラムからの出力は次のとおりです。

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

それがあなたにも役立つことを願っています。

于 2013-03-16T22:54:01.703 に答える
4

FASYNC問題は、。を使用してフラグをクリアすることにより、ファイル記述子からのシグナルを無効にしていることですF_SETFL。シグナルを取得したい場合は、これを設定する必要があります。

fcntl(fd, F_SETFL, FNDELAY|FASYNC);

また、移植性を高めるために、BSD名ではなくPOSIX名(O_NDELAYおよび)を使用することもできますが、どちらもLinuxで機能します。O_ASYNC

于 2013-03-16T23:26:16.560 に答える
1

この問題を解決するための提案はありますか?また、システムは割り込みをシリアルポートとどのように関連付けますか?

シリアルポート割り込みは、Linuxカーネルのシリアルドライバーのデバイス部分に書き込まれます。割り込みはドライバ自体によって処理されるため、制御することはできません。

上記のプログラムが実行しているのは、シリアルパーツデバイスの受信割り込みがトリガーされたときに、信号を介して通知することです。

上記の信号処理は、割り込みとは関係ありません。より均等な処理です。まず、プログラムを登録して、io割り込みが発生したときにシグナルを取得すると、プログラムのシグナルハンドラーがprintfメッセージを表示します。

プログラムの信号処理が正しく実装されていないと思いますプログラムの信号部分を修正するだけです

sigset_t mskvar_1                   //Variable of signal bitfieldtype
struct sigaction sigio_action       //Structure which describes signal handler
void sio_handler(void);             //Signal handler function

int main()
{
  sigfillset(&mskvar_1);                    //set all mask bits of maskbit variable
  sigprocmask(SIG_SETMASK,&mskvar_1,NULL);  //write the mask info present in mskvar_1 to the pd
  sigdelset(&mskvar_1,SIGIO);               //Unmask SIGIO , to register for IO Interrupt Events

  sigio_action.sa_handler = sio_handler;    //Configure Signal Handler
  sigio_action.sa_flags  = 0;
  sigfillset(&sigio_action.sa_mask);
  sigaction(SIGIO,&sigio_action,NULL);      //Install Signal handler

  // Serial port initializtion here
  // Set Serial port parameters , Baud Rate and flags


while(1);
return 0;
}


void sio_handler()
{
  printf("\nSIGIO RECEIVED , I/O interrupt signalled?\n");
  return;
}
于 2013-02-27T19:00:10.460 に答える