树莓派GPIO控制指南:从sysfs到Python脚本的完整教程

张开发
2026/5/10 5:09:25 15 分钟阅读

分享文章

树莓派GPIO控制指南:从sysfs到Python脚本的完整教程
树莓派GPIO控制指南从sysfs到Python脚本的完整教程树莓派作为一款广受欢迎的单板计算机其强大的GPIO通用输入输出功能使其成为物联网和智能硬件项目的理想选择。无论您是想控制LED灯、读取传感器数据还是构建复杂的自动化系统掌握GPIO控制都是必备技能。本文将带您从最基础的sysfs文件系统操作开始逐步深入到Python脚本控制为您呈现一套完整的GPIO控制解决方案。1. 理解树莓派GPIO基础树莓派的GPIO引脚是其与外部世界交互的桥梁。不同型号的树莓派GPIO布局略有差异但基本原理相同。在开始实际操作前我们需要先了解几个关键概念物理引脚编号这是GPIO接口板上实际的引脚排列编号从1开始依次递增。BCM编号这是Broadcom芯片级别的编号方式在编程中更常用。WiringPi编号另一种编程使用的编号方案现已逐渐被淘汰。提示建议始终使用BCM编号方式这是大多数Python库的默认选择。树莓派GPIO引脚主要有三种工作模式输入模式用于读取外部信号如按钮状态、传感器数据等输出模式用于控制外部设备如LED、继电器等特殊功能模式如PWM、I2C、SPI等通信协议2. 通过sysfs文件系统控制GPIOsysfs是Linux内核提供的一种虚拟文件系统它将内核数据结构以文件形式暴露给用户空间。对于GPIO控制sysfs提供了直观的文件操作接口。2.1 基本操作步骤要使用sysfs控制GPIO需要按照以下步骤操作导出GPIO引脚echo 17 /sys/class/gpio/export这会在/sys/class/gpio目录下创建一个gpio17的子目录。设置引脚方向echo out /sys/class/gpio/gpio17/direction # 设置为输出 echo in /sys/class/gpio/gpio17/direction # 设置为输入读写引脚值echo 1 /sys/class/gpio/gpio17/value # 输出高电平 echo 0 /sys/class/gpio/gpio17/value # 输出低电平 cat /sys/class/gpio/gpio17/value # 读取当前电平取消导出echo 17 /sys/class/gpio/unexport2.2 使用Python封装sysfs操作虽然可以直接通过shell命令操作sysfs但在Python中封装这些操作会更加方便import os class SysfsGPIO: GPIO_BASE /sys/class/gpio def __init__(self, pin): self.pin pin self.export() def export(self): if not os.path.exists(f{self.GPIO_BASE}/gpio{self.pin}): with open(f{self.GPIO_BASE}/export, w) as f: f.write(str(self.pin)) def unexport(self): with open(f{self.GPIO_BASE}/unexport, w) as f: f.write(str(self.pin)) def set_direction(self, direction): with open(f{self.GPIO_BASE}/gpio{self.pin}/direction, w) as f: f.write(direction) def write(self, value): with open(f{self.GPIO_BASE}/gpio{self.pin}/value, w) as f: f.write(str(value)) def read(self): with open(f{self.GPIO_BASE}/gpio{self.pin}/value, r) as f: return int(f.read()) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.unexport() # 使用示例 with SysfsGPIO(17) as gpio: gpio.set_direction(out) gpio.write(1) # 输出高电平3. 使用Python GPIO库简化开发虽然sysfs提供了底层控制接口但在实际项目中使用专门的Python库会更加高效。以下是几个常用的GPIO控制库库名称特点适用场景RPi.GPIO官方推荐简单易用基础GPIO控制gpiozero面向对象设计高级抽象快速原型开发pigpio支持远程控制功能丰富需要精确时序控制或远程控制wiringpi兼容Arduino风格需要与Arduino代码兼容的项目3.1 RPi.GPIO基础使用RPi.GPIO是最常用的GPIO控制库安装简单pip install RPi.GPIO基本使用示例import RPi.GPIO as GPIO import time # 设置编号模式 GPIO.setmode(GPIO.BCM) # 使用BCM编号 # 设置引脚17为输出 GPIO.setup(17, GPIO.OUT) try: while True: GPIO.output(17, GPIO.HIGH) # 点亮LED time.sleep(1) GPIO.output(17, GPIO.LOW) # 熄灭LED time.sleep(1) except KeyboardInterrupt: GPIO.cleanup() # 清理GPIO设置3.2 gpiozero的高级抽象gpiozero提供了更高级的设备抽象让代码更加简洁from gpiozero import LED, Button from signal import pause led LED(17) button Button(2) button.when_pressed led.on button.when_released led.off pause() # 保持程序运行4. 实战项目环境监测系统让我们结合所学知识构建一个简单的环境监测系统使用DHT11温湿度传感器和LED指示灯。4.1 硬件连接树莓派引脚传感器引脚说明GPIO17DATA数据线3.3VVCC电源正极GNDGND电源负极GPIO27-LED正极4.2 软件实现首先安装必要的库pip install Adafruit_DHT RPi.GPIO完整代码import Adafruit_DHT import RPi.GPIO as GPIO import time # 设置传感器类型和引脚 DHT_SENSOR Adafruit_DHT.DHT11 DHT_PIN 17 LED_PIN 27 # 初始化GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT) try: while True: # 读取温湿度 humidity, temperature Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN) if humidity is not None and temperature is not None: print(f温度: {temperature}°C, 湿度: {humidity}%) # 根据温度控制LED if temperature 25: GPIO.output(LED_PIN, GPIO.HIGH) # 温度高点亮LED else: GPIO.output(LED_PIN, GPIO.LOW) # 温度正常熄灭LED else: print(传感器读取失败请检查连接) time.sleep(2) except KeyboardInterrupt: GPIO.cleanup()4.3 系统优化为了使系统更加稳定可靠我们可以做以下改进添加异常处理增加对传感器读取失败的重试机制日志记录将监测数据保存到文件或数据库网络接口添加Web服务远程查看数据报警功能当温湿度超出阈值时发出警报5. 高级主题与性能优化5.1 中断与事件检测在需要快速响应GPIO状态变化的场景中轮询方式效率低下。我们可以使用中断机制import RPi.GPIO as GPIO def button_callback(channel): print(按钮被按下!) GPIO.setmode(GPIO.BCM) GPIO.setup(2, GPIO.IN, pull_up_downGPIO.PUD_UP) GPIO.add_event_detect(2, GPIO.FALLING, callbackbutton_callback, bouncetime300) try: while True: time.sleep(1) except KeyboardInterrupt: GPIO.cleanup()5.2 PWM控制PWM脉冲宽度调制可用于控制LED亮度、电机速度等import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.OUT) pwm GPIO.PWM(18, 100) # 频率100Hz pwm.start(0) # 初始占空比0% try: while True: for dc in range(0, 101, 5): pwm.ChangeDutyCycle(dc) time.sleep(0.1) for dc in range(100, -1, -5): pwm.ChangeDutyCycle(dc) time.sleep(0.1) except KeyboardInterrupt: pwm.stop() GPIO.cleanup()5.3 多线程GPIO控制对于复杂的项目可能需要同时处理多个GPIO操作这时可以使用多线程import threading import RPi.GPIO as GPIO import time def led_controller(pin, interval): GPIO.setup(pin, GPIO.OUT) try: while True: GPIO.output(pin, GPIO.HIGH) time.sleep(interval) GPIO.output(pin, GPIO.LOW) time.sleep(interval) except: pass GPIO.setmode(GPIO.BCM) # 创建两个LED控制线程 thread1 threading.Thread(targetled_controller, args(17, 0.5)) thread2 threading.Thread(targetled_controller, args(27, 1.0)) thread1.start() thread2.start() try: while True: time.sleep(1) except KeyboardInterrupt: GPIO.cleanup()在实际项目中我发现合理规划GPIO引脚的使用非常重要。特别是在同时使用多种外设时需要避免引脚功能冲突。例如某些引脚同时支持GPIO和SPI/I2C功能使用时需要特别注意。

更多文章