在配置完串口的相关属性后,就可以对串口进行打开、读写操作了。它所使用的函数和普通文件读写的函数一样,都是open、write和read,由于串口是一个终端设备,因此在函数的具体参数的选择时会有一些区别,另外,这里会用到一些附加的函数,用于测试终端设备的连接情况等,下面对其进行具体讲解。
1、打开串口
打开串口和打开普通文件一样,使用的函数同打开普通文件是一样的,都是open函数,如下所示:
fd = open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
可以看到,这里除了普通的读写参数外,还有两个参数O_NOCTTY和O_NDELAY.
O_NOCTTY标志用于通知Linux系统这个程序不会成为对应这个端口的控制终端。如果没有指定这个标志,那么任何一个输入(诸如键盘终止信号等)都将影响用户的进程。
O_NDELAY标志通知Linux系统这个程序不关心DCD信号线所处的状态(端口的另一端是否激活或者停止)。如果用户指定了这个标志,则进程将会一直处于睡眠态,直到DCD信号线被激活。
接下来可恢复串口的状态为阻塞状态,用于等待串口数据的读入,可用fcntl函数实现,如下所示:
fcntl(fd,F_SETFL,0);
再接下来可以测试打开文件描述符是否引用一个终端设备,以进一步确认串口是否正确打开,如下所示:
isatty(STDIN_FILEN0);
该函数调用成功则返回0,若失败则返回-1.
这时,一个串口就已经成功打开了。接下来就可以对这个串口进行读、写操作。
下面给出了一个完整的打开串口的函数,同样写考虑到了各种不同的情况,程序如下所示:
/*打开串口函数*/
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't Open Serial Port");
return (-1);
}
}
else if(comport==2){
fd = open("dev/ttyS1",O_RDWR|O_NOCTTY)|O_NDELAY);
if(-1 == fd){
perror("Can't Open Serial Port");
return (-1);
}
}
if(comport==3){
fd = open("dev/ttyS3",O_RDWR|O_NOCTTY)|O_NDELAY);
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;
}
2、读写串口
读写串口的操作和读写普通文件一样,使用read、write函数即可,如下所示:
write(fd,buff,8);
read(fd,buff,8);
下面两个实例给出了串口读和写的两个程序的main函数部分,这里用到的函数有前面讲述到的open_port和set_opt函数。
/*写串口程序*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*读串口程序*/
int main(){
int fd;
int nread,i;
char buff[]="Hello/n";
if((fd=open_port(fd,1))<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);
nread=read(fd,buff,8);
printf("nread=%d","%s/n",nread,buff);
close(fd);
return;
}
这里的读串口程序使用select函数实现多路复用式串口读写。读者在这里可以进一步了解select函数的使用方法。
/*读串口*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(){
int fd;
int nread,nwrite,i;
char buff[8];
fd_set rd;
/*打开串口*/
if((fd=open_port(fd,1))<0){
perror("open_port error");
return;
}
/*设置串口*/
if((i=set_opt(fd,115200,8,'N',1))<0){
perror("set_opt error");
return;
}
/*利用select函数来实现多个串口的读写*/
FD_ZERO(&rd);
FD_SET(fd,&rd);
while(FD_ISSET(fd,&rd)){
if(select(fd+1,&rd,NULL,NULL,NULL)<0)
perror("select");
else{
while((nread = read(fd,buff,8))>0){
printf("nread=%d,%s/n",nread,buff);
}
}
close(fd);
return;
}}
读者可以将该程序在宿主机上运行,然后用串口线将目标板和宿主机连接起来,之后将目标板上电,就可以看到宿主机上有目标板的串口输出。
[root@(none) 1]# ./write
fcntl=0
isatty success!
fd-open=3
set done
fd=3