首页 > Python资料 博客日记
[MaixCam]使用心得二:UART串口通信
2024-08-22 09:00:07Python资料围观106次
前言
"MaixCam"系列文章主要介绍一下本人在暑假期间使用该摄像头模组的心得。该摄像头模组相较于传统的K210、OpenMV有着很明显的优点:更清晰的LCD屏幕、更强大的支持yolo5的算力、更高清的摄像头。
我认为如果你电赛选择摄像头模组,想要低学习成本实现电赛题目的基本要求,不想使用树莓派、OpenCV等工具,强烈建议使用MaixCam来替代OpenMV或K210,MaixCam的封装的函数大部分与前两者相同,可以对网上OpenMV和K210的资源轻松进行移植,并且实现效果更好。
本文只介绍简单的串口通信方式,即传输数据只使用针头帧尾和数据长度,如果你想要适用性更广的方法,即帧头、数据长度、校检和,可以阅读这位博主的文章,讲的十分详细:欠羽-CSDN博客https://blog.csdn.net/adas323?type=blog 最后,如果你想要实现快速配置,直接跳转到总结部分即可。
串口配置
from maix import uart
devices = uart.list_devices()
serial = uart.UART(devices[0], 115200)
该串口使用的是A16(TX)和A17(RX)引脚,即使用官方附赠的Type-C 转接小板上面的串口引脚。当然你也可以自己注册想要使用的引脚,这里使用A19(TX)和A18(RX)举例:
from maix import uart, pinmap
pinmap.set_pin_function("A18", "UART1_RX")
pinmap.set_pin_function("A19", "UART1_TX")
device = "/dev/ttyS1"
serial1 = uart.UART(device, 115200)
这里简要介绍一下uart.UART这个函数:
serial = uart.UART(
#端口名称
port: str = '',
#传输的波特率
baudrate: int = 115200,
#数据位
databits: BITS = ...,
#校验位
parity: PARITY = ...,
#停止位
stopbits: STOP = ...,
#流量控制
flow_ctrl: FLOW_CTRL = ...
)
#通常来说做以下配置 波特率115200 数据位8 校验位NONE 停止位1
serial = uart.UART(
devices[0],
115200,
uart.BITS.BITS_8,
uart.PARITY.PARITY_NONE,
uart.STOP.STOP_1
)
定时器配置
由于MaixCam的api文档目前还没有Timer相关的定义,即官方还没有移植K210中的Timer函数,所以我只能简易的制作一个定时器,用于每隔一段时间对数据进行接收和发送。
在这里我创建了一个定时器类,用于不同定时器的计时。其中count_flag为定时器完成计时的标志,每当count_flag == 1,我们将执行一次需要定时的程序。
class Timer():
#定时器类
def __init__(self) -> None:
#计时数
self.count = 0
#计时数上限
self.count_max = 0
#计时完成标识
self.count_flag = 0
timer0 = Timer()
timer0.count_max = 100000
之后创建一个开始计时函数,用于启动定时器和记录定时器是否完成计时。
def TimerStart(Timer):
if Timer.count < Timer.count_max:
#计时开始,计时器标识位置0
Timer.count_flag = 0
Timer.count += 1
else:
#计时完成,计时器标识位置1
Timer.count_flag = 1
Timer.count = 0
while True:
#使用定时器
TimerStart(timer0)
if timer0.count_flag == 1:
#需要执行的函数
pass
串口发送
这里我创建了一个发送测试数据类,你可以根据发送数据的需要,自己定义需要的类。在该类中有一个"发送标识位",用来判断数据发送的方式,该变量将在后面的函数中使用。
#发送测试数据类
class TTest():
def __init__(self) -> None:
#发送标识位
self.Tflag = 0
#发送数据内容
self.test_number0 = 0
self.test_number1 = 0
self.test_number2 = 0
TTest0 = TTest()
TTest0.Tflag = 1
TTest0.test_number0 = 0
TTest0.test_number1 = 1
TTest0.test_number2 = 2
之后我创建了一个用于发送数据的函数,叫"串口发送函数",调用该函数即可直接发送打包好的数据。其中输入的参数为帧头(head),帧尾(tail),想要发送的数据(TData),本文中为TTest0,发送数据的串口(serial),本文中为serial。
#串口发送函数
def DataTransimit(head, tail, TData, serial):
data = ()
if TData.Tflag == 1:
data = bytes([
head,
TData.test_number0,
TData.test_number1,
TData.test_number2,
tail
])
elif TData.Tflag == 2:
data = bytes([
head,
#想要发送的数据
tail
])
if data != ():
#发送数据
serial.write(data)
这里简单解释一下write函数,即UART.write函数,它发送的类型为字节类型,如果你想要发送字符串类型,可以使用write_str函数。或者使用str.encode()函数,将字符型转换为字节型后,再使用write函数。
我们在主函数中调用串口发送函数,就可以实现对数据的发送了。
while True:
TimerStart(timer0)
if timer0.count_flag == 1:
DataTransimit(0xAA, 0xBB, TTest0, serial)
如图所示,这样数据就带着帧头和帧尾发送出去了。
串口接收
串口接收相较于串口发送复杂一些,但是由于我们只使用帧头帧尾,在解析数据的时候逻辑简单,适用于一些低频率数据的接收。
这里我创建了一个接收测试数据类,你可以根据接收数据的需要,自己定义需要的类。在该类中有一个"接收标识位",用来判断数据接收的方式,该变量将在后面的函数中使用。
#接收测试数据类
class RTest():
def __init__(self) -> None:
#接收标识位
self.Rflag = 0
#发送数据标识位 用于测试是否接收到数据
self.Tflag = 0
#接收数据内容
self.test_number0 = 0
self.test_number1 = 0
self.test_number2 = 0
RTest0 = RTest()
RTest0.Rflag = 1
RTest0.Tflag = 1
之后我创建了一个用于接收数据的函数,叫"串口接收函数",调用该函数可返回缓存数据(BufData),用于后续对函数进行解析。其中输入的参数为帧头(head),帧尾(tail),想要接收的数据长度(length),本文中为5,即帧头、三个测试数字、帧尾,接收数据的串口(serial),本文中为serial。
#串口接收函数
def ReceiveData(head, tail, length, serial):
BufData = serial.read(40)
if BufData and len(BufData) >= length:
if BufData[0] == head and BufData[length-1] == tail:
return BufData
else:
return None
这里对read函数进行一下解释,即UART.read,该函数调用后返回的是字节或者字符类型,其中read(40)表示最大接收的字节数量,如果你单次发送超过40个字节的数据,这个程序就会报错,如果不想出现这种情况,可以不填写最大接收字节,即read(),它会一直读取缓存区的数据。
最后使用接收数据解析函数,对数据进行解析,这样RTest0中的数据就改变了。
#接收数据解析函数
def ParseData(RData, BufData):
if BufData != None:
if RData.Rflag == 1:
RData.test_number0 = BufData[1]
RData.test_number1 = BufData[2]
RData.test_number2 = BufData[3]
elif RData.Rflag == 2:
#接收数据内容
pass
我们来测试一下效果,接收完数据后再发送出去。
while True:
TimerStart(timer0)
if timer0.count_flag == 1:
ParseData(RTest0, ReceiveData(0xAA, 0xBB, 5, serial))
DataTransimit(0xCC, 0xDD, RTest0, serial)
如图所示,接受前发送的三个测试数据为0,接收后数据改变了,证明接收成功了。
总结
这一期我们使用MaixCam中的write和read函数,实现了数据的接收和发送,如果你想要快速实现配置,复制一下代码,稍作更改即可。
from maix import time, uart, pinmap
devices = uart.list_devices()
serial = uart.UART(devices[0], 115200, uart.BITS.BITS_8, uart.PARITY.PARITY_NONE, uart.STOP.STOP_1)
#发送测试数据类
class TTest():
def __init__(self) -> None:
#发送标识位
self.Tflag = 0
#发送数据内容
self.test_number0 = 0
self.test_number1 = 0
self.test_number2 = 0
TTest0 = TTest()
TTest0.Tflag = 1
TTest0.test_number0 = 0
TTest0.test_number1 = 1
TTest0.test_number2 = 2
#串口发送函数
def DataTransimit(head, tail, TData, serial):
data = ()
if TData.Tflag == 1:
data = bytes([
head,
TData.test_number0,
TData.test_number1,
TData.test_number2,
tail
])
elif TData.Tflag == 2:
data = bytes([
head,
#想要发送的数据
tail
])
if data != ():
#发送数据
serial.write(data)
#接受测试数据类
class RTest():
def __init__(self) -> None:
#接收标识位
self.Rflag = 0
#发送数据标识位
self.Tflag = 0
#接收数据内容
self.test_number0 = 0
self.test_number1 = 0
self.test_number2 = 0
RTest0 = RTest()
RTest0.Rflag = 1
RTest0.Tflag = 1
#串口接受函数
def ReceiveData(head, tail, length, serial):
BufData = serial.read(40)
if BufData and len(BufData) >= length:
if BufData[0] == head and BufData[length-1] == tail:
return BufData
else:
return None
#接收数据解析函数
def ParseData(RData, BufData):
if BufData != None:
if RData.Rflag == 1:
RData.test_number0 = BufData[1]
RData.test_number1 = BufData[2]
RData.test_number2 = BufData[3]
elif RData.Rflag == 2:
#接收数据内容
pass
class Timer():
#定时器类
def __init__(self) -> None:
#计时数
self.count = 0
#计时数上限
self.count_max = 0
#计时完成标识
self.count_flag = 0
timer0 = Timer()
timer0.count_max = 100000
def TimerStart(Timer):
if Timer.count < Timer.count_max:
#计时开始,计时器标识位置0
Timer.count_flag = 0
Timer.count += 1
else:
#计时完成,计时器标识位置1
Timer.count_flag = 1
Timer.count = 0
while True:
TimerStart(timer0)
if timer0.count_flag == 1:
ParseData(RTest0, ReceiveData(0xAA, 0xBB, 5, serial))
DataTransimit(0xCC, 0xDD, RTest0, serial)
标签:
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj