串行终端设备操作函数

struct termios

这些函数可以用于操作串行端口设备,例如调制解调器、串行打印机、串行鼠标等。
它们允许程序员设置和获取串行端口的属性,例如波特率、数据位、停止位、奇偶校验等。同时,这些函数还可以用于刷新串行端口的输入和输出缓冲区。

常用于操作串行终端设备函数

termios,  tcgetattr,  tcsetattr,  tcsendbreak,  tcdrain,  tcflush,  tcflow, cfsetispeed, cfsetospeed 

其他函数

 reset(1), setterm(1), stty(1), tput(1), tset(1), tty(1), ioctl_console(2), ioctl_tty(2), setserial(8)

需要包含的头文件

	#include <termios.h>
	#include <unistd.h>

返回值

	All other functions return:
	0      on success.
	-1     on failure and set errno to indicate the error.	
	// 注意,如果请求的任何更改可以成功执行,tcsetattr()将返回成功。
	// 因此,当进行多个更改时,可能需要在此调用之后进一步调用tcgetattr(),
	// 以检查是否已成功执行了所有更改。

struct termios结构体定义

struct termios{
	tcflag_t c_iflag;      /* input modes */
	tcflag_t c_oflag;      /* output modes */
	tcflag_t c_cflag;      /* control modes */
	tcflag_t c_lflag;      /* local modes */
	cc_t     c_cc[NCCS];   /* special characters */
};
c_iflag flag constants:
	IGNBRK 
	 // 忽略输入的BREAK条件。
	 // 在Linux C编程中,通常是指Ctrl+C组合键,也即按下Ctrl键不放,再按下C键(Ctrl+C),
	 // 这个组合键通常用来发送中断信号(SIGINT)给当前运行的程序,以停止程序的执行。
	 // 在终端环境下,按下Ctrl+C会发送SIGINT信号给前台进程,这通常会导致程序结束执行。
	 // 因此,当说到Linux C中的BREAK按键时,通常是指Ctrl+C组合键。
	 // 在编写程序时,可以通过捕获SIGINT信号并设置信号处理程序来处理或忽略Ctrl+C按键对程序的影响。
	BRKINT
	 // 如果设置了IGNBRK, BREAK将被忽略。
	 // 如果没有设置IGNBRK,但是设置了BRKINT,那么BREAK会导致输入和输出队列被刷新。
	 // 如果终端是前台进程组的控制终端,它会导致SIGINT被发送到这个前台进程组。
	 // 当既没有设置IGNBRK,也没有设置BRKINT时,BREAK读取为空字节('\0'),
	 // 除非设置PARMRK,在这种情况下,它读取为序列\377 \0 \0。
	IGNPAR 
	 // 忽略帧错误和奇偶校验错误。
	PARMRK
	 // 如果设置了此位,则在传递给程序时标记带有奇偶校验或帧错误的输入字节。
	 // 只有当INPCK被设置,而IGNPAR没有设置时,这个位才有意义。
	 // 错误字节的标记方式是用两个前字节,\377和\0。
	 // 因此,程序实际上为从终端接收到的一个错误字节读取三个字节。
	 // 如果一个有效字节的值为\377,并且没有设置ISTRIP(见下文),
	 // 则程序可能会将其与标记奇偶校验错误的前缀混淆。
	 // 因此,一个有效字节\377作为两个字节传递给程序,在本例中为\377 \377。

	 // 如果既没有设置IGNPAR也没有设置PARMRK,则将奇偶校验错误或帧错误的字符读取为\0。
              
	INPCK
	 // 启用输入奇偶校验。
	ISTRIP
	 // 去掉第8位。
	INLCR
	 // 在输入时将NL翻译成CR。
	IGNCR
	 // 忽略输入上的回车。
	ICRNL
	 // 在输入时将回车符转换为换行符(除非设置了IGNCR)。
	IUCLC
	 // (不支持POSIX)在输入时将大写字符映射为小写字符。
	IXON
	 // 在输出上启用XON/XOFF流量控制。
	IXANY
	 // (XSI)输入任何字符将重启已停止的输出。(默认情况下只允许使用START字符重新启动输出。)
	IXOFF
	 // 在输入端启用XON/XOFF流量控制。
	IMAXBEL
	 // (不支持POSIX)当输入队列满时响铃。Linux没有实现这一点,并且好像它总是被设置。
	IUTF8 (since Linux 2.6.4)
	 // (非POSIX)输入为UTF8;这允许字符擦除在熟化模式下正确执行。
c_oflag flag constants:
	OPOST
	 // 启用实现定义的输出处理。
	OLCUC
	 // (不支持POSIX)在输出中将小写字符映射为大写字符。
	ONLCR
	 // (XSI)在输出上映射NL到CR-NL。
	OCRNL
	 // 在输出上映射CR到NL。
	ONOCR
	 // 在第0列不输出CR。
	ONLRET
	 // 不要输出CR。
	OFILL
	 // 为延迟发送填充字符,而不是使用定时延迟。
	NLDLY
	 // 换行延迟掩码。取值为NL0和NL1。[需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
c_cflag flag constants:
	CSIZE
	 // 字符大小掩码。取值为CS5、CS6、CS7、CS8
	CSTOPB
	 // 设置两个停止位,而不是一个
	CREAD
	 // 使能接收
	PARENB
	 // 启用输出奇偶校验和输入奇偶校验
	PARODD
	 // 如果设置,则输入和输出的奇偶校验为奇数;否则使用偶数奇偶校验
	HUPCL
	 // 在最后一个进程关闭设备(挂机)后,较低的调制解调器控制线
	CLOCAL
	 // 忽略调制解调器控制线
	CMSPAR
	 // 使用“stick”(mark/space)奇偶校验(在某些串行设备上支持):
	 // 如果设置了PARODD,奇偶校验位始终为1;
	 // 如果PARODD未设置,则奇偶校验位始终为0。[需要_BSD_SOURCE或_SVID_SOURCE]	
	CRTSCTS
	 // (不支持POSIX)启用RTS/CTS(硬件)流量控制。[需要_BSD_SOURCE或_SVID_SOURCE]
c_lflag flag constants:
	ISIG
	 // 当接收到INTR、QUIT、SUSP、DSUSP中的任意一个字符时,产生相应的信号。
	ICANON
	 // 启用规范模式(如下所述)。
	XCASE
	 // (不支持POSIX;如果还设置了ICANON,则terminal仅为大写。输入将被转换为小写,但以\开头的字符除外。
	 // 在输出时,大写字符前面加\,小写字符被转换成大写。[需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE]
	ECHO
	 // 回显输入字符。
	ECHOE
	 // 如果还设置了ICANON,则ERASE字符将擦除前面的输入字符,而WERASE将擦除前面的单词。
	ECHOK
	 // 如果还设置了ICANON, KILL字符将擦除当前行。
	ECHONL
	 // 如果还设置了ICANON,即使没有设置echo,也会回显NL字符。
	ECHOCTL
	 // (非POSIX)如果还设置了ECHO,则除TAB、NL、START、STOP以外的终端特殊字符将回显为^X,
	 // 其中X为ASCII码0x40大于该特殊字符的字符。
	 // 例如,字符0x08 (BS)回显为^H。[需要_BSD_SOURCE或_SVID_SOURCE]
	ECHOPRT
	 // (非POSIX)如果ICANON和ECHO也被设置,字符在被擦除时被打印。[需要_BSD_SOURCE或_SVID_SOURCE]
	ECHOKE
	 // (非POSIX)如果也设置了ICANON, KILL通过擦除行上的每个字符来响应,
	 // 如ECHOE和ECHOPRT所指定的。[需要_BSD_SOURCE或_SVID_SOURCE]
	NOFLSH
	 // 在为INT、QUIT和SUSP字符生成信号时,禁用刷新输入和输出队列。
	TOSTOP
	 // 发送SIGTTOU信号给一个后台进程的进程组,这个后台进程试图写它的控制终端。
	IEXTEN
	 // 启用实现定义的输入处理。这个标志,以及ICANON必须启用特殊字符EOL2, LNEXT, REPRINT, WERASE进行解释,
	 // 并使IUCLC标志有效。

Send Break

函数说明:异步传输时,发送break信号。
		 fd:指定的终端设备文件描述符,通常通过open()函数获取。
		 duration:发送break信号的时间长度,以秒为单位。如果设置为0,表示发送的时间至少为0.25,不超过0.5break信号。
		 发送的是一个中断信号,而非数据传输,主要用于控制目的而非数据接收。
		 // 如果终端使用异步串行数据传输,tcsendbreak()在特定的持续时间内传输零值位的连续流。
       	 // 如果终端不使用异步串行数据传输,tcsendbreak()返回而不做任何操作
int tcsendbreak(int fd, int duration);
c_cc数组定义了终端特殊字符。符号指标(初值)及含义为:
	VEOF
	 // (004, EOT, Ctrl-D)文件结束字符(EOF)。
	 // 更准确地说:这个字符导致挂起的tty缓冲区被发送到等待的用户程序而不需要等待行结束符。
	 // 如果它是该行的第一个字符,则用户程序中的read(2)返回0,表示文件结束。当ICANON设置时被识别,然后不作为输入传递。
	VEOL
	 // (0, NUL)额外的行结束字符(EOL)。设置ICANON时识别。
	VEOL2
	 // (不支持POSIX;0, NUL)又一个行结束字符(EOL2)。设置ICANON时识别。
	VERASE
	 // (0177, DEL, rubout,或010,BS, Ctrl-H,或#)擦除字符(Erase)。
	 // 这将擦除之前尚未擦除的字符,但不会擦除过去的EOF或行开始。当ICANON设置时被识别,然后不作为输入传递。
	VINTR
	 // (003, ETX, Ctrl-C,或0177,DEL, rubout)中断字符(INTR)。
	 // 发送SIGINT信号。当设置ISIG时识别,然后不作为输入传递。
	VKILL
	 // (025, NAK, Ctrl-U,或Ctrl-X,或@)杀死字符(Kill)。
	 // 这将擦除自最后一次EOF或行开始以来的输入。当ICANON设置时被识别,然后不作为输入传递。
	VLNEXT
	 // (不支持POSIX;026, SYN, Ctrl-V) Literal next (LNEXT)。
	 // 引用下一个输入字符,使其失去可能的特殊含义。当设置IEXTEN时识别,然后不作为输入传递。
	VMIN
	 // 非规范读取的最小字符数(MIN)。
	VQUIT
	 // (034, FS, Ctrl-\)退出字符(Quit)。发送SIGQUIT信号。当设置ISIG时识别,然后不作为输入传递。
	VREPRINT
	 // (不支持POSIX;022, DC2, Ctrl-R)转载未读字符(转载)。当ICANON和IEXTEN设置时被识别,然后不作为输入传递。
	VSTART
	 // (021, DC1, Ctrl-Q)起始字符(Start)。重新启动由Stop字符停止的输出。当IXON设置时被识别,然后不作为输入传递。
	VSTOP
	 // (023, DC3, Ctrl-S)停止字符(Stop)。停止输出,直到开始字符输入。当IXON设置时被识别,然后不作为输入传递。
	VSUSP
	 // (032, SUB, Ctrl-Z)暂停字符(SUSP)。发送SIGTSTP信号。当设置ISIG时识别,然后不作为输入传递。
	VTIME
	 // 非规范读取超时(TIME),以毫秒为单位。
	VWERASE
	 // (不支持POSIX;027, ETB, Ctrl-W)字擦除(WERASE)。当ICANON和IEXTEN设置时被识别,然后不作为输入传递。
	 // 可以通过将相应的c_cc元素的值设置为_POSIX_VDISABLE来禁用单个终端特殊字符。
	 // 上述符号下标值除了VTIME、VMIN可能分别与VEOL、VEOF具有相同的值外,都是不同的。在非规范模式下,特殊字符含义由超时含义替换。有关VMIN和VTIME的解释,请参见下面对非规范模式的描述。
	// 规范模式和非规范模式
	// c_lflag中ICANON标志的设置决定了终端是在规范模式(ICANON set)还是非规范模式(ICANON unset)下运行。
	// 缺省情况下,已设置ICANON。
	
	// 规范模式
	// 逐行提供输入。当输入其中一个行分隔符(NL, EOL, EOL2;或行首的EOF)。除EOF外,行分隔符都包含在read(2)返回的缓冲区中。
	// 启用行编辑(ERASE, KILL;如果设置了iextten标志:WERASE, REPRINT, LNEXT)。read(2)最多返回一行输入;
	// 如果read(2)请求的字节数少于当前输入行中可用的字节数,则只读取所请求的字节数,其余字符将供将来的read(2)使用。
	// 最大行长度为4096个字符(包括结束换行字符);长度超过4096个字符的行将被截断。在4095个字符之后,输入处理(例如,ISIG和ECHO*处理)继续进行,
	// 但是在4095个字符之后的任何输入数据,直到(但不包括)任何终止换行符都被丢弃。这确保终端总是可以接收更多的输入,直到至少有一行可以被读取。
	// 非规范模式
	// 在非规范模式下,可以立即输入(用户不必键入行分隔符),不执行任何输入处理,并且禁用行编辑。读缓冲区只接受4095个字符;如果输入模式切换为规范模式,
	// 这将为换行字符提供必要的空间。MIN (c_cc[VMIN])和TIME (c_cc[VTIME])的设置决定了读取(2)完成的情况;有四种不同的情况:
	MIN == 0, TIME == 0 (polling read)
	// 如果数据可用,read(2)立即返回,可用字节数或请求字节数中较小者返回。如果没有可用的数据,read(2)返回0。
	MIN > 0, TIME == 0 (blocking read)
	// read(2)块直到可用的最小字节,并返回所请求的字节数。
	MIN == 0, TIME > 0 (read with timeout)
	// TIME指定计时器的限制,以十分之一秒为单位。定时器在read(2)被调用时启动。
	// Read(2)在至少有一个字节的数据可用时返回,或者在计时器到期时返回。
	// 如果计时器过期而没有任何输入可用,read(2)返回0。
	// 如果在调用read(2)时数据已经可用,则调用的行为就好像在调用后立即接收到数据一样。
	MIN > 0, TIME > 0 (read with interbyte timeout)
	// TIME指定计时器的限制,以十分之一秒为单位。一旦输入的初始字节可用,计时器将在每接收到一个字节后重新启动。
	// 当满足以下任何一个条件时,Read(2)返回:
	*  MIN bytes have been received. 	// 已接收到MIN字节。
	*  The interbyte timer expires.		// 字节间定时器过期。
	*  The  number  of  bytes requested by read(2) has been received.  (POSIX does not specify this termination condition, and on some other implementations read(2) does not return in this case.)
	// read(2)请求的字节数已被接收。(POSIX没有指定这个终止条件,在其他一些实现中read(2)在这种情况下不会返回。)
	
	Because the timer is started only after the initial byte becomes available, at least one byte will be read.  If data is already available at the time of the call to read(2), the call behaves as though the data was received immediately after the call.
	// 因为只有在初始字节可用之后才启动计时器,所以至少会读取一个字节。
	// 如果在调用read(2)时数据已经可用,则调用的行为就好像在调用后立即接收到数据一样。
	
	// POSIX没有指定O_NONBLOCK文件状态标志的设置是否优先于MIN和TIME设置。如果设置了O_NONBLOCK,则不管MIN或TIME的设置如何,非规范模式的read(2)都可以立即返回。
	// 此外,如果没有可用的数据,POSIX允许非规范模式下的read(2)返回0或-1,并将errno设置为EAGAIN。

	termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
	    | INLCR | IGNCR | ICRNL | IXON);
	termios_p->c_oflag &= ~OPOST;
	termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
	termios_p->c_cflag &= ~(CSIZE | PARENB);
	termios_p->c_cflag |= CS8;

阻塞等待传输完成

函数说明:等待,直到写入fd引用的对象的所有输出都已传输。
		 读取数据的行为,用于清理已接收的数据。
		 用于清除终端设备的输入缓冲区,将所有等待读取的数据从终端读出。
		 这对于处理用户输入并且期望立即看到结果的应用非常关键。
		 参数说明:int fd - 即终端设备文件描述符。
		 用途:确保网络数据的一致性和完整性,在处理大块数据传输或高延迟网络环境时很有用。
int tcdrain(int fd);

输入输出流控制

函数说明:用于对输入和输出流控制进行控制。根据action的值,暂停或启动fd所指对象上数据的传输或接收。
		action参数应当是下列四个值之一
       // TCOOFF     输出被挂起
       // TCOON      重新启动以前被挂起的输出
       // TCIOFF     系统发送一个STOP字符。这将使终端设备暂停发送数据
       // TCION      系统发送一个START字符。这将使终端恢复发送数据
       // 打开终端文件时的默认设置是,它的输入和输出都不会被挂起。
int tcflow(int fd, int action);

清空缓存队列

函数说明:清空输入缓存区(终端驱动已经接收到数据,但用户尚未读)
		  或输出缓存(用户已经写,但尚未发送)
		  queue_selector参数应当是下列三个值之一:
	      // TCIFLUSH  刷清输入队列
          // TCOFLUSH  刷清输出队列
          // TCIOFLUSH 刷清输入、输出队列
int tcflush(int fd, int queue_selector);

获取终端属性

函数说明:获取与由fd指定的对象相联系的参数,并将其存入由termios_p指向的struct termios结构中。
		 允许此函数在后台执行,但是,终端属性可能随后被前台进程更改。
		 当使用tcsetattr对终端多个属性进行设置时,可使用tcgetattr函数来验证操作所有更改是否成功。
int tcgetattr(int fd, struct termios* termios_p);

设置终端属性(检索和更改终端设置)

函数说明:根据termios_p指向的termios结构设置终端fd。
   		 在成功调用tcsetattr()之前,新值不会生效。
		 参数optional_actions指定更改何时生效:
		// TCSANOW       变化立即发生。
		// TCSADRAIN     在所有写入fd的输出都传输完成后,会发生更改。当更改影响输出的参数时,应该使用此选项。
		// TCSAFLUSH     更改发生在所有写入fd引用的对象的输出都被传输之后,并且所有已接收但未读取的输入将在更改之前被丢弃。
int tcsetattr(int fd, int optional_actions, const struct termios* termios_p);

设置波特率

函数说明:将存储在termios结构中的输入波特率设置为speed。
		speed必须指定为宏定义中列出的常量之一。
		如果输入波特率设置为0,则输入波特率等于输出波特率。
int cfsetispeed(struct termios* termios_p, speed_t speed);
函数说明:将存储在termios结构中的输出波特率设置为speed。
		 该波特率必须是以下宏定义常量之一。
int cfsetospeed(struct termios* termios_p, speed_t speed);
函数说明:将存储在termios结构中的输入输出波特率设置为speed。
int cfsetspeed(struct termios* termios_p, speed_t speed);

获取波特率

函数说明:返回存储在终端结构体termios_p中的输入波特率。
speed_t cfgetispeed(const struct termios* termios_p);
函数功能:返回存储在termios_p所指向的termios结构中的输出波特率。
speed_t cfgetospeed(const struct termios* termios_p);

波特率常量宏定义

将termios_p指向的termios结构中存储的输出波特率设置为speed,该波特率必须是以下常量之一:

宏定义十进制值十六进制值
B000x0000
B5010x0001
B7520x0002
B11030x0003
B13440x0004
B15050x0005
B20060x0006
B30070x0007
B60080x0008
B120090x0009
B1800100x000A
B2400110x000B
B4800120x000C
B9600130x000D
B19200140x000E
B38400150x000F
B5760040970x1001
B11520040980x1002
B23040040990x1003
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值