Python 应用开发
1. 概述
1.1 功能简介
Python 是一种高级编程语言,以其简洁的语法和丰富的库生态著称。在 RK3576 平台上,Python 应用开发主要基于 Debian 系统,支持 Python 3.x 版本,可用于快速开发外设控制、网络通信、数据处理、Web 服务等应用。RK3576 的 8 核 4×Cortex-A72 + 4×Cortex-A53 处理器提供了充足的算力,配合 Python 的简洁性,可以快速实现原型验证和产品开发。
1.2 应用场景
- 外设控制:GPIO、I2C、SPI、UART 等外设的 Python 接口
- 网络通信:TCP/UDP、HTTP、MQTT 客户端/服务器
- 数据处理:NumPy、Pandas 数据分析
- Web 服务:Flask、Django Web 应用
- AI 推理:配合 RKNN 运行 Python 推理应用
1.3 工作原理
RK3576 Python 开发架构:
Python 应用层
├── pyserial — 串口通信
├── smbus2 — I2C 通信
├── spidev — SPI 通信
├── RPi.GPIO — GPIO 控制(通过 sysfs)
├── Flask — Web 服务
└── RKNN Lite — NPU 推理
操作系统层(Debian)
├── Python 3.x 解释器
├── 系统调用
└── 设备文件(/dev/*, /sys/*)
硬件层(RK3576)
├── UART、I2C、SPI 控制器
├── GPIO 控制器
└── NPU 加速器(6 TOPS)2. 硬件准备
2.1 硬件清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | C-3576BQ 核心板 + M4-R2 底板 | 1 | 运行 Debian 系统 |
| 调试串口线 | USB 转 TTL(3.3V) | 1 | 波特率 1500000 |
| 传感器模块(可选) | 温度传感器、LED 等 | 若干 | 用于 GPIO/I2C 实验 |
| 网线 | 标准 RJ45 | 1 | 用于网络和 SSH 连接 |
2.2 硬件确认
# 确认 Python 版本
python3 --version
# 输出:Python 3.x.x
# 确认 pip 版本
pip3 --version
# 确认系统架构
uname -m
# 输出:aarch643. 软件准备
3.1 Python 环境安装
# Debian 系统默认已安装 Python 3
sudo apt-get update
sudo apt-get install python3 python3-pip python3-dev
# 升级 pip
pip3 install --upgrade pip
# 安装虚拟环境工具
sudo apt-get install python3-venv3.2 常用外设库安装
# GPIO 控制
sudo apt-get install python3-gpiozero python3-rpi.gpio
# I2C 通信
pip3 install smbus2
# SPI 通信
sudo apt-get install python3-spidev
# 串口通信
pip3 install pyserial
# Web 框架
pip3 install flask
# 数据处理
pip3 install numpy pandas3.3 启用外设接口
# 启用 I2C
sudo modprobe i2c-dev
echo "i2c-dev" | sudo tee -a /etc/modules
# 启用 SPI
sudo modprobe spi-rockchip
echo "spi-rockchip" | sudo tee -a /etc/modules
# 检查 I2C 设备
i2cdetect -y 1
# 输出: 0 1 2 3 4 5 6 7 8 9 a b c d e f
# 0: -- -- -- -- -- -- -- --
# 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
# ...具体 I2C 总线号及 SPI 控制器编号以实际 SDK 内核配置与设备树为准。
4. 操作步骤
4.1 GPIO 控制示例
#!/usr/bin/env python3
"""GPIO LED 闪烁示例(RK3576)"""
import time
import sys
# 使用 sysfs 方式控制 GPIO(通用方法)
# RK3576 GPIO0-GPIO4,每个 bank 32 个引脚
class RK3576GPIO:
"""RK3576 GPIO 控制类"""
def __init__(self, gpio_num):
self.gpio_num = gpio_num
self.gpio_path = f"/sys/class/gpio/gpio{gpio_num}"
def export(self):
"""导出 GPIO"""
try:
with open("/sys/class/gpio/export", "w") as f:
f.write(str(self.gpio_num))
time.sleep(0.1)
except FileNotFoundError:
print(f"GPIO {self.gpio_num} already exported")
def set_direction(self, direction):
"""设置方向:in 或 out"""
with open(f"{self.gpio_path}/direction", "w") as f:
f.write(direction)
def set_value(self, value):
"""设置值:0 或 1"""
with open(f"{self.gpio_path}/value", "w") as f:
f.write(str(value))
def get_value(self):
"""读取值"""
with open(f"{self.gpio_path}/value", "r") as f:
return int(f.read().strip())
def cleanup(self):
"""取消导出"""
try:
with open("/sys/class/gpio/unexport", "w") as f:
f.write(str(self.gpio_num))
except FileNotFoundError:
pass
def blink_led(gpio_num, count=5, interval=0.5):
"""LED 闪烁"""
gpio = RK3576GPIO(gpio_num)
gpio.export()
gpio.set_direction("out")
try:
for i in range(count):
gpio.set_value(1)
print(f"LED ON ({i + 1}/{count})")
time.sleep(interval)
gpio.set_value(0)
print(f"LED OFF ({i + 1}/{count})")
time.sleep(interval)
finally:
gpio.cleanup()
if __name__ == "__main__":
# 使用 GPIO4_D5 (GPIO bank 4, pin 29)
# GPIO 编号 = bank * 32 + pin = 4 * 32 + 29 = 157
blink_led(gpio_num=157, count=5, interval=0.5)示例引脚 GPIO4_D5 为通用演示引脚,实际使用请根据底板原理图(S-04)选择未被占用的 GPIO。
4.2 I2C 通信示例
#!/usr/bin/env python3
"""I2C 通信示例 — 读取温湿度传感器(SHT30)"""
from smbus2 import SMBus
import time
# SHT30 I2C 地址
SHT30_ADDR = 0x44
I2C_BUS = 1 # RK3576 I2C1
def read_sht30():
"""读取 SHT30 温湿度"""
with SMBus(I2C_BUS) as bus:
# 发送测量命令(单次测量,高重复性)
bus.write_i2c_block_data(SHT30_ADDR, 0x24, [0x00])
time.sleep(0.5)
# 读取 6 字节数据
data = bus.read_i2c_block_data(SHT30_ADDR, 0x00, 6)
# 解析温度
temp_raw = (data[0] << 8) | data[1]
temperature = -45 + 175 * temp_raw / 65535.0
# 解析湿度
hum_raw = (data[3] << 8) | data[4]
humidity = 100 * hum_raw / 65535.0
return temperature, humidity
if __name__ == "__main__":
try:
temp, hum = read_sht30()
print(f"Temperature: {temp:.2f} °C")
print(f"Humidity: {hum:.2f} %")
except Exception as e:
print(f"Error: {e}")4.3 UART 串口通信示例
#!/usr/bin/env python3
"""UART 串口通信示例"""
import serial
import time
# RK3576 UART(调试串口为 ttyFIQ0)
# 注意:调试串口通常用于日志输出,实际应用请使用其他 UART
SERIAL_PORT = "/dev/ttyFIQ0"
BAUD_RATE = 1500000
def uart_communication():
"""UART 收发示例"""
ser = serial.Serial(
port=SERIAL_PORT,
baudrate=BAUD_RATE,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1
)
try:
print(f"Serial port {SERIAL_PORT} opened")
# 发送数据
ser.write(b"Hello RK3576!\r\n")
print("Data sent")
# 接收数据
data = ser.readline()
if data:
print(f"Received: {data.decode('utf-8', errors='ignore')}")
else:
print("No data received (timeout)")
finally:
ser.close()
print("Serial port closed")
if __name__ == "__main__":
uart_communication()具体 UART 设备节点(/dev/ttySx 或 /dev/ttyFIQ0)以实际 SDK 内核配置为准。
4.4 Flask Web 服务示例
#!/usr/bin/env python3
"""Flask Web 服务 — RK3576 系统信息展示"""
from flask import Flask, jsonify
import os
import subprocess
app = Flask(__name__)
@app.route("/")
def index():
return """
<html>
<head><title>RK3576 System Monitor</title></head>
<body>
<h1>RK3576 System Monitor</h1>
<ul>
<li><a href="/api/system">System Info</a></li>
<li><a href="/api/temperature">Temperature</a></li>
<li><a href="/api/cpu">CPU Usage</a></li>
</ul>
</body>
</html>
"""
@app.route("/api/system")
def system_info():
"""系统信息"""
info = {
"kernel": os.uname().release,
"machine": os.uname().machine,
"hostname": os.uname().nodename,
}
# 获取内存信息
try:
with open("/proc/meminfo", "r") as f:
for line in f:
if line.startswith("MemTotal"):
info["mem_total"] = line.split()[1] + " kB"
elif line.startswith("MemAvailable"):
info["mem_available"] = line.split()[1] + " kB"
except Exception:
pass
return jsonify(info)
@app.route("/api/temperature")
def temperature():
"""CPU 温度"""
try:
with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
temp = int(f.read().strip()) / 1000.0
return jsonify({"temperature": f"{temp:.1f} °C"})
except Exception:
return jsonify({"temperature": "N/A"})
@app.route("/api/cpu")
def cpu_usage():
"""CPU 使用率"""
try:
result = subprocess.run(
["grep", "cpu ", "/proc/stat"],
capture_output=True, text=True
)
fields = result.stdout.split()
# 简单计算 CPU 使用率
total = sum(int(x) for x in fields[1:])
idle = int(fields[4])
usage = (total - idle) / total * 100
return jsonify({"cpu_usage": f"{usage:.1f}%"})
except Exception:
return jsonify({"cpu_usage": "N/A"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)# 运行 Web 服务
python3 web_monitor.py
# 在浏览器访问
# http://192.168.1.100:50004.5 使用 SSH 远程部署
# 从主机传输文件到 RK3576
scp my_app.py root@192.168.1.100:/root/
# 在 RK3576 上运行
ssh root@192.168.1.100 "python3 /root/my_app.py"
# 使用 scp 传输整个目录
scp -r my_project/ root@192.168.1.100:/root/my_project/5. 代码详解
5.1 RK3576 GPIO 编号规则
RK3576 GPIO bank 和 pin 编号:
GPIO0: bank 0, GPIO0_A0(0) ~ GPIO0_D7(31)
GPIO1: bank 1, GPIO1_A0(32) ~ GPIO1_D7(63)
GPIO2: bank 2, GPIO2_A0(64) ~ GPIO2_D7(95)
GPIO3: bank 3, GPIO3_A0(96) ~ GPIO3_D7(127)
GPIO4: bank 4, GPIO4_A0(128) ~ GPIO4_D7(159)
计算公式:
GPIO 编号 = bank × 32 + pin_in_bank
示例:
GPIO4_D5 = 4 × 32 + 29 = 1575.2 RK3576 I2C 总线
RK3576 I2C 总线映射(示例):
I2C0: /dev/i2c-0
I2C1: /dev/i2c-1
I2C2: /dev/i2c-2
I2C3: /dev/i2c-3
I2C4: /dev/i2c-4
I2C5: /dev/i2c-5
I2C6: /dev/i2c-6
I2C7: /dev/i2c-7各 I2C 控制器的寄存器基地址与总线编号以实际发布的 RK3576 SDK 设备树为准(待板上确认)。
6. 常见问题
6.1 smbus2 安装失败
现象: pip3 install smbus2 报错
解决方案:
# 安装依赖
sudo apt-get install python3-dev libi2c-dev
# 重新安装
pip3 install smbus2
# 如果还是失败,使用系统包
sudo apt-get install python3-smbus6.2 I2C 设备无法检测
现象: i2cdetect 扫描不到设备
解决方案:
# 检查 I2C 模块是否加载
lsmod | grep i2c
# 检查 I2C 设备节点
ls /dev/i2c-*
# 检查设备树中 I2C 节点状态
# 具体节点路径以实际 DTB 反编译结果为准
dtc -I dtb -O dts /sys/firmware/fdt | grep -A3 "i2c@"
# 手动加载模块
sudo modprobe i2c-dev6.3 权限问题
现象: 访问 /dev/i2c-* 或 /sys/class/gpio/ 权限不足
解决方案:
# 将当前用户添加到 i2c 和 gpio 组
sudo usermod -aG i2c,gpio $USER
# 或使用 root 运行
sudo python3 my_app.py相关文档
- C/C++应用开发入门 — C/C++ 开发
- 网络编程与应用 — 网络编程
- 文件系统与存储 — 存储管理
- RKNN Toolkit2安装与使用 — NPU Python 接口
- GPIO驱动与控制 — GPIO 控制
