[具身智能-567]:RDK(X3/X5)button_led.py 代码完整详解
·
RDK(X3/X5)button_led.py 代码完整详解
适用平台:地平线 RDK X3、RDK X5;
库:Hobot.GPIO(地平线自研 Python GPIO 库,语法高度兼容 RPi.GPIO)
功能简述:读取按键输入,同步控制 LED 输出;
按键电平状态直接映射到 LED,按键按下 LED 点亮、松开熄灭。
一、硬件接线说明
python
运行
led_pin = 31 # BOARD物理引脚31 → LED阳极(串220Ω限流电阻)
but_pin = 37 # BOARD物理引脚37 → 按键一端
推荐接线方案:
- LED 回路:
Pin31 → 220Ω电阻 → LED正极 → GND - 按键回路(上拉推荐)
- 方案 A(开发板内部上拉):按键一端 Pin37,另一端接 GND
- 方案 B(外部):Pin37 外接 10k 上拉电阻到 3.3V,按键另一端接 GND
⚠️ BOARD 编码 = 开发板 40Pin 排针丝印物理编号,不需要记忆芯片 GPIO 编号,新手首选。
二、逐段源码解析
1. 文件头 & 导入模块
python
运行
#!/usr/bin/env python3
################################################################################
# Apache2.0开源协议声明
################################################################################
import sys
import signal
import Hobot.GPIO as GPIO
import time
#!/usr/bin/env python3:指定解释器,可直接chmod +x ./xxx.py直接运行Hobot.GPIO:地平线 RDK 平台专用 GPIO 库,RDK 系统预装,无需手动 pip 安装
2. Ctrl+C 信号捕获函数
python
运行
def signal_handler(signal, frame):
sys.exit(0)
作用:捕获 SIGINT(键盘 Ctrl+C 中断信号),优雅退出程序。
补充:真正的资源释放放在
finally块,信号 handler 只负责退出循环。
3. 全局引脚定义
python
运行
led_pin = 31 # BOARD 编码 31(输出)
but_pin = 37 # BOARD 编码 37(输入)
GPIO.setwarnings(False)
GPIO.setwarnings(False):关闭警告;当引脚已经被其他进程占用时,库默认打印警告,调试稳定后可以关闭。
4. 核心主函数 main ()
python
运行
def main():
prev_value = None
# ========== 引脚初始化 ==========
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初始状态:熄灭
print("Starting demo now! Press CTRL+C to exit")
try:
while True:
curr_value = GPIO.input(but_pin) # 读取按键当前电平
# 判断电平是否发生跳变(按键按下/松开)
if curr_value != prev_value:
GPIO.output(led_pin, curr_value) # 按键电平直接输出给LED
prev_value = curr_value
print("Outputting {} to Pin {}".format(curr_value, led_pin))
time.sleep(1) # 循环间隔1秒
finally:
GPIO.cleanup() # 【重点】程序退出时,释放所有GPIO资源
关键逻辑拆解
GPIO.setmode(GPIO.BOARD)引脚编号模式一共 4 种:BOARD(电路板编号模式):40Pin 排针物理丝印号(推荐,此 demo 使用)BCM:模仿树莓派 BCM 编号SOC:芯片内核原始 GPIO 号(查阅芯片手册使用)CVM:连接器信号名称字符串
- 电平跳变检测
prev_value保存上一次按键状态;只有按键电平发生变化,才修改 LED 状态,避免重复输出。 time.sleep(1)轮询⚠️【缺陷提醒】这种是轮询查询方式,最低 1 秒才能识别一次按键动作,按键快速按放会丢失事件; 优化方案:使用中断边沿检测
GPIO.add_event_detect()(后面补充优化代码)- try ... finally 结构 无论程序正常结束、Ctrl+C 强制退出、异常崩溃,
finally块一定会执行;GPIO.cleanup()把 GPIO 恢复为默认输入状态,防止引脚持续输出电平造成硬件隐患。
5. 程序入口
python
运行
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main()
signal.signal(SIGINT, handler):注册 Ctrl+C 中断回调- Python 标准写法,防止代码被其他文件 import 时自动执行
三、运行操作步骤(RDK X5 实测)
- 赋予执行权限
bash
运行
chmod +x button_led.py
- 必须使用 root 权限操作 GPIO(硬件权限限制)
bash
运行
sudo python3 button_led.py
- 操作:按下按键 → LED 点亮;松开按键 → LED 熄灭;控制台打印电平变化日志
四、原生代码优缺点
✅ 优点:逻辑极简,新手入门,容易理解输入输出映射关系 ❌ 缺点:
- 轮询延时 1s,响应慢,快速按键会丢失;
- CPU 持续循环占用资源;
- 没有启用内部上下拉电阻,浮空输入容易出现电平抖动。
五、进阶优化版本(中断方式,推荐项目使用)
使用边沿中断,不需要 while 轮询,实时响应按键,节省 CPU
python
运行
#!/usr/bin/env python3
import sys
import signal
import Hobot.GPIO as GPIO
import time
led_pin = 31
but_pin = 37
GPIO.setwarnings(False)
def signal_handler(signal, frame):
GPIO.cleanup()
sys.exit(0)
# 按键中断回调函数
def button_callback(channel):
val = GPIO.input(but_pin)
GPIO.output(led_pin, val)
print(f"Button state changed: {val}, LED set to {val}")
def main():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(led_pin, GPIO.OUT)
# 启用内部上拉电阻,防止浮空抖动
GPIO.setup(but_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.output(led_pin, GPIO.LOW)
# 注册双边沿中断:上升沿+下降沿都触发
GPIO.add_event_detect(but_pin, GPIO.BOTH, callback=button_callback, bouncetime=200)
print("Waiting button trigger, CTRL+C exit")
while True:
time.sleep(0.1)
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main()
重点新增特性:
pull_up_down=GPIO.PUD_UP:开启芯片内部上拉电阻,解决浮空杂波;add_event_detect硬件边沿中断;bouncetime=200:消抖,防止机械按键抖动多次触发;- 无需高频轮询,空闲时 CPU 低负载。
六、常见踩坑清单(RDK 开发高频问题)
- 报错 Permission denied ✅ 解决:GPIO 操作必须加
sudo运行 - 按键没反应,电平一直不变 检查:接线、上下拉配置、确认引脚没有被系统设备树复用(串口 / SPI 等功能占用)
- LED 不亮 检查 LED 正负极、限流电阻,确认输出引脚是 BOARD 编号
- 引脚被占用警告 ✅ 临时关闭:
GPIO.setwarnings(False);长期方案:确认没有其他程序占用同一引脚
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)