串口及其使用

  1. 物理特性定义
  2. 串行通信协议
  3. Linux上的串口操作
    1. 如何进行终端设置
    2. 终端的模式
    3. 线路控制
    4. 波特率设置
    5. 例子
  4. 附录

物理特性定义

串行通信接口的基本任务

  • 实现数据格式化:因为来自CPU的是普通的并行数据,所以,接口电路应具有实现不同串行通信方式下的数据格式化的任务.在异步通信方式下,接口自动生成起止式的帧数据格式.在面向字符的同步方式下,接口要在待传送的数据块前加上同步字符;
  • 进行串-并转换:串行传送,数据是一位一位串行传送的,而计算机处理数据是并行数据.所以当数据由计算机送至数据发送器时,首先把串行数据转换为并行数才能送入计算机处理.因此串并转换是串行接口电路的重要任务;
  • 控制数据传输速率:串行通信接口电路应具有对数据传输速率——波特率进行选择和控制的能力;
  • 进行错误检测:在发送时接口电路对传送的字符数据自动生成奇偶校验位或其他校验码.在接收时,接口电路检查字符的奇偶校验或其他校验码,确定是否发生传送错误;
  • 进行TTL与EIA电平转换:CPU和终端均采用TTL电平及正逻辑,它们与EIA采用的电平及负逻辑不兼容,需在接口电路中进行转换;
  • 提供EIA-RS-232C接口标准所要求的信号线:远距离通信采用MODEM时,需要9根信号线;近距离零MODEM方式,只需要3根信号线.这些信号线由接口电路提供,以便与MODEM或终端进行联络与控制;

串行通信接口电路的组成

为了完成上述串行接口的任务,串行通信接口电路一般由可编程的串行接口芯片,波特率发生器,EIA与TTL电平转换器以及地址译码电路组成.其中,串行接口芯片,随着大规模继承电路技术的发展,通用的同步(USRT)和异步(UART)接口芯片种类越来越多,如下表所示.

这里写图片描述

标准定义

传输率,电特性,信号名称和接口标准是定义串口的几个基本要素。

  • 传输率,是指每秒传输多少位,传输率也常叫波特率.国际上规定了一个标准波特率系列,标准波特率也是最常用的波特率,标准波特率系列为110,300,600,1200,4800,9600等。
  • RS-232-C标准,RS-232-C标准对两个方面作了规定,即信号电平标准和控制信号线的定义.RS-232-C采用负逻辑规定逻辑电平,信号电平与通常的TTL电平也不兼容,RS-232-C将-5V~-15V规定为”1”,+5V~+15V规定为”0”。

串行通信协议

起止式异步协议
这里写图片描述

面向字符的同步协议

这种协议可参考IBM公司的二进制同步通信协议(BSC)。在此不再赘述。

面向比特的同步协议

可参考IBM的同步数据链路控制规程SDLC(Synchronous Data Link Control),国际标准化组织ISO(International Standard Organization)的高级数据链路控制规程HDLC(High Level Data link Control),美国国家标准协会(Americal National Standard Institute)的先进数据通信规程ADCCP(Advanced Data Communication Control Procedure)。其协议帧格式通常如下:

这里写图片描述

Linux上的串口操作

如何进行终端设置

串口通信在Linux上被封装成了终端的概念,因此,对于串口的操作和利用串口进行数据传输其实都是对终端进行操作,终端配置的方法很简单,利用如下两个接口就可对终端进行设置
1
2
int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
其中termios结构体及相关信息可参考附录,这儿来说说optional_actions参数的配置,这是配置对于终端设置参数后的生效方式的,具体可选方式如下

TCSANOW——设置后立即生效
TCSADRAIN——所有输出被写入串口传输完毕后生效
TCSAFLUSH——所有输出传输完毕后生效,说有输入将在生效前被丢弃

终端的模式

终端的配置分为标准模式与非标准模式。标准模式下特殊字符会被解释执行,可以用来建立一个可交互的终端,非标准模式下特殊字符会被当做常规字符被传输,MIN和TIME的不同配置会使得read产生不同的效果。除了以上两种模式外还有一种RAW模式,在RAW模式下回显被关闭,所有终端对输入输出字符的特殊处理都被关闭。由于RAW模式的这种特性,我们就可以利用RAW来传输数据而不会因终端对某些字符的特殊处理导致传输的数据丢失或改变。RAW模式的配置可参考如下代码:
1
2
3
4
5
6
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;

线路控制

对于串口的线路控制Linux提供了如下接口
1
2
3
4
int tcsendbreak(int fd, int duration);
int tcdrain(int fd);
int tcflush(int fd, int queue_selector);
int tcflow(int fd, int action);
tcsendbreak()接口在异步串口通信中使用,作用是在通信双方保持一个连续的数据流。当duration为0时,在传输的空闲时间将以至少0.25s,至多0.5s的间隔发送数据0,如果duration不为0,发送数据0的间隔将是一些预定义的时间。在同步通信中此接口无任何作用。
tcdrain()接口的作用是等待所有写入串口的输出数据都发送完毕后返回
tcflush()接口是用于刷新输入输出队列的。queue_selector的可选值如下
    TCIFLUSH——清空接收的未读数据
    TCOFLUSH——清空写入发送队列但未传输的数据
    TCIOFLUSH——以上功能的全集
tcflow()接口用于流控,action定义了不同流控的动作,定义如下
    TCOOFF——暂停输出
    TCOON——重启暂停的输出
    TCIOFF——传输一个STOP字符
    TCION——传输一个START字符

波特率设置

串口波特率获取与设置接口如下
1
2
3
4
5
speed_t cfgetispeed(const struct termios *termios_p);
speed_t cfgetospeed(const struct termios *termios_p);
int cfsetispeed(struct termios *termios_p, speed_t speed);
int cfsetospeed(struct termios *termios_p, speed_t speed);
int cfsetspeed(struct termios *termios_p, speed_t speed);
波特率可选值(speed)如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
B0
B50
B75
B110
B134
B150
B200
B300
B600
B1200
B1800
B2400
B4800
B9600
B19200
B38400
B57600
B115200
B230400
B460800
B500000
B576000
B921600
B1000000
B1152000
B1500000
B2000000
B2500000
B3000000
B3500000
其中设置B0用于中断连接。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <termios.h>
#include <unistd.h>

int32_t configure_serial(int32_t fd)
{
struct termios termios_c;
termios_c.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
termios_c.c_oflag &= ~OPOST;
termios_c.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios_c.c_cflag &= ~(CSIZE | PARENB);
termios_c.c_cflag |= CS8;
termios_c.c_cc[VMIN] = 1;
termios_c.c_cc[VTIME] = 1;

cfsetspeed(&termios_c, B115200);

tcsetattr(fd, TCSANOW, &termios_c);
}

int32_t main(int32_t argc, char** argv)
{
int32_t fd = open("/dev/ttyS0", O_RDWR);
int32_t ready_bytes;
char buf[1024];
configure_serial(fd);
while(1){
ready_bytes = read(fd, buf, 1024);
}
}

附录

termios是POSIX标准的串行通信接口,其定义了一组函数接口用于控制异步串口通信。以下是termios结构的定义,
1
2
3
4
5
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,c_oflag,c_cflag,c_lflag,c_cc等设置不同的值,可以获得不同的串口通信效果。

输入模式的配置(c_iflag)

输入模式的常量定义
IGNBRK——忽略BREAK条件
BRKINT——IGNBRK如果设置了,则BRKINT将会被忽略;如果IGNBRK没设置,BRKINT设置了,有BREAK产生的时候,输入输出队列将会被冲掉,前台进程组会收到SIGINT信号。
IGNPAR——忽略帧错误和奇偶校验错误
PARMRK——如果IGNPAR没有设置,将得到\377\0开头的错误字符,否则将得到\0
INPCK——开启奇偶校验检查
ISTRIP——去掉第8位
INLCR——在输入流中将NL转换成CR
IGNCR——在输入流中的传输返回
ICRNL——将传输返回转换到新的一行
IUCLC——将输入流中的大写字母映射到小写字母
IXON——当输出时开启XON/XOFF流控
IXANY——键入任何字符时将重启停止的输出流
IXOFF——当输入时开启XON/XOFF流控
IMAXBEL——输入队列满一直响铃,Linux未实现
IUTF8——输入字符为UTF8字符,这个可以允许擦除字符在缓存模式下正常工作

输出模式的配置(c_oflag)

输出模式的常量定义
OPOST——开启定义的输出流处理
OLCUC(not in POSIX)——在输出流中将小写字母映射到大写字符
ONLCR——在输出流中将CR映射到CR-NL
OCRNL——在输出流中将CR映射到NL
ONOCR——在第0列不输出CR
ONLRET——不输出CR
OFILL——发送填充字符作为时间延时
OFDEL(not in POSIX)——填充字符设置位DEL(0177),如果未设置,填充字符位NUL('\0')
NLDLY——新行延迟掩码,值为NL0与NL1.[requires _BSD_SOURCE or _SVID_SOURCE or _XOPEN_SOURCE]
CRDLY——传输返回延迟掩码,值为CR0,CR1,CR2,CR3.[requires _BSD_SOURCE or _SVID_SOURCE or _XOPEN_SOURCE]
TABDLY——水平tab延迟掩码,值为TAB0,TAB1,TAB2,TAB3
BSDLY——退格延迟掩码,值为BS0,BS1
VTDLY——垂直tab延迟掩码,值为VT0,VT1
FFDLY——换页符(form feed)延迟掩码,值为FF0,FF1

控制模式的配置(c_cflag)

控制模式的常量定义
CBAUD——(not in POSIX)波特率掩码(4+1位)
CBAUDEX——(not in POSIX)额外的波特率掩码(1位)
CSIZE——字符大小掩码,值为CS5,CS6,CS7或CS8
CSTOPB——设置两个停止位
CREAD——使能接收数据
PARENB——使能奇偶校验,在输出数据时生成奇偶校验,接收数据时检查奇偶校验
PARODD——奇数校验
HUPCL——挂起modem控制线,当上一个设备关闭后
CLOCAL——忽略modem控制线
CMSPAR——如果PARODD被设置,奇偶校验位一直是1,否则一直是0
CRTSCTS——使能RTS/CTS流控

本地模式配置

本地模式的常量定义
ISIG——当INTR, QUIT, SUSP或DSUSP这些字符被接收到时,将产生相应信号
ICANON——使能标准模式
ECHO——回显输入字符
ECHOE——如果标准模式开启,ERASE字符将可以删除当前输入字符
ECHOK——如果标准模式开启,KILL字符将擦除当前的数据线
ECHONL——如果标准模式开启,NL字符将回显,即使ECHO没设置
ECHOCTL——入股ECHO被设置,终端的特殊字符将回显成^X,X是特殊字符的ASCII码的值加上0x40后的字符
ECHOPRT——如果标准模式和回显都开启,字符将被打印,即使它们被擦除
ECHOKE——如果标准模式开启,KILL将被回显,就像指定ECHOE和ECHOPRT一样
NOFLSH——关闭在收到INT,QUIT,SUSP时冲洗输入输出队列的功能
TOSTOP——当对一个后台进程组的控制终端进行写操作时,发送一个SIGTTOU信号到该进程组
IEXTEN——使能预定义输入处理

特殊字符定义

VDISCARD——(not in POSIX; not supported under Linux; 017, SI, Ctrl-O)
VDSUSP——(not in POSIX; not supported under Linux; 031, EM, Ctrl-Y)
VEOF——(004, EOT, Ctrl-D),文件结束符(EOF)
VEOL——(0, NUL),行结束符(EOL)
VERASE——(0177, DEL, rubout, or 010, BS, Ctrl-H, or also #),擦除字符(ERASE)
VINTR——(003, ETX, Ctrl-C, or also 0177, DEL, rubout),中断字符(INTR),产生一个SIGINT信号
VKILL——(025,  NAK,  Ctrl-U,  or Ctrl-X, or also @),KILL字符
VLNEXT——(not in POSIX; 026, SYN, Ctrl-V)
VMIN——非标准模式下可读的最小字符数(MIN)
VQUIT——(034, FS, Ctrl-\),产生一个SIGQUIT信号
VREPRINT——(not in POSIX; 022, DC2, Ctrl-R),重复打印未读字符,在ICANON与IEXTEN设置后有效
VSTART——(021, DC1, Ctrl-Q),开始字符(START),IXON设置后有效
VSTOP——(023, DC3, Ctrl-S),停止字符(STOP),IXON设置后有效
VSUSP——(032, SUB, Ctrl-Z),暂停字符(SUSP),ISIG设置后有效,产生一个SIGTSTP信号
VTIME——非标准模式下读的超时时间(TIME),单位1/10s
VWERASE—— (not in POSIX; 027, ETB, Ctrl-W)

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 yxhlfx@163.com

文章标题:串口及其使用

本文作者:红尘追风

发布时间:2017-04-06, 22:07:15

原始链接:http://www.micernel.com/2017/04/06/%E4%B8%B2%E5%8F%A3%E5%8F%8A%E5%85%B6%E4%BD%BF%E7%94%A8/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录