其实linux串口挺简单的,只用找到串口号,再程序上配置成功,打开串口,直接用read write函数就能接受 发送数据了。现在详细讲解一下怎么使用两个串口,一个串口发送数据,一个串口接受数据。
一:linux串口编程的组成
1.打开串口
2.串口初始化
3.读写串口
4.关闭串口
5.结束
二:串口打开
1.在Linxu中,串口设备是通过串口终端设备文件来访问的,即通过访问/dev/ttyS0,/dev/ttyS1,/dev/ttyS2这些设备文件实现对串口的访问
2.调用open()函数来代开串口设备,对于串口的打开操作,必须使用O_NOCTTY参数。
l O_NOCTTY:表示打开的是一个终端设备,程序不会成为该端口的控制终端。如果不使用此标志,任务一个输入(eg:键盘中止信号等)都将影响进程。
l O_NDELAY:表示不关心DCD信号线所处的状态(端口的另一端是否激活或者停止)。
3.打开串口模块有那及部分组成
1>调用open()函数打开串口,获取串口设备文件描述符
2>获取串口状态,判断是否阻塞
3>测试打开的文件描述符是否为终端设备
char *uart2 = "/dev/ttySAC1";
fd_uart2 = open(uart2, O_RDWR|O_NOCTTY)
三.串口的初始化
在linux中的串口初始化和前面的串口初始化一样。需要设置串口波特率,数据流控制,帧的格式(即数据位个数,停止位,校验位,数据流控制)
串口初始化模块有那几部分组成:
1设置波特率
2设置数据流控制
3设置帧的格式(即数据位个数,停止位,校验位)
1>设置串口参数时要用到termios结构体,因此先要通过函数
tcgettattr(fd,&options)获得串口指向termios结构的指针。
2>通过cfsetispeed函数和cfsetospeed函数用来设置串口的输入/输出波特率。一般情况下,输入和输出波特率相等的。
3>设置数据位可以通过修改termios机构体中c_flag来实现。其中CS5,CS6,CS7,CS8对应数据位的5,6,7,8。在设置数据位时,必须要用CSIZE做位屏蔽。
4>数据流控制是使用何种方法来标志数据传输的开始和结束。
5>在设置完波特率,数据流控制,数据位,校验位,停止位,停止位后,还要设置最小等待时间和最小接收字符。
6>在完成配置后要通过tcsetattr()函数来激活配置。
四:串口的读写
串口读写是通过read函数读数据,write函数发数据来实现的。
ssize_t read(int fd,void *buf,size_t nbyte)
read函数就是从fd中读取nbyte个字节的内容存发哦*buf中去。在串口读中fd取的就是open打开串口后返回的文件描述符,成功时,read返回实际所读的字节数,如果返回的值是0,表示已经读到文件的结束了。
nByte = read(fd_uart2, buffer, 512)
下面的程序中就是在串口2中读取数据,然后存到定义的buffer数组中。
ssize_t write(int fd,const void *buf,size_t nbytes)
write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量.
write(fd_uart0,buffer,strlen(buffer)
下面的程序中是在串口0发送数据。读取到串口2的数据后存到buffer中后串口0就发送buffer中的数据。
1)write的返回值大于0,表示写了部分或者是全部的数据.
2)返回的值小于0,此时出现了错误.我们要根据错误类型来处理.
程序中的memset函数:
void *memset(void *s,int c,size_t n)
作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。
所以在下面的程序中用于buffer数组的清零初始化
memset(buffer, 0, sizeof(buffer));
把buffer中的首
sizeof(buffer)个字节设为0.
sizeof是对传入的变量算出其字节长度
例如:定义的buffer[512]
sizeof(buffer)算出来就是512字节
-
#include <stdio.h>
-
#include <string.h>
-
#include <unistd.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
#include <termios.h>
-
#include <errno.h>
-
-
int set_opt(int,int,int,char,int);
-
-
void main()
-
{
-
int fd_uart1,nByte,fd_uart2;
-
char *uart0 = "/dev/ttySAC0";
-
char *uart2 = "/dev/ttySAC1"; //串口com2
-
char buffer[512];
-
char *uart_out = "please input\r\n";
-
-
memset(buffer, 0, sizeof(buffer)); //给数组清零
-
-
if((fd_uart2 = open(uart2, O_RDWR|O_NOCTTY))<0) //打开串口com2 ,fd_uart2为串口com2的文件描述符
-
printf("open %s is failed",uart2);
-
else{
-
printf("open com2 success!\n");
-
}
-
-
if((fd_uart0 = open(uart0, O_RDWR|O_NOCTTY))<0) //打开串口com0,fd_uart0为串口com0的文件描述符
-
printf("open %s is failed",uart0);
-
else{
-
printf("open com0 success!\n");
-
}
-
-
set_opt(fd_uart1, 115200, 8, 'N', 1); //配置串口
-
set_opt(fd_uart2, 115200, 8, 'N', 1);
-
//再读写函数中操作文件描述符
-
write(fd_uart0,uart_out, strlen(uart_out)); //再com0输出please input
-
-
while(1){
-
while((nByte = read(fd_uart2, buffer, 512))>0){ //循环判断com2是否读到字节
-
buffer[nByte+1] = '\0'; //再接受到的字符最后一位加个\0,字符串的结束符
-
write(fd_uart0,buffer,strlen(buffer)); //往com0口发出读到的数据
-
memset(buffer, 0, strlen(buffer)); //给数组清零
-
nByte = 0;
-
}
-
}
-
-
-
}
-
-
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.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[VTIME] = 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\r");
-
return 0;
-
}
阅读(3358) | 评论(0) | 转发(1) |