设为首页 收藏本站
查看: 510|回复: 0

[经验分享] Linux系统串口接收数据编

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2013-12-19 09:02:31 | 显示全部楼层 |阅读模式
之前基于IBM deveplopworks社区的代码,做了串口初始化和发送的程序,今天在此基础上添加了读取串口数据的程序。首先是最简单的循环读取程序,第二个是通过软中断方式,使用信号signal机制读取串口,这里需要注意的是硬件中断是设备驱动层级的,而读写串口是用户级行为,只能通过信号机制模拟中断,信号机制的发生和处理其实于硬件中断无异,第三个是通过select系统调用,在没有数据时阻塞进程,串口有数据需要读时唤醒进程。第二个和第三个例子都能用来后台读取数据,值得学习。

代码一:循环读取数据



[cpp] view plaincopy

#include<stdio.h>  
#include<stdlib.h>  
#include<unistd.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<fcntl.h>  
#include<termios.h>  
#include<errno.h>  

#define FALSE -1  
#define TRUE 0  

int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,B38400, B19200, B9600, B4800, B2400, B1200, B300, };  
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300, 38400, 19200,  9600, 4800, 2400, 1200,  300, };  
void set_speed(int fd, int speed){  
  int   i;   
  int   status;   
  struct termios   Opt;  
  tcgetattr(fd, &Opt);   
  for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++) {   
    if  (speed == name_arr[i]) {      
      tcflush(fd, TCIOFLUSH);      
      cfsetispeed(&Opt, speed_arr[i]);   
      cfsetospeed(&Opt, speed_arr[i]);     
      status = tcsetattr(fd, TCSANOW, &Opt);   
      if  (status != 0) {         
        perror("tcsetattr fd1");   
        return;      
      }      
      tcflush(fd,TCIOFLUSH);     
    }   
  }  
}  

int set_Parity(int fd,int databits,int stopbits,int parity)  
{   
    struct termios options;   
    if  ( tcgetattr( fd,&options)  !=  0) {   
        perror("SetupSerial 1");      
        return(FALSE);   
    }  
    options.c_cflag &= ~CSIZE;   
    switch (databits)   
    {     
    case 7:      
        options.c_cflag |= CS7;   
        break;  
    case 8:      
        options.c_cflag |= CS8;  
        break;     
    default:      
        fprintf(stderr,"Unsupported data size\n"); return (FALSE);   
    }  
    switch (parity)   
    {     
        case 'n':  
        case 'N':      
            options.c_cflag &= ~PARENB;   /* Clear parity enable */  
            options.c_iflag &= ~INPCK;     /* Enable parity checking */   
            break;   
        case 'o':     
        case 'O':      
            options.c_cflag |= (PARODD | PARENB);   
            options.c_iflag |= INPCK;             /* Disnable parity checking */   
            break;   
        case 'e':   
        case 'E':     
            options.c_cflag |= PARENB;     /* Enable parity */      
            options.c_cflag &= ~PARODD;      
            options.c_iflag |= INPCK;       /* Disnable parity checking */  
            break;  
        case 'S':   
        case 's':  /*as no parity*/     
            options.c_cflag &= ~PARENB;  
            options.c_cflag &= ~CSTOPB;break;   
        default:     
            fprintf(stderr,"Unsupported parity\n");      
            return (FALSE);   
        }   

    switch (stopbits)  
    {     
        case 1:      
            options.c_cflag &= ~CSTOPB;   
            break;   
        case 2:      
            options.c_cflag |= CSTOPB;   
           break;  
        default:      
             fprintf(stderr,"Unsupported stop bits\n");   
             return (FALSE);   
    }   
    /* Set input parity option */   
    if (parity != 'n')     
        options.c_iflag |= INPCK;   
    tcflush(fd,TCIFLUSH);  
    options.c_cc[VTIME] = 150;   
    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */  
    if (tcsetattr(fd,TCSANOW,&options) != 0)     
    {   
        perror("SetupSerial 3");     
        return (FALSE);   
    }   
    return (TRUE);   
}  

int main()  
{  
    printf("This program updates last time at %s   %s\n",__TIME__,__DATE__);  
    printf("STDIO COM1\n");  
    int fd;  
    fd = open("/dev/ttyS0",O_RDWR);  
    if(fd == -1)  
    {  
        perror("serialport error\n");  
    }  
    else  
    {  
        printf("open ");  
        printf("%s",ttyname(fd));  
        printf(" succesfully\n");  
    }  

    set_speed(fd,115200);  
    if (set_Parity(fd,8,1,'N') == FALSE)  {  
        printf("Set Parity Error\n");  
        exit (0);  
    }  
    char buf[] = "fe55aa07bc010203040506073d";  
    write(fd,&buf,26);  
    char buff[512];   
    int nread;   
    while(1)  
    {  
        if((nread = read(fd, buff, 512))>0)  
        {  
            printf("\nLen: %d\n",nread);  
            buff[nread+1] = '\0';  
            printf("%s",buff);  
        }  
    }  
    close(fd);  
    return 0;  
}  

代码清单二:通过signal机制读取数据





[cpp] view plaincopy

#include<stdio.h>  
#include<stdlib.h>  
#include<unistd.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<sys/signal.h>  
#include<fcntl.h>  
#include<termios.h>  
#include<errno.h>  

#define FALSE -1  
#define TRUE 0  
#define flag 1  
#define noflag 0  

int wait_flag = noflag;  
int STOP = 0;  
int res;  

int speed_arr[] =  
  { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600,  
B4800, B2400, B1200, B300, };  
int name_arr[] =  
  { 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400,  
1200, 300, };  
void  
set_speed (int fd, int speed)  
{  
  int i;  
  int status;  
  struct termios Opt;  
  tcgetattr (fd, &Opt);  
  for (i = 0; i < sizeof (speed_arr) / sizeof (int); i++)  
    {  
      if (speed == name_arr[i])  
    {  
      tcflush (fd, TCIOFLUSH);  
      cfsetispeed (&Opt, speed_arr[i]);  
      cfsetospeed (&Opt, speed_arr[i]);  
      status = tcsetattr (fd, TCSANOW, &Opt);  
      if (status != 0)  
        {  
          perror ("tcsetattr fd1");  
          return;  
        }  
      tcflush (fd, TCIOFLUSH);  
    }  
    }  
}  

int  
set_Parity (int fd, int databits, int stopbits, int parity)  
{  
  struct termios options;  
  if (tcgetattr (fd, &options) != 0)  
    {  
      perror ("SetupSerial 1");  
      return (FALSE);  
    }  
  options.c_cflag &= ~CSIZE;  
  switch (databits)  
    {  
    case 7:  
      options.c_cflag |= CS7;  
      break;  
    case 8:  
      options.c_cflag |= CS8;  
      break;  
    default:  
      fprintf (stderr, "Unsupported data size\n");  
      return (FALSE);  
    }  
  switch (parity)  
    {  
    case 'n':  
    case 'N':  
      options.c_cflag &= ~PARENB;   /* Clear parity enable */  
      options.c_iflag &= ~INPCK;    /* Enable parity checking */  
      break;  
    case 'o':  
    case 'O':  
      options.c_cflag |= (PARODD | PARENB);  
      options.c_iflag |= INPCK; /* Disnable parity checking */  
      break;  
    case 'e':  
    case 'E':  
      options.c_cflag |= PARENB;    /* Enable parity */  
      options.c_cflag &= ~PARODD;  
      options.c_iflag |= INPCK; /* Disnable parity checking */  
      break;  
    case 'S':  
    case 's':           /*as no parity */  
      options.c_cflag &= ~PARENB;  
      options.c_cflag &= ~CSTOPB;  
      break;  
    default:  
      fprintf (stderr, "Unsupported parity\n");  
      return (FALSE);  
    }  

  switch (stopbits)  
    {  
    case 1:  
      options.c_cflag &= ~CSTOPB;  
      break;  
    case 2:  
      options.c_cflag |= CSTOPB;  
      break;  
    default:  
      fprintf (stderr, "Unsupported stop bits\n");  
      return (FALSE);  
    }  
  /* Set input parity option */  
  if (parity != 'n')  
    options.c_iflag |= INPCK;  
  tcflush (fd, TCIFLUSH);  
  options.c_cc[VTIME] = 150;  
  options.c_cc[VMIN] = 0;   /* Update the options and do it NOW */  
  if (tcsetattr (fd, TCSANOW, &options) != 0)  
    {  
      perror ("SetupSerial 3");  
      return (FALSE);  
    }  
  return (TRUE);  
}  

void  
signal_handler_IO (int status)  
{  
  printf ("received SIGIO signale.\n");  
  wait_flag = noflag;  
}  

int  
main ()  
{  
  printf ("This program updates last time at %s   %s\n", __TIME__, __DATE__);  
  printf ("STDIO COM1\n");  
  int fd;  
  struct sigaction saio;  
  fd = open ("/dev/ttyUSB0", O_RDWR);  
  if (fd == -1)  
    {  
      perror ("serialport error\n");  
    }  
  else  
    {  
      printf ("open ");  
      printf ("%s", ttyname (fd));  
      printf (" succesfully\n");  
    }  

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

  //allow the process to receive SIGIO  
  fcntl (fd, F_SETOWN, getpid ());  
  //make the file descriptor asynchronous  
  fcntl (fd, F_SETFL, FASYNC);  

  set_speed (fd, 115200);  
  if (set_Parity (fd, 8, 1, 'N') == FALSE)  
    {  
      printf ("Set Parity Error\n");  
      exit (0);  
    }  

  char buf[255];  
while (STOP == 0)  
    {  
      usleep (100000);  
      /* after receving SIGIO ,wait_flag = FALSE,input is availabe and can be read */  
      if (wait_flag == 0)  
    {  
      memset (buf, 0, sizeof(buf));  
      res = read (fd, buf, 255);  
      printf ("nread=%d,%s\n", res, buf);  
//    if (res ==1)  
//      STOP = 1;       /*stop loop if only a CR was input */  
      wait_flag = flag; /*wait for new input */  
    }  
    }  


  close (fd);  
  return 0;  
}  





代码三:通过select系统调用进行io多路切换,实现异步读取串口数据



[python] view plaincopy

#include<stdio.h>  
#include<stdlib.h>  
#include<unistd.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<sys/signal.h>  
#include<fcntl.h>  
#include<termios.h>  
#include<errno.h>  

#define FALSE -1  
#define TRUE 0  
#define flag 1  
#define noflag 0  

int wait_flag = noflag;  
int STOP = 0;  
int res;  

int speed_arr[] =  
  { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600,  
B4800, B2400, B1200, B300, };  
int name_arr[] =  
  { 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400,  
1200, 300, };  
void  
set_speed (int fd, int speed)  
{  
  int i;  
  int status;  
  struct termios Opt;  
  tcgetattr (fd, &Opt);  
  for (i = 0; i < sizeof (speed_arr) / sizeof (int); i++)  
    {  
      if (speed == name_arr[i])  
    {  
      tcflush (fd, TCIOFLUSH);  
      cfsetispeed (&Opt, speed_arr[i]);  
      cfsetospeed (&Opt, speed_arr[i]);  
      status = tcsetattr (fd, TCSANOW, &Opt);  
      if (status != 0)  
        {  
          perror ("tcsetattr fd1");  
          return;  
        }  
      tcflush (fd, TCIOFLUSH);  
    }  
    }  
}  

int  
set_Parity (int fd, int databits, int stopbits, int parity)  
{  
  struct termios options;  
  if (tcgetattr (fd, &options) != 0)  
    {  
      perror ("SetupSerial 1");  
      return (FALSE);  
    }  
  options.c_cflag &= ~CSIZE;  
  switch (databits)  
    {  
    case 7:  
      options.c_cflag |= CS7;  
      break;  
    case 8:  
      options.c_cflag |= CS8;  
      break;  
    default:  
      fprintf (stderr, "Unsupported data size\n");  
      return (FALSE);  
    }  
  switch (parity)  
    {  
    case 'n':  
    case 'N':  
      options.c_cflag &= ~PARENB;   /* Clear parity enable */  
      options.c_iflag &= ~INPCK;    /* Enable parity checking */  
      break;  
    case 'o':  
    case 'O':  
      options.c_cflag |= (PARODD | PARENB);  
      options.c_iflag |= INPCK; /* Disnable parity checking */  
      break;  
    case 'e':  
    case 'E':  
      options.c_cflag |= PARENB;    /* Enable parity */  
      options.c_cflag &= ~PARODD;  
      options.c_iflag |= INPCK; /* Disnable parity checking */  
      break;  
    case 'S':  
    case 's':           /*as no parity */  
      options.c_cflag &= ~PARENB;  
      options.c_cflag &= ~CSTOPB;  
      break;  
    default:  
      fprintf (stderr, "Unsupported parity\n");  
      return (FALSE);  
    }  

  switch (stopbits)  
    {  
    case 1:  
      options.c_cflag &= ~CSTOPB;  
      break;  
    case 2:  
      options.c_cflag |= CSTOPB;  
      break;  
    default:  
      fprintf (stderr, "Unsupported stop bits\n");  
      return (FALSE);  
    }  
  /* Set input parity option */  
  if (parity != 'n')  
    options.c_iflag |= INPCK;  
  tcflush (fd, TCIFLUSH);  
  options.c_cc[VTIME] = 150;  
  options.c_cc[VMIN] = 0;   /* Update the options and do it NOW */  
  if (tcsetattr (fd, TCSANOW, &options) != 0)  
    {  
      perror ("SetupSerial 3");  
      return (FALSE);  
    }  
  return (TRUE);  
}  

void  
signal_handler_IO (int status)  
{  
  printf ("received SIGIO signale.\n");  
  wait_flag = noflag;  
}  

int  
main ()  
{  
  printf ("This program updates last time at %s   %s\n", __TIME__, __DATE__);  
  printf ("STDIO COM1\n");  
  int fd;  
  fd = open ("/dev/ttyUSB0", O_RDWR);  
  if (fd == -1)  
    {  
      perror ("serialport error\n");  
    }  
  else  
    {  
      printf ("open ");  
      printf ("%s", ttyname (fd));  
      printf (" succesfully\n");  
    }  

  set_speed (fd, 115200);  
  if (set_Parity (fd, 8, 1, 'N') == FALSE)  
    {  
      printf ("Set Parity Error\n");  
      exit (0);  
    }  

  char buf[255];  
  fd_set rd;  
  int nread = 0;  
  while(1)  
  {  
    FD_ZERO(&rd);  
    FD_SET(fd, &rd);  
    while(FD_ISSET(fd, &rd))  
    {  
        if(select(fd+1, &rd, NULL,NULL,NULL) < 0)  
        {  
            perror("select error\n");  
        }  
        else  
        {  
            while((nread = read(fd, buf, sizeof(buf))) > 0)  
            {  
                printf("nread = %d,%s\n",nread, buf);  
                printf("test\n");  
                memset(buf, 0 , sizeof(buf));  
            }  
        }  
    }  
  }  
  close (fd);  
  return 0;  
}  


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-11888-1-1.html 上篇帖子: linux内核数据结构之kfifo 下篇帖子: CentOS系统中手动调整系统时间的方法 Linux
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表