[具身智能-568]:地平线 RDK(X3/X5)Hobot.GPIO 按键控制 LED 代码完整解读
·
#!/usr/bin/env python3
################################################################################
# Copyright (c) 2024,D-Robotics.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
################################################################################
import sys
import signal
import Hobot.GPIO as GPIO
import time
def signal_handler(signal, frame):
sys.exit(0)
# 定义使用的GPIO通道:
# 31号作为输出,可以点亮一个LED
# 37号作为输入,可以接一个按钮
led_pin = 31 # BOARD 编码 31
but_pin = 37 # BOARD 编码 37
# 禁用警告信息
GPIO.setwarnings(False)
def main():
# 设置管脚编码模式为硬件编号 BOARD
GPIO.setmode(GPIO.BOARD)
GPIO.setup(led_pin, GPIO.OUT) # LED pin set as output
GPIO.setup(but_pin, GPIO.IN) # button pin set as input
# Initial state for LEDs:
GPIO.output(led_pin, GPIO.LOW)
print("Starting demo now! Press CTRL+C to exit")
try:
while True:
print("Waiting for button event")
GPIO.wait_for_edge(but_pin, GPIO.FALLING)
# event received when button pressed
print("Button Pressed!")
GPIO.output(led_pin, GPIO.HIGH)
time.sleep(1)
GPIO.output(led_pin, GPIO.LOW)
finally:
GPIO.cleanup() # cleanup all GPIOs
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main()
一、代码整体概述
这是地平线旭日系列开发板官方 GPIO 示例程序,实现下降沿中断检测按键 + LED 输出控制,具备Ctrl+C 优雅退出、GPIO 资源自动释放能力。
- 运行平台:D-Robotics RDK X3 / X5
- 依赖库:
Hobot.GPIO(地平线自研用户态 GPIO 库,替代树莓派 RPi.GPIO) - 硬件接线:
- BOARD 引脚 31 → LED 正极(串限流电阻),GND 接 LED 负极
- BOARD 引脚 37 → 按键一端,按键另一端接 GND(默认上拉,按下电平拉低)
- 核心逻辑:循环阻塞等待按键按下,按键触发后 LED 点亮 1 秒再熄灭。
二、逐段分层拆解
1. 文件头部声明
python
运行
#!/usr/bin/env python3
# Apache 2.0开源协议声明
#!/usr/bin/env python3:脚本解释器声明,终端可直接python3 xxx.py或./xxx.py运行。- Apache2.0 协议:允许商用、修改、分发,保留版权声明即可。
2. 导入依赖模块
python
运行
import sys
import signal
import Hobot.GPIO as GPIO
import time
sys:系统工具,用于程序退出sys.exit(0)signal:Linux 信号捕获,处理键盘中断Ctrl+CHobot.GPIO as GPIO:地平线 GPIO 操作核心库,API 语法兼容 RPi.GPIO,适配旭日 SOC 硬件time:延时函数time.sleep()
3. Ctrl+C 信号处理函数 signal_handler
python
运行
def signal_handler(signal, frame):
sys.exit(0)
- 作用:捕获
SIGINT(Ctrl+C 键盘中断信号),直接正常退出程序; - 若不注册该函数,按下 Ctrl+C 会直接抛出
KeyboardInterrupt异常,跳过 GPIO 资源清理,导致引脚占用、后续程序报错。
4. 全局引脚定义
python
运行
led_pin = 31 # BOARD物理板载引脚编号31,输出
but_pin = 37 # BOARD物理板载引脚编号37,输入按键
GPIO.setwarnings(False) # 关闭GPIO重复初始化警告
GPIO.BOARD:按开发板丝印物理引脚编号操作(推荐新手,不用记忆芯片 BCM 内核编号);setwarnings(False):屏蔽 “引脚已被占用、重复 setup” 的冗余警告日志。
5. 主业务函数 main ()
(1)GPIO 初始化配置
python
运行
GPIO.setmode(GPIO.BOARD)
GPIO.setup(led_pin, GPIO.OUT) # 31脚设为输出模式
GPIO.setup(but_pin, GPIO.IN) # 37脚设为输入模式
GPIO.output(led_pin, GPIO.LOW)# LED初始低电平,熄灭
setmode(GPIO.BOARD):指定引脚编码规则,全局统一;setup(pin, mode):配置引脚方向GPIO.OUT:输出,高低电平控制外设(LED、继电器)GPIO.IN:输入,读取外部电平(按键、传感器)
output(pin, level):设置输出引脚初始电平,LOW=0熄灭 LED。
(2)主循环:阻塞式等待按键中断
python
运行
try:
while True:
print("Waiting for button event")
# 阻塞等待引脚下降沿(高→低)触发
GPIO.wait_for_edge(but_pin, GPIO.FALLING)
print("Button Pressed!")
GPIO.output(led_pin, GPIO.HIGH) # 点亮LED
time.sleep(1)
GPIO.output(led_pin, GPIO.LOW) # 1秒后熄灭
核心 API:GPIO.wait_for_edge(pin, edge_type)
- 阻塞特性:程序停在此处,不占用 CPU 轮询,内核硬件中断等待,低功耗;
GPIO.FALLING下降沿触发:- 按键默认上拉:空闲 = 高电平;按键按下接地 = 低电平;
- 电平从高变低瞬间触发中断,进入后续 LED 逻辑;
- 执行流程:按键按下 → 打印提示 → LED 高电平亮 1s → 熄灭,回到循环继续等待下一次按键。也就是按键的迟滞响应时间为2s。
(3)finally 资源释放(必执行)
python
运行
finally:
GPIO.cleanup() # 释放所有配置过的GPIO引脚
- 无论循环正常结束、还是 Ctrl+C 中断、代码异常,
finally块一定会执行; GPIO.cleanup():重置所有 GPIO 为默认浮空输入,释放内核设备占用,避免下次运行提示引脚被占用。
6. 程序入口与信号注册
python
运行
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main()
if __name__ == '__main__':标准 Python 程序入口,仅直接运行脚本时执行;signal.signal(signal.SIGINT, signal_handler):注册中断回调,按下 Ctrl+C 触发自定义处理函数,保证走finally清理 GPIO 资源。
三、核心 API 详解(Hobot.GPIO)
GPIO.setmode(GPIO.BOARD)物理丝印编号,RDK 开发板丝印数字直接对应,入门首选;另一种GPIO.BCM为芯片内核 GPIO 编号。GPIO.setup(pin, mode)配置输入 / 输出,输入可额外带上拉下拉:GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)。GPIO.output(pin, GPIO.HIGH/GPIO.LOW)输出高低电平控制外设。GPIO.wait_for_edge(pin, edge)硬件中断阻塞等待,三种触发模式:GPIO.FALLING下降沿(按键按下推荐)GPIO.RISING上升沿(按键松开)GPIO.BOTH双边沿(按下 + 松开都触发)
GPIO.cleanup()资源回收,嵌入式 GPIO 程序强制规范,防止硬件资源泄漏。
四、硬件接线逻辑说明
按键引脚 37 配置为输入,内部默认上拉电阻:
- 按键松开:引脚 37 = 高电平;
- 按键按下:引脚 37 接地,电平变低,产生下降沿,
wait_for_edge捕获事件; - LED 引脚 31 输出高电平时导通点亮,低电平熄灭。
五、程序运行完整时序
- 脚本启动 → 注册 Ctrl+C 信号处理;
- 初始化 GPIO,LED 默认熄灭;
- 进入 while 循环,阻塞等待按键;
- 按下按键 → 捕获下降沿 → LED 亮 1 秒后熄灭;
- 重复等待按键;
- 按下 Ctrl+C → 触发 signal_handler,执行 sys.exit;
- 程序退出前进入 finally,执行
GPIO.cleanup()释放所有 IO。
六、关键优势与工程规范点
- 硬件中断非轮询:
wait_for_edge阻塞等待,CPU 不循环扫描引脚,资源占用极低; - 安全退出机制:信号捕获 + finally 双重保障,GPIO 一定会释放;
- 分层清晰:硬件引脚定义、初始化、业务逻辑、资源回收完全分离;
- 适配地平线全系列 RDK 平台,Hobot.GPIO 库开箱即用,无需额外驱动编译。
七、常见踩坑补充
- 按键抖动:机械按键按下会产生电平毛刺,短时间多次触发;可在
wait_for_edge后加time.sleep(0.02)软件消抖; - 引脚编号混淆:
BOARD与BCM模式不可混用,否则引脚控制错乱; - 忘记 cleanup:程序异常退出后 GPIO 保持输出电平,LED 常亮、引脚被锁死;
- 权限问题:部分 RDK 系统操作 GPIO 需要 root 权限,运行加
sudo python3 xxx.py。
消抖优化补充代码片段
python
运行
GPIO.wait_for_edge(but_pin, GPIO.FALLING)
time.sleep(0.02) # 20ms消抖延时
# 二次读取电平确认真实按下,过滤抖动
if GPIO.input(but_pin) == 0:
print("Button Pressed!")
GPIO.output(led_pin, GPIO.HIGH)
time.sleep(1)
GPIO.output(led_pin, GPIO.LOW)
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)