Python之树莓派GPIO篇:从零开始掌控硬件(完整版)

Python之树莓派GPIO篇:从零开始掌控硬件(完整版)

树莓派(Raspberry Pi)之所以如此受欢迎,很大程度上归功于它那排标志性的GPIO(通用输入输出)引脚。通过Python,你可以轻松地控制这些引脚,让树莓派与传感器、LED、电机、显示屏等物理世界交互。本文将系统性地带你从零开始,深入掌握使用Python控制树莓派GPIO的全部核心技能。


第一部分:GPIO基础认知

1.1 什么是GPIO?

GPIO是“通用输入/输出”(General Purpose Input/Output)的缩写,是树莓派与外部世界沟通的桥梁。通过编程,你可以:

  • **设置某个引脚为高电平(3.3V)或低电平(0V)**来控制外部设备(如点亮LED、驱动电机)
  • 读取某个引脚的电平状态来感知外部世界(如检测按钮是否被按下、读取传感器数据)

树莓派上的GPIO引脚本质上是芯片(Broadcom SoC)直接引出的接口,可以通过软件控制其行为。

1.2 GPIO引脚布局详解

树莓派主板上的40个引脚(部分早期型号为26脚)有着各自不同的功能。以最新型号为例,引脚按功能可分为以下几类:

电源引脚(POWER)

  • 提供稳定的3.3V或5V电压,用于为外部电路供电
  • 3.3V引脚:1号、17号(最大电流约50mA)
  • 5V引脚:2号、4号(最大电流取决于USB电源适配器)

接地引脚(GND)

  • 用于闭合电路,是任何电子项目的“负极”
  • 6号、9号、14号、20号、25号、30号、34号、39号

GPIO控制引脚

  • 这才是我们可以编程控制的引脚,数量有26个
  • 它们可以被灵活地设置为输入或输出模式
  • 部分引脚还具备特殊功能(如I2C、SPI、UART、PWM)

特殊功能引脚

功能引脚(BCM编号)用途
I2CBCM 2(SDA), BCM 3(SCL)连接I2C传感器
SPIBCM 7-11连接SPI设备(显示屏等)
UARTBCM 14(TX), BCM 15(RX)串口通信
PWMBCM 12, 13, 18, 19硬件PWM输出

💡 快速查询引脚功能
在树莓派终端输入 pinout 命令,系统会以清晰的图表显示你当前所用树莓派型号的完整GPIO引脚布局。或参考官方GPIO引脚图:

  +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+
  | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
  +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
  |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
  |   2 |   8 |   SDA.1 |   IN | 1 |  3 || 4  |   |      | 5v      |     |     |
  |   3 |   9 |   SCL.1 |   IN | 1 |  5 || 6  |   |      | 0v      |     |     |
  |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 0 | IN   | TxD     | 15  | 14  |
  |     |     |      0v |      |   |  9 || 10 | 1 | IN   | RxD     | 16  | 15  |
  |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |
  |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
  |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |
  |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |
  |  10 |  12 |    MOSI |   IN | 0 | 19 || 20 |   |      | 0v      |     |     |
  |   9 |  13 |    MISO |   IN | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |
  |  11 |  14 |    SCLK |   IN | 0 | 23 || 24 | 1 | IN   | CE0     | 10  | 8   |
  |     |     |      0v |      |   | 25 || 26 | 1 | IN   | CE1     | 11  | 7   |
  |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
  |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
  |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
  |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
  |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |
  |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |
  |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |
  +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+

1.3 GPIO的两种主流编码方式

使用Python的RPi.GPIO库时,首先要决定如何“指代”一个引脚,这需要在代码开头用 GPIO.setmode() 声明。

编码方式说明使用场景
BOARD使用引脚在物理排针上的位置编号(1至40)推荐新手,最直观,和GPIO图一一对应
BCM使用Broadcom SoC的通道编号官方习惯,但需对照引脚图查找

示例:

import RPi.GPIO as GPIO

# 方式一:使用物理引脚编号(推荐)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT) # 将物理引脚11(对应BCM17)设置为输出

# 方式二:使用BCM编号
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT) # 将BCM17设置为输出

⚠️ 注意
一旦选择了一种编码方式,整个程序中必须保持一致,混用会导致引脚混淆。


第二部分:RPi.GPIO核心库详解

RPi.GPIO是Python控制GPIO的核心库,在官方Raspberry Pi OS中已预装。如需手动安装:

sudo apt update
sudo apt install python3-rpi.gpio

2.1 基础用法四步走

第一步:导入库并设置编码

这是所有GPIO程序的标准开头。

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)  # 选择你习惯的编码方式
GPIO.setwarnings(False)   # 可选:关闭警告信息

第二步:初始化引脚模式

使用 GPIO.setup(pin, mode) 来设置引脚是输入还是输出。

GPIO.setup(12, GPIO.OUT)   # 将物理引脚12设置为输出模式
GPIO.setup(16, GPIO.IN)    # 将物理引脚16设置为输入模式

# 设置输出引脚的初始状态
GPIO.setup(12, GPIO.OUT, initial=GPIO.HIGH)  # 初始为高电平

# 设置输入引脚的上拉/下拉电阻
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)   # 上拉电阻
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # 下拉电阻

第三步:读/写引脚数据

  • 写入:用 GPIO.output(pin, state) 让输出引脚输出高或低电平。
GPIO.output(12, GPIO.HIGH)   # 引脚12输出高电平(3.3V)
GPIO.output(12, GPIO.LOW)    # 引脚12输出低电平(0V)
  • 读取:用 GPIO.input(pin) 读取输入引脚的电平状态,返回 GPIO.HIGH(1)或 GPIO.LOW(0)。
state = GPIO.input(16)       # 读取引脚16的状态
if state == GPIO.HIGH:
    print("引脚16检测到高电平")
else:
    print("引脚16检测到低电平")

第四步:清理引脚

程序结束时,务必调用 GPIO.cleanup() 来释放资源,将所有引脚恢复到默认状态,避免后续程序出问题。

GPIO.cleanup()          # 清理所有引脚
GPIO.cleanup(12)        # 仅清理指定引脚

2.2 完整代码模板

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)

# 定义引脚
LED_PIN = 33
BUTTON_PIN = 31

# 初始化
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

print("程序启动,按Ctrl+C退出")
try:
    while True:
        if GPIO.input(BUTTON_PIN) == GPIO.LOW:
            GPIO.output(LED_PIN, GPIO.HIGH)
        else:
            GPIO.output(LED_PIN, GPIO.LOW)
        time.sleep(0.01)
except KeyboardInterrupt:
    print("程序被手动终止")
finally:
    GPIO.cleanup()
    print("GPIO清理完成")

第三部分:动手实验

3.1 实验一:点亮LED

通过一个最简单的“点亮LED”实验,快速理解GPIO的输出功能。

硬件连接(以物理引脚为例):

  • LED的正极(长脚)通过一个限流电阻(约220Ω)连接到树莓派的 GPIO输出引脚(例如物理引脚33)
  • LED的负极(短脚)连接到树莓派的 GND引脚(例如物理引脚34)

⚠️ 安全提示
树莓派GPIO引脚只能提供约3.3V电压和很低的电流(最大约16mA),必须串联限流电阻(220Ω-1kΩ),否则可能会烧坏LED或GPIO引脚。

树莓派 (物理引脚33) --- 220Ω电阻 --- [LED+ (长脚)] --- [LED- (短脚)] --- GND (物理引脚34)

Python代码

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
LED_PIN = 33
GPIO.setup(LED_PIN, GPIO.OUT)

print("开始闪烁LED")
try:
    while True:
        GPIO.output(LED_PIN, GPIO.HIGH)
        print("LED点亮")
        time.sleep(1)
        GPIO.output(LED_PIN, GPIO.LOW)
        print("LED熄灭")
        time.sleep(1)
except KeyboardInterrupt:
    print("程序被手动终止")
finally:
    GPIO.cleanup()

运行

sudo python led_blink.py

3.2 实验二:读取按钮输入

使用按键检测GPIO的输入功能。

硬件连接

  • 按钮一端连接到树莓派的 GPIO输入引脚(如物理引脚31)
  • 按钮另一端连接到 GND
  • 在GPIO引脚和3.3V之间连接一个上拉电阻(10kΩ),或使用GPIO内置上拉

两种接法对比

接法GPIO初始状态按钮按下时优点缺点
上拉电阻HIGHLOW信号稳定,抗干扰强需要外部电阻
下拉电阻LOWHIGH信号稳定,抗干扰强需要外部电阻
浮空输入不确定-无需电阻信号不稳定,不推荐

推荐方案:使用GPIO内置上拉电阻,无需外部电阻:

树莓派 (物理引脚31) --- 按钮 --- GND (物理引脚34)

Python代码

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
BUTTON_PIN = 31

# 启用内置上拉电阻
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

print("等待按钮按下...")
try:
    while True:
        if GPIO.input(BUTTON_PIN) == GPIO.LOW:
            print("按钮被按下!")
            time.sleep(0.3)  # 简单消抖
except KeyboardInterrupt:
    print("程序终止")
finally:
    GPIO.cleanup()

3.3 实验三:按钮控制LED

结合输入和输出,制作一个按钮开关灯。

硬件连接

  • 按钮:物理引脚31到GND(使用上拉电阻)
  • LED:物理引脚33经220Ω电阻到GND

Python代码

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

LED_PIN = 33
BUTTON_PIN = 31

GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

print("按钮按下时LED点亮,松开熄灭")
try:
    while True:
        if GPIO.input(BUTTON_PIN) == GPIO.LOW:
            GPIO.output(LED_PIN, GPIO.HIGH)
        else:
            GPIO.output(LED_PIN, GPIO.LOW)
        time.sleep(0.01)
except KeyboardInterrupt:
    print("程序终止")
finally:
    GPIO.cleanup()

3.4 实验四:按钮切换LED(自锁开关)

每次按下按钮切换LED的状态。

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

LED_PIN = 33
BUTTON_PIN = 31

GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

led_state = False
last_button_state = GPIO.HIGH

print("每次按下按钮切换LED状态")
try:
    while True:
        button_state = GPIO.input(BUTTON_PIN)
        # 检测下降沿(从HIGH到LOW)
        if last_button_state == GPIO.HIGH and button_state == GPIO.LOW:
            led_state = not led_state
            GPIO.output(LED_PIN, GPIO.HIGH if led_state else GPIO.LOW)
            print("LED", "点亮" if led_state else "熄灭")
            time.sleep(0.2)  # 消抖
        last_button_state = button_state
        time.sleep(0.01)
except KeyboardInterrupt:
    print("程序终止")
finally:
    GPIO.cleanup()

第四部分:PWM与呼吸灯

PWM(脉冲宽度调制)技术可以让数字信号模拟出模拟信号的效果,最经典的例子就是控制LED的亮度和电机转速。

4.1 PWM原理详解

PWM通过在一个固定周期内快速切换高电平和低电平,并调整高电平所占的时间比例(即占空比) 来实现“看起来”的不同亮度。占空比越大,LED就越亮。

占空比效果
0%LED完全熄灭
25%LED亮度约25%
50%LED亮度为50%
75%LED亮度约75%
100%LED完全点亮

树莓派提供两种PWM方式:

  • 软件PWM:由CPU模拟,精度较低,占用CPU资源
  • 硬件PWM:由专用硬件产生,精度高,不占用CPU(支持BCM 12, 13, 18, 19)

4.2 RPi.GPIO实现呼吸灯

使用RPi.GPIO库的PWM功能,实现让LED像呼吸一样柔和变化。

硬件连接:同实验一(LED接物理引脚33)

Python代码

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
LED_PIN = 33
GPIO.setup(LED_PIN, GPIO.OUT)

# 创建PWM实例:频率100Hz
p = GPIO.PWM(LED_PIN, 100)
p.start(0)  # 以0%占空比启动(LED熄灭)

print("呼吸灯效果,按Ctrl+C退出")
try:
    while True:
        # 渐亮:从0%到100%
        for dc in range(0, 101, 2):
            p.ChangeDutyCycle(dc)
            time.sleep(0.02)
        # 渐暗:从100%到0%
        for dc in range(100, -1, -2):
            p.ChangeDutyCycle(dc)
            time.sleep(0.02)
except KeyboardInterrupt:
    print("程序终止")
finally:
    p.stop()
    GPIO.cleanup()

参数调优

  • frequency(频率):50-200Hz适合LED,20-50kHz适合电机
  • sleep(步进延时):值越小变化越平滑,值越大变化越快
  • step(步长):值越小变化越细腻

4.3 使用硬件PWM

如果希望更精确的PWM控制,可以使用硬件PWM引脚(BCM 12, 13, 18, 19)。以BCM 18(物理引脚12)为例:

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)  # 使用BCM编号
PWM_PIN = 18            # BCM 18对应硬件PWM

GPIO.setup(PWM_PIN, GPIO.OUT)
p = GPIO.PWM(PWM_PIN, 1000)  # 1kHz频率
p.start(0)

try:
    while True:
        for duty in range(0, 101, 1):
            p.ChangeDutyCycle(duty)
            time.sleep(0.01)
        for duty in range(100, -1, -1):
            p.ChangeDutyCycle(duty)
            time.sleep(0.01)
except KeyboardInterrupt:
    pass
finally:
    p.stop()
    GPIO.cleanup()

第五部分:传感器实战

5.1 温度传感器DHT11

DHT11是最常用的温湿度传感器之一,单总线通信。

硬件连接

  • VCC → 3.3V(物理引脚1)
  • GND → GND
  • DATA → GPIO引脚(如物理引脚29,BCM 5)

安装依赖库

sudo pip3 install Adafruit-DHT

Python代码

#!/usr/bin/python
# coding:utf-8
import Adafruit_DHT
import time

DHT_SENSOR = Adafruit_DHT.DHT11
DHT_PIN = 5  # BCM编号

print("读取DHT11温湿度数据")
try:
    while True:
        humidity, temperature = Adafruit_DHT.read(DHT_SENSOR, DHT_PIN)
        if humidity is not None and temperature is not None:
            print(f"温度: {temperature:.1f}°C  湿度: {humidity:.1f}%")
        else:
            print("读取失败,重试...")
        time.sleep(2)
except KeyboardInterrupt:
    print("程序终止")

5.2 超声波测距模块HC-SR04

通过发出超声波并接收回波来测量距离。

硬件连接

  • VCC → 5V(物理引脚2或4)
  • GND → GND
  • TRIG → GPIO引脚(如物理引脚31)
  • ECHO → GPIO引脚(需注意3.3V电平兼容)

⚠️ 注意:HC-SR04的ECHO引脚输出5V信号,需要用电阻分压或电平转换模块,否则会损坏树莓派。

Python代码

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

TRIG = 31
ECHO = 33

GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)

def get_distance():
    GPIO.output(TRIG, GPIO.LOW)
    time.sleep(0.000002)
    GPIO.output(TRIG, GPIO.HIGH)
    time.sleep(0.000010)
    GPIO.output(TRIG, GPIO.LOW)

    # 等待ECHO变高
    while GPIO.input(ECHO) == GPIO.LOW:
        pulse_start = time.time()

    # 等待ECHO变低
    while GPIO.input(ECHO) == GPIO.HIGH:
        pulse_end = time.time()

    pulse_duration = pulse_end - pulse_start
    distance = pulse_duration * 17150  # 声速343m/s,往返除以2
    return distance

print("超声波测距开始")
try:
    while True:
        dist = get_distance()
        print(f"距离: {dist:.1f} cm")
        time.sleep(0.5)
except KeyboardInterrupt:
    print("程序终止")
finally:
    GPIO.cleanup()

5.3 光敏传感器

使用光敏电阻和ADC(模数转换器)读取光照强度。如果需要读取模拟信号,可使用MCP3008等ADC芯片。

硬件连接(使用MCP3008,通过SPI通信):

  • MCP3008 VDD → 3.3V
  • MCP3008 VREF → 3.3V
  • MCP3008 AGND → GND
  • MCP3008 CLK → GPIO 11(SPI CLK)
  • MCP3008 DOUT → GPIO 9(SPI MISO)
  • MCP3008 DIN → GPIO 10(SPI MOSI)
  • MCP3008 CS → GPIO 8(SPI CE0)

安装依赖

sudo pip3 install spidev

Python代码

#!/usr/bin/python
# coding:utf-8
import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1350000

def read_adc(channel):
    if channel < 0 or channel > 7:
        return -1
    # 发送读取命令
    r = spi.xfer2([1, (8 + channel) << 4, 0])
    adc_value = ((r[1] & 3) << 8) + r[2]
    return adc_value

try:
    while True:
        light_value = read_adc(0)
        print(f"光照值: {light_value}")
        time.sleep(0.5)
except KeyboardInterrupt:
    print("程序终止")
finally:
    spi.close()

第六部分:中断与事件检测

使用 GPIO.add_event_detect() 可以在引脚状态变化时触发回调函数,无需循环轮询,效率更高。

6.1 事件检测基础

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
BUTTON_PIN = 31
LED_PIN = 33

GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)

def button_callback(channel):
    print("按钮按下!")
    GPIO.output(LED_PIN, GPIO.HIGH)
    time.sleep(0.5)
    GPIO.output(LED_PIN, GPIO.LOW)

# 检测下降沿触发
GPIO.add_event_detect(BUTTON_PIN, GPIO.FALLING,
                      callback=button_callback,
                      bouncetime=200)  # 消抖时间200ms

print("等待按钮事件...")
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("程序终止")
finally:
    GPIO.cleanup()

6.2 多种边沿触发方式

触发方式说明
GPIO.RISING检测上升沿(低电平→高电平)
GPIO.FALLING检测下降沿(高电平→低电平)
GPIO.BOTH检测上升沿和下降沿

6.3 同时检测多个引脚

GPIO.add_event_detect(31, GPIO.FALLING, callback=func1, bouncetime=200)
GPIO.add_event_detect(33, GPIO.RISING, callback=func2, bouncetime=200)

第七部分:扩展库与替代方案

7.1 常用GPIO库对比

库名特点适用场景
RPi.GPIO最基础,预装,简单易用新手入门,简单项目
gpiozero更高级的封装,对象化接口推荐新手,更Pythonic
pigpio硬件PWM,精确时序,支持网络控制需要高精度PWM或远程控制
WiringPi源自Arduino风格,C/Python支持Arduino用户迁移
periphery跨平台,支持多种接口需要跨平台兼容

7.2 gpiozero示例(更简洁)

gpiozero是官方推荐的高级库,接口更加友好。

安装

sudo apt install python3-gpiozero

点亮LED

from gpiozero import LED
from time import sleep

led = LED(17)  # BCM编号
while True:
    led.on()
    sleep(1)
    led.off()
    sleep(1)

按钮控制LED

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()

PWM呼吸灯

from gpiozero import PWMLED
from time import sleep

led = PWMLED(17)

while True:
    led.value = 0.0
    sleep(1)
    for i in range(0, 101, 1):
        led.value = i / 100
        sleep(0.02)
    for i in range(100, -1, -1):
        led.value = i / 100
        sleep(0.02)

7.3 pigpio高级应用

适用于需要精确PWM或远程网络控制的场景。

启动pigpiod服务

sudo systemctl enable pigpiod
sudo systemctl start pigpiod

Python示例

import pigpio
import time

pi = pigpio.pi()
pi.set_mode(17, pigpio.OUTPUT)

# 硬件PWM输出
pi.hardware_PWM(12, 1000, 500000)  # 1kHz, 50%占空比

# 读取GPIO
state = pi.read(17)

pi.stop()

第八部分:安全与最佳实践

8.1 电气安全

原则说明
3.3V逻辑电平树莓派GPIO是3.3V逻辑电平,连接5V设备会导致永久损坏
限流电阻所有LED必须串联220Ω-1kΩ的限流电阻
电流限制每个GPIO引脚最大输出电流约16mA,所有引脚总和不超过50mA
电源设计驱动电机等大功率设备必须使用外接电源和驱动电路
电平转换连接5V传感器时使用电平转换模块(如TXS0108E)

8.2 软件最佳实践

  • 使用 try...except...finally:确保 GPIO.cleanup() 始终被执行
  • 设置 GPIO.setwarnings(False):避免重复引脚设置警告
  • 合理使用上拉/下拉电阻:避免引脚浮空导致信号不稳定
  • 消抖处理:机械开关/按钮必须做消抖(软件延时或硬件电容)
  • 避免阻塞循环:使用事件检测替代轮询,提高响应效率

8.3 常见问题排查

问题可能原因解决方案
LED不亮引脚接错或电阻太大检查接线,减少电阻
引脚没有权限未使用sudo运行sudo python script.py
信号不稳定引脚浮空启用上拉/下拉电阻
按钮误触发机械抖动增加消抖时间 bouncetime=200
GPIO已占用上次未清理运行 GPIO.cleanup() 或重启

第九部分:项目实战

9.1 智能交通灯系统

使用3个LED模拟交通灯逻辑。

硬件连接

  • 红灯 → 物理引脚33
  • 黄灯 → 物理引脚31
  • 绿灯 → 物理引脚29
  • 按钮(行人过街)→ 物理引脚27

Python代码

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

RED = 33
YELLOW = 31
GREEN = 29
BUTTON = 27

GPIO.setup(RED, GPIO.OUT)
GPIO.setup(YELLOW, GPIO.OUT)
GPIO.setup(GREEN, GPIO.OUT)
GPIO.setup(BUTTON, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def traffic_light_state(state):
    GPIO.output(RED, GPIO.LOW)
    GPIO.output(YELLOW, GPIO.LOW)
    GPIO.output(GREEN, GPIO.LOW)

    if state == "red":
        GPIO.output(RED, GPIO.HIGH)
    elif state == "yellow":
        GPIO.output(YELLOW, GPIO.HIGH)
    elif state == "green":
        GPIO.output(GREEN, GPIO.HIGH)

def pedestrian_crossing():
    print("行人过街请求")
    # 黄灯闪烁
    for i in range(3):
        traffic_light_state("yellow")
        time.sleep(0.5)
        traffic_light_state("off")
        time.sleep(0.5)
    # 红灯
    traffic_light_state("red")
    time.sleep(3)
    # 恢复绿灯
    traffic_light_state("green")

print("交通灯系统启动")
traffic_light_state("green")
try:
    while True:
        # 检测按钮
        if GPIO.input(BUTTON) == GPIO.LOW:
            pedestrian_crossing()
            time.sleep(1)
        time.sleep(0.1)
except KeyboardInterrupt:
    print("程序终止")
finally:
    GPIO.cleanup()

9.2 家庭安全报警系统

使用PIR人体红外传感器和蜂鸣器。

硬件连接

  • PIR传感器 VCC → 5V(物理引脚2)
  • PIR传感器 GND → GND
  • PIR传感器 OUT → GPIO(如物理引脚29)
  • 蜂鸣器 → GPIO(如物理引脚31)

Python代码

#!/usr/bin/python
# coding:utf-8
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

PIR_PIN = 29
BUZZER_PIN = 31

GPIO.setup(PIR_PIN, GPIO.IN)
GPIO.setup(BUZZER_PIN, GPIO.OUT, initial=GPIO.LOW)

def alarm():
    for i in range(3):
        GPIO.output(BUZZER_PIN, GPIO.HIGH)
        time.sleep(0.2)
        GPIO.output(BUZZER_PIN, GPIO.LOW)
        time.sleep(0.1)

print("安防系统启动,检测到移动将报警")
try:
    while True:
        if GPIO.input(PIR_PIN) == GPIO.HIGH:
            print("检测到移动!")
            alarm()
            time.sleep(2)
        time.sleep(0.1)
except KeyboardInterrupt:
    print("程序终止")
finally:
    GPIO.cleanup()

掌握了这些核心概念、工具和实践案例,你就为更复杂的树莓派硬件项目(如机器人控制、智能家居、物联网设备等)打下了坚实的基础。现在,拿出你的树莓派和传感器,开始你的硬件编程之旅吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王小玗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值