1. GPIO 控制
小技巧
Linux系统控制主板上的外设接口需要root权限,可以通过临时更改外设节点权限或者使用root用户来操作。
对比纯软件开发,在嵌入式应用开发过程中,我们经常需要通过代码控制GPIO、PWM、ADC、I2C及SPI等外设,这些外设的控制需要通过系统调用或者库函数来实现。 常用的Python库包括:
python3-libgpiod :标准GPIO libgpiod库的python版本,只支持控制IO输入输出。
python-periphery:支持GPIO、PWM、I2C、SPI、UART等多种接口的基础控制。
Adafruit Blinka:支持GPIO、PWM、I2C、SPI、UART等,还带有一些常用传感器、OLED屏的应用示例。
在控制GPIO前我们需要先获得待控制GPIO的chip和line,CPU的GPIO引脚使用(chip, line)
的方式命名,使用以下命令可以查看:
cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins
板卡引出的接口与GPIO(chip,line)的对应关系举例如下:
GPIO0_B0 -> (chip=0, line=8)
GPIO3_B3 -> (chip=3, line=11)
GPIO3_B4 -> (chip=3, line=12)
GPIO3_C5 -> (chip=3, line=21)
GPIO3_D6 -> (chip=3, line=30)
1.1 python3-libgpiod
python3-libgpiod是标准GPIO libgpiod库的python版本,只支持控制IO输入输出。利用 python3-libgpiod 软件包,可以轻松使用Python控制GPIO引脚。
1.1.1 安装 python3-libgpiod
# 在板卡使用如下命令安装
sudo apt -y install python3-libgpiod
使用过程如有疑问,可以在import该软件包后使用help查看帮助文件。
python3 -c "import gpiod; help(gpiod)"
输出如下:
Help on module gpiod:
NAME
gpiod - Python interface to libgpiod
FILE
/usr/lib/python3/dist-packages/gpiod/__init__.py
PACKAGE CONTENTS
chip (module)
chip_info (module)
chip_info_list (module)
chip_list (module)
line (module)
line_event (module)
line_event_list (module)
line_request (module)
line_request_list (module)
line_set (module)
line_set_list (module)
line_value (module)
line_value_list (module)
version (module)
1.1.2 libgpiod 输出
python3-libgpiod 提供了两种方式来控制GPIO输出:
使用 chip.get_line(line) 获得line对象后,调用 line.set_value(value) 直接设置电平。
使用 chip.set_line_values(values) 批量设置电平,该方法一次可设置多个引脚电平。
举一个例子: 现在我们要通过python3-libgpiod控制LED指示灯和一个按键联动。LED正极接在GPIO3_b3,负极接在GND;按键接在GPIO0_C2上,默认拉高按下GPIO0_C2拉低。我们需要实现:按键按下LED灯亮,按键松开LED灯灭。
# -*- coding: utf-8 -*-
# 导入必要库
import gpiod
import time
# 硬件连接说明
'''
[LED连接]
正极 -> GPIO3_B3 (对应chip3 line11)
负极 -> GND
[按键连接]
引脚 -> GPIO0_C2 (对应chip0 line18)
特性 -> 默认高电平(3.3V),按下时变为低电平(0V)
'''
# GPIO映射计算函数
'''
Rockchip GPIO命名规则:
格式为GPIO<bank>_<port><pin>
示例:GPIO3_B3 表示:
- Bank编号:3 → 对应chip3
- Port字母:B → 第1个端口(A=0,B=1,C=2)
- Pin编号:3 → 端口内第3个引脚
计算公式:line = port字母序数*8 + pin编号
'''
def calculate_line(port_letter, pin_number):
# 将字母转换为大写并计算序数(A=0,B=1,...)
port_index = ord(port_letter.upper()) - ord('A')
return port_index * 8 + pin_number
# 初始化GPIO
with gpiod.Chip('gpiochip3') as led_chip, \
gpiod.Chip('gpiochip0') as btn_chip:
# 获取GPIO线路(计算后的line值)
led_line = led_chip.get_line(calculate_line('B', 3)) # GPIO3_B3 → line11
btn_line = btn_chip.get_line(calculate_line('C', 2)) # GPIO0_C2 → line18
# 配置LED为输出模式
led_line.request(consumer="LED_Control", type=gpiod.LINE_REQ_DIR_OUT)
# 配置按键为输入模式,启用上拉电阻
btn_line.request(consumer="Button_Input",
type=gpiod.LINE_REQ_DIR_IN,
flags=gpiod.LINE_REQ_FLAG_BIAS_PULL_UP)
# 主控制循环
print("开始检测按键状态,按Ctrl+C退出")
try:
while True:
# 读取按键状态(0=按下,1=松开)
btn_state = btn_line.get_value()
# 控制LED与按键状态相反(按下时亮灯)
led_line.set_value(0 if btn_state == 0 else 1)
# 添加50ms防抖延迟
time.sleep(0.05)
except KeyboardInterrupt:
# 安全退出处理
print("\n正在释放GPIO资源...")
led_line.set_value(0) # 关闭LED
led_line.release()
btn_line.release()
print("程序已安全退出")
1.2 python-periphery
python-periphery 是一个支持GPIO、PWM、I2C、SPI、UART等多种接口的基础控制库,使用简单,功能强大。
1.2.1 安装python-periphery
# 在板卡使用如下命令安装
pip3 install python-periphery
1.2.2 periphery输入输出
from periphery import GPIO
# 根据具体板卡的LED灯和按键连接修改使用的Chip和Line
# 这里使用GPIO0_B0接LED,GPIO0_C2接按键
LED_CHIP = "/dev/gpiochip0"
LED_LINE_OFFSET = 8
BUTTON_CHIP = "/dev/gpiochip0"
BUTTON_LINE_OFFSET = 18
led = GPIO(LED_CHIP, LED_LINE_OFFSET, "out")
button = GPIO(BUTTON_CHIP, BUTTON_LINE_OFFSET, "in")
try:
while True:
led.write(button.read())
finally:
led.write(True)
led.close()
button.close()
1.3 Adafruit Blinka
Adafruit Blinka 与 python-periphery 功能类似,除支持GPIO输入输出控制外, 都支持I2C、SPI等总线协议,但Adafruit基于blinka还提供了更丰富的应用demo,如控制屏幕等。
1.3.1 安装Adafruit Blinka
# 在板卡使用如下命令安装
sudo apt -y install python3-libgpiod # 注:如果python3-libgpiod已安装,忽略此步
pip3 install Adafruit-Blinka
具体使用方法暂略,感兴趣的用户可以自行研究!