Chinaunix首页 | 论坛 | 博客
  • 博客访问: 713587
  • 博文数量: 240
  • 博客积分: 3616
  • 博客等级: 大校
  • 技术积分: 2663
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-21 23:59
文章分类

全部博文(240)

文章存档

2013年(6)

2012年(80)

2011年(119)

2010年(35)

分类: LINUX

2010-10-21 11:42:58

串口在实际的使用中非常普通,下面我们分析一下对串口进行操作:

#include
#include
#include
#include
#include
#include
#include
#include//终端输入输出函数头文件,主要定义控制异步通信口的终端接口
#include

int set_opt(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
 struct termios newtio,oldtio;
 /*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/
 if(tcgetattr(fd,&oldtio)!=0)
 {
  perror("SetupSerial 1");
  return -1; 
 } 
 bzero(&newtio,sizeof(newtio));//将newtio所指的内存区域的sizeof(newtio)个字节,
                               //全部设为0
 /*步骤一:设置字符大小*/                           
 newtio.c_cflag |=CLOCAL |CREAD;
 newtio.c_cflag &=~CSIZE;
 /*步骤二:设置停止位*/
 switch(nBits)
 {
  case 7:
   newtio.c_cflag |=CS7;
   break;
  case 8:
   newtio.c_cflag |=CS8;
   break;
 }
 /*步骤三:设置奇偶校验位 */
 switch(nEvent)
 {
  case 'O':  //奇数
   newtio.c_cflag |=PARENB;
   newtio.c_cflag |=PARODD;
   newtio.c_iflag |=(INPCK |ISTRIP);
   break;
  case 'E'://偶数
   newtio.c_iflag |=(INPCK|ISTRIP);
   newtio.c_cflag |=PARENB;
   newtio.c_cflag &=~PARODD;
   break;
  case 'N'://无奇偶校验位
   newtio.c_cflag &=~PARENB;
   break; 
   
 }
 /*步骤四:设置波特率*/
 switch(nSpeed)
 {
  case 2400:
   cfsetispeed(&newtio,B2400);
   cfsetospeed(&newtio,B2400);
   break;
  case 4800:
   cfsetispeed(&newtio,B4800);
   cfsetospeed(&newtio,B4800);
   break;
  case 9600:
   cfsetispeed(&newtio,B9600);
   cfsetospeed(&newtio,B9600);
   break;
   
  case 115200:
   cfsetispeed(&newtio,B115200);
   cfsetospeed(&newtio,B115200);
   break; 
  case 460800:
   cfsetispeed(&newtio,B460800);
   cfsetospeed(&newtio,B460800); 
   break;
  default:
   cfsetispeed(&newtio,B9600);
   cfsetospeed(&newtio,B9600);
   break;
  
 }
 /*步骤五:设置停止位*/
 if(nStop==1)
 { 
  newtio.c_cflag &=~CSTOPB;
 }
 else if(nStop==2)
 {
  newtio.c_cflag |=CSTOPB; 
 }
 /*步骤六:设置等待时间和最小接收字符*/
 newtio.c_cc[CTIME]=0;
 newtio.c_cc[VMIN]=0;
 /* 步骤七:处理未接收字符*/
 tcflush(fd,TCIFLUSH);
 /*步骤八:激活新配置 */
 if((tcsetattr(fd,TCSANOW,&newtio))!=0)
 {
  perror("com set error");
  return -1; 
 }
 printf("set done !\n");
 return 0;
}

int open_port(int fd,int comport)
{
 char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};//定义一个字符串指针,用于定义串口个数
 long vdisable;
 /*根据输入参数,选择打开那个串口*/
 if(comport==1)
 {
  fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
  if(-1==fd)
  {
   perror("can not open serial port");
   return(-1); 
  } 
 }
 else if(comport==2)
 {
  fd=open("/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
  if(-1==fd)
  {
   perror("can not open serial port");
   return(-1); 
  } 
 }
 else if(comport==3)
 {
  fd=open("/dev/ttyS2",O_RDWR|O_NOCTTY|O_NDELAY);
  if(-1==fd)
  {
   perror("can not open serial port");
   return(-1); 
  } 
  
 }
 /*恢复串口为阻塞状态*/
 if(fcntl(fd,F_SETFL,0)<0)
 {
  printf("fcntl failed !\n"); 
 }
 else
 {
  printf("fcntl=%d\n",fcntl(fd,F_SETFL,0)); 
 }
 /*测试是否为终端设备  */
 if(isatty(STDIN_FILENO)==0)
 {
  printf("standard input is not a terminal device \n"); 
 }
 else
 {
  printf("isatty success !\n"); 
 }
 printf("fd-open=%d\n",fd);
 return fd ;
}

int main(void)
{
 int fd;
 int nwrite,i;
 char buff[]="hello\n";
 if((fd=open_port(fd,1))<0)//打开串口0
 {
  perror("open_port error");
  return;
 }

 if((i=set_opt(fd,115200,8,'N',1))<0)//设置串口有关参数
 {
  perror("set_opt error");
  return;
 }
 printf("fd=%d\n",fd);//打印文件描述符
 nwrite=write(fd,buff,8);//在串口中写数据
 printf("nwrite=%d\n",nwrite);//打印串口中的数据
 close(fd);
 return;
}
/*--------------------------------
1.设置串口中最基本的包括波特频设置,校验位和停止位设置。串口的设置主要
是设置struct termios结构体的各成员值,如下所示:
#include
struct termio
{
 unsigned short c_iflag;  //输入模式标志
 unsigned short c_oflag;  //输出模式标志
 unsigned short c_cflag;  //控制模式标志
 unsigned short c_lflag;  //本地模式标志
 unsigned char c_line;    //line discipline
 unsigned char c_cc[NCC]; //control characters
};
在这个结构中最重要的是c_cflag,通过对它的赋值,用户可以设置波特率,字符大小,
数据位,停止位,奇偶校验位和硬件控制流等.另外c_iflag和c_cc也是比较常用的标志.
c_cflag支持的常量如下图所示.其中设置波特率为相应的波特率前加上'B'.
 
 

在这里,对于c_cflag成员不能直接对起初始化,而要将其通过"与","或"操作使用其中的
某些选项.
输入模式c_iflag成员控制端口接收端的字符输入处理.c_iflag支持的变量名称,如下图所示.
 
 

c_cc包含了超时参数和控制字符的定义.c_cc所支持的常用变量名称,如下表所示:
 
 
2.保存原先串口配置
为了安全起见和以后调试程序方便,可以先保存原先串口的配置,在这里可以使用函数
tcgetattr(fd,&oldtio).该函数得到与fd指向对象的相关参数,并将它们保存于oldtio
引用的termios结构中.该函数还可以测试配置是否正确,该串口是否可用等.若调用成功,
函数返回值为0,若调用失败,函数返回值为-1.其使用如下:
if(tcgetattr(fd,&oldtio)!=0)
{
 perror("setup serial 1"); 
 return -1;
}
3.激活选项有CLOCAL和CREAD
CLOCAL和CREAD分别用于连接和接受使能,因此,首先要通过位掩码的方式激活这两个选项.
newtio.c_cflag |=CLOCAL|CREAT
4.设置波特率
设置波特率有专门的函数,用户不能直接通过位掩码来操作.设置波特率的主要函数有:
cfsetispeed和cfsetospeed.这两个函数的使用很简单,如下所示:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
一般地,用户需将输入输出函数的波特率设置成一样.这几个函数在成功时返回,失败时返回-1.
5.设置字符大小
与设置波特率不同,设置字符大小并没有现成可用的函数,需要用位掩码.一般首先去除数据位
中的位掩码,再重新按要求设置,如下所示:
options.c_cflag &=~ CSIZE; //mask the character size bits
options.c_cflag |=CS8;
6.设置奇偶校验位
设置奇偶校验位需要用到两个termio中的成员:c_cflag和c_iflag.首先要激活c_cflag中的
校验位使能标志PARENB和是否需要偶校验,同时还要激活c_iflag中的奇偶校验使能.如使能
奇校验时,代码如下所示:
newtio.c_cflag |=PARENB;
newtio.c_cflag |=PARODD;
newtio.c_iflag |=(INPCK |ISTRIP);
而使能偶校验时代码为:
newtio.c_iflag |=(INPCK |ISTRIP);
newtio.c_cflag |=PARENB
newtio.c_cflag &=~PARODD;
7.设置停止位
设置停止位通过激活c_cflag中的CSTOPB而实现的,若停止位为1,则清除CSTOPB,若停止位
为0,则激活CSTOPB.下面是停止位是1时的代码:
newtio.c_cflag &=~CSTOPB;
8.设置最小字符和等待时间
在对接收字符和等待时间没有特别要求的情况下,可以将其设置为0,如下所示:
newtio.c_cc[VTIME] =0;
newtio.c_cc[VMIN] =0;
9.处理要写入的引用对象
由于串口在重新设置之后,在此之前要写入的引用对象要重新处理,这时就可调用函数tcfush
(fd,queue_selector)来处理要写入引用的对象.对于尚未传输的数据,或者收到的但是尚未
读取的数据,其处理方法取决于queue_selector的值.
这里,queue_selector可能的取值有以下几种.
.TCIFLUSH:刷新收到的数据但是不读.
.TCOFLUSH:刷新写入的数据但是不传送.
.TCIOFLUSH:同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送.
10.激活配置
在完成全部串口配置之后,要激活刚才的配置并使配置生效.这里用到的函数是tcsetattr,
它的函数原型是:
tcsetattr(fd,OPTION,&newtio);
这里的newtio就是termios类型的变量,OPTION可能的取值有以下三种:
.TCSANOW:
.TCSADRAIN:
.TCSAFLUSH:改变的配置在所有写入fd引用对象的输出都被结束后生效,所有已接受但未
读入的输入都在改变发生前丢弃.
该函数若调用成功则返回0,若失败则返回-1.
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
 perror("com set error"); 
 return -1;
}
11.bzero(将一段内存内容全清为0)
1)头文件:#include
2)函数原型:void bzero(void *s,int n)
3)函数说明:bzero()会将参数s所指的内存区域前n个字节,全部设为0.
------------------------------------------------------------*/

 

阅读(1770) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~