1 本节介绍
📝本节您将学习如何通过将K230开发板的GPIO引脚复用为串口(UART)功能并输出和接收串口数据;
🏆学习目标
1️⃣如何将K230的引脚配置为UART模式,与外部串口(UART)设备进行发送和接收数据。
2️⃣如何进行简单的串口回环测试。
3️⃣进阶应用【等待后续更新】
2 名词解释
名词 | 说明 |
---|---|
串口(UART) | Universal Asynchronous Receiver/Transmitter (通常称为:UART,通用异步串行通讯) |
3 什么是串口?
UART(Universal Asynchronous Receiver-Transmitter,通用异步收发传输器)是嵌入式系统和电子设备中常用的一种串行通信协议。UART的广泛应用主要集中在微控制器、嵌入式系统模块、传感器以及调试接口等方面。甚至以前的电脑都是自带串口的老式的DB9
接口,不过随着科技发展在个人PC上被逐渐淘汰了,被USB等更现代化的接口替代了。
其是一种异步串行通信协议,发送端和接收端的数据传输不需要时钟信号同步,也就是说不需要额外的时钟线。UART主要通过以下两条线来进行数据传输:
- TXD(Transmit Data):数据发送端,将数据从发送设备发送到接收设备。
- RXD(Receive Data):数据接收端,用于接收从发送设备发来的数据。
通信时,UART会将并行数据(如8位数据)用移位寄存器转换成串行格式逐位按照比特顺序发送发送;接收端会将将比特(bit)数据组装为字节,供系统进一步处理。
3.1 串口通讯参数
- 波特率: 衡量通信速度的参数,它表示每秒钟传送的 bit 的个数。常用的波特率有115200(本文默认都是用这个波特率),9600,1.5M(泰山派的调试串口使用的波特率)。
- 数据位: 衡量通信中实际数据位的参数,表示一个信息包里包含的数据位的个数,常用的数据位为8bit。
- 停止位: 用于表示单个信息包的最后位,典型值为 1、1.5 和 2 位。由于数据是在传输线上传输的,每个设备都有自己的时钟,很有可能在通信过程中出现不同步,停止位不仅仅表示传输的结束,还能提供校正时钟同步的机会。停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率也越慢。
- 奇偶检验位: 用于错误检测,常见的校验方式包括奇偶校验。
- 起始位:通常是1位逻辑低电平(0),标志着数据帧的开始。
3.2 串口工作模式
串口可以工作在单工【一根数据线】、半双工【一根数据线】和全双工【两根数据线】模式下。
- 单工:在通信的任意时刻,信息只能由 A 传到 B。
- 半双工:在通信的任意时刻,信息即可由 A 传到 B,又能由 B 传到 A,但同时只能有一个方向上的传输存在。同一条数据线。
- 全双工:在通信的任意时刻,通信线路上存在 A 到 B 和 B 到 A 的双向信号传输。
3.3 通讯波形
这是一个典型的UART串行通信数据帧结构的示意图,展示了UART帧中的起始位、数据位、校验位和停止位,大家可以结合理解:
空闲状态下串口是高电平,发出低电平表示起始位,表示数据开始Start
;
接下来就是数据位了(D0-D7
),如果你设置是8bit,那么这里就会有8个位,每个位的持续时间是波特率的倒数。假设波特率为 9600 bps,那么每个位的持续时间(Bit Time)为Tbit=1/9600≈104.17us。
带*号的p
是Parity的缩写,也就是奇偶校验位的缩写,是可选的,普通的通讯中不需要使能。
最后的Stop
就是停止位了,一般都是用1位的。当传输完成后数据线又会恢复为高电平,表示这一帧传输结束,重新变为空闲状态。
总结一下:
- 发送端:先发送起始位,将TX线拉低,然后依次发送数据位,接着发送可选的奇偶校验位,最后发送停止位。
- 接收端:检测起始位的到来,然后按顺序接收数据位,校验位(如果有),并通过停止位判断传输结束。
4 开发板上可用的串口
40PIN排针引出脚:
从上图中可以看到在排针处可以使用串口1
,串口2
,串口3
,串口4
。
排针引脚号 | 芯片引脚号 | 串口功能号 | 备注 |
---|---|---|---|
03 | GPIO 49 | UART4_RXD | 同时连入摄像头2(CSI2)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V |
05 | GPIO 48 | UART4_TXD | 同时连入摄像头2(CSI2)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V |
08 | GPIO 03 | UART1_TXD | Na |
10 | GPIO 04 | UART1_RXD | Na |
11 | GPIO 05 | UART2_TXD | Na |
13 | GPIO 06 | UART2_RXD | Na |
27 | GPIO 41 | UART1_RXD | 同时连入摄像头1(CSI1)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V |
28 | GPIO 40 | UART1_TXD | 同时连入摄像头1(CSI1)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V |
29 | GPIO 36 | UART4_TXD | Na |
31 | GPIO 37 | UART4_RXD | Na |
37 | GPIO 32 | UART3_TXD | Na |
40 | GPIO 33 | UART3_RXD | Na |
三个GH1.25-4P带锁座:
【TODO】用实物图把这三个串口接口标注出来。要标出序号,1️⃣是串口2(亦可复用为iic,最重要的外接通讯接口),2️⃣是串口3(当前固件没被占用,但如果使用的是Linux+RT-Smart SDK就会被小核占用,如果用最新的CanMV固件则用户可以使用),3️⃣是串口0(被RT-Smart占用,最新的CanMV K230固件中只在大核中运行了RT-Smart)
这三个串口的物理接口都是GH1.25-4P带锁接口,具有良好的物理连接稳定性,可以确保在设备连接过程中不会因震动或意外拔出而导致连接松动或数据传输中断,该接口在拔出时必须下压上方卡扣才能顺利拔出。⚠️千万不要大力出奇迹哦,严重时会导致线材断裂甚至接口脱落。(PS:选用这个接口主要是方便打电赛和实际做项目的同学,提供稳定通讯的物理连接前提)
这三个座子的线序都是一致的,和泰山派上的串口调试口线序是一致的,线序定义如下:
序号 | 简称 | 功能 |
---|---|---|
1 | V | 5V输入输出口 |
2 | R | RXD,串口信号接收线 |
3 | T | TXD,串口信号发送线 |
4 | G | GND,接地点 |
1️⃣:GH1.25-4P带锁座:
第一个座子在两个侧按按钮中间,丝印标号为2,该接口既可以被复用为串口2(也可以被复用为IIC2,在后面的章节也会介绍,在本章只介绍它作为串口功能的实现)
丝印简称 | 芯片引脚号 | 串口功能号 | 备注 |
---|---|---|---|
V | Na | Na | 5V输入输出口 |
R | GPIO 11 | UART2_RXD | Na |
T | GPIO 12 | UART2_TXD | Na |
G | Na | Na | GND,接地点 |
2️⃣:GH1.25-4P带锁座:
第二个座子在12V电源输入(GH1.25-2P)旁边,丝印标号为3,代表本接口占用的是串口3。
丝印简称 | 芯片引脚号 | 串口功能号 | 备注 |
---|---|---|---|
V | Na | Na | 5V输入输出口 |
R | GPIO 51 | UART3_RXD | Na |
T | GPIO 50 | UART3_TXD | Na |
G | Na | Na | GND,接地点 |
3️⃣:GH1.25-4P带锁座:
第三个座子在USB HOST座子旁边,丝印标号为0,表示本接口占用的是串口0,用户无法调用,被内部系统(RT-Smart)占用为控制台串口。
丝印简称 | 芯片引脚号 | 串口功能号 | 备注 |
---|---|---|---|
V | Na | Na | 5V输入输出口 |
R | GPIO 39 | UART0_RXD | Na |
T | GPIO 38 | UART0_TXD | Na |
G | Na | Na | GND,接地点 |
⚠️注意!
串口0【第三个座子】无法在CanMV固件中被用户调用,做项目时需要注意,其被内部系统(RT-Smart)占用为finsh
控制台串口。如果想看其具体输出内容,可以借助外部USB转串口工具,连入例如MobaXterm
软件,串口参数是:115200@8N1
。
背面大触点,可焊排针处串口:
【TODO】用实物图把这三个串口接口标注出来。要标出序号,1️⃣是串口2(亦可复用为iic),2️⃣是串口3(当前固件没被占用),3️⃣是串口0(被RT-Smart占用)
这里只标注处具体串口号,其电气连接与上述的4P-GH1.25带锁座是一致的,如果使用GH1.25座子不方便,就可以直接将线焊接在这些大触点上,同时,也考虑到部分同学可能想直接使用杜邦线,这些焊盘的间距也都是2.54mm的,可以直接焊接排针。
若各位考虑给庐山派开发板做配套扩展板,需要用到这些通讯接口或电源,亦可板载pogo pin
,用螺丝固定后就可以稳定连接这些大触电焊盘,组装起来就不会有乱糟糟的线了,更优雅。在这里期待一手各位的扩展板,比如笔者就想要一个UPS电源扩展板,让庐山派能自带电池运行。
5 UART使用指南
K230 内部集成了五个 UART(通用异步收发传输器)硬件模块,串口3(当前固件没被占用,但如果使用的是Linux+RT-Smart SDK就会被小核占用,如果用最新的CanMV固件则用户可以使用);串口0(被RT-Smart占用,最新的CanMV K230固件中只在大核中运行了RT-Smart),剩下的串口1,2,3,4均可被用户正常调用。
要使用 machine.UART
,首先需要导入该模块,然后按我们之前在GPIO和FPIOA章节中所说进行GPIO的配置,这里不再赘述。先用FPIOA
的set_function
方法把对应GPIO配置为UART模式。如下所示(默认例程均以上一节 开发板上可用的串口 中1️⃣号GH1.25带锁座为举例,也就是串口2(TX:GPIO11,RX:GPIO12
)):
from machine import UART
from machine import FPIOA
fpioa = FPIOA()
# 将指定引脚配置为 UART 功能
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
2
3
4
5
6
7
8
9
5.1 构造函数
用于构造uart对象,可同时对串口进行初始化。
uart = UART(id, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
参数
id
: UART 模块编号,有效值为UART.UART1
、UART.UART2
、UART.UART3
、UART.UART4
。baudrate
: UART 波特率,可选参数,默认值为 115200。bits
: 每个字符的数据位数,有效值为UART.FIVEBITS
、UART.SIXBITS
、UART.SEVENBITS
、UART.EIGHTBITS
,可选参数,默认值为UART.EIGHTBITS
。parity
: 奇偶校验,有效值为UART.PARITY_NONE
、UART.PARITY_ODD
、UART.PARITY_EVEN
,可选参数,默认值为UART.PARITY_NONE
。stop
: 停止位数,有效值为UART.STOPBITS_ONE
、UART.STOPBITS_TWO
,可选参数,默认值为UART.STOPBITS_ONE
。
5.2 init
方法
uart.init(baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
配置 UART 参数。
参数
参考上面的构造函数。
返回值
无
5.3 read
方法
uart.read([nbytes])
读取字符。如果指定了 nbytes
,则最多读取该数量的字节;否则,将尽可能多地读取数据。
参数
nbytes
: 最多读取的字节数,可选参数。
返回值
返回一个包含读取字节的字节对象。
5.4 readline
方法
uart.readline()
读取一行数据,并以换行符结束。
参数
无
返回值
返回一个包含读取字节的字节对象。
5.5 readinto
方法
uart.readinto(buf[, nbytes])
将字节读取到 buf
中。如果指定了 nbytes
,则最多读取该数量的字节;否则,最多读取 len(buf)
数量的字节。
参数
buf
: 一个缓冲区对象。nbytes
: 最多读取的字节数,可选参数。
返回值
返回读取并存入 buf
的字节数。
5.6 write
方法
uart.write(buf)
将字节缓冲区写入 UART。
参数
buf
: 一个缓冲区对象。
返回值
返回写入的字节数。
5.7 deinit
方法
uart.deinit()
释放 UART 资源。
参数
无
返回值
无
6 用串口发送数据
在完成了前面介绍的引脚配置和UART模块初始化之后,我们就可以使用UART模块来发送数据了。下面将详细介绍如何通过串口发送数据,并展示一些代码示例。这里以上一节 开发板上可用的串口 中1️⃣号GH1.25带锁座为举例,也就是串口2(TX:GPIO11,RX:GPIO12
),也推荐大家在与外部设备通讯时首选这个串口座。
TODO:重新标识一下实物图中这个串口座子的位置
6.1 基本发送方法
要通过UART发送数据,可以使用 uart.write(buf)
方法,其中 buf
是要发送的数据,可以是字符串、字节数组或字节序列。
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
# 要发送的字符串
message = "Hello,LuShan-Pi!\n"
# 通过UART发送数据
uart.write(message)
# 释放UART资源
uart.deinit()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 引脚配置:使用
FPIOA
将 GPIO11 和 GPIO12 配置为 UART2 的 TXD 和 RXD 功能。 - 初始化UART:创建一个 UART2 实例,设置波特率为 115200,8 位数据位,无校验,1 位停止位。
- 发送数据:使用
uart.write()
方法将数据发送出去。 - 资源释放:操作完成后,使用
uart.deinit()
方法释放 UART 资源。
将USB转TTL连入电脑,把庐山派的串口2(TX:GPIO11,RX:GPIO12
)和你的串口工具连接在一起,打开电脑上的串口软件,配置为115200波特率,在庐山派上运行上面的程序就能收到Hello,LuShan-Pi!
的串口数据了。
6.2 发送字节数组
有时,我们需要和其他外部设备比如STM32进行通讯就需要发送二进制数据,比如各种传感器的原始数据。可以使用字节数组或 bytes
类型的数据。
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
# 发送字节数组
data = bytes([0x01, 0x02, 0x03, 0x04])
uart.write(data)
# 释放UART资源
uart.deinit()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
基本操作和上面类似,不过如果你还是连入串口助手进行查看数据的话,记得把串口工具的显示格式从字符串改为十六进制显示,如果连线配置等正常,你就可以在屏幕上看到01 02 03 04
这些数据了。
6.3 连续发送数据
如果需要持续发送数据,例如在循环中重复发送传感器读数,这里假设你获取到的传感器数据为42。
import time
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
# 获取传感器数据(假设为变量sensor_value)
sensor_value = 0 # 示例数据
while True:
message = "Sensor Value: {}\n".format(sensor_value)
uart.write(message)
sensor_value = sensor_value+1
time.sleep(0.1)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
运行上述程序,串口2就会打印如下数据:
Sensor Value: 0
Sensor Value: 1
Sensor Value: 2
Sensor Value: 3
Sensor Value: 4
Sensor Value: 5
Sensor Value: 6
Sensor Value: 7
Sensor Value: 8
Sensor Value: 9
Sensor Value: 10
Sensor Value: 11
Sensor Value: 12
2
3
4
5
6
7
8
9
10
11
12
13
7 用串口接收数据
接收数据是串口通信的重要部分,下面将介绍如何通过 UART 接收数据,包括基本的读取方法和数据处理。
7.1 基本接收方法
使用 uart.read(nbytes)
方法可以从 UART 接收数据,其中 nbytes
是要读取的字节数,不写参数就是读取尽量多的数据。
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
data = None
#如果接收不到数据就一直尝试读取
while data == None:
# 读取数据
data = uart.read() # 尝试读取数据
#通过CanMV IDE K230中的串行终端控制台打印出来
print("Received:", data)
#通过串口2发送接收到的数据
uart.write("UART2 Received:{}\n".format(data))
# 释放UART资源
uart.deinit()
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
首先使用FPIOA模块配置了引脚,将11号引脚设为发送端(TXD),12号引脚设为接收端(RXD)。然后,初始化UART2接口,设置波特率为115200,数据位为8位,无校验,停止位为1位。
在数据接收部分,代码使用循环不断读取数据,uart.read()
是一个读取函数,尝试从UART接收数据。如果没有数据,这个函数会返回 None
或者空字节串 b''
。直到接收到非空数据为止,并通过串行控制台输出接收到的数据,同时将数据从串口2的发送口发回去。
最后,调用deinit
释放UART资源,确保系统资源不被占用。
接好线开始运行程序,打开电脑上的串口助手,发送数据到庐山派开发板,比如我这里向庐山派发送的数据是
3465345612yzh
,那么我电脑的串口助手和CanMV IDE的串行终端就会打印这句话Received: b'3465345612yzh'
,代表开发板正常收到了数据。同时,串口助手软件也会收到这个信息:UART2 Received:b'3465345612yzh'
7.2 使用 readline
方法
TODO :有问题,读取一行没办法正常运行,需要再测试一下
如果接收的数据是以换行符结尾的文本,可以使用 uart.readline()
方法读取一整行数据。
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
line = b''
#如果接收不到数据就一直尝试读取
while line == b'':
# 读取数据
line = uart.read() # 尝试读取数据
#通过CanMV IDE K230中的串行终端控制台打印出来
print("Received:", line)
#通过串口2发送接收到的数据
uart.write("UART2 Received:{}\n".format(line))
# 释放UART资源
uart.deinit()
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
7.3 使用 readinto
方法
TODO :有问题,第一次运行时会默认接收一个0, bytearray(b'\x00')
在有些情况下,为了提高读取效率,可以创建一个固定大小的缓冲区来存储接收的数据。readinto
方法允许将数据直接写入指定的缓冲区,这在需要较高效的数据处理时很高效。
以下代码示例演示了如何使用 readinto
方法读取数据:
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
# 创建一个空的缓冲区,大小为10字节(根据需要调整大小)
buffer = bytearray(10)
# 进入循环,如果接收不到数据就一直尝试读取
bytes_received = 0 # 记录实际读取到的字节数
while bytes_received == 0:
# 使用readinto将数据读取到缓冲区
bytes_received = uart.readinto(buffer)
#通过CanMV IDE K230中的串行终端控制台打印出来
print("Received:", buffer[:bytes_received]) # 仅打印接收到的字节数内容
# 将接收到的数据通过串口2发送回去
uart.write("UART2 Received:{}\n".format(buffer[:bytes_received].decode()))
# 释放UART资源
uart.deinit()
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
开头就是引脚配置和串口初始化了,这里不再赘述。
- 使用
bytearray(10)
创建一个大小为 10 字节的缓冲区buffer
,以存储接收的数据。可以根据实际需求调整缓冲区的大小。 - 进入
while
循环,如果接收不到数据则持续尝试读取。readinto(buffer)
会将接收到的字节数存入bytes_received
,如果接收到的数据大于 0,则跳出循环并处理数据。 - 之后再IDE的终端和串口2中都打印一下收到的数据,并添加前缀标识,方便用户测试。
7.4 连续接收数据
在实际应用中,可能需要持续监听串口数据,可以使用循环来实现。
import time
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
data = b''
while True:
data = uart.read()
if data:
#通过CanMV IDE K230中的串行终端控制台打印出来
print("Received:", data)
#通过串口2发送接收到的数据
uart.write("UART2 Received:{}\n".format(data))
time.sleep(0.1) # 延时避免占用过多CPU资源
# 释放UART资源
uart.deinit()
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
开头就是引脚配置和串口初始化了,这里不再赘述。
接下来进入一个无限循环:
在每次循环中调用
uart.read()
尝试从串口读取数据。uart.read()
会返回一个字节串,如果没有数据则返回None
或空字节串b''
。为了避免空输出,使用if data:
进行判断,确保只有在接收到有效数据时才执行后续操作。如果接收到的数据有效,将其打印到 CanMV IDE 的 K230 串行终端。
使用
uart.write()
将接收到的数据原样回传,并在其前加上前缀"UART2 Received:"
以确认回传的数据。
延时time.sleep(0.1)
是为了防止连续读取操作占用过多的 CPU 资源。
如果通过串口助手向开发板发送 "Hello, UART!"
,串行终端会显示:
Received: b'Hello, UART!'
串口助手会收到回传信息:
UART2 Received:b'Hello, UART!'
这就表明数据接收和回传功能正常。
8 进行串口回环测试
串口回环测试是验证串口发送和接收功能的有效方法。通过将 UART 的发送端(TXD)和接收端(RXD)连接在一起,可以实现自发自收,检测 UART 模块的工作情况。
8.1 硬件连接
将 UART 的 TXD 和 RXD 引脚直接相连,在开发板上,用杜邦线或跳线将对应的 TXD 和 RXD 引脚连接起来。
对于我们现在使用的串口2(GPIO12 和 GPIO11),将 GPIO12(TXD)和 GPIO11(RXD)连接在一起,可以使用一个双头等长插针将GH1.25转杜邦线连接再一起。
注意
在进行回环测试时,确保没有其他设备连接到 UART 引脚上,以避免信号冲突。
8.2 回环测试代码
下面的代码将在 UART 上发送数据,并尝试立即读取,如果接收的数据与发送的数据一致,则说明 UART 工作正常。
import time
from machine import UART
from machine import FPIOA
# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
# 要测试的消息
test_message = b'UART Loopback Test!'
# 发送数据
uart.write(test_message)
# 等待数据发送和接收(根据波特率和数据长度,调整延时)
time.sleep(0.1)
# 如果接收不到数据就一直尝试读取
received_data = b''
received_data = uart.read()
if received_data:
received_message = received_data
print("Received:", received_message)
if received_message == test_message:
print("Loopback Test Passed!")
else:
print("Loopback Test Failed: Data Mismatch")
else:
print("Loopback Test Failed: No Data Received")
print("test_message is {}".format(test_message))
print("received_message is {}".format(received_message))
# 释放UART资源
uart.deinit()
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
31
32
33
34
35
36
37
38
39
40
41
前面初始化部分不再赘述,下面的代码总的来说就是发送一条测试消息并等待回传,然后对比接收数据与发送数据是否一致,以验证串口的回环通信功能是否正常。最后输出测试结果并释放 UART 资源。
发送测试消息:初始化完成后,代码首先通过
uart.write()
发送了一条固定的消息——'UART Loopback Test!'
。等待数据传输完成:因为UART是串行通信,每次只能发送一个比特,所以发送和接收需要时间,尤其是波特率较低时。因此,代码使用了
time.sleep(0.1)
来稍作等待,确保数据已经完全传输完毕。读取接收到的数据:
uart.read()
用于读取串口接收到的数据,如果有数据收到,程序会对比接收到的数据和发送的数据是否一致。如果一致,则表示回环测试成功;否则,说明数据有丢失或错误。此外,如果没有收到任何数据,就会提示接收失败。结果输出:代码通过
print()
打印结果,表明是否测试通过,以及发送和接收的数据各是什么,以便用户查看对比结果。
如果以上操作正常,会在CanMV K230 IDE的串行终端中打印结果:
如果发送的数据与接收的数据一致,打印“Loopback Test Passed!”,说明硬件UART功能正常,回环测试通过。
如果接收不到数据或者数据不一致,会打印失败信息,说明可能存在硬件连接或配置上的问题。
进阶应用
TODO:等待后续更新。
参考资料: