【无标题】树莓派 4B 多串口配置

0. 实验准备以及原理
0.1 实验准备
安装树莓派官方系统的树莓派 4B,有 python 环境,安装了 serial 库
杜邦线若干
屏幕或者可以使用 VNC 进入到树莓派的图形界面

0.2 原理
树莓派 4B 有 UART0(PL011)、UART1(mini UART)和 4 个 PL011 串口共计有 6 个 UART

1. 硬件串口配置
可以将硬件串口(例如 /dev/ttyAMA0)配置为普通的串口设备,以便与其他设备进行串口通信

确保树莓派的引脚上的串口功能没有被占用。默认情况下,树莓派的 GPIO 引脚会使用串口功能。可以通过编辑 /boot/config.txt 文件来禁用串口功能。在文件的末尾添加或修改以下行,保存文件后重启树莓派(可以使用vi来编辑此文件,vi 的使用可以查看这一篇文章):

enable_uart=1
 

enable_uart=1

在终端中运行以下命令可以确认驱动是否已经加载:

ls -l /dev/ttyAMA0
1
能看到下面的输出就代表驱动是正常的

默认情况下,树莓派会将 /dev/ttyAMA0 用作终端串口,而不是普通的串口设备。可以通过编辑 /boot/cmdline.txt 文件来禁用终端串口。找到以 console=serial0 开头的行,并将其修改为 console=tty1,如下图所示


确保你的用户被添加到 dialout 组中,以便具有串口访问权限。运行以下命令将当前用户添加到 dialout 组:

sudo usermod -a -G dialout $USER
1
在添加到 dialout 组后,需要注销并重新登录才能使更改生效,到这里硬件串口就配置完成了,不需要看其他的可以直接跳到最后一节进行验证

2. 其他串口配置
2.1 展示所有串口命令
输出下面的命令可以看到所有的串口

dtoverlay -a | grep uart
1


2.2 查看特定串口信息
使用下面的命令会展示串口的配置信息

dtoverlay -h uart3
1


2.3 配置开启串口 UART2-5
在/boot/config.txt的末尾添加如下的代码,保存重启树莓派

dtoverlay=uart2
dtoverlay=uart3
dtoverlay=uart4
dtoverlay=uart5

查看是否生效

ls /dev/ttyAMA*
1
结果如下图

到这里就打开了所有的串口了

3. 验证结果
各 UART 串口与 GPIO 对应关系:

GPIO14 = TXD0 -> ttyAMA0
GPIO0  = TXD2 -> ttyAMA1
GPIO4  = TXD3 -> ttyAMA2
GPIO8  = TXD4 -> ttyAMA3
GPIO12 = TXD5 -> ttyAMA4

GPIO15 = RXD0 -> ttyAMA0
GPIO1  = RXD2 -> ttyAMA1
GPIO5  = RXD3 -> ttyAMA2
GPIO9  = RXD4 -> ttyAMA3
GPIO13 = RXD5 -> ttyAMA4
 

GPIO14 = TXD0 -> ttyAMA0
GPIO0  = TXD2 -> ttyAMA1
GPIO4  = TXD3 -> ttyAMA2
GPIO8  = TXD4 -> ttyAMA3
GPIO12 = TXD5 -> ttyAMA4

GPIO15 = RXD0 -> ttyAMA0
GPIO1  = RXD2 -> ttyAMA1
GPIO5  = RXD3 -> ttyAMA2
GPIO9  = RXD4 -> ttyAMA3
GPIO13 = RXD5 -> ttyAMA4

这里进行两个验证:UART2的自环测试,UART2和3的串口间通信,以及一个究极测试:同时打开所有的串口(包括USB转的,看看树莓派的CPU使用率有多少)

3.1 UART2的自环测试
杜邦线短接 GPIO4 和 GPIO5
编写下面的 python 程序

import serial

ser1 = serial.Serial(port='/dev/ttyAMA2',baudrate=115200)
ser1.write(b'Hello, World!\n')

data = ser1.readline()
print(data)


执行结果如下图


3.2 UART2和3的串口间通信
使用杜邦线按照下图的方式进行连接

GPIO4(TXD3)-------GPIO9(RXD2)
GPIO5(RXD3)-------GPIO8(TXD2)
1
2
然后编写如下的程序

import serial

ser2 = serial.Serial(port='/dev/ttyAMA2',baudrate=115200)
ser3 = serial.Serial(port='/dev/ttyAMA3',baudrate=115200)

ser2.write(b'hello ser3,I am ser2\n')
ser3.write(b'hello ser2,I am ser3\n')
line2 = ser2.readline()
line3 = ser3.readline()
print('ser2Rec:'+str(line2))
print('ser3Rec:'+str(line3))


结果如下图,说明串口生效,实验成功:


3.3 究极测试
同时打开 USB0、USB1 和 ttyAMA0 到 ttyAMA4 一共 7 个串口,发送数据的同时存储数据,查看一下 CPU 的使用率
我的配置为:
USB0、1 使用 UART 转 TTL 模块,使用电脑发送数据过来
ttyAMA0 作为硬件串口,然后改为的通用串口,也使用 UART 转 TTL 模块,电脑发送数据过来
ttyAMA1 和 ttyAMA4 连接
ttyAMA2 和 ttyAMA3 连接
对应的连接图可以参考上面的GPIO对照着连线
代码如下

import serial
import time
import threading
import sys
READ = 1
READTIME = 600

ser0 = serial.Serial(port='/dev/ttyAMA0',baudrate=115200)
ser1 = serial.Serial(port='/dev/ttyAMA1',baudrate=115200)
ser2 = serial.Serial(port='/dev/ttyAMA2',baudrate=115200)
ser3 = serial.Serial(port='/dev/ttyAMA3',baudrate=115200)
ser4 = serial.Serial(port='/dev/ttyAMA4',baudrate=115200)
serUSB0 = serial.Serial(port='/dev/ttyUSB0',baudrate=115200)
serUSB1 = serial.Serial(port='/dev/ttyUSB1',baudrate=115200)

def WriteSer1():
    global READ
    while(READ):
        ser1.write(b'I am ser1')
        
def WriteSer2():
    global READ
    while(READ):
        ser2.write(b'I am ser2')
        
def WriteSer3():
    global READ
    while(READ):
        ser3.write(b'I am ser3')
        
def WriteSer4():
    global READ
    while(READ):
        ser4.write(b'I am ser4')
        
def ReadSer0():
    ser0.write(bytearray([0xaa,0x0a]))
    global READ
    data0 = b''
    while(READ):
        if(ser0.in_waiting):
            data0 +=  ser0.read(ser0.in_waiting)
    f = open('ser0.bin','ab')
    f.write(data0)
    f.close()
    
def ReadSer1():
    global READ
    data1 = b''
    while(READ):
        if(ser1.in_waiting):
            data1 +=  ser1.read(ser1.in_waiting)
    f = open('ser1.bin','ab')
    f.write(data1)
    f.close()
    
def ReadSer2():
    global READ
    data2 = b''
    while(READ):
        if(ser2.in_waiting):
            data2 +=  ser2.read(ser2.in_waiting)
    f = open('ser2.bin','ab')
    f.write(data2)
    f.close()

def ReadSer3():
    global READ
    data3 = b''
    while(READ):
        if(ser3.in_waiting):
            data3 +=  ser3.read(ser3.in_waiting)
    f = open('ser3.bin','ab')
    f.write(data3)
    f.close()
    
def ReadSer4():
    global READ
    data4 = b''
    while(READ):
        if(ser4.in_waiting):
            data4 +=  ser4.read(ser4.in_waiting)
    f = open('ser4.bin','ab')
    f.write(data4)
    f.close()
    
def ReadSerUSB0():
    global READ
    dataUSB0 = b''
    while(READ):
        if(serUSB0.in_waiting):
            dataUSB0 +=  serUSB0.read(serUSB0.in_waiting)
    f = open('serUSB0.bin','ab')
    f.write(dataUSB0)
    f.close()
    
def ReadSerUSB1():
    global READ
    dataUSB1 = b''
    while(READ):
        if(serUSB1.in_waiting):
            dataUSB1 +=  serUSB1.read(serUSB1.in_waiting)
    f = open('serUSB1.bin','ab')
    f.write(dataUSB1)
    f.close()
#%%
def start():
    global READ
    timeStart = time.time()
    
    ser1Write_thread = threading.Thread(target=WriteSer1)
    ser2Write_thread = threading.Thread(target=WriteSer2)
    ser3Write_thread = threading.Thread(target=WriteSer3)
    ser4Write_thread = threading.Thread(target=WriteSer4)
    
    ser0_thread = threading.Thread(target=ReadSer0)
    ser1_thread = threading.Thread(target=ReadSer1)
    ser2_thread = threading.Thread(target=ReadSer2)
    ser3_thread = threading.Thread(target=ReadSer3)
    ser4_thread = threading.Thread(target=ReadSer4)
    serUSB0_thread = threading.Thread(target=ReadSerUSB0)
    serUSB1_thread = threading.Thread(target=ReadSerUSB1)
    
    ser1Write_thread.start()
    ser2Write_thread.start()
    ser3Write_thread.start()
    ser4Write_thread.start()
    
    ser0_thread.start()
    ser1_thread.start()
    ser2_thread.start()
    ser3_thread.start()
    ser4_thread.start()
    serUSB0_thread.start()
    serUSB1_thread.start()
    
    time.sleep(READTIME)

    READ = False

    print('test time'+str(time.time()-timeStart))
    sys.exit()
    
if __name__ == '__main__':
    start()


    



使用命令,来查看当前CPU的使用率

htop

htop


可以发现即使跑了这么多的串口,树莓派的 CPU 使用率依旧不算很高,4 核差不多都在 40% 的利用率左右

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/239128.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8改进实验:一文了解YOLOv8如何打印FPS指标

💡该教程为改进YOLOv8指南,属于《芒果书》📚系列,包含大量的原创首发改进方式🚀 💡🚀🚀🚀本博客内含改进源代码,按步骤操作运行改进后的代码即可 💡更方便的统计更多实验数据,方便写作 新增YOLOv8打印FPS指标 完善(一键YOLOv8打印FPS指标) 文章目录 完善…

MySQL - 事务隔离级别

MySQL 事务 本文所说的 MySQL 事务都是指在 InnoDB 引擎下,MyISAM 引擎是不支持事务的。 数据库事务指的是一组数据操作,事务内的操作要么就是全部成功,要么就是全部失败 事务具有原子性(Atomicity)、一致性&#xff0…

软件压力测试的重要性与用途

在当今数字化的时代,软件已经成为几乎所有行业不可或缺的一部分。随着软件应用规模的增加和用户数量的上升,软件的性能变得尤为关键。为了确保软件在面对高并发和大负载时仍然能够保持稳定性和可靠性,软件压力测试变得至关重要。下面是软件压…

vue2-elementUI部分组件样式修改

el-radio样式: /deep/ .el-radio__input .el-radio__inner {width: 20px;height: 20px;position: relative;cursor: pointer;-webkit-appearance: none;-moz-appearance: none;appearance: none;border: 1px solid #999;border-radius: 0;outline: none;transition…

LeetCode刷题--- 二叉树剪枝

个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏:http://t.csdnimg.cn/ZxuNL http://t.csdnimg.cn/c9twt 前言:这个专栏主要讲述递归递归、搜索与回溯算法,所以下面题目主要也是这些算法做的 我讲述…

渗透测试是什么

随着信息技术的飞速发展,网络安全问题日益凸显。其中,渗透测试作为一种重要的安全评估方法,已经被越来越多的企业和组织所采用。渗透测试通过模拟黑客攻击,发现并修复潜在的安全漏洞,从而提高系统的安全性。 直白的说…

题目:肖恩的苹果林(蓝桥OJ 3683)

题目描述&#xff1a; 解题思路&#xff1a; 本题采用二分中的二分答案。枚举每一个最大距离&#xff08;i&#xff1a;1 ~ n&#xff09;以及他们至少能容纳的树木数&#xff08;上一题&#xff1a;跳石头-蓝桥OJ 364&#xff09; 判断二分内判断条件是>还是<以及是lmi…

满载re:Invent 2023全新发布惊喜,亚马逊云科技下一站GenAI@巡演来啦

无限构建&#xff0c;成为生成式AI原生开发者前沿生成式AI技术之旅正式启程&#xff0c;穿越多个中国的城市&#xff0c;开发者一站式体验&#xff0c;满载re:Invent 2023全新发布惊喜。 LET’S Demo 「构」硬核 生成式AI时代的开发新范式 Amazon Q 全新的企业级生成式AI助手…

CNN、LeNet、AlexNet基于MNIST数据集进行训练和测试,并可视化对比结果

完成内容&#xff1a; 构建CNN并基于MNIST数据集进行训练和测试构建LeNet并基于MNIST数据集进行训练和测试构建AlexNet并基于MNIST数据集进行训练和测试对比了不同网络在MNIST数据集上训练的效果 准备工作 import torch import torch.nn as nn import torch.optim as optim …

【Canvas】记录一次从0到1绘制风场空间分布图的过程

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热衷分享有趣实用的文章&#xff0c;希望大家多多支持&#xff0c;一起进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 背景 前置知识 风场数据 绘制风场 准备工作 生成二维网格 获取…

vxe-table 右键菜单+权限控制(v3)

1.menu-config 是用于配置右键菜单的属性。通过 menu-config 属性&#xff0c;定义右键菜单的内容、显示方式和样式。 通过 menu-config 属性配置了右键菜单&#xff0c;其中的 options 属性定义了右键菜单的选项。用户在表格中右键点击时&#xff0c;将会弹出包含这些选项的自…

md笔记使用加自动备份整理

1、安装使用 TyporaGiteePicGo搭建图床&#xff08;解决使用Typora写的笔记上传csdn图片无法正常显示问题&#xff09; 2、修改主题 文件-》偏好设置-》外观-》打开主题文件夹 将css文件放到里面然后重启typora&#xff08;css文件可以参考参考链接&#xff09; 3、设置自动备份…

数据结构二维数组计算题,以行为主?以列为主?

1.假设以行序为主序存储二维数组Aarray[1..100,1..100]&#xff0c;设每个数据元素占2个存储单元&#xff0c;基地址为10&#xff0c;则LOC[5,5]&#xff08; &#xff09;。 A&#xff0e;808 B&#xff0e;818 C&#xff0e;1010 D&…

包装效果图渲染技巧:怎么用云渲染省钱、省时间

在今天这个市场竞争白热化的时代&#xff0c;一个产品的包装设计往往决定了它在架上是否能够脱颖而出。因此&#xff0c;品牌在推向市场前精心设计的包装效果图显得尤为重要。在这里&#xff0c;我们将探究包装效果图渲染的关键性、渲染技巧及云渲染技术如何在提升渲染品质与降…

Matlab 点云收缩L1中值(Weiszfeld算法)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 对于之前的加权均值收缩方式,它存在一个很大的缺点,即容易受到噪声的影响,因此这里我们采用另一种统计学方案:L1中值。其形式如下所示: 其中 x i x_i

DICOM 文件中,VR,VL,Sequence,图像二进制的几个注意点

DICOM 文件中&#xff0c;VR&#xff0c;VL&#xff0c;Sequence&#xff0c;图像二进制的几个注意点 1. 传输语法 DICOM 文件的结构&#xff0c;在网上有很多的学习资料&#xff0c;这里只介绍些容易混淆的概念&#xff0c;作为回看笔记。 每个传输语法&#xff0c;起都是表…

openGauss学习笔记-154 openGauss 数据库运维-备份与恢复-闪回恢复

文章目录 openGauss学习笔记-154 openGauss 数据库运维-备份与恢复-闪回恢复154.1 闪回查询154.1.1 背景信息154.1.2 前提条件154.1.3 语法154.1.4 参数说明154.1.5 使用示例 154.2 闪回表154.2.1 背景信息154.2.2 前提条件154.2.3 语法154.2.4 使用示例 154.3 闪回DROP/TRUNCA…

【清晰明了】Jenkins邮件发送配置

自带邮件插件 首先要知道的是jenkins是自带邮件插件的&#xff0c;且不支持卸载。 下面开始配置自带邮件插件。 配置默认邮件管理员 系统管理 --> 系统配置&#xff0c;进行如下配置&#xff1a; 不配置管理员邮件地址报错如下 jakarta.mail.internet.AddressException:…

网络编程----select 模型总结

为什么要使用select模型&#xff1f; 答&#xff1a;解决基本C/S模型中&#xff0c;accept()、recv()、send()阻塞的问题 select模型与C/S模型的不同点 C/S模型中accept()会阻塞一直傻等socket来链接select模型只解决accept()傻等的问题&#xff0c;不解决recv(),send()执行…

大厂大数据面试题收录(1)

目录 1.java 中 object 类有哪些方法? 2.说一下和equals的区别&#xff1f; 3.为什么要重写 equals 和 hashcode()方法&#xff1f; 4.机器学习中&#xff0c;监督学习 和 无监督学习的区别是啥&#xff1f;&#xff1f; 5.kafka 组件熟悉吗,kafka 如何实现消息的有序的&a…