Chinaunix首页 | 论坛 | 博客
  • 博客访问: 200146
  • 博文数量: 27
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 350
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-22 08:34
文章分类

全部博文(27)

文章存档

2011年(1)

2010年(1)

2009年(25)

我的朋友

分类: 嵌入式

2009-11-23 11:07:38

一、简介:
  Linux操作系统从一开始就对串行口提供了很好的支持,本文就Linux下的串行口通讯编程进行简单的介绍。
  二、串口简介:
   串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的 全名是"数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准"该标准规定采用一个25个脚的DB25连接器,对连接器的 每个引脚的信号内容加以规定,还对各种信号的电平加以规定。传输距离在码元畸变小于4%的情况下,传输电缆长度应为50英尺。

Linux操作系统从一开始就对串行口提供了很好的支持,本文就Linux下的串行口通讯编程进行简单的介绍,如果要非常深入了解,建议看看本文所参考的《Serial Programming Guide for POSIX Operating Systems》
   三、串口操作:
  串口操作需要的头文件
    #include          
    #include         
    #include         
    #include      
    #include       
    #include          
    #include
    #include          
3.1 打开串口
    在 Linux 下串口文件是位于 /dev 下的。串口一 为 /dev/ttyS0,串口二 为 /dev/ttyS1。打开串口是通过使用标准的文件打开函数操作:
     int fd;
     fd = open( "/dev/ttyS0", O_RDWR);
     if (-1 == fd)

{
         perror(" 提示错误!");
    }
3.2设置串口
  最基本的设置串口包括波特率设置,效验位和停止位设置。串口的设置主要是设置 struct termios 结构体的各成员值。
  struct termio
  {

  unsigned short  c_iflag;
      unsigned short  c_oflag; 
      unsigned short  c_cflag; 
      unsigned short  c_lflag; 
      unsigned char  c_line;     
      unsigned char  c_cc[NCC];   
   };
 设置这个结构体很复杂,我这里就只说说常见的一些设置:
 3.2.1 波特率设置

下面是修改波特率的代码:
      struct  termios Opt;
      tcgetattr(fd, &Opt);
      cfsetispeed(&Opt,B19200);    
      cfsetospeed(&Opt,B19200);
      tcsetattr(fd,TCANOW,&Opt);
      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(fd1, TCSANOW, &Opt); 
                     if  (status != 0)

                       
                          perror("tcsetattr fd1"); 
                          return;    
                       
                     tcflush(fd,TCIOFLUSH);  
               
          }
     }
  3.2.2 设置效验的函数:

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

                return (FALSE); 
           }
           switch (parity)
           
                case 'n':
                case 'N':   
                     options.c_cflag &= ~PARENB;  
                     options.c_iflag &= ~INPCK;    
                     break; 
                case 'o':  
                case 'O':    
                     options.c_cflag |= (PARODD | PARENB);  
                     options.c_iflag |= INPCK;            
                     break; 
                case 'e': 
                case 'E':  
                     options.c_cflag |= PARENB;        
                     options.c_cflag &= ~PARODD;       
                     options.c_iflag |= INPCK;      
                     break;
                case 'S':
                case 's':    
                     options.c_cflag &= ~PARENB;
                     options.c_cflag &= ~CSTOPB;break; 
                default:  
                     fprintf(stderr,"Unsupported parity ");   
                     return (FALSE); 
           
 
          switch (stopbits)
           
              case 1:   
                    options.c_cflag &= ~CSTOPB; 
                    break; 
              case 2:   
                    options.c_cflag |= CSTOPB; 
                    break;
              default:   
                    fprintf(stderr,"Unsupported stop bits "); 
                    return (FALSE);
          }

          if (parity != 'n')  
                  options.c_iflag |= INPCK;
           tcflush(fd,TCIFLUSH);
           options.c_cc[VTIME] = 150;   
           options.c_cc[VMIN] = 0;
           if (tcsetattr(fd,TCSANOW,&options) != 0)  
           {
                 perror("SetupSerial 3");  
                 return (FALSE); 
           }
           return (TRUE); 
      }

需要注意的是: 如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯,设置方式如下:
     options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG); 
     options.c_oflag  &= ~OPOST;  
 3.3 读写串口
设置好串口之后,读写串口就很容易了,把串口当作文件读写就是。
    3.3.1 发送数据
          char  buffer[1024];
          int    Length;
          int    nByte;
          nByte = write(fd, buffer ,Length)
   3.3.2 读取串口数据
    使用文件操作read函数读取,如果设置为原始模式(Raw Mode)传输数据,那么read函数返回的字符数是实际串口收到的字符数。可以使用操作文件的函数来实现异步读取,如fcntl,或者select等来操作。
         char  buff[1024];
         int    Len;
         int  readByte = read(fd,buff,Len);
3.4 关闭串口
  关闭串口就是关闭文件。
  close(fd);
3.5 例子
下面是一个简单的读取串口数据的例子,使用了上面定义的一些函数和头文件

#define FALSE  -1
#define TRUE   0

int OpenDev(char *Dev)
{
    int fd = open( Dev, O_RDWR );
        //| O_NOCTTY | O_NDELAY
    if (-1 == fd)
     
        perror("Can't Open Serial Port");
        return -1; 
    }
    else
         return fd;
}
int main(int argc, char **argv)
{
    int fd;
    int nread;
    char buff[512];
    char *dev  = "/dev/ttyS1"; //串口二
    fd = OpenDev(dev);
    set_speed(fd,19200);
    if (set_Parity(fd,8,1,'N') == FALSE) 
    {
        printf("Set Parity Error ");
        exit (0);
    }
    while (1) //循环读取数据
   
       while((nread = read(fd, buff, 512))>0)
      {
           printf(" Len %d ",nread);
           buff[nread+1] = '';  
           printf( " %s", buff);  
      }
   }
   //close(fd); 
   // exit (0);
}
阅读(2033) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~