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

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

具体使用方法暂略,感兴趣的用户可以自行研究!