我正在尝试在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接收数据。&#34;永远不会显示。
有什么建议可以解决这个问题吗?另外,系统如何将中断与串口相关联?,我已经读过有关signal.h但我还没有找到答案。我从这个页面得到了中断的想法:http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html
提前感谢您的帮助。 提前谢谢。
答案 0 :(得分: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
我希望这也适合你。
答案 1 :(得分:4)
问题是您通过使用FASYNC
清除F_SETFL
标志来禁用文件描述符中的信号。如果你想获得信号,你需要设置它:
fcntl(fd, F_SETFL, FNDELAY|FASYNC);
此外,您可能希望将POSIX名称用于这些标志(O_NDELAY
和O_ASYNC
)而不是BSD名称以获得更多可移植性,尽管其中任何一个都适用于Linux。
答案 2 :(得分: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;
}