详细解读11、串口编程

简介: 详细解读11、串口编程

1、串口的 介绍

串口的介绍,

串口发送的顺序;

1.空闲位:这里是连续的 1

2.起始位:低电平

3.数据位:对于传输的数据位这里是自己去设定传输位数,可以5、6、7、8位,但是我们一般设置为 8位

串口的数据是从低位开始发送

4.奇偶校验位:保证传输数据位中的 1 的个数是奇数还是偶数。奇校验;保证数据位中的‘1’是奇数个,当数据位中的‘1’是奇数个的时候,那么校验位填零;当数据位中的‘1’是偶数个的时候,则校验位填为‘1’。

5.停止位:低电平。持续时间为一个或者 1.5 个字符的时间。

2、硬件引脚的认识

3、Linux 下端口 /dev/ttyn、/dev/pts/n、/dev/ttySn:

终端的查看,是借用了 tty 命令去查看。

/dev/ttyn : 终端,一般就是我们在 ubuntu 里面终端的时候,就是 ttyn

/dev/pts/n : 虚拟终端 ,比如当我们使用 secureCRT 连接 ubuntu 的时候,这个时候 secureCRT 的终端。

/dev/ttySn: 使用串口登录串行端口终端,也就是设备通过串口端连接终端,ttyS0、ttyS1,分别对应了 COM1 和 COM 2

4、串口的基本知识 4.1、串口传输模式

串口传输的模式,可以分为两种,标准输入模式(规范模式)和非标//代码效果参考:http://www.zidongmutanji.com/bxxx/113334.html

准输入模式(非规范模式)

标准输入模式:

这种模式是终端设备标准的处理模式。通信中,是以行为单位进行传输,行的结束是以 enter 为结束符。read 的时候,会将一行的数据,完整地进行输入,一行的结束默认是 enter (ASCII 是 LF,既换行 ,回车是 cr,)。在标准输入模式下,字符被输入终端之后,还可以进行清除,删除,重写,换行等操作,所以,根据自己的实际需求,写好字符之后,按下 enter 作为作为一行输入的结束。

非标准输入模式:

这种模式一般是用于需要每次读取固定字符的情况下(比如一个字符),并允许使用,字符接收时间的定时器。也就是说,可以在每次读取固定长度字符串的程序中,或者连接的设备会突然发送大量的字符内容的情况下。

4.2、流控

流控,可以分为硬件流控和软件流控。流控实现的是,当接收端不能接收串口数据的时候,通知数据的发送端,使其不再发送数据的这么一种机制。软件流控,实现的方法是通过一些特殊的字符进行定义,X0N(DC1,八进制的话是,021) 和 结束,X0FF(DC3,八进制是,023),来开始和结束数据流的进行。开始和结束的这个特殊的字符,是被定义在 ASCII 。所以,当传输的信息是文本信息的时候,软件流控是非常的好用的。但是,流控是不被建议运用在传输二进制文件。

硬件流控,是通过硬件特定的管脚,发送电平实现的。

4.3、ASCII

CR-od(十六进制)--回车---\r(C语言)

NL(LF)-oa(new line、line feed)-换行\n(C语言)

5、串口的操作 5.1、文件的打开

int open_port(void)

{

int fd; / File descriptor for the port / //代码效果参考:http://www.zidongmutanji.com/bxxx/161362.html

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

if (fd == ?1)

{

/

Could not open the port.

/

perror("open_port: Unable to open /dev/ttyf1 ? ");

}

else

fcntl(fd, F_SETFL, 0);

return (fd);

}

O_NOCTTY : 告诉系统,当前的程序上不受终端的控制,所以就不会受到 ctrl+ c 的影响。

NDELAY : 和 NONBLOCK 类似。NDELAY 不会受到 DCD 信号的影响。非阻塞

5.2、串口读

n = write(fd, "ATZ\r", 4);

if (n < 0)

fputs("write() of 4 bytes failed!\n", stderr);

5.3、串口的写

相比于串口读,串口写的操作,还是存在一点的技巧的。当 read 一个以 原始模式的传输数据串口的时候,read 的返回值,是串口实际接收字符的个数。当没有 read 到字符的时候,read 操作会编程阻塞模式,直到字符的到来,或者错误的发生。所以,为了 read 的时候,读取不到字符的时候,立即马上返回,可以进行下面的操作:

fcntl( fd, F_SETFL, FNDELAY)

FNDELAY 会导致,当串口没有字符被读取到的时候,立即返回 零//代码效果参考:http://www.zidongmutanji.com/bxxx/322232.html

。如果需要设置阻塞模式的话:

fcntl( fd, F_SETFL, 0);

5.4、关闭

close( fd )

6、接口

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 / 控制字符

};、

6.1、control flag

控制模式,主要是对,波特率,传输的数据位,校验位、停止位、和流控进行设置。对于控制标志的设置,是通过下面的常量(宏)进行配置。

Constant Description

CBAUD Bit mask for baud rate

B0 0 baud (drop DTR) // 波特率

B50 50 baud

B75 75 baud

B110 110 baud

B134 134.5 baud

B150 150 baud

B200 200 baud

B300 300 baud

B600 600 baud

B1200 1200 baud

B1800 1800 baud

B2400 2400 baud

B4800 4800 baud

B9600 9600 baud

B19200 19200 baud

B38400 38400 baud

B57600 57,600 baud

B76800 76,800 baud

B115200 115,200 baud

EXTA External rate clock

EXTB External rate clock

CSIZE Bit mask for data bits // 传输数据位的掩模

CS5 5 data bits

CS6 6 data bits

CS7 7 data bits

CS8 8 data bits // 8 bit 数据位

CSTOPB 2 stop bits (1 otherwise) // 2 个停止位

CREAD Enable receiver // 允许接收字符

PARENB Enable parity bit // 使能校验位

PARODD Use odd parity instead of even // 使用奇校验

HUPCL Hangup (drop DTR) on last close

CLOCAL Local line ? do not change "owner" // 本地接收

of port

LOBLK Block job control output

CNEW_RTSCTS // CNEW_RTSCTS 和CRTSCTS 使能硬件流控

CRTSCTS Enable hardware flow control (notsupported on all platforms)

CLOCAL 和 CREAD 这两个选项,应该被选中。而对标志的设置,永远也不要对这些标志做初始化的操作,而应该是使用与、或 的操作,达到清零或者置一的操作。

6.1.1、波特率的设置

tcgetattr(fd, options);

struct termios options;

options.c_cflag |= (CLOCAL | CREAD);

tcgetattr(fd, option);

cfsetispeed(fd, B115200);

tcsetattr(fd, TCSANOW, options);

tcgetattr 函数,实现获取当前串口的配置信息。当完成新的配置之后,就需要将这些信息进行激活。,就使用tcsetattr。

TCSANOW Make changes now without waiting for data to complete

TCSADRAIN Wait until everything has been transmitted

TCSAFLUSH Flush input and output buffers and make the change

TCSANOW 标志,表明所做的更改设置,会立即生效,不会等待数据发送或者接收完毕,

6.1.2、设置字符大小

传输字符大小的设置,没有函数接收可以使用,而是通过 宏代码 实现。

options.c_cflag = ~CSIZE; / Mask the character size bits /

options.c_cflag |= CS8; / Select 8 data bits /

实现传输字符的设置,一定先要进行 options.c_cflag = ~CSIZE 之后,才可以进行位数的设置。

6.1.3、校验位和停止位的设置

校验位可以设置为,无校验、奇校验、偶校验,三种。

? No parity (8N1): // 8bitdata 无校验,1个停止位

options.c_cflag = ~PARENB // 关闭校验

options.c_cflag = ~CSTOPB // 一个停止位

options.c_cflag = ~CSIZE; // 8个数据位

options.c_cflag |= CS8;

? Even parity (7E1): // 7个 数据位,偶校验,一个停止位

options.c_cflag |= PARENB // 校验使能

options.c_cflag = ~PARODD // 偶校验

options.c_cflag = ~CSTOPB // 一个停止位

options.c_cflag = ~CSIZE; // 7个数据位

options.c_cflag |= CS7;

? Odd parity (7O1):

options.c_cflag |= PARENB // 校验使能

options.c_cflag |= PARODD // 奇校验

options.c_cflag = ~CSTOPB // 一个停止位

options.c_cflag |= CS7;

停止位的设定是通过 CSTOPB 实现的。如停止位为 1 ,则清除 CSTOPB。如停止位为 2,则激活 CSTOPB。

6.1.4、硬件流控的设置

一些 Linux 系统是支持硬件流控的。如果 CNEW_RTSCTS 和 CRTSCTS 在自己的系统中,是被定义的话,就可以借助他们来实现硬件流控的开启:

options.c_cflag |= CNEW_RTSCTS; / Also called CRTSCTS /

当然,也可以进行关闭:

options.c_cflag = ~CNEW_RTSCTS

6.2、local flag

本地模式,c_lflag 用于控制串口输入的字符,比如终端输入的字符是否支持回显。通常上,需要对 c_lflag 设置,实现,规范模式,或者原始模式。

ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP,and SIGQUIT signals

ICANON Enable canonical input (else raw)

XCASE Map uppercase \lowercase (obsolete)

ECHO Enable echoing of input characters

ECHOE Echo erase character as BS?SP?BS

ECHOK Echo NL after kill character

ECHONL Echo NL

NOFLSH Disable flushing of input buffers after interrupt or quit characters

IEXTEN Enable extended functions

ECHOCTL Echo control characters as ^char and delete as ~?

ECHOPRT Echo erased character as character erased

ECHOKE BS?SP?BS entire line on line kill

FLUSHO Output being flushed

PENDIN Retype pending input at next read or input char

TOSTOP Send SIGTTOU for background output

如果终端的模式,设置为规范模式(标准输入),那么需要设置 ICANNO ECHO ECHOE选项。

options.c_lflag |= (ICANON | ECHO | ECHOE);

如果终端是原始模式(非标准输入),那么就需要进行不选中ICANNO ECHO ECHOE,同时添加 ISIG 选项。

options.c_lflag = ~(ICANON | ECHO | ECHOE | ISIG);

注意:

当传输的命令是传送给 MODEN 的时候,或者传送的命令是发送给已经开启了回显的 B 电脑的时候,发送端 A ,绝对不要打开回显功能(不要打开 ECHO 和 ECHOE ),因为会在两个串口之间生成回环的反馈。

6.3、输入模式

输入模式的,c_iflag ,对串口接收的 字符 进行的操作。

Constant Description

INPCK Enable parity check // 使能校验检查

IGNPAR Ignore parity errors

PARMRK Mark parity errors

ISTRIP Strip parity bits // 删除校验位

IXON Enable software flow control (outgoing)

IXOFF Enable software flow control (incoming)

IXANY Allow any character to start flow again

IGNBRK Ignore break condition

BRKINT Send a SIGINT when a break condition isdetected

INLCR Map NL to CR

IGNCR Ignore CR

ICRNL Map CR to NL

IUCLC Map uppercase to lowercase

IMAXBEL Echo BEL on input line too long

6.3.1、设置输入校验

如果在 c_cflag 中使能了 PARENB,也就是使能了校验位,那么就需要在输入模式,使能校验检测。

一般是:

options.c_iflag |= (INPCK | ISTRIP);

6.3.2、软件流控

软件流控的实现是,需要 IXON, IXOFF, and IXANY 常量

打开软件流控:

options.c_iflag |= (IXON | IXOFF | IXANY)

关闭:

options.c_iflag = ~(IXON | IXOFF | IXANY);

IXON 和 IXOFF 是被定义在 c_cc 数组当中。

6.4、输出模式

设置 c_oflag 控制的是当串口完成数据的接收,并且完成输入模式操作之后,如果将数据进行数据。数据的输出,可以进行操作,或者直接以原始的模式进行输出。

Constant Description

OPOST Postprocess output (not set = raw output)

OLCUC Map lowercase to uppercase

ONLCR Map NL to CR?NL

OCRNL Map CR to NL

NOCR No CR output at column 0

ONLRET NL performs CR function

OFILL Use fill characters for delay

OFDEL Fill character is DEL

NLDLY Mask for delay time needed between lines

NL0 No delay for NLs

NL1 Delay further output after newline for 100 milliseconds

CRDLY Mask for delay time needed to return carriage to left column

CR0 No delay for CRs

CR1 Delay after CRs depending on current column position

CR2 Delay 100 milliseconds after sending CRs

CR3 Delay 150 milliseconds after sending CRs

TABDLY Mask for delay time needed after TABs

TAB0 No delay for TABs

TAB1 Delay after TABs depending on current column position

TAB2 Delay 100 milliseconds after sending

TABs

TAB3 Expand TAB characters to spaces

BSDLY Mask for delay time needed after BSs

BS0 No delay for BSs

BS1 Delay 50 milliseconds after sending BSs

VTDLY Mask for delay time needed after VTs

VT0 No delay for VTs

VT1 Delay 2 seconds after sending VTs

FFDLY Mask for delay time needed after FFs

FF0 No delay for FFs

FF1 Delay 2 seconds after sending FFs

6.4.1、 输出的字符,如果进行操作的话,需要对 OPOST 进行设置:

options.c_oflag |= OPOST;

6.4.2、如果选择为原始数据输出的话:

options.c_oflag = ~OPOST;

当 OPOST 被关闭之后,那么对于 c_oflag 所有的设置将会被忽略。

6.5、字符控制

在 c_cc 数组中,实现了对定时器等一些操作,下面是配置信息:

Constant Description Key

VINTR Interrupt CTRL?C

VQUIT Quit CTRL?Z

VERASE Erase Backspace (BS)

VKILL Kill?line CTRL?U

VEOF End?of?file CTRL?D

VEOL End?of?line Carriage return (CR)

VEOL2 Second end?of?line Line feed (LF)

VMIN Minimum number of characters to read

VTIME Time to wait for data (tenths of seconds)

6.5.1、设置软件流控的字符

当使用了软件流控的时候,需要对,c_cc【VSTART】 和 c_cc【VSTOP】 进行设置,他们应该被设置为 DC1 和 DC3,DC1 和 DC3 在 SCII 中,代表了 XON 和 XOFF。

6.5.2、定时和字符个数的设置

MIN > 0, TIME = 0 : 读取函数在读到了 MIN 值的字符数后返回。

MIN = 0, TIME > 0 : TIME 决定了超时值,读取函数在读到一个字节的字符,或者等待读

取时间超过 TIME (t = TIME 0.1s)以后返回,也就是说,即使没有从串口中读到数

据,读取函数也会在 TIME 时间后返回。

MIN > 0, TIME > 0 : 读取函数会在收到了 MIN 字节的数据后,或者超过 TIME 时间没收

到数据后返回。此计时器会在每次收到字符的时候重新计时,也只会在收到第一个字节后才

启动。

MIN = 0, TIME = 0 : 读取函数会立即返回。实际读取到的字符数,或者要读到的字符

数,会作为返回值返回。根据 Antonino(参考 conditions), 可以使用 fcntl(fd, F_SETFL,

FNDELAY), 在读取前获得同样的结果。

7、串口的操作介

(1)头文件

#include

#include

#include

#include

#include

#include

#include

常用串口设置函数:

(1)属性的获取与设置

int tcgetattr(int fd, struct termios termios_p);

获取属性存放在 struct termios 里面,而 fd 是打开串口的的文件描述符。

int tcsetattr(int fd, int optional_actions, const struct termios termios_p); 设置属性(termios结构) // 激活自己的配置

cfgetispeed 得到输入速度

Cfgetospeed 得到输出速度

Cfsetispeed 设置输入速度

Cfsetospeed 设置输出速度

Tcdrain 等待所有输出都被传输

tcflow 挂起传输或接收

tcflush 刷清未决输入和/或输出

Tcsendbreak 送BREAK字符

tcgetpgrp 得到前台进程组ID

tcsetpgrp 设置前台进程组ID

8、串口流程

(1)保存原先串口的配置

struct termios newtio,oldtio;

tcgetattr(fd, oldtio);

获取原先串口的配置。

(2)激活本地连接和接收使能

这一步,是用于本地进行接收的。

newtio.c_cflag |= CLOCAL | CREAD;

(3)设置波特率

cfsetispeed(Opt,B19200); /设置为19200Bps/

cfsetospeed(Opt,B19200); // 设置输出的波特率为 19200

波特率的设置,都是 BXXXXX

(4)设置数据位的位数

newtio.c_cflag = ~CSIZE;

newtio.c_cflag |= CS8; // 设置数据位为 8 位

(5)设置奇偶校验

设置奇校验

newtio.c_cflag |= PARENB;

newtio.c_cflag |= PARODD;

newtio.c_iflag |= (INPCK | ISTRIP);

设置偶校验:

newtio.c_iflag |= (INPCK|ISTRIP);

相关文章
|
7月前
|
存储 网络协议 C语言
【C/C++ 串口编程 】深入探讨C/C++与Qt串口编程中的粘包现象及其解决策略
【C/C++ 串口编程 】深入探讨C/C++与Qt串口编程中的粘包现象及其解决策略
478 0
|
6月前
|
Ubuntu Linux C语言
详细解读11、串口编程
详细解读11、串口编程
14 0
|
6月前
|
机器学习/深度学习 网络协议 C语言
程序技术好文:网络编程中的SIGPIPE信号
程序技术好文:网络编程中的SIGPIPE信号
133 0
|
7月前
|
传感器 Linux API
嵌入式Linux串口编程简介
嵌入式Linux串口编程简介
57 1
|
7月前
|
监控 Linux 定位技术
Linux应用开发基础知识——串口应用编程(十一)
Linux应用开发基础知识——串口应用编程(十一)
184 0
Linux应用开发基础知识——串口应用编程(十一)
|
7月前
|
存储 Linux 开发者
Linux驱动编程必备基础知识分享
Linux驱动编程必备基础知识分享
61 0
|
存储
14个PLC入门基础知识
14个PLC入门基础知识
251 0
14个PLC入门基础知识
下一篇
DataWorks