2013-02-27 184 views
7

我想設置ubuntu中的串口中斷(在用C編寫的程序中),但它不起作用。我已經檢查過串行通訊沒有中斷情況下正常工作,所以我可能會設置錯誤。 代碼如下:在linux中設置串口中斷

#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

在此先感謝您的幫助。 在此先感謝。

+0

1)我不會在ttyS初始化完成之前安裝信號處理程序。2)你不應該從信號處理程序調用printf(); printf()是不可重入的。 – wildplasser 2013-02-27 20:09:11

+0

感謝您的回答,但是根據您的意見,「中斷」仍然無效。還有什麼想法? – gus 2013-02-27 23:36:03

回答

4

問題是,您通過使用F_SETFL清除FASYNC標誌來禁用文件描述符中的信號。您需要設置,如果你想獲得的信號:

fcntl(fd, F_SETFL, FNDELAY|FASYNC); 

此外,您可能想使用POSIX的名字,這些標誌(O_NDELAYO_ASYNC),而不是更便攜的BSD的名字,但無論是將工作在Linux上。

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; 
} 
+0

感謝您的回答,但信號(「中斷」)仍然不起作用,並且我已經檢查過程序是否通過端口正確接收/發送數據。你有解決這個問題的另一種方法嗎? – gus 2013-02-27 23:35:23

6

我發現了一段代碼缺少原始代碼爲工作程序的信號部分預期。下面的代碼在使用gcc編譯的Linux上工作。增加的代碼行是標有/**<<<<<<------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 

我希望你的作品了。

+0

非常感謝您的回答,現在有道理。 – gus 2013-04-17 17:15:32