树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。

从树莓派的相关资料我们可以看到,树莓派有两个串口可以使用,一个是硬件串口(/dev/ttyAMA0),另一个是mini串口(/dev/ttyS0)。硬件串口有单独的波特率时钟源,性能好,稳定性强;mini串口功能简单,稳定性较差,波特率由CPU内核时钟提供,受内核时钟影响。 树莓派(3/4代)板载蓝牙模块,默认的硬件串口是分配给蓝牙模块使用的,而性能较差的mini串口是分配给GPIO串口 TXD0、RXD0。
因为树莓派初始时默认把性能较差的mini串口分配给GPIO上的TX、RX。我们要使用性能好的串口就需要把两者交换过来。以下是交换的步骤:

  • 1.运行命令,查看串口分配情况
ls /dev -al

树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
文章图片

  • 2.由于硬件串口分配给板载蓝牙使用,所以要释放掉,并设置硬件串口分配给GPIO串口。
    首先登陆终端后,输入sudo raspi-config命令进入树莓派系统配置界面,选择第五个Interfacing Options:
    树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
    文章图片

    树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
    文章图片
  • 3.选择关闭串口登录功能,打开硬件串口调试功能:树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
    文章图片

    树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
    文章图片

    树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
    文章图片
    1. 设置硬件串口为GPIO串口
      接着将串口配置为我们的GPIO串口,对输入命令
sudo vim /boot/config.txt

  • 5.将下面两行代码添加到最后:
dtoverlay=miniuart-bt force_turbo=1

树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
文章图片

  • 6.树莓派重启,再次输出:
ls /dev -al

可以看到;两个串口互换了位置:
树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。
文章图片

  • 7 禁用串口的控制台功能
    前面步骤已经交换了硬件串口与mini串口的映射关系,但是,现在还不能使用树莓派串口模块与电脑进行通信,因为,树莓派gpio口引出串口默认是用来做控制台使用的,即是为了用串口控制树莓派,而不是通信。所以我们要禁用此默认设置。
首先执行命令如下:
sudo systemctl stop serial-getty@ttyAMA0.service sudo systemctl disable serial-getty@ttyAMA0.service

然后执行命令:
sudo nano /boot/cmdline.txt 并删除语句console=serial0,115200(没有的话就不需要此步骤)

删除语句:(没有的话就不需要此步骤)
console=serial0,115200

  • 8 测试与验证串口通讯功能
    这里使用三种方式进行测试验证, c语言下使用wiringPi库, python语言下使用serial包,最后命令行使用minicom工具。
先安装以上开发工具:
sudo apt-get install wiringpi sudo apt-get install python-serial sudo apt-get install minicom

将usb转ttl模块引脚的GND、TX、RX分别与树莓派的GND、RX、TX连接;电脑端启用串口调试助手,波特率设置一致。
Python语言实现:
# -*- coding: utf-8 -* import serial import timeser = serial.Serial("/dev/ttyAMA0",115200)if not ser.isOpen(): print("open failed") else: print("open success: ") print(ser)try: while True: count = ser.inWaiting() if count > 0: recv = ser.read(count) print("recv: " + recv) ser.write(recv) sleep(0.05) except KeyboardInterrupt: if ser != None: ser.close()

C语言实现:
#include .h> #include #include int main() { int fd; if(wiringPiSetup()<0) { return 1; }//if((fd=serialOpen("/dev/ttyS0",115200))<0) { // gpio 使用mini串口 if((fd=serialOpen("/dev/ttyAMA0",115200))<0) { // gpio 使用硬件串口 return 1; } printf("serial test output ...\n"); serialPrintf(fd,"1234567890abcdef"); serialClose(fd); return 0; }

【树莓派|树莓派4B的串口使用,并通过串口与其他设备经过通讯协议发送、接收数据。】树莓派上用Python写的串口发送(16进制)、接收数据(16进制),把16进制的数组转成数组,然后提取出来,在转换成16进制,在转换成10进制。
import RPi.GPIO as GPIO import serial import time import binasciiGPIO.setmode(GPIO.BCM)s = serial.Serial("/dev/ttyAMA0",9600)send_data = https://www.it610.com/article/bytes.fromhex('A3 00 A2 A4 A5') s.write(send_data) time.sleep(1) # rece_data = https://www.it610.com/article/s.read(10) # 接收返回的16进制数组,并把数组转换成字符 print(send_data) rece_data = str(binascii.b2a_hex(s.read(10)))[10:16] rece_data_High_16 = rece_data[0:2]# 数据高16位 rece_data_High_8= rece_data[2:4]# 数据高8位 rece_data_Low_8= rece_data[4:6]# 数据低8位的第1位print(rece_data) print(str("yuanshi:{}".format(rece_data))) print(str("rece_data_High_16 :{}".format(rece_data_High_16)))# 数据高16位的第1位 print(str("rece_data_High_8 :{}".format(rece_data_High_8)))# 数据高8位的第1位 print(str("rece_data_Low_8 :{}".format(rece_data_Low_8)))# 数据低8位的第1位rece_data_High_16_to_int = int(rece_data_High_16) rece_data_High_8_to_int= int(rece_data_High_8) rece_data_Low_8_to_int= int(rece_data_Low_8,16)# 将16进制转换成10进制# 重量运算计算公式 rece_data_High_16 * 65536 +rece_data_High_8 * 256 + rece_data_Low g = ((rece_data_High_16_to_int * 65536) + (rece_data_High_8_to_int * 256) + (rece_data_Low_8_to_int)) print("重量:{}".format(g) + "g")time.sleep(3)

    推荐阅读