在嵌入式Linux中,串口是一个字设备,访问具体的串行端口的编程与读/写文件 的操作类似,只需打开相应的设备文件即可操作。串口编程特殊在于串 口通信时相关参数与属性的设置。嵌入式Linux的串口编程时应注意,若在根文件中没有串口设备文件,应使用mknod命令创建,这这里假设串口设备是 /dev/ttyS0,介绍一下串口的编程过程。
#mknod /dev/ttyS0 c 4 64
1、打开串口
    打开串口设备文件的操作与普通文件的操作类似,都采用标准的I/O操作函数open()。
    fd = open("/dev/ttyS0",O_RDWR|O_NDELAY|O_NOCTTY);

open()函数有两个参数,第一个参数是要打开的文件名(此处为串口设备文件/dev/ttyS0);第二个参数设置打开的方式,O_RDWR表示打开
的文件可读/写,O_NDELAY表示以非阻塞方式打开,O_NOCTTY表示若打开的文件为终端设备,则不会将终端作为进程控制终端。
2、设置串口属性
     串口通信时的属性设置是串口编程的关键问题,许多串口通信时的错误都与串口的设置相关,所以编程时应特别注意这些设置,最常见的设置包括波特率、奇偶校验和停止位以及流控制等。
    在Linux中,串口被作为终端I/O,它的参数设置需要使用struct termios结构体,这个结构体在termio.h文件中定义,且应在程序中包含这个头文件。
          typedef unsigned char         cc_t ;
          typedef unsigned int            speed_t ;
          typedef unsigned int            tcflag_t ;
          struct termios
          {
             tcflag_t      c_iflag ;          /*输入模式标志*/ 
             tcflag_t      c_oflag ;         /*输出模式标志*/
             tcflag_t      c_cflag ;            /*控制模式标志*/
             tcflag_t      c_lflag ;            /*本地模式标志*/
             tcflag_t      c_line ;            /*行规程类型,一般应用程序不使用*/
             cc_t         c_cc[NCC];      /*控制字符*/
             speed_t      c_ispeed ;      /*输入数据波特率*/
             speed_t      c_ospeed ;      /*输出数据波特率*/
       };
       串口的设置主要是设置这个结构体的各成员值,然后利用该结构体将参数传给硬件驱动程序。在Linux中,串口以串行终端的方式进行处理,因而,可以使用tcgetattr()/tcsetattr()函数获取/设置串口的参数。
       int tcgetattr( int fd, struct termios *termios_p );
       int tcsetattr( int fd, int optional_actions , struct termios *termios_p );
   
  
这两个参数都有一个批向termios结构体的指针作为参数,用于返回当前终端的属性或设置该终端的属性。参数fd就是用open()函数打开的终端文件
句柄,而串口就是用open()打开的串口设备文件句柄。tcsetattr()函数的optional_action参数用于指定新设定的参数起作用的
时间,其设定值可以为:
       TCSANOW         改变立即生效
       TCSADRAIN      在所有的输出都被传输后改变生效,适用于更改影响输出参数的情况。
       TCSAFLUSH    在所有输出都被传输后改变生效,丢弃所有末读入的输入(清空输入缓                                存)。
(1)设置波特率
   
  
使用cfsetospeed()/cfsetispeed()函数设置波特率,它们分别用于在termios结构体中设置输出和输入的波特率。设置波特率
可以使用波特率常数,其定义为字母“B+速率”,如B19200就是波特率为19200bps,B115200就是波特率为115200bps。
int cfsetispeed( struct termios *termios_p, speed_t speed );     //speed为波特率常数
int cfsetospeed( struct termios *termios_p, speed_t speed );
例 :
cfsetispeed( ttys0_opt, B115200 );
cfsetospeed( ttys0_opt, B115200 );
(2)设置控制模式标志
       控制模式标志c_cflag主要用于设置串口对DCD信号状态检测、硬件流控制、字符位宽、停止位和奇偶校验等,常用标志位如下:
CLOCAL   忽略DCD信号,若不使用MODEM,或没有串口没有CD脚就设置此标志
CREAD    启用接收装置,可以接收字符
CRTSCTS启用硬件流控制,对于许多三线制的串不应使用,需设置~CRTCTS
CSIZE      字符位数掩码,常用CS8
CSTOPB   使用两个停止位,若用一位应设置~CSTOPB
PARENB   启用奇偶校验
       例如,下面的代码将串口设置为忽略DCD信号,启用接收装置,关闭硬件流控制,传输数据时使用8位数据位和一位停止位(8N1),不使用奇偶校验。
       struct temios ttys0
       ttyso_opt.c_cflag |= CLOCAL | CREAD ;      //将CLOCAL与CREAD位设置为1
       ttys0_opt.c_cflag &= ~CRTSCTS ;               //将硬件流控制位CRTSCTS清0,其他位不变
       ttys0_opt.c_cflag &= ~CSIZE ;               //清除数据位掩码
       ttys0_opt.c_cflag |= CS8 ;                           //设置8位数据位标志CS8
       ttys0_opt.c_cflag &= ~(PARENB|CSTOPB);//使用1位停止位,停用奇偶校验
(3)设置本地模式标志
   
  
本地模式标志c_lflag主要用于设置终端与用户的交互方式,常见的设置标志位有ICAN-ON,ECHO和ECHOE等。其中,ICANON标志位用
于实现规范输入,即read()读到行结束符后返回,常用于终端的处理;若串口用于发送/接收数据,则应清除此标志,使用非规范模式(raw
mode)。非规范模式中,输入数据不组成行,不处规范模式中的特殊字符。在规范模式中,当设置ECHO标志位时,用户向终端输入的字符将被回传给用户;
当设置ECHOE标志位时,用户输入退格键时,则回传“退格-空格-退格”序列给用户,使得退格键覆盖的字符从显示中消失,这样更符合用户的习惯(若未设
置此标志,输入退格键时,则光标回退一个字符,但原有的字符未从显示中消失)。
(4)设置输入模式标志
      
输入模式标志c_iflag主要用于控制串口的输入特性,常用的设置有IXOFF和IXON,分别用于软件流控制。其中,IXOFF用于防止输入缓冲区溢
出;IXON则是在输入数据中识别软件流控制标志。由于许多嵌入式系统无法使用硬件流控制,因此,只能使用软件流控制数据传输的速度,但是,它可能降低串
口数据传输效率。启用软件流控制的代码如下:
       ttys0_opt.c_iflag |= IXOFF|IXON ;
(5)设置输出模式标志
       输出模式标志c_oflag主要用于对串口在规范模式时输出的特殊字符处理,而对非规范模式无效。
(6)设置控制字符
       在非规范模式中,控制字符数组c_cc[]中的变量c_cc[VMIN]和c_cc[VTIME]用于设置read()返回前读到的最少字节数和读超时时间,其值分为四种情况:
    (a)c_cc[VMIN]>0,c_cc[VTIME]>0
          读到一个字节后,启动定时器,其超时时间为c_cc[VTIME],read()返回的条件为至少读到c_cc[VMIN]个字符或定时器超期。
    (b)c_cc[VMIN]>0, c_cc[VTIME] ==0
          只要读到数据的字节数大于等于c_cc[VMIN],则read()返回;否则,将无限期阻塞等待。
      (c)c_cc[VMIN] == 0, c_cc[VTIME]>0
          只要读到数据,则read()返回;若定时器超期(定时时间c_cc[VTIME])却未读到数据,则read()返回0;
      (d)c_cc[VMIN] == 0, c_cc[VTIME] == 0
          若有数据,则read()读取指定数量的数据后返回;若没有数据,则read()返回0;
在termios结构体中填写完这些参数后,接下来就可以使用tcsetattr()函数设置串口的属性。
       tcsetattr( fd, &old_opt );         //将原有的设置保存到old_opt,以便程序结束后恢复
       tcsetattr( fd, TCSANOW, &ttsy0_opt );
3、清空发送/接收缓冲区
       为保证读/写操作不被串口缓冲区中原有的数据干拢,可以在读/写数据前用tcflush()函数清空串口发送/接收缓冲区。tcflush()函数的参数可为:
        TCIFLUSH      清空输入队列
        TCOFLUSH   清空输出队列
        TCIOFLUSH   同时清空输入和输出队列
4、从串口读写数据
        串口的数据读/写与普通文件的读/写一样,都是使用read()/write()函数实现。
        n = write( fd, buf, len );         //将buf中len个字节的数据从串口输出,返回输出的字节数
        n = read( fd, buf, len );         //从串口读入len个字节的数据并放入buf, 返回读取的字节数
5、关闭串口
    关闭串口的操作很简单,将打开的串口设备文件句柄关闭即可。
    close(fd);

参数设置程序如下:

int set_Parity(int fd,int databits,int stopbits,int parity)
{
 struct termios options;
 if  ( tcgetattr( fd,&options)  !=  0) {
  perror("SetupSerial 1");    
  return(CHK_ERR); 
 }
 options.c_cflag &= ~CSIZE;

switch (databits) /*设置数据位数*/
 {  
 case 7:  
  options.c_cflag |= CS7;
  break;
 case 8:    
  options.c_cflag |= CS8;
  break;  
 default:   
  fprintf(stderr,"Unsupported data size\n"); return (CHK_ERR); 
 }
 switch (parity)
 {  
  case 'n':
  case 'N':   
   options.c_cflag &= ~PARENB;   /* Clear parity enable */
   options.c_iflag &= ~INPCK;     /* Enable parity checking */
   break; 
  case 'o':  
  case 'O':    
   options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ 
   options.c_iflag |= INPCK;             /* Disnable parity checking */
   break; 
  case 'e': 
  case 'E':  
   options.c_cflag |= PARENB;     /* Enable parity */   
   options.c_cflag &= ~PARODD;   /* 转换为偶效验*/    
   options.c_iflag |= INPCK;       /* Disnable parity checking */
   break;
  case 'S':
  case 's':  /*as no parity*/  
      options.c_cflag &= ~PARENB;
   options.c_cflag &= ~CSTOPB;break; 
  default:  
   fprintf(stderr,"Unsupported parity\n");   
   return (CHK_ERR); 
 } 
 /* 设置停止位*/ 
 switch (stopbits)
 {  
  case 1:   
   options.c_cflag &= ~CSTOPB; 
   break; 
  case 2:   
   options.c_cflag |= CSTOPB; 
     break;
  default:   
    fprintf(stderr,"Unsupported stop bits\n"); 
    return (CHK_ERR);
 }
 /* Set input parity option */
 if (parity != 'n')   options.c_iflag |= INPCK;

//清bit位  关闭字符映射 0x0a 0x0d
 options.c_iflag &= ~(INLCR|ICRNL);
 //清bit位  关闭流控字符 0x11 0x13
 options.c_iflag &= ~(IXON);
 
 //需要注意的是:
 //如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯,设置方式如下:
 options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  //Input
 options.c_oflag  &= ~OPOST;   //Output

tcflush(fd,TCIFLUSH);
 options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/  
 options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
 if (tcsetattr(fd,TCSANOW,&options) != 0)  
 {
  perror("SetupSerial 3");  
  return (CHK_ERR); 
 }
 return (CHK_OK); 
}

Linux串口编程(转载)的更多相关文章

  1. storysnail的Linux串口编程笔记

    storysnail的Linux串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据Ge ...

  2. Linux串口编程详解(转)

    串口本身,标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接 ...

  3. linux串口编程总结

    串口本身.标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口以前被广泛用于连接计算机和终端设备和各种外部设备.尽管以太网接口和USB接口也是以一个串行流进行数据传送的.可是串口连接 ...

  4. linux串口编程参数配置详解(转)

    1.linux串口编程需要的头文件 #include <stdio.h>         //标准输入输出定义#include <stdlib.h>        //标准函数 ...

  5. linux串口编程参数配置详解

    1.linux串口编程需要的头文件 #include <stdio.h>         //标准输入输出定义 #include <stdlib.h>        //标准函 ...

  6. linux串口编程

    按照对linux系统的理解,串口编程的顺序无非就是open,read,write,close,而串口有波特率.数据位等重要参数需要设置,因此还应该用到设置函数,那么接下来就带着这几个问题去学习linu ...

  7. Linux串口编程进阶

    在<Linux串口编程>编程一文中介绍了串口应用中常用的基本操作,如:串口打开关闭.串口设置.数据收发等.本篇文章主要基于常规串口操作进行了扩充,主要介绍如下操作: Linux系统使用非标 ...

  8. linux串口编程设置(转载)

    (转载)在嵌入式Linux中,串口是一个字设备,访问具体的串行端口的编程与读/写文件 的操作类似,只需打开相应的设备文件即可操作.串口编程特殊在于串 口通信时相关参数与属性的设置.嵌入式Linux的串 ...

  9. Linux 串口编程

    今天对应用层串口编程进行了验证.程序来源于以下参考链接,自己进行了一些注释和更改,记录于此. Tony Liu, 2016-6-17, Shenzhen 参考链接 https://www.ibm.co ...

随机推荐

  1. typedef typedef struct的使用

    typedef通常情况用于声明结构体之类的 1,定义某些便于记忆的结构体或者使现有的类型看上去更加整齐,比如后来因为经常使用而被添加进入c/c++标准头文件的stdint.h typedef sign ...

  2. JAVA中的常见面试题1

    1.线程同步的方法的使用. sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常. wait():使一个线程处于等待状态,并且 ...

  3. HDU 5831 Rikka with Parenthesis II (栈+模拟)

    Rikka with Parenthesis II 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5831 Description As we kno ...

  4. AngularJS 学习笔记二

    AngularJS指令 指令 描述 讲解 ng_app 定义应用程序的根元素. 指令 ng_bind 绑定 HTML 元素到应用程序数据. 简介 ng_click 定义元素被单击时的行为. HTML ...

  5. Codeforces Round #260 (Div. 1) A. Boredom (简单dp)

    题目链接:http://codeforces.com/problemset/problem/455/A 给你n个数,要是其中取一个大小为x的数,那x+1和x-1都不能取了,问你最后取完最大的和是多少. ...

  6. HDU 3265 Posters (线段树+扫描线)(面积并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3265 给你n个中间被挖空了一个矩形的中空矩形,让你求他们的面积并. 其实一个中空矩形可以分成4个小的矩 ...

  7. UVaLive 6859 Points (几何,凸包)

    题意:给定 n 个点,让你用最长的周长把它们严格包围起来,边长只能用小格子边长或者是小格子对角线. 析:先把每个点的上下左右都放到一个集合中,然后求出一个凸包,然后先边长转成题目的方式,也好转两个点的 ...

  8. 模拟学信网登录,Cookie 序列化,在反序列化之后不能用的问题

    昨天和今天在模拟学信网登录,然后抓取用户的信息数据的时候发现一直登录不成功, 登录页面,https://account.chsi.com.cn/passport/login?service=http% ...

  9. C#全角半角转换函数

    Code#region 全角半角转换 /// <summary> /// 转全角的函数(SBC case) /// </summary> /// <param name= ...

  10. Kerberos和NTLM - SQL Server

    当我们使用Windows Authentication去连接SQL Server的时候,SQL Server可能会使用Kerberos或者是NTLM来进行认证,有时间就会因为认证失败的缘故造成各种登录 ...