本节讲解串口通信的接线方式。
但是,听起来很高深的概念,其实就是上面gif里的模型,两个设备,一根线串起来,发送方在线的一头将数据转换为二进制序列,用高低电平按照顺序依次发送01信号,接收方在线的另一头读取这根信号线上的高低电平信号,对应转化为二进制的01序列。
为什么叫异步收发呢?因为如果给上图的两个设备再加一根线,比如下图,让左边的设备也可以成为接收方,右边的设备也可以成为发送方,那么对于左右两个设备而言,发送和接受便可以在两根线上同时进行,所以说,发送和接收是异步的。
两个UART设备的连接示意图如下,UART与其他模块一般用2线相连,它们分别是:
TX:发送数据端,和对端的RX相连;
RX:接收数据端,和对端的TX相连;
**波特率(bandrate
)**是指,每秒钟我们的串口通信所传输的bit个数,通俗的讲就是在一秒内能够发送多少个1和0的二进制数。
比如,波特率是9600,就意味着1S中可以发送9600个0和1组成的二级制序列。
在串口通信的过程中,波特率直接影响着通信的速率,而且在发送端和接收端必须保证同样的波特率,这样才能在一定程度上保证发送和接收保持同步。
然而实际上在发送方和接收方波特率不匹配或者波特率较高的时候,或者有信号干扰,很可能发送和接收的顺序会发生错乱,导致数据的溢出,就像下面的动图中展示的那样——发送方波特率高于接收方:
暂时请忽略上面的DTR和DSR所连接的线,只借此图说明串口通信中波特率不一致或波特率极高的情况下会出现的数据丢失问题。
当然一般在9600和115200的波特率下,上面的情况几乎不会发生,但是这种靠发送接收速率来保持数据同步的方式显然还是存在缺陷的。
为了改进上面的问题,很多基于串口通信的协议都会加上一条时钟信号线,信息的发送和接受,发送方和接收方都要完全按照时钟信号线上的信号来执行,这样,有了第三者 的介入,就使得数据发送和接受能够完全的保证同步。
做个不恰当的比方:
在串口通信中,最基本的一帧数据,至少包含了 起始位+数据位+停止位
,就如同上图红线框中所示。
起始位(Start)是必须存在的,他必须是一个bit位的低电平,即逻辑0,标志着数据传输即将开始。
紧随其后的便是数据位(Data Bits)。数据位包含了通信中的真正有效的信息,自然也是必须存在的。通常我们在配置串口选项时可选的值为 6
, 7
, 8
, 9
,默认8
,这些数字标识了数据位的位数: 数据位的位数由通信双方共同约定,一般可以是6位、7位或8位,比如标准的ASCII码是0127(7位),扩展的ASCII码是0255(8位),因此通信的内容如果都是ASCII码的话,8位的2进制数构成的编码范围0-255即可表示完整的ASCII码字符集。
校验位(Parity)可有可无。如果在通信协议的配置中,规定没有校验位,则数据位后直接跟随停止位。
如果设置了校验位,则有奇偶两种校验方式:
奇偶校验位靠数一数每一帧的数据里逻辑1的个数是偶数还是奇数,来简单的判断数据在发送过程中是否有出错。这种方式在传输过程中只要有一位出错,都能够检测出来。除非校验位出错了!
停止位(Stop Bit)是一帧数据的结束标志,停止位将信号线置位高电平。可以是1bit、1.5bit、2bit的高电平。可能大家会觉得很奇怪,怎么会有1.5位~没错,确实有的。一般我们常选1bit,这样尽可能的压缩了一帧数据的体积,提高了传输的速率。
以传送一个大写字母A为例,波形图如下:
在串口通信以及之后要讲的几种总线协议中,存在传输方向这一概念。
通常,默认都是MSB的传输方向。上面的字母A的波形图,便是MSB。
如果是LSB,则A的Ascii码的区间里,从左至右的0100 0001
的顺序就需要颠倒过来,写成1000 0010
UART接口定义了操作UART端口的通用方法集合,包括:
有14个引脚可以用作UART
waffle nano开发板中有三组支持串口的GPIO,第一组是 TX0 和 RX0,这一组串口资源被REPL所占用,所以无法被用户所使用。
waffle nano还可以自定义GPIO作为UART,只要该GPIO满足以下关系:
作为TX的GPIO能够进行输出
作为RX的GPIO能够作为输入
UART组号 | TX | RX |
---|---|---|
UART 0 | pin 3、pin 13 | pin 4、pin 14 |
UART 1 | pin 0、pin 6 | pin 1、pin 5 |
UART 2 | pin 11 | pin 12、pin 9 |
使用from machine import UART
导入machine
模块的串口通信类UART
再使用TAB
按键来查看Pin
中所包含的内容:
>>>from machine import UART
>>>UART.
read readinto readline write
PARITY_EVEN PARITY_NONE PARITY_ODD bufempty
deinit init isbusy
下面的宏定义用于配置uart,设置校验位。
宏定义 | 含义 |
---|---|
UART.PARITY_EVEN | 校验位偶校验 |
UART.PARITY_NONE | 不设置校验位 |
UART.PARITY_ODD | 校验位奇校验 |
class UART(id[, baudrate, databits, parity, rx, tx, stopbit, timeout])
id
— 串口编号,可用的UART资源只有两个, id有效取值为 1
,2baudrate
— 波特率,常用波特率为:9600
115200
, 默认为115200
databits
— 数据位,是通信中的真正有效信息的每一个字节单元所包含的比特位数。可选的值为 6
, 7
, 8
, 9
,默认8
。 数据位的位数由通信双方共同约定,一般可以是6位、7位或8位,比如标准的ASCII码是0parity
— 基础校验方式 ,None
不进行校验,1
奇校验 0
偶校验rx
— 接收口的GPIO编号 tx
—发送口的GPIO编号stopbit
—停止位个数, 有效取值为1
,2
, 默认值为1
timeout
—超时时间,取值范围: 0 < timeout ≤ 2147483647
用UART对象的构造器函数
示例:
>>> from machine import UART,Pin
>>> uart = UART(1, baudrate=9600,parity=0,rx=Pin(5),tx=Pin(6),timeout=10) #配置UART 1波特率为9600,偶校验,接收口的引脚为5,发送口的引脚为6,超时时间为10
>>>uart
UART(1, baudrate=9600, databits=8, parity=0, stopbits=1, tx=6, rx=5)
使用ID直接构造
UART的id只能取0,1,2
的,可以通过id来直接构造这三组串口。无法使用第0组UART资源,他被python的REPL所占用,以及我们无法给串口id赋予大于2的id
示例:
>>> from machine import UART
>>> uart0 = UART(0)#无法构造UART0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: UART(0) is disabled (dedicated to REPL)
>>> uart3 = UART(3)#无法构造UART3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: UART(3) does not exist
>>>uart1=UART(1)#构造UART1
>>>uart1
UART(1, baudrate=115200, databits=8, parity=None, stopbits=1, tx=6, rx=5)
>>>uart2=UART(2)#构造UART1
>>>uart2
UART(2, baudrate=115200, databits=8, parity=None, stopbits=1, tx=11, rx=12)
在接下来的示例中, 构造id=1
的uart
对象来列举UART对象的函数。
>>>from machine import UART
>>>uart = UART(1)
uart.init(id, baudrate, databits, parity, stopbits, tx, rx)
函数说明:初始UART串口
参数含义同上文UART对象的构造器函数一致
示例:
>>>from machine import UART,Pin
>>>uart = UART(1)#构造UART1串口
>>>uart.init(baudrate=9600,parity=1,tx=Pin(6),rx=Pin(5),timeout=10)#初始化UART串口波特率为9600,奇校验,接收口的引脚为5,发送口的引脚为6,超时时间为10
>>>uart
UART(1, baudrate=9600, databits=8, parity=ODD, stopbits=1, tx=6, rx=5)
uart.write(data)
函数说明:向串口写入(发送)数据,返回data的长度.
data
: 需要写入(发送)的数据
示例:
>>>from machine import UART
>>>uart = UART(1)#构造UART1串口
>>>uart.write('abc')#向串口写入abc,返回数据长度3
3
uart.read(length)
函数说明:从串口读取指定长度的缓冲数据并返回,若长度未指定则读取所有数据.
length
: 读入的字节数
>>>from machine import UART
>>>uart = UART(1)#构造UART1串口
>>>uart.read(2)#从串口缓冲区内读取两个字节的数据
>>>uart.read()#从串口缓冲区内读取所有数据
uart.readline()
函数说明:从串口读取一行缓冲数据
示例:
>>>from machine import UART
>>>uart = UART(1)#构造UART1串口
>>> uart.readline()#读取一行数据
uart.readinto(buf)
函数说明:读入并且保存到缓冲区
buf
: 缓冲区
示例:
>>>from machine import UART
>>>uart = UART(1)#构造UART1串口
>>>buf=bytearray(8)
>>>uart.readinto(buf)
uart.bufempty()
函数说明:不对串口缓冲区数据进行破坏性操作,判断串口缓冲区内数据是否为空。若串口缓冲区是否为空则返回True
,若串口缓冲区存在未被读取的新数据,则返回False
。
示例:
>>>from machine import UART, Pin
>>>uart = UART(1)#构造串口UART
>>>uart.bufempty()#返回串口缓冲区是否为空
uart.isbusy()
函数说明:判断串口是否处于忙碌状态。若处于忙碌状态则返回False
,若处于空闲状态则返回True
。
示例:
>>>from machine import UART, Pin
>>>uart = UART(1)#构造串口UART
>>>uart.isbusy()#返回是否忙碌状态
uart.deinit()
函数说明:关闭UART,释放占用资源。
示例:
>>>from machine import UART, Pin
>>>uart = UART(1)#构造串口UART
>>>uart.deinit()#关闭UART
对waffle nano构建UART串口1,向串口写入(发送)数据,读取数据。
from machine import UART,Pin
uart = UART(1, rx=Pin(5), tx=Pin(6))
uart.write(b'Hello World\r\n')
while True:
print(uart.read())
第一行导入machine
模块的硬件类Pin
和串口类UART
第二行构造UART
串口1,GPIO 5号引脚接收数据,GPIO 6号引脚传输数据
第三行向UART
串口1传入数据
无限循环打印出uart串口1每行读取的数据
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )