linux应用编程12-串口终端

目录

1、终端

1.1、终端分类

1.1.1、本地终端和远程终端

1.1.2、物理终端和伪终端

1.2、查看连接终端

1.3、终端参数

1.4、终端的工作模式

1.4.1、规范模式

1.4.2、非规范模式

1.4.3、原始模式

2、termios API

2.1、struct termios结构体

2.1.1、c_iflag

2.1.2、c_oflag

2.1.3、c_cflag

2.1.4、c_lflag

2.1.5、c_cc

2.2、函数

2.2.1、cfmakeraw()函数

2.2.2、cfsetispeed()函数

2.2.3、cfsetospeed()函数

2.2.4、cfsetspeed()函数

2.2.5、tcdrain()函数

2.2.6、tcflush()函数

2.2.6、tcflow()函数

2.2.7、tcgetattr()函数

2.2.8、tcsetattr()函数

3、串口应用编程流程


1、终端

1.1、终端分类

1.1.1、本地终端和远程终端

本地终端鼠标、键盘、显示器
远程终端串口远程终端通过串口登录
网络远程终端通过 ssh、 Telnet 等协议登录到一个远程主机

注:/dev/ttyX是本地终端对应的设备节点, 包括/dev/tty1~/dev/tty63 一共63 个本地终端。 

1.1.2、物理终端和伪终端

物理终端本地直接关联物理设备
伪终端没有关联任何物理设备

注:/dev/pts/X是伪终端对应的设备节点。

1.2、查看连接终端

使用who 命令可以查看系统当前连接了哪些终端。

1.3、终端参数

输入模式输入模式控制输入数据(如终端驱动程序从串口或键盘接收到的字符数据)在被传递给应用程序之前的处理方式。
输出模式输出模式控制输出字符的处理方式,即由应用程序发送出去的字符数据在传递到串口或屏幕之前是如何处理的。
控制模式控制模式控制终端设备的硬件特性,譬如对于串口来说,该字段比较重要,可设置串口波特率、数据位、校验位、停止位等硬件特性。
本地模式本地模式用于控制终端的本地数据处理和工作模式。
特殊控制字符特殊控制字符是一些字符组合如 Ctrl+C、 Ctrl+Z 等, 当用户键入这样的组合键,终端会采取特殊处理方式。
输入速率终端的输入速率
输出速率终端的输出速率

1.4、终端的工作模式

1.4.1、规范模式

在规范模式下,所有的输入是基于行进行处理的。在用户输入一个行结束符(回车符、 EOF 等)之前,系统调用 read()函数是读不到用户输入的任何字符的。除了 EOF 之外的行结束符(回车符等)与普通字符一样会被 read()函数读取到缓冲区中。在规范模式中,行编辑是可行的,而且一次 read()调用最多只能读取一行数据。如果在 read()函数中被请求读取的数据字节数小于当前行可读取的字节数,则 read()函数只会读取被请求的字节数,剩下的字节下次再被读取。

1.4.2、非规范模式

在非规范模式下,所有的输入是即时有效的,不需要用户另外输入行结束符,而且不可进行行编辑。

TIME 和 MIN 的值只能用于非规范模式,两者结合起来可以控制对输入数据的读取方式。
MIN = 0 和 TIME = 0在这种情况下, read()调用总是会立即返回。若有可读数据,则读取数据并返回被读取的字节数; 否则读取不到任何数据并返回 0。
MIN > 0 和 TIME = 0在这种情况下, read()函数会被阻塞, 直到有 MIN 个字符可以读取时才返回。返回值是读取的字符数量。到达文件尾时返回 0。
MIN = 0 和 TIME > 0在这种情况下, 只要有数据可读或者经过 TIME 个十分之一秒的时间, read()函数则立即返回返回值为被读取的字节数。如果超时并且未读到数据,则 read()函数返回 0。
MIN > 0 和 TIME > 0
 
在这种情况下, 当有 MIN 个字节可读或者两个输入字符之间的时间间隔超过 TIME 个十分之一秒时, read()函数才返回。因为在输入第一个字符后系统才会启动定时器,所以,在这种情况下, read()函数至少读取一个字节后才返回。

1.4.3、原始模式

原始模式是一种特殊的非规范模式。在原始模式下,所有的输入数据以字节为单位被处理。在这个模式下,终端是不可回显的, 并且禁用终端输入和输出字符的所有特殊处理。

2、termios API

串口的应用编程可以通过 ioctl()对串口进行配置,调用 read()读取串口的数据、调用 write()向串口写入数据。但是通常不这么做!因为 Linux 为上层用户做了一层封装,将这些 ioctl()操作封装成了一套标准的 API。可以直接使用这套标准 API 进行串口应用编程。

注:这一套接口并不是针对串口开发的,而是针对所有的终端设备。

2.1、struct termios结构体

struct termios
{
    tcflag_t c_iflag; /* input mode flags */
    tcflag_t c_oflag; /* output mode flags */
    tcflag_t c_cflag; /* control mode flags */
    tcflag_t c_lflag; /* local mode flags */
    cc_t c_line; /* line discipline */
    cc_t c_cc[NCCS]; /* control characters */
    speed_t c_ispeed; /* input speed */
    speed_t c_ospeed; /* output speed */
};

注:对于这些变量尽量不要直接对其初始化,而要将其通过“按位与”、“按位或” 等操作添加标志或清除某个标志。

注:不同的终端设备,本身硬件上就存在很大的区别,所以配置参数不是对所有终端设备都是有效的。

2.1.1、c_iflag

输入模式标志。

说明
IGNBRK忽略输入终止条件
BRKINT当检测到输入终止条件时发送 SIGINT 信号
IGNPAR忽略帧错误和奇偶校验错误
PARMRK对奇偶校验错误做出标记
INPCK对接收到的数据执行奇偶校验
ISTRIP将所有接收到的数据裁剪为 7 比特位、也就是去除第八位
INLCR将接收到的 NL(换行符)转换为 CR(回车符)
IGNCR忽略接收到的 CR(回车符)
ICRNL将接收到的 CR(回车符)转换为 NL(换行符)
IUCLC将接收到的大写字符映射为小写字符
IXON启动输出软件流控
IXOFF启动输入软件流控
IXANY允许任意字节启动流控

2.1.2、c_oflag

输出模式标志。

说明
OPOST启用输出处理功能,如果不设置该标志则下面其他标志都被忽略
OLCUC将输出字符中的大写字符转换成小写字符
ONLCR将输出中的换行符(NL '\n')转换成回车符(CR '\r')
OCRNL将输出中的回车符(CR '\r')转换成换行符(NL '\n')
ONOCR在第 0 列不输出回车符(CR)
ONLRET不输出回车符
OFILL发送填充字符以提供延时
OFDEL如果设置该标志,则表示填充字符为 DEL 字符,否则为 NULL
字符

2.1.3、c_cflag

控制模式控制终端设备的硬件特性(串口波特率、数据位、校验位、停止位等)。

CBAUD波特率的位掩码
B0波特率为 0
B300300 波特率
B12001200 波特率
B18001800 波特率
B24002400 波特率
B48004800 波特率
B96009600 波特率
B1920019200 波特率
B3840038400 波特率
B5760057600 波特率
B115200115200 波特率
B230400230400 波特率
B460800460800 波特率
B500000500000 波特率
B576000576000 波特率
B921600921600 波特率
B10000001000000 波特率
B11520001152000 波特率
B15000001500000 波特率
B20000002000000 波特率
B25000002500000 波特率
B30000003000000 波特率

注:在 Linux 系统下, 使用 CBAUD 位掩码所选择的位来指定串口波特率;在其它一些系统中,可能使用c_ispeed 成员变量和 c_ospeed 成员变量来指定串口的波特率。

CSIZE数据位的位掩码
CS55 个数据位
CS66 个数据位
CS77 个数据位
CS88 个数据位
CSTOPB2 个停止位,如果不设置该标志则默认是一个停止位
CREAD接收使能
PARENB使能奇偶校验
PARODD使用奇校验、而不是偶校验
HUPCL关闭时挂断调制解调器
CLOCAL忽略调制解调器控制线
CRTSCTS使能硬件流控

2.1.4、c_lflag

本地模式用于控制终端的本地数据处理和工作模式。

ISIG若收到信号字符(INTR、 QUIT 等),则会产生相应的信号
ICANON启用规范模式
ECHO启用输入字符的本地回显功能。
ECHOE若设置 ICANON,则允许退格操作
ECHOK若设置 ICANON,则 KILL 字符会删除当前行
ECHONL若设置 ICANON,则允许回显换行符
ECHOCTL若设置 ECHO,则控制字符(制表符、换行符等)会显示成“^X”,其中 X 的 ASCII 码等于给相应控制字符的 ASCII 码加上 0x40。例如,退格字符(0x08)会显示为“^H”('H'的 ASCII 码为 0x48)
ECHOPRT若设置 ICANON 和 IECHO,则删除字符(退格符等)和被删除的字符都会被显示
ECHOKE若设置 ICANON,则允许回显在 ECHOE 和 ECHOPRT 中设定的 KILL字符
NOFLSH在通常情况下,当接收到 INTR、 QUIT 和 SUSP 控制字符时,会清空
输入和输出队列。如果设置该标志,则所有的队列不会被清空
TOSTOP若一个后台进程试图向它的控制终端进行写操作,则系统向该后台进程的进程组发送 SIGTTOU 信号。该信号通常终止进程的执行
IEXTEN启用输入处理功能

2.1.5、c_cc

特殊控制字符是一些字符组合,如 Ctrl+C、 Ctrl+Z 等, 当用户键入这样的组合键,终端会采取特殊处理方式。

VEOF文件结尾符 EOF,对应键为 Ctrl+D; 该字符使终端驱动程序将输入行中的全部字符传递给正在读取输入的应用程序。如果文件结尾符是该行的第一个字符,则用户程序中的 read 返回 0,表示文件结束。
VEOL附加行结尾符 EOL,对应键为 Carriage return(CR) ; 作用类似于行结束符。
VEOL2第二行结尾符 EOL2,对应键为 Line feed(LF) ;
VERASE删除操作符 ERASE,对应键为 Backspace(BS) ; 该字符使终端驱动程序删除输入行中的最后一个字符;
VINTR中断控制字符 INTR,对应键为 Ctrl+C; 该字符使终端驱动程序向与终端相连的进程发送SIGINT 信号;
VKILL删除行符 KILL,对应键为 Ctrl+U, 该字符使终端驱动程序删除整个输入行;
VMIN在非规范模式下,指定最少读取的字符数 MIN;
VQUIT退出操作符 QUIT,对应键为 Ctrl+Z; 该字符使终端驱动程序向与终端相连的进程发送
SIGQUIT 信号。
VSTART开始字符 START,对应键为 Ctrl+Q; 重新启动被 STOP 暂停的输出。
VSTOP停止字符 STOP,对应键为 Ctrl+S; 字符作用“截流”,即阻止向终端的进一步输出。用于支持 XON/XOFF 流控。
VSUSP挂起字符 SUSP,对应键为 Ctrl+Z; 该字符使终端驱动程序向与终端相连的进程发送SIGSUSP 信号,用于挂起当前应用程序。
VTIME非规范模式下, 指定读取的每个字符之间的超时时间(以分秒为单位) TIME。

2.2、函数

2.2.1、cfmakeraw()函数

将终端配置为原始模式。

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

void cfmakeraw(struct termios *termios_p);

2.2.2、cfsetispeed()函数

设置输入波特率。

注:设置波特率有专门的函数,用户不能直接通过位掩码来操作。

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

int cfsetispeed(struct termios *termios_p, speed_t speed);

2.2.3、cfsetospeed()函数

设置输出波特率。

注:设置波特率有专门的函数,用户不能直接通过位掩码来操作。

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

int cfsetospeed(struct termios *termios_p, speed_t speed);

2.2.4、cfsetspeed()函数

设置波特率。

注:设置波特率有专门的函数,用户不能直接通过位掩码来操作。

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

int cfsetspeed(struct termios *termios_p, speed_t speed);

2.2.5、tcdrain()函数

调用 tcdrain()函数后会使得应用程序阻塞, 直到串口输出缓冲区中的数据全部发送完毕为止!

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

int tcdrain(int fd);

参数 fd:文件描述符。

返回值:调用成功时返回 0;失败将返回-1,并设置 errno。 

2.2.6、tcflush()函数

调用该函数会清空输入/输出缓冲区中的数据。

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

int tcflush(int fd, int queue_selector);

参数 fd:文件描述符。

参数 queue_selector:

TCIFLUSH对接收到而未被读取的数据进行清空处理
TCOFLUSH对尚未传输成功的输出数据进行清空处理
TCIOFLUSH对尚未处理的输入/输出数据进行清空处理

返回值:调用成功时返回 0;失败将返回-1,并设置 errno。

2.2.6、tcflow()函数

调用 tcflow()函数会暂停数据传输或接收工作。

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

int tcflow(int fd, int action);

 参数 fd:文件描述符

参数 action:

TCOOFF暂停数据输出(输出传输)
TCOON重新启动暂停的输出
TCIOFF发送 STOP 字符,停止终端设备向系统发送数据
TCION发送一个 START 字符,启动终端设备向系统发送数据;

返回值:调用成功时返回 0;失败将返回-1,并设置 errno。

2.2.7、tcgetattr()函数

获取到终端当前的配置参数。

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

int tcgetattr(int fd, struct termios *termios_p);

参数 fd:文件描述符

参数 termios_p:保存获取的配置参数。

返回值:调用成功时返回 0;失败将返回-1,并设置 errno。

2.2.8、tcsetattr()函数

将配置参数写入到终端设备,使其生效。

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

int tcsetattr(int fd, int optional_actions,const struct termios *termios_p);

参数 fd:文件描述符

参数 optional_actions:指定更改何时生效

TCSANOW配置立即生效
TCSADRAIN配置在所有写入 fd 的输出都传输完毕之后生效
TCSAFLUSH所有已接收但未读取的输入都将在配置生效之前被丢弃

参数 termios_p:将 struct termios 对象中的配置参数写入到终端设备中。
返回值:调用成功时返回 0;失败将返回-1,并设置 errno。

3、串口应用编程流程

1)调用open()打开串口设备文件

注:调用 open()函数时,使用 O_NOCTTY 标志,该标志用于告知系统它不会成为进程的控制终端。

2)调用cfmakeraw()将终端配置为原始模式
3)接收使能

4)调用tcflush()刷新缓冲区

5)设置输入输出波特率

6)设置数据位

7)设置停止位

8)设置奇偶校验位

9)设置 MIN 和 TIME 的值

10) 调用tcsetattr()更新配置

11)调用read()/write()读写数据

       

  • 9
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux串口编程可以使用C语言和系统调用来实现。以下是一些基本步骤: 1. 打开串口设备文件。在Linux中,每个串口都会有一个设备文件。您可以使用open系统调用来打开串口设备文件,例如: ```c int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY); ``` 其中,/dev/ttyS0是串口设备文件的路径,O_RDWR表示以读写方式打开设备文件,O_NOCTTY表示不将串口设备作为控制终端。 2. 配置串口参数。在进行串口通信之前,需要对串口进行一些配置,例如波特率、数据位、停止位、奇偶校验位等等。您可以使用tcgetattr和tcsetattr系统调用来获取和设置串口参数,例如: ```c struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B9600); cfsetospeed(&options, B9600); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; tcsetattr(fd, TCSANOW, &options); ``` 其中,B9600表示波特率为9600,CLOCAL和CREAD表示忽略调制解调器信号和启用接收器,PARENB表示启用奇偶校验,CSTOPB表示两个停止位,CSIZE表示数据位数,CS8表示8位数据位。 3. 读写串口数据。在配置好串口参数之后,您可以使用read和write系统调用来进行串口数据的读写操作,例如: ```c char buf[256]; int n = read(fd, buf, sizeof(buf)); write(fd, buf, n); ``` 其中,fd是打开的串口设备文件描述符,buf是读写数据的缓冲区,sizeof(buf)表示缓冲区的大小,n是读取到的数据字节数。 4. 关闭串口设备。在程序结束之前,需要使用close系统调用来关闭串口设备文件,例如: ```c close(fd); ``` 以上是一些基本的步骤,但是具体的操作可能因设备型号、Linux版本等因素而有所不同。如果您遇到了问题,可以查阅相关的文档或者向社区寻求帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值