Linux下串口应用开发代码详解

来源:互联网 发布:java方法的覆盖调用 编辑:程序博客网 时间:2024/05/19 02:20

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

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop) /*设置结构体,fd文件描述符;nSpeed为串口传输速度;nBits为比特率;nEvent传输结果;nStop传输结束*/
{
 struct termios newtio,oldtio;              //termios 函数族提供了一个常规的终端接口,用于控制非同步通信端口,newtio我理解为新建立的串口配置,oldtio为linux默认的串口配置
 if  ( tcgetattr( fd,&oldtio)  !=  0) { /*保存原先的串口配置使用( tcgetattr( fd,&oldtio) ;(oldtio上面已经解释过为linux默认的串口配置。)该函数可到与fd指向对象的相关参数,并将他们保存与oidtio的应用的termios结构体中。termios结构体参
  perror("SetupSerial 1");  //在库函数中有个error变量,每个error值对应着以字符串表示的错误类型。这里返回错误提示
  return -1;     //跳转出去
 }
 bzero( &newtio, sizeof( newtio ) ); /*sizeof(newtio)表示计算新建立串口配置newtio在内存中所占有的地址空间。切记这里sizeof为运算符不是函数!bzero()清空端口数据,bzero中表示的"b"表bytetop(比特率)bzero( &newtio, sizeof( newtio ) )表示计算出新建串口的内存地址空间,然后清空newtio地址中的数据*/
 newtio.c_cflag  |=  CLOCAL | CREAD; //通过位掩码方式激活CLOCAL(本地链接)和CREAD(接受使能)
 newtio.c_cflag &= ~CSIZE; //通过c_cflag设置比特率掩码位的大小

 switch( nBits ) //计算比特率
 {
 case 7:                  /*比较比特率 
  newtio.c_cflag |= CS7;  是否为7个数据位*/
  break;                  //中断当前循环
 case 8:                  /*比较比特率
  newtio.c_cflag |= CS8;   是否为8个数据位*/
  break;                   //中断当前循环
 }

 switch( nEvent )
 {
 case 'O':  //使用奇校验,'O'表示odd
  newtio.c_cflag |= PARENB;
  newtio.c_cflag |= PARODD;
  newtio.c_iflag |= (INPCK | ISTRIP);
  break;
 case 'E': //使用偶校验,'E'表示even
  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:             //缺省设置比特率上行下行为9600
  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[VTIME]  = 0;  //接受数据字符
 newtio.c_cc[VMIN] = 0;    //接受数据时间
 tcflush(fd,TCIFLUSH);//调用tcflush函数,刷清未决定操作的输入和输出数据。比如终端驱动程序已接收到,但用户程序尚未读。用户程序已经写,但尚未发送
 if((tcsetattr(fd,TCSANOW,&newtio))!=0) // 当不等于0的时候,表示清空失败,执行perror()
 {
  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"}; //定义char型数组
 long  vdisable; 
 if (comport==1)      //当调用一号端口
 { fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);  //对/dev/ttyS0文件设置读写权限,O_NOCTTY:如果路径名指向终端设备,不要把这个设备用作控制终端.O_NDELAY指定非阻塞方式
  if (-1 == fd){      //当文件描述符为-1
   perror("Can't Open Serial Port"); //调用perror函数显示不能打开端口
   return(-1);         //退出 
  }
 }
 else if(comport==2)   //当调用二号端口
 { fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY); //对/dev/ttyS2文件设置权限
  if (-1 == fd){
   perror("Can't Open Serial Port");
   return(-1);
  }
 }
 else if (comport==3)   //当调用三号端口
 {
  fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY); //对/dev/ttyS3文件设置权限
  if (-1 == fd){
   perror("Can't 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;
}

原创粉丝点击