Chinaunix首页 | 论坛 | 博客
  • 博客访问: 91560
  • 博文数量: 19
  • 博客积分: 760
  • 博客等级: 军士长
  • 技术积分: 260
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 16:30
文章存档

2011年(1)

2009年(18)

我的朋友

分类: LINUX

2009-07-30 16:49:41

Linux下串口程序开发

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

linux文件中,所有的设备文件一般都位于/dev下,其中串口一、串口二分别对应的设备名依次为“/dev/ttyS0、“/dev/ttyS1,可以查看在/dev下的文件以确认。在linux下面对于串口的读写就可以通过简单的readwrite函数来完成,所不同的是只是需要对串口的其他参数另坐配置。

1.   串口编程需要用到的头文件

#include // 标准输入输出定义

#include

#include // 文件控制定义,主要完成串口通信中对文件的读写操作

#include // linux标准函数定义

#include

#include    // POSIX终端控制定义                        

#include  

#include  

2.   串口终端函数

2.1      打开串口设备

     int fd

       char *device = "/dev/tts/0";                   // 设备路径,初始使用UART0

      

       for(t=1;t                                // 获取程序入口时输入的参数

       {

              if(!strcmp(argv[t],"-d") && (argc > (t+1)))

              {

                     device = argv[t+1];

              }

       }

       if(!strcmp(device,"/dev/tts/1"))               // 不允许使用UART1,因为它已和PC相连。

       {

              printf("can not use /dev/tts/1\n");

              return -1;     

       }

       fd = open(device, O_RDWR);                         // 打开设备

       if (fd < 0)                                          // 设备打开失败

       {

              printf("open device error\n");

              return -1;

       }

2.2      设置串口

最基本的串口设置包括波特率设置,校验位和停止位设置。实际上串口的设置只要是设置Struct termios()结构体中各成员的值。

struct termio

{     unsigned short  c_iflag;    /* 输入模式标志 */

       unsigned short  c_oflag;          /* 输出模式标志 */

       unsigned short  c_cflag;          /* 控制模式标志*/ 

       unsigned short  c_lflag;           /* local mode flags */

       unsigned char  c_line;                  /* line discipline */      

       unsigned char  c_cc[NCC];    /* control characters */

};

2.2.1  波特率设置

struct  termios Opt;

tcgetattr(fd, &Opt);             // 得到当前串口的参数

cfsetispeed(&Opt,B19200);     /*设置为19200Bps*/

cfsetospeed(&Opt,B19200);

tcsetattr(fd,TCANOW,&Opt);    // 激活新配置

设置波特率的例子函数:

/**

*@brief  设置串口通信速率

*@param  fd     类型 int  打开串口的文件句柄

*@param  speed  类型 int  串口速度

*@return  void

*/

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

              } 

       }

}

2.2.2  校验位和停止位设置

/**

*@brief   设置串口数据位,停止位和效验位

*@param  fd     类型  int  打开的串口文件句柄

*@param  databits 类型  int 数据位   取值 7 或者8

*@param  stopbits 类型  int 停止位   取值为 1 或者2

*@param  parity  类型  int  效验类型 取值为N,E,O,,S

*/

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 */

        break; 

case 'o':  

case 'O':    

        options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ 

        options.c_iflag |= INPCK;  // INPCK:奇偶校验使能

        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':    // Space 校验

case 's':  /*as no parity*/  

     options.c_cflag &= ~PARENB;

        options.c_cflag &= ~CSTOPB;

        options.c_iflag |= INPCK;

break; 

default:  

        fprintf(stderr,"Unsupported parity\n");   

        return (FALSE); 

} 

 

// 设置停止位 

switch (stopbits)

{  

  case 1:   

         options.c_cflag &= ~CSTOPB;  // 1个停止位

         break; 

  case 2:   

         options.c_cflag |= CSTOPB;  // 2个停止位

     break;

  default:   

          fprintf(stderr,"Unsupported stop bits\n"); 

          return (FALSE);

}

 

// 处理未接收的字符

tcflush(fd,TCIFLUSH);

 

// 设置等待时间和最小接收字符

options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/  

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

}

2.2.3  模式设置

需要注意的是,如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通信。

       newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始数据输入

       newtio.c_oflag &= ~(OPOST); // 原始数据输出

2.2.4  串口配置实例

void init_ttyS(int fd)

{

       struct termios newtio;

 

       bzero(&newtio, sizeof(newtio));

// 得到当前串口的参数

       tcgetattr(fd, &newtio);             

                    

// 将输入波特率设为19200

// 将输出波特率设为19200

       cfsetispeed(&newtio, B19200);                           

       cfsetospeed(&newtio, B19200);            

             

// 使能接收并使能本地状态

       newtio.c_cflag |= (CLOCAL | CREAD);                  

 

// 无校验 8位数据位1位停止位

       newtio.c_cflag &= ~PARENB;                        

       newtio.c_cflag &= ~CSTOPB;

       newtio.c_cflag &= ~CSIZE;

 

// 8个数据位

       newtio.c_cflag |= CS8;

 

// 原始数据输入

       newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

       newtio.c_oflag &= ~(OPOST);

 

// 设置等待时间和最小接收字符数

       newtio.c_cc[VTIME]    = 0;                         

       newtio.c_cc[VMIN]     = 0;  

 

// 处理未接收的字符

       tcflush(fd, TCIFLUSH);                            

 

// 激活新配置

       tcsetattr(fd,TCSANOW,&newtio);                        

}

阅读(2012) | 评论(0) | 转发(1) |
0

上一篇:没有了

下一篇:Linux下串口程序开发(2)

给主人留下些什么吧!~~