Linux下串口应用开发代码详解
#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;
}
更多推荐
所有评论(0)