资讯详情

linux 串口编程详解

tcgetattr

该函数用于获取与终端相关的参数。fd为终端的文件描述符,保存了返回的结果termios结构体中

http://baike.baidu.com/view/5644808.htm?fr=aladdin

tcsetattr 设置终端相关参数的函数

tcflush

Unix终端I/O函数。功能:清空终端未完成的输入/输出请求和数据

通常使用波特率设置cfsetospeed和cfsetispeed函数完成。获取波特率信息是通过cfgetispeed和cfgetospeed完成函数。

常用函数

使用open()函数打开串口,open()函数有两个参数,第一个是要打开的设备名(如:/dev/ttyS0)。第二个是打开的方式。

打开方式有以下三种:

成功打开串口则会返回文件描述符,打开失败则返回-1。下面是一个打开串口的示例:

fd = open("/dev/ttyS0",O_RDWR|O_NDELAY|O_NDELAY);

使用close()关闭打开的串口,唯一的参数是打开串口的文件描述符。下面是一个关闭串口的示例:

close(fd);        //fd是打开串口返回的文件描述符

用write()函数向串口写数据。下面是一个向串口写数据的示例:

n = write(fd,buff,len);    
/* n表示成功写到串口的字节数,如果写入失败则返回-1
   fd是打开串口返回的文件描述符
   buff表示写入的内容
   len表示写入信息的长度。
*/

用read()函数从串口读取数据。下面是一个从串口读数据的示例:

n = read(fd,buff,len);
/* n表示从串口读到字节数
   fd是文件描述符
   buff是读入字节存放的缓冲区
   len表示读入的字节数
*/

通过fcntl()函数可以操作文件描述符,用以控制读取数据的状态。fcntl(fd,F_SETFL,0)表示没有数据则阻塞,处于等待状态,

直到有数据到来;fcntl(fd,F_SETFL,FNDELAY)表示当端口没有数据时马上返回0。

所有的串口属性都在一个名为termios的结构体中,要使用该结构体要包含termios.h头文件。在该头文件中还定义两个重要的

函数tcgetattr()和tcsetattr(),分别用以获取和设置串口的属性。如:tcgetattr(fd,&old_termios),tcsetattr

(fd,TCSANOW,&new_termios)。old_termios是旧的串口属性,new_termios是重新设置的新串口属性。tcsetattr()

函数中常量的意义是:

  • TCSANOW表示新设置的串口属性马上生效。

  • TCSADRAIN表示等所有数据传送完成后才生效。

  • TCSAFLUSH表示马上清空输入和输出缓存,然后应用新的串口设置。

termios结构体内容:

成员            描述
-------------------------------------------
c_cflag         控制模式标志
c_lflag         本地模式标志
c_iflag         输入模式标志
c_oflag         输出模式标志
c_line          line discipline
c_cc[NCCS]      控制字符
c_ispeed        输入波特率
c_ospeed        输出波特率

在termios结构中的四个标志控制了输入输出的四个不同部份。输入模式标志c_iflag决定如何解释和处理接收的字符。输出模式标

志c_oflag决定如何解释和处理发送到tty设备的字符。控制模式标志决定设备的一系列协议特征,这一标志只对物理设备有效。

本地模式标志c_lflag决定字符在输出前如何收集和处理。

在串口传输中,用波特率来表示传输的速度,1波特表示在1秒钟内可以传输1个码元。波特率设置可以使用

cfsetispeed(&new_termios,B19200)和cfsetospeed(&new_termios,B19200)这两个函数来完成,默认的波特率为

9600baud。cfsetispeed()函数用来设置输入的波特率,cfsetospeed()函数用来设置输出的波特率。B19200是termios.h头文

件里定义的一个宏,表示19200的波特率。

CLOCAL和CREAD是c_cflag成员中与速率相关的标志,在串口编程中,这两个标志一定要有效,以确保程序在突发的作业控制

或挂起时,不会成为端口的占有都,同时串口的接收驱动会自动读入数据。设置方法如下:

termios_new.c_cflag |= CLOCAL;                 //保证程序不会成为端的占有者
termios_new.c_cflag |= CREAD;                  //使端口能读取输入的数据

设置串口属性不能直接赋值,要通过对termios不同成员进行"与"和"或"操作来实现。在termios.h文件,定义了各种常量,

如上面介绍的CLOCAL,CREAD。这些常量的值是掩码,通过把这些常量与termios结构成员进行逻辑操作就可实现串口属性的设置。

在编程时用"|="来启用属性,用"&=~"来取消属性。

  • BRKINT和IGNBRK

    如果设置了IGNBRK,中断条件被忽略。如果没有设置IGNBRK而设置了BRKINT,中断条件清空输入输出队列中所有的数据并

  • 且向tty的前台进程组中所有进程发送一个SIGINT信号。如果这两个都没有设置,中断条件会被看作一个0字符。这时,如

  • 果设置了PARMRK,当检测到一个帧误差时将会向应用程序发送三个字节'\377''\0''\0',而不是只发送一个'\0'。

  • PARMRK和IGNPAR

    如果设定了IGNPAR,则忽略接收到的数据的奇偶检验错误或帧错误(除了前面提到的中断条件)。如果没有设置IGNPAR而

  • 设置了PARMRK,当接收到的字节存在奇偶检验错误或帧错误的时候。将向应用程序发送一个三字节的'\377''\0''\n'错误

  • 报告。其中n表示所接收到的字节。如果两者都没有设置,除了接收到的字节存在奇偶检验错误或帧误差之外的中止条件

  • 都会向应用程序发送一个单字节('\0')的报告。

  • INPCK

    如果设置,则进行奇偶校验。如果不进行奇偶检验,PARMRK和IGNPAR将对存在的奇偶校验错误不产生任何的影响。

  • ISTRIP

    如果设置,所接收到的所有字节的高位将会被去除,保证它们是一个7位的字符。

  • INLCR

    如果设置,所接收到的换行字符('\n')将会被转换成回车符('\r')。

  • IGNCR

    如果设置,则会忽略所有接收的回车符('\r')。

  • ICRNL

    如果设置,但IGNCR没有设置,接收到的回车符向应用程序发送时会变换成换行符。

  • IUCLC

    如果IUCLC和IEXTEN都设置,接收到的所有大写字母发送给应程序时都被转换成小写字母。POSIX中没有定义该标记。

  • IXOFF

    如果设置,为避免tty设备的输入缓冲区溢出,tty设备可以向终端发送停止符^S和开始符^Q,要求终端停止或重新开始

  • 向计算机发送数据。通过停止符和开始符来控制数据流的方式叫软件流控制,软件流控制方式较少用,我们主要还是用

  • 硬件流控制方式。硬件流控制在c_cflag标志中设置。

  • IXON

    如果设置,接收到^S后会停止向这个tty设备输出,接收到^Q后会恢复输出。

  • IXANY

    如果设置,则接到任何字符都会重新开始输出,而不仅仅是^Q字符。

  • IMAXBEL

    如果设置,当输入缓冲区空间满时,再接收到的任何字符就会发出警报符'\a'。POSIX中没有定义该标记。

OPOST是POSIX定义的唯一一个标志,只有设置了该标志后,其它非POSIX的输出标记才会生效。

  • OPOST

    开启该标记,后面的输出标记才会生效。否则,不会对输出数据进行处理。

  • OLCUC

    如果设置,大写字母被转换成小写字母输出。

  • ONLCR

    如果设置,在发送换行符('\n')前先发送回车符('\r')。

  • ONOCR

    如果设置,当current column为0时,回车符不会被发送也不会被处理。

  • OCRNL

    如果设置,回车符会被转换成换行符。另外,如果设置了ONLRET,则current column会被设为0.

  • ONLRET

    如果设置,当一个换行符或回车符被发送的时候,current column会被设置为0。

  • OXTABS

    如果设置,制表符会被转换成空格符。

只有在本地模式标志c_lflag中设置了IEXITEN时,POSIX没有定义的控制字符才能在Linux中使用。每个控制字符都对应一个

按键组合(^C、^H等),但VMIN和VTIME这两个控制字符除外,它们不对应控制符。这两个控制字符只在原始模式下才有效。

  • c_cc[VINTR]

    默认对应的控制符是^C,作用是清空输入和输出队列的数据并且向tty设备的前台进程组中的每一个程序发送一个SIGINT信号

  • ,对SIGINT信号没有定义处理程序的进程会马上退出。

  • c_cc[VQUIT]

    默认对应的控制符是^\,作用是清空输入和输出队列的数据并向tty设备的前台进程组中的每一个程序发送一个SIGQUIT

  • 信号,对SIGQUIT信号没有定义处理程序的进程会马上退出。

  • c_cc[verase]

    默认对应的控制符是^H或^?,作用是在标准模式下,删除本行前一个字符,该字符在原始模式下没有作用。

  • c_cc[VKILL]

    默认对应的控制符是^U,在标准模式下,删除整行字符,该字符在原始模式下没有作用。

  • c_cc[VEOF]

    默认对应的控制符是^D,在标准模式下,使用read()返回0,标志一个文件结束。

  • c_cc[VSTOP]

    默认对应的控制字符是^S,作用是使用tty设备暂停输出直到接收到VSTART控制字符。或者,如果设备了IXANY,

  • 则等收到任何字符就开始输出。

  • c_cc[VSTART]

    默认对应的控制字符是^Q,作用是重新开始被暂停的tty设备的输出。

  • c_cc[VSUSP]

    默认对应的控制字符是^Z,使当前的前台进程接收到一个SIGTSTP信号。

  • c_cc[VEOL]和c_cc[VEOL2]

    在标准模式下,这两个下标在行的末尾加上一个换行符('\n'),标志一个行的结束,从而使用缓冲区中的数据被发送,

  • 并开始新的一行。POSIX中没有定义VEOL2。

  • c_cc[VREPRINT]

    默认对应的控制符是^R,在标准模式下,如果设置了本地模式标志ECHO,使用VERPRINT对应的控制符和换行符在本地显示,

  • 并且重新打印当前缓冲区中的字符。POSIX中没有定义VERPRINT。

  • c_cc[VWERASE]

    默认对应的控制字符是^W,在标准模式下,删除缓冲区末端的所有空格符,然后删除与之相邻的非空格符,从而起到在一

  • 行中删除前一个单词的效果。POSIX中没有定义VWERASE。

  • c_cc[VLNEXT]

    默认对应的控制符是^V,作用是让下一个字符原封不动地进入缓冲区。如果要让^V字符进入缓冲区,需要按两下^V。POSIX中

  • 没有定义VLNEXT。

要禁用某个控制字符,只需把它设置为_POSIX_VDISABLE即可。但该常量只在Linux中有效,所以如果程序要考虑移植性的问题,

请不要使用该常量。

  • ICANON

    如果设置,则启动标准模式,如果没有设置,则启动原始模式。

  • ECHO

    如果设置,则启动本地回显。如果没有设置,则除了ECHONL之外,其他以ECHO开头的标记都会失效。

  • ECHOCTL

    如果设置,则以^C的形式打印控制字符,如:按Ctrl+C显示^C,按Ctrl+?显示^?。

  • ECHOE

    如果在标准模式下设定了ECHOE标志,则当收到一个ERASE控制符时将删除前一个显示字符。

  • ECHOK和ECHOKE

    在标准模式下,当接收到一个KILL控制符,则在缓冲区中删除当前行。如果ECHOK、ECHOKE和ECHOE都没有设置,则用ECHOCTL

    如果已经设置了ECHOE和ECHOK,但没有设置ECHOKE,将会在输出终端显示ECHOCTL表示的KILL字符,紧接着是换行,如果设

    如果ECHOK、ECHOKE和ECHOE都有设置,则会删除当前行。

    在POSIX中没有定义ECHOKE标记,在没有定义ECHOKE标记的系统中,设置ECHOK则表示同时设置了ECHOKE标志。

  • 置了OPOST,将会通过OPOST处理程序进行适当的处理。

  • 表示的KILL字符(^U)将会在输出终端上显示,表示当前行已经被删除。

  • ECHONL

    如果在标准模式下设置了该标志,即使没有设置ECHO标志,换行符还是会被显示出来。

  • ECHOPRT

    如果设置,则字符会被简单地打印出来,包括各种控制字符。在POSIX中没有定义该标志。

  • ISIG

    如果设置,与INTR、QUIT和SUSP相对应的信号SIGINT、SIGQUIT和SIGTSTP会发送到tty设备的前台进程组中的所有进程。

  • NOFLSH

    一般情况下,当接收到INTR或QUIT控制符的时候会清空输入输出队列,当接收到SUSP控制符时会清空输入队列。但是如果

  • 设置了NOFLUSH标志,则所有队列都不会被清空。

  • TOSTOP

    如果设置,则当一个非前台进程组的进程试图向它的控制终端写入数据时,信号SIGTTOU会被被发送到这个进程所在的进

  • 程组。默认情况下,这个信号会使进程停止,就像收到SUSP控制符一样。

  • IEXIEN

    默认已设置,我们不应修改它。在Linux中IUCLC和几个与删除字符相关的标记都要求在设置了IEXIEN才能正常工作。

  • 设置流控制

    termios_new.c_cflag &= ~CRTSCTS;            //不使用流控制
    termios_new.c_cflag |= CRTSCTS;                 //使用硬件流控制
    termios_new.c_iflag |= IXON|IXOFF|IXANY;        //使用软件流控制
    
  • 屏蔽字符大小位

    termios_new.c_cflag &= ~CSIZE; 
    
  • 设置数据位大小

    termios_new.c_cflag |= CS8;         //使用8位数据位
    termios_new.c_cflag |= CS7;         //使用7位数据位
    termios_new.c_cflag |= CS6;         //使用6位数据位
    termios_new.c_cflag |= CS5;         //使用5位数据位
    
  • 设置奇偶校验方式

    termios_new.c_cflag &= ~PARENB;       //无奇偶校验
    
    termios_new.c_cflag |= PARENB;            //奇校验
    termios_new.c_cflag &= ~PARODD;       
    
    termios_new.c_cflag |= PARENB;            //偶校验
    termios_new.c_cflag &= ~PARODD;       
    
  • 停止位

    termios_new.c_cflag |= CSTOPB;            //2位停止位
    termios_new.c_cflag &= ~CSTOPB;       //1位停止位  
    
  • 输出模式

    termios_new.c_cflag &= ~OPOST;        //原始数据(RAW)输出
    
  • 控制字符

    termios_new.c_cc[VMIN] = 1;               //读取字符的最小数量
    termios_new.c_cc[VTIME] = 1;              //读取第一个字符的等待时间
    
  • 关闭终端回显,键盘输入的字符不会在终端窗口显示。

    #include <stdio.h>
    #include <stdlib.h>
    #include <termios.h>
    #include <unistd.h>
    
    int main(void)
    {
            struct termios ts,ots;
            char passbuf[1024];
    
            tcgetattr(STDIN_FILENO,&ts);  /* STDIN_FILENO的值是1,表示标准输入的文件描述符 */
            ots = ts;
    
            ts.c_lflag &= ~ECHO;         /* 关闭回终端回显功能*/
            ts.c_lflag |= ECHONL;
            tcsetattr(STDIN_FILENO,TCSAFLUSH,&ts);  /* 应用新终端设置 */
    
            fgets(passbuf,1024,stdin);     /* 输入字符不会在终端显示 */
            printf("you input character = %s\n",passbuf);
    
            tcsetattr(STDIN_FILENO,TCSANOW,&ots);  /* 恢复旧的终端设备 */
    }

串口本身,标准和硬件 

串口是计算机上的串行通讯的物理接口。计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备。虽然以太网接口和USB接口也

是以一个串行流进行数据传送的,但是串口连接通常特指那些与RS-232标准兼容的硬件或者调制解调器的接口。虽然现在在很多个人计算机上,

原来用以连接外部设备的串口已经广泛的被USB和Firewire替代;而原来用以连接网络的串口则被以太网替代,还有用以连接终端的串口设备则已经

被MDA或者VGA取而代之。但是,一方面因为串口本身造价便宜技术成熟,另一方面因为串口的控制台功能RS-232标准高度标准化并且非常普及,

所以直到现在它仍然被广泛应用到各种设备上。 某些计算机使用一个叫做UART的集成电路来作为串口设备。这个集成电路可以进行字符和异步串行

标签: 2cr3z集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台