news 2026/7/19 5:01:30

树莓派UART串口通信详解与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
树莓派UART串口通信详解与实战

1. 树莓派串口通信基础解析

树莓派的串口通信功能是其与外部设备交互的重要方式之一。作为一名嵌入式开发者,我经常使用UART接口连接各种传感器、模块和其他微控制器。树莓派提供了两种UART硬件:PL011和mini UART,它们各有特点。

PL011 UART是ARM架构的原生UART控制器,性能稳定且功能完整。它支持高达3Mbps的波特率,具有独立的64字节收发FIFO,支持硬件流控(RTS/CTS)。在实际项目中,当需要可靠的高速通信时,PL011是首选。

mini UART则是Broadcom设计的简化版UART,它的波特率与GPU核心频率相关。这意味着当GPU频率变化时(如进行图形密集型任务时),mini UART的波特率会随之漂移,可能导致通信错误。mini UART也没有硬件流控和奇偶校验功能,适合对稳定性要求不高的场景。

注意:树莓派3及更新型号默认将PL011分配给蓝牙模块,而将mini UART分配给GPIO的UART引脚。这是很多初学者容易混淆的地方。

2. 硬件准备与引脚配置

2.1 硬件连接方式

树莓派的UART使用GPIO14(TXD)和GPIO15(RXD)引脚。与PC或其他设备连接时,需要注意电平转换:

  1. 直接连接其他3.3V设备时,可以直连:

    • 树莓派TXD → 对方RXD
    • 树莓派RXD → 对方TXD
    • 共地连接必不可少
  2. 连接5V设备或PC时需要电平转换:

    • 推荐使用MAX3232或CH340G等转换芯片
    • 也可以使用分压电阻(1kΩ+2kΩ)进行简易转换

2.2 启用UART接口

在最新版Raspbian系统中,UART默认是禁用的(分配给蓝牙)。启用步骤:

sudo raspi-config

选择"Interfacing Options" → "Serial":

  • 第一个提示选择"No"(禁用控制台登录)
  • 第二个提示选择"Yes"(启用硬件串口)

然后修改/boot/config.txt文件:

sudo nano /boot/config.txt

添加或修改以下行:

enable_uart=1 dtoverlay=pi3-miniuart-bt

保存后重启系统。

3. Python实现UART通信

3.1 安装pyserial库

pip install pyserial

3.2 基础通信示例

import serial import time # 配置串口参数 ser = serial.Serial( port='/dev/serial0', # 使用别名确保兼容性 baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1 ) try: while True: # 发送数据 ser.write(b'Hello from Raspberry Pi\n') # 接收数据 if ser.in_waiting > 0: received_data = ser.readline() print(f"Received: {received_data.decode('utf-8').strip()}") time.sleep(1) except KeyboardInterrupt: print("Program terminated") finally: ser.close()

3.3 高级功能实现

  1. 二进制数据传输:
# 发送二进制数据 data = bytes([0xAA, 0xBB, 0xCC]) ser.write(data) # 接收二进制数据 raw_data = ser.read(3) # 读取3个字节
  1. 使用线程实现全双工通信:
from threading import Thread def receive_thread(): while True: if ser.in_waiting: print(ser.readline().decode()) Thread(target=receive_thread, daemon=True).start()

4. C语言实现UART通信

4.1 使用wiringPi库

首先安装wiringPi:

sudo apt-get install wiringpi

基础通信代码:

#include <stdio.h> #include <string.h> #include <wiringPi.h> #include <wiringSerial.h> int main() { int serial_port; char buffer[256]; if ((serial_port = serialOpen("/dev/serial0", 115200)) < 0) { fprintf(stderr, "Unable to open serial device: %s\n", strerror(errno)); return 1; } if (wiringPiSetup() == -1) { fprintf(stdout, "Unable to start wiringPi: %s\n", strerror(errno)); return 1; } while (1) { // 发送数据 sprintf(buffer, "Counter: %d\n", millis()/1000); serialPuts(serial_port, buffer); // 接收数据 while (serialDataAvail(serial_port)) { printf("%c", serialGetchar(serial_port)); fflush(stdout); } delay(1000); } return 0; }

4.2 使用Linux原生API

对于更底层的控制,可以直接使用termios:

#include <fcntl.h> #include <termios.h> #include <unistd.h> int setup_uart(const char *device) { int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) return -1; struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; tcsetattr(fd, TCSANOW, &options); return fd; }

5. 常见问题与解决方案

5.1 波特率不匹配问题

症状:接收到的数据乱码 解决方法:

  1. 确认双方波特率设置一致
  2. 检查时钟稳定性(特别是使用mini UART时)
  3. 在config.txt中添加core_freq=250固定核心频率

5.2 数据丢失问题

症状:部分数据包丢失 解决方法:

  1. 实现软件流控(XON/XOFF)
  2. 减小数据包大小
  3. 增加接收缓冲区:
    ser = serial.Serial(..., rtscts=True) # 启用硬件流控

5.3 权限问题

症状:无法打开/dev/serial0 解决方法:

sudo usermod -a -G dialout pi

然后注销重新登录。

6. 性能优化技巧

  1. 提高通信可靠性:

    • 添加数据校验(CRC或校验和)
    • 实现重传机制
    • 使用消息帧格式(如[STX][DATA][ETX][CRC])
  2. 提高吞吐量:

    • 增大缓冲区大小
    ser = serial.Serial(..., write_timeout=0, xonxoff=True, rtscts=True, dsrdtr=True)
    • 使用DMA传输(C语言实现)
  3. 多串口扩展:

    • 使用USB转串口适配器(如CP2102)
    • 通过GPIO模拟软串口(需要精确计时)

在实际项目中,我通常会结合Python的快速开发优势和C语言的高性能特点。例如用Python实现上层协议解析,而用C处理底层的高速数据采集。这种混合编程方式既能保证开发效率,又能满足性能需求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 5:00:47

C++构建容错量子逻辑比特:从表面码模拟到高性能解码器实现

1. 项目概述&#xff1a;为什么C是构建容错逻辑比特的“硬核”选择在量子计算这个听起来前沿又有些缥缈的领域里&#xff0c;我们开发者每天面对的不是玄学&#xff0c;而是实打实的代码、算法和工程难题。当讨论从理论物理和基础算法下沉到“构建容错逻辑比特”这个层面时&…

作者头像 李华
网站建设 2026/7/19 5:00:20

杭州萧然医院服务好不好?

不少在萧山开服装工厂、做跨境直播的姑娘私下吐槽&#xff0c;平时连抽空喝杯热姜茶的功夫都没有&#xff0c;月经乱了大半年都挤不出时间跑大医院排队&#xff0c;好不容易挂上号&#xff0c;等两小时问诊三分钟&#xff0c;私密情况半句话都不好意思说&#xff0c;最近刷到好…

作者头像 李华
网站建设 2026/7/19 5:00:04

Minecraft无规则生存服务器:死亡掉落机制与硬核玩法解析

这次我们来看一个特殊的 Minecraft 服务器类型——无规则生存服务器。这类服务器最大的特点就是"保留物品栏已经关闭"&#xff0c;这意味着玩家死亡后不会保留背包里的物品&#xff0c;完全回归生存模式的原始挑战。对于喜欢高难度生存和纯粹 PvP 的玩家来说&#xf…

作者头像 李华
网站建设 2026/7/19 4:59:18

Python最简单列表操作指南

一、定义二、索引三、切片四、遍历五、常用方法一、定义列表&#xff08;List&#xff09;是 Python 中最基础且最强大的数据结构之一&#xff0c;用于存储多个数据项&#xff1a;创建方式&#xff1a;使用方括号 [] 直接定义&#xff08;如 [1, 2, 3]&#xff09;&#xff0c;…

作者头像 李华
网站建设 2026/7/19 4:58:58

Unity性能优化实战:从CPU/GPU瓶颈诊断到内存管理全解析

1. 项目概述&#xff1a;为什么Unity性能优化是开发者的必修课做Unity开发这些年&#xff0c;我最大的感受是&#xff1a;一个项目能不能成&#xff0c;技术实现只是第一步&#xff0c;性能表现才是决定它能否“活下来”的关键。无论是上线后玩家抱怨的“手机发烫、卡成PPT”&a…

作者头像 李华
网站建设 2026/7/19 4:57:41

用纯C语言实现Llama 2推理:llama2.c项目实践与原理剖析

1. 项目概述&#xff1a;当C语言遇见AI推理如果你是一名C语言开发者&#xff0c;或者对底层系统、嵌入式开发感兴趣&#xff0c;最近可能被一个叫“llama2.c”的项目刷屏了。它的名字听起来就有点“离经叛道”&#xff1a;用纯C语言&#xff0c;去运行一个原本需要庞大PyTorch、…

作者头像 李华