Chinaunix首页 | 论坛 | 博客
  • 博客访问: 111563
  • 博文数量: 35
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 287
  • 用 户 组: 普通用户
  • 注册时间: 2015-08-01 19:56
文章分类
文章存档

2017年(6)

2016年(21)

2015年(8)

我的朋友

分类: 嵌入式

2016-03-16 13:15:40

其实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字节

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <termios.h>
  8. #include <errno.h>

  9. int set_opt(int,int,int,char,int);

  10. void main()
  11. {
  12.     int fd_uart1,nByte,fd_uart2;
  13.     char *uart0 = "/dev/ttySAC0";
  14.     char *uart2 = "/dev/ttySAC1"; //串口com2
  15.     char buffer[512];
  16.     char *uart_out = "please input\r\n";
  17.     
  18.     memset(buffer, 0, sizeof(buffer)); //给数组清零
  19.     
  20.     if((fd_uart2 = open(uart2, O_RDWR|O_NOCTTY))<0) //打开串口com2 ,fd_uart2为串口com2的文件描述符
  21.         printf("open %s is failed",uart2);
  22.     else{
  23.      printf("open com2 success!\n");    
  24.      }
  25.     
  26.     if((fd_uart0 = open(uart0, O_RDWR|O_NOCTTY))<0) //打开串口com0,fd_uart0为串口com0的文件描述符
  27.         printf("open %s is failed",uart0);
  28.     else{
  29.      printf("open com0 success!\n");    
  30.      }
  31.     
  32.         set_opt(fd_uart1, 115200, 8, 'N', 1); //配置串口
  33.         set_opt(fd_uart2, 115200, 8, 'N', 1);
  34.          //再读写函数中操作文件描述符
  35.         write(fd_uart0,uart_out, strlen(uart_out)); //再com0输出please input
  36.         
  37.         while(1){
  38.             while((nByte = read(fd_uart2, buffer, 512))>0){ //循环判断com2是否读到字节
  39.                 buffer[nByte+1] = '\0';             //再接受到的字符最后一位加个\0,字符串的结束符
  40.                 write(fd_uart0,buffer,strlen(buffer)); //往com0口发出读到的数据
  41.                 memset(buffer, 0, strlen(buffer)); //给数组清零
  42.                 nByte = 0;
  43.             }
  44.         }
  45.     

  46. }

  47. int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop) //串口配置
  48. {
  49.     struct termios newtio,oldtio;
  50.     if ( tcgetattr( fd,&oldtio) != 0) {
  51.         perror("SetupSerial 1");
  52.         return -1;
  53.     }
  54.     bzero( &newtio, sizeof( newtio ) );
  55.     newtio.c_cflag |= CLOCAL | CREAD;
  56.     newtio.c_cflag &= ~CSIZE;

  57.     switch( nBits
  58.     {
  59.         case 7:
  60.             newtio.c_cflag |= CS7;
  61.             break;
  62.         case 8:
  63.             newtio.c_cflag |= CS8;
  64.             break;
  65.     }

  66.     switch( nEvent )
  67.     {
  68.     case 'O':
  69.         newtio.c_cflag |= PARENB;
  70.         newtio.c_cflag |= PARODD;
  71.         newtio.c_iflag |= (INPCK | ISTRIP);
  72.         break;
  73.     case 'E':
  74.         newtio.c_iflag |= (INPCK | ISTRIP);
  75.         newtio.c_cflag |= PARENB;
  76.         newtio.c_cflag &= ~PARODD;
  77.         break;
  78.     case 'N':
  79.         newtio.c_cflag &= ~PARENB;
  80.         break;
  81.     }

  82.     switch( nSpeed )
  83.     {
  84.         case 2400:
  85.             cfsetispeed(&newtio, B2400);
  86.             cfsetospeed(&newtio, B2400);
  87.             break;
  88.         case 4800:
  89.             cfsetispeed(&newtio, B4800);
  90.             cfsetospeed(&newtio, B4800);
  91.             break;
  92.         case 9600:
  93.             cfsetispeed(&newtio, B9600);
  94.             cfsetospeed(&newtio, B9600);
  95.             break;
  96.         case 115200:
  97.             cfsetispeed(&newtio, B115200);
  98.             cfsetospeed(&newtio, B115200);
  99.             break;
  100.         case 460800:
  101.             cfsetispeed(&newtio, B460800);
  102.             cfsetospeed(&newtio, B460800);
  103.             break;
  104.         default:
  105.             cfsetispeed(&newtio, B9600);
  106.             cfsetospeed(&newtio, B9600);
  107.             break;
  108.     }
  109.     if( nStop == 1 )
  110.         newtio.c_cflag &= ~CSTOPB;
  111.     else if ( nStop == 2 )
  112.         newtio.c_cflag |= CSTOPB;
  113.         newtio.c_cc[VTIME] = 0;
  114.         newtio.c_cc[VMIN] = 0;
  115.         tcflush(fd,TCIFLUSH);
  116.     if((tcsetattr(fd,TCSANOW,&newtio))!=0)
  117.     {
  118.         perror("com set error");
  119.         return -1;
  120.     }
  121.     
  122.         printf("set done!\n\r");
  123.     return 0;
  124. }


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