Linux串口编程示例

Unix终端I/O:深入理解termios库
本文详细介绍了Unix系统中用于串行通信的termios库,包括termios结构体的各个字段及其在输入输出处理、通信参数配置等方面的作用。通过termios,程序员可以设置波特率、数据位、校验位、停止位等,以及控制流控制、输入输出模式。此外,还讨论了如ECHO、ICANON等本地模式标志,以及如何使用tcgetattr和tcsetattr进行配置。文章适合对低级别串口通信感兴趣的读者。

termios

termios是用于终端I/O的较新(现在已经有几十年历史)Unix API。在termios的帮助下执行串行I/O的程序剖析如下:

  1. 通过系统调用open打开串行端口
  2. 通过特定的termios函数和数据结构配置通信参数和其他接口属性
  3. 通过如下系统调用write,read,readv,writev,select,poll进行读写、轮询。
  4. 通过close关闭设备

termios 的必要声明和常量可以在头文件 <termios.h> 中找到。

#include <termios.h>

termios I/O API 支持两种不同的模式:

  1. 规范模式。
    对终端输入以行为单位进行处理。对于每个读请求,终端驱动程序最多返回一行。
  2. 非规范模式。
    输入字符不装配成行。

如果没有特殊处理,默认的模式是规范模式

termios.h

串口所有的配置都是通过使用在 termios.h 标头中定义的 struct termios 数据结构完成的。 此结构对于串行设备的配置和查询其设置都至关重要。 它至少包含以下字段:

glibc-2.34 termios.h

struct termios
{
   
   
  tcflag_t c_iflag;//输入标志
  tcflag_t c_oflag;//输出标志
  tcflag_t c_cflag;//控制标志
  tcflag_t c_lflag;//本地标志
  cc_t c_cc[NCCS];//特殊字符
  speed_t __ispeed, __ospeed;//输入输出波特率
};
  • 输入标志被终端设备驱动控制输入特性(例如输入字节宽,使能输入校验检查)。
  • 输出标志控制着驱动输出(例如,执行输出进程,映射新行到CR/LF)
  • 控制标志影响RS-232串行线(例如忽略调制解调器状态行,每个字符一个或两个停止位)。
  • 本地标志影响驱动和用户间的接口(例如回显是否打开,擦除字符是否可见,使能中断产生的信号,工作为后台输出控制停止信号)
  • POSIX.1在输入上定义了11个特殊字符(例如文件结束符EOF),可以选择是否需要特殊处理这些字符。

c_iflag

c_iflag 配置串口输入属性。

/* 
忽略中断条件
在异步串行数据传输的上下文中,中断条件被定义为比单个字节长的一系列零值位(低电平)。  
*/
#define	IGNBRK	(1 << 0)	

/*
如果设置了该位而未设置 IGNBRK,则中断条件会清除终端输入和输出队列,并为与终端关联的前台进程组发出 SIGINT 信号。
如果 BRKINT 和 IGNBRK 均未设置,则在未设置 PARMRK 时将中断条件作为单个 '\0' 字符传递给应用程序,否则作为三字符序列 '\377'、'\0'、'\ 0'。
*/
#define	BRKINT	(1 << 1)	/* Signal interrupt on break.  */

/*
当设置了INPCK 
如果设置了该位,则忽略任何帧或奇偶校验错误的字节。
*/
#define	IGNPAR	(1 << 2)	/* Ignore characters with parity errors.  */

/*
当设置了INPCK 且未设置 IGNPAR 时
如果设置了该位,则在传递给程序时会标记具有奇偶校验或帧错误的输入字节。
*/
#define	PARMRK	(1 << 3)	/* Mark parity and framing errors.  */

/*
如果设置了该位,则启用输入奇偶校验。 如果未设置,则不检查输入的奇偶校验错误; 字符被简单地传递给应用程序。
输入处理的奇偶校验与是否启用底层终端硬件上的奇偶校验检测和生成无关;
例如,您可以清除 INPCK 输入模式标志并设置 PARENB 控制模式标志以忽略输入的奇偶校验错误,但仍生成输出奇偶校验。
如果设置了该位,则检测到奇偶校验错误时会发生什么取决于是设置了 IGNPAR 位还是 PARMRK 位。 如果这些位均未设置,则将带有奇偶校验错误的字节作为“\0”字符传递给应用程序。
*/
#define	INPCK	(1 << 4)	/* Enable input parity check.  */

/*
如果设置了该位,则有效输入字节将被剥离为 7 位; 否则,所有八位都可供程序读取。
*/
#define	ISTRIP	(1 << 5)	/* Strip 8th bit off characters.  */

/*
如果设置了该位,则作为输入接收到的换行符 ('\n') 将作为回车符 ('\r') 传递给应用程序。
*/
#define	INLCR	(1 << 6)	/* Map NL to CR on input.  */

/*
如果设置了该位,则在输入时会丢弃回车字符 ('\r')。 当您键入 RET 键时,放弃回车可能对发送回车和换行的终端很有用。
*/
#define	IGNCR	(1 << 7)	/* Ignore CR.  */

/*
如果设置了该位但未设置 IGNCR,则作为输入接收到的回车字符 ('\r') 将作为换行符 ('\n') 传递给应用程序。
*/
#define	ICRNL	(1 << 8)	/* Map CR to NL on input.  */

/*
如果设置了该位,则启用输出的启动/停止控制。 换句话说,如果计算机收到一个 STOP 字符,它会暂停输出,直到收到一个 START 字符。 在这种情况下,STOP 和 START 字符永远不会传递给应用程序。 如果未设置该位,则 START 和 STOP 可以作为普通字符读取。
*/
#define	IXON	(1 << 9)	/* Enable start/stop output control.  */

/*
如果设置了该位,则启用对输入的启动/停止控制。 换句话说,计算机会根据需要发送 STOP 和 START 字符,以防止输入比程序读取它的速度更快。 这个想法是生成输入数据的实际终端硬件通过暂停传输来响应 STOP 字符,并通过恢复传输来响应 START 字符。
*/
#define	IXOFF	(1 << 10)	/* Enable start/stop input control.  */


#if defined __USE_MISC || defined __USE_XOPEN || defined __USE_XOPEN2K8

/*
如果设置了该位,则当输出已被 STOP 字符挂起时,任何输入字符将重新开始输出。 否则,只有 START 字符重新启动输出。
这是一个 BSD 扩展; 它只存在于 BSD 系统和 GNU/Linux 和 GNU/Hurd 系统上。
*/
# define IXANY	(1 << 11)	/* Any character will restart after stop.  */
#endif
#ifdef	__USE_MISC

/*
如果设置了该位,则填充终端输入缓冲区会向终端发送 BEL 字符(代码 007)以响铃。
*/
# define IMAXBEL (1 << 13)	/* Ring bell when input queue is full.  */
#endif
#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K)

/*
(POSIX 不支持)在输入时将大写字符映射为小写。
*/
# define IUCLC	(1 << 14)	/* Translate upper case input to lower case. */
#endif

c_oflag

c_oflag 配置串口输出属性。

/*
如果设置了该位,则输出数据将以某种未指定的方式进行处理,以便在终端设备上正确显示。 这通常包括将换行符 ('\n') 映射到回车和换行对。
如果未设置该位,则字符按原样传输。
*/
#define	OPOST	(1 << 0)	/* Perform output processing.  */
#if defined __USE_MISC || defined __USE_XOPEN
/*
当设置了 OPOST时	 
如果设置了此位,则将输出中的换行符转换为一对字符,回车后跟换行符。
*/
# define ONLCR	(1 << 1)	/* Map NL to CR-NL on output.  */
#endif
#ifdef	__USE_MISC
/*
当设置了 OPOST时	 
如果设置了该位,则将输出中的制表符转换为适当数量的空格,以每八列模拟一个制表位。 该位仅存在于 BSD 系统和 GNU/Hurd 系统上; 在 GNU/Linux 系统上,它可以作为 XTABS 使用。
*/
# define OXTABS	TAB3		/* Expand tabs to spaces.  */

/*
当设置了 OPOST时	 
如果设置了该位,则丢弃输出中的 C-d 字符(代码 004)。 这些字符会导致许多拨号终端断开连接。 该位仅存在于 BSD 系统和 GNU/Hurd 系统上。
*/
# define ONOEOT	(1 << 3)	/* Discard EOT (^D) on output.  */
#endif
#if defined __USE_MISC || defined __USE_XOPEN
# define OCRNL	(1 << 4)	/* Map CR to NL.  */
# define ONOCR	(1 << 5)	/* Discard CR's when on column 0.  */
# define ONLRET	(1 << 6)	/* Move to column 0 on NL.  */</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知否,知否

来一杯冰美式把

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值