1. 程式人生 > >樹莓派RPi.GPIO使用手冊

樹莓派RPi.GPIO使用手冊

參考源:http://blog.csdn.net/qq_35893742/article/details/53428679

1.RPi.GPIO模組基本使用

匯入模組

匯入 RPi.GPIO 模組:

import RPi.GPIO as GPIO
  • 1

通過下面的程式碼可以檢測匯入是否成功

try:
    import RPi.GPIO as GPIO
except RuntimeError:
    print("Error importing RPi.GPIO!  This is probably because you need superuser privileges.  You can achieve this by using 'sudo' to run your script"
)
  • 1
  • 2
  • 3
  • 4

引腳編號方式

RPi.GPIO中有兩種引腳的編號方式。第一個是使用電路板編號系統。這指的是在樹莓派電路板上P1開頭的。使用這個編號系統的優勢是,您的硬體將總是工作,不管電路板是哪個版本的。你不需要重新修改程式碼。
第二個編號系統是BCM數字。這是一個低水平的工作方式,它指的是電路板引腳的位置號。電路板版本變化時指令碼程式需要對應修改。 
必須指定使用哪種:

GPIO.setmode(GPIO.BOARD)
  # or
GPIO.setmode(GPIO.BCM)
  • 1
  • 2
  • 3

可以查詢使用的哪種編號方法

mode = GPIO.getmode()
#輸出: GPIO.BOARD, GPIO.BCM or None
  • 1
  • 2

設定一個通道

作為輸入

GPIO.setup(channel, GPIO.IN)
#chanel與使用的編號方式對應
  • 1
  • 2

作為輸出:

GPIO.setup(channel, GPIO.OUT)
GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)
  • 1
  • 2

設定多個通道

chan_list = [11,12]    # add as many channels as you want!
GPIO.setup(chan_list, GPIO.OUT)
  • 1
  • 2

輸入

讀取一個GPIO口的值

GPIO.input(channel)
#返回:0 / GPIO.LOW / False or 1 / GPIO.HIGH / True.
  • 1
  • 2

輸出

設定一個GPIO口的輸出值

GPIO.output(channel, state)
#State 可以是 0 / GPIO.LOW / False or 1 / GPIO.HIGH / True.
  • 1
  • 2

設定多個通道的輸出

chan_list = [11,12]           # also works with tuples
GPIO.output(chan_list, GPIO.LOW)   # sets all to GPIO.LOW
GPIO.output(chan_list, (GPIO.HIGH, GPIO.LOW))
# sets first HIGH and second LOW
  • 1
  • 2
  • 3
  • 4

清空

在程式的末尾可以加上

GPIO.cleanup()
  • 1

如果想清理特定的通道

GPIO.cleanup(channel)
GPIO.cleanup( (channel1, channel2) )
GPIO.cleanup( [channel1, channel2] )
  • 1
  • 2
  • 3

2.GPIO 輸入

要得到GPIO輸入到你的程式的幾種方法。第一個和最簡單的方法是在時間點上檢查輸入值。這被稱為“輪詢”,如果你的程式在錯誤的時間讀取值,可能會錯過一個輸入。輪詢是在迴圈中進行的。另外一種方法來響應一個GPIO輸入是使用“中斷”(邊沿檢測)。邊沿是由高到低(下降沿)或低到高(上升沿)的過渡的名稱。

上拉或者下拉電阻

如果您沒有連線到任何硬體的輸入引腳,它將’浮動’。換句話說,讀取的值是未定義的,因為它沒有連線到任何事情,直到你按一個按鈕或開關。由於受電干擾,它的值可能會改變。
為了實現這一點,我們使用了上拉或下拉電阻。以這種方式,可以設定輸入的預設值。在硬體和軟體上有上拉/下拉電阻是可能的。在硬體上,在輸入通道和3.3V(上拉)之間的或0V(下拉)使用10K電阻是常用的。通過rpi.gpio模組配置GPIO口可以實現同樣的功能

GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  # or
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
  • 1
  • 2
  • 3

測試輸入(輪詢)

可以在一個時間點檢視輸入

if GPIO.input(channel):
    print('Input was HIGH')
else:
    print('Input was LOW')
  • 1
  • 2
  • 3
  • 4

在迴圈中使用輪詢來檢測按鈕是否按下

while GPIO.input(channel) == GPIO.LOW:
    time.sleep(0.01)  # wait 10 ms to give CPU chance to do other things
  • 1
  • 2

中斷與邊沿檢測

邊沿是電訊號從低到高(上升沿)或從高到低(下降沿)的改變。這種改是一種事件,為了使程式在執行的過程中檢測到按鈕按下這樣的事件: 
• wait_for_edge() 
• event_detected() 
• 另外一個執行緒的回撥方法 
wait_for_edge()方法不會執行,只到檢測到邊沿,檢測按鈕按下也可以寫成:

GPIO.wait_for_edge(channel, GPIO.RISING)
  • 1

這種檢測邊沿( GPIO.RISING, GPIO.FALLING or GPIO.BOTH)的優勢是使用CPU的資源很少 
可以加一個timeout引數

#wait for up to 5 seconds for a rising edge (timeout is in milliseconds)
channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000)
if channel is None:
    print('Timeout occurred')
else:
    print('Edge detected on channel', channel)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

event_detected()方法是用在迴圈事件中,在Pygame或PyQt這種存在一個主迴圈監聽GUI時非常有用.

GPIO.add_event_detect(channel, GPIO.RISING)  # add rising edge detection on a channel
do_something()
if GPIO.event_detected(channel):
    print('Button pressed')
  • 1
  • 2
  • 3
  • 4

執行緒回撥

RPi.GPIO執行第二個執行緒來處理回撥函式:

def my_callback(channel):
    print('This is a edge event callback function!')
    print('Edge detected on channel %s'%channel)
    print('This is run in a different thread to your main program')

GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback)  # add rising edge detection on a channel
...the rest of your program...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

多個回撥函式:

def my_callback_one(channel):
    print('Callback one')

def my_callback_two(channel):
    print('Callback two')

GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, my_callback_one)
GPIO.add_event_callback(channel, my_callback_two)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

這裡的回撥函式是按順序執行的,不是同時執行的,因為只有一個程序(process)在執行

開關去抖

開關在按下的過程中回撥函式會執行多次,這是因為開關按下的過程中由於抖動產生多個邊沿的原因,下面的方法可以解決這個問題: 
• 增加一個0.1uF的電容與開關串接 
• 軟體去抖 
• 結合上述兩種方法 
在程式中增加一個bouncetime引數可以現實去抖:

# add rising edge detection on a channel, ignoring further edges for 200ms for switch bounce handling
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200)
or
GPIO.add_event_callback(channel, my_callback, bouncetime=200)
  • 1
  • 2
  • 3
  • 4

移除事件監聽

GPIO.remove_event_detect(channel)
  • 1

3.GPIO 輸出

設定RPi.GPIO

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
  • 1
  • 2
  • 3
  • 設定為高電平輸出:
GPIO.output(12, GPIO.HIGH)
 # or
GPIO.output(12, 1)
 # or
GPIO.output(12, True)
  • 1
  • 2
  • 3
  • 4
  • 5

設定低電平輸出

GPIO.output(12, GPIO.LOW)
 # or
GPIO.output(12, 0)
 # or
GPIO.output(12, False)
  • 1
  • 2
  • 3
  • 4
  • 5

同時設定多個通道的輸出

chan_list = (11,12)
GPIO.output(chan_list, GPIO.LOW) # all LOW
GPIO.output(chan_list, (GPIO.HIGH,GPIO.LOW))  # first LOW, second HIGH
  • 1
  • 2
  • 3

清空

GPIO.cleanup()
input()方法可以讀取目前通道的輸出:
GPIO.output(12, not GPIO.input(12))
  • 1
  • 2
  • 3

4.PWM(脈衝寬度調製)

建立PWM 例項

p = GPIO.PWM(channel, frequency)
  • 1

啟動PWM

p.start(dc)   # where dc is the duty cycle (0.0 <= dc <= 100.0)
  • 1

改變頻率

p.ChangeFrequency(freq)   # where freq is the new frequency in Hz
  • 1

改變佔空比

p.ChangeDutyCycle(dc)  # where 0.0 <= dc <= 100.0
  • 1

停止PWM

p.stop()
  • 1

變數P超出範圍時PWM也會停止.

LED每兩秒閃爍一次:

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)

p = GPIO.PWM(12, 0.5)
p.start(1)
input('Press return to stop:')   # use raw_input for Python 2
p.stop()
GPIO.cleanup()
An example to brighten/dim an LED:
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)

p = GPIO.PWM(12, 50)  # channel=12 frequency=50Hz
p.start(0)
try:
    while 1:
        for dc in range(0, 101, 5):
            p.ChangeDutyCycle(dc)
            time.sleep(0.1)
        for dc in range(100, -1, -5):
            p.ChangeDutyCycle(dc)
            time.sleep(0.1)
except KeyboardInterrupt:
    pass
p.stop()
GPIO.cleanup()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

gpio_function(channel) 
顯示一個GPIO口的功能:

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
func = GPIO.gpio_function(pin)
#返回值:GPIO.IN, GPIO.OUT, GPIO.SPI, GPIO.I2C, GPIO.HARD_PWM, GPIO.SERIAL, GPIO.UNKNOWN
  • 1
  • 2
  • 3
  • 4
  • 5