在樹莓派3B上使用RPi.GPIO

一直都據說樹莓派功能很強大,這幾天就買了個pi3試玩一下。拿到手裝好系統,就開始測試GPIO口,點亮一個LED。直接用python去操做GPIO好像不行,還好網上有不少python封裝包能夠用。RPi.GPIO使用比較簡單,官方主頁也給比較詳細的介紹也附帶了例子。python

RPi.GPIO主頁:https://sourceforge.net/p/raspberry-gpio-python/wiki/Home/git

官網介紹的是英文了,我本身寫了箇中文的使用手冊:函數

https://git.oschina.net/null_693_8693/RPi.GPIO-use-introduction/attach_files測試

RPi.GPIO是python調用包,提供了一些方法來操做樹莓派上GPIO引腳。使用python程序能夠很方便的調用這些方法。目前RPi.GPIO提供了GPIO輸入、輸出和軟件模擬PWM方法,惋惜的是暫不提供SPI、I2C、UART和硬件PWM方法。.net

使用不難,接下來我就來介紹下使用它的一些感覺吧。code

 

首先,既然是控制GPIO口,那就得看看它操做的速度了,雖然python是出了名的慢。token

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setup(35, GPIO.OUT)

start_time = time.time()
for i in range(0, 1000000):
    GPIO.output(35, 1)
    pass
end_time = time.time()

print(end_time - start_time)
GPIO.cleanup()

上面代碼我運行了五次,平均下來每次時間爲2.4396s。而後去除GPIO.output(35, 1),運行五次,每次平均時間爲0.5222s。有這些數據就能夠計算出執行1000000次GPIO.output(35, 1)的時間爲1.9174s,則每次執行GPIO.output(35, 1)時間是1.9us。個人個神啊太慢了吧,後面我又對輸出0和改爲輸入模式,測試的時間都基本同樣,一個字「慢」。如今不少8位單片機都比這速度快了。估計用這速度去軟件模擬SPI、I2C傳大點的數據是不行了。原本還想模擬個SPI驅動下TFT顯示屏,看到這速度只能放棄了。事件

 

RPi.GPIO有個相似硬件中斷的函數,挺好玩的。文檔

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(35, GPIO.IN, GPIO.PUD_DOWN)

def my_callback(channel):
    print('--my_callback start--')
    for i in range(0, 10000000):
        pass
    print('--my_callback end--')
GPIO.add_event_detect(35, GPIO.RISING, my_callback, bouncetime=200)

while True:
    time.sleep(1)
GPIO.cleanup()

GPIO.add_event_detect添加事件檢測,GPIO.RISING上升沿觸發,my_callback回調函數,它還有個防抖延時bouncetime(單位ms),免得咱們本身去軟件防抖。爲何我要加for i in range(0, 10000000)呢?我是想知道當中斷被觸發後但尚未退出來,再次給它個上升沿,它會不會再次進入回調函數呢?答案是不會。get

 

硬件中的中斷有嵌套關係,須要給每一箇中斷設定優先級。51類的需設定一個(不設定就默認),stm32要設置兩個:搶佔優先級和子優先級。RPi.GPIO主頁文檔中沒有說明這一點,我想經過一段代碼測試一下。

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup([35,37], GPIO.IN, GPIO.PUD_UP)

def my_callback_one(channel):
    print('--my_callback_one start--')
    for i in range(0, 100000):
        pass
    print('--my_callback_one end--')
def my_callback_two(channel):
    print('--my_callback_two start--')
    for i in range(0, 100000):
        pass
    print('--my_callback_two end--')
GPIO.add_event_detect(35, GPIO.FALLING, my_callback_one, bouncetime=200)
GPIO.add_event_detect(37, GPIO.FALLING, my_callback_two, bouncetime=200)

while True:
    time.sleep(1)
GPIO.cleanup()

我先是把35和37引腳連在一塊兒,同時給降低沿,發現它們雖然都被觸發了,但仍是會先執行一個,執行完後再執行下一個,而不會出現嵌套現象。而後我再嘗試先給35引腳一個降低沿,當35引腳的中斷被觸發,開始執行回調函數時但尚未退出回調的時候我立刻給37引腳一個降低沿,此時37引腳並無立刻被觸發去調用它的回調函數而是等35引腳的回調函數執行完才被觸發。把35引腳和37引腳順序調過來狀況也同樣。按理說樹莓派用3的BCM2837處理器的GPIO口中斷應該有嵌套、優先級的,估計已經被RPi.GPIO默認設置好了。可能被測試的引腳恰好被RPi.GPIO設置成優先級一個高一個低,不能被搶佔。

 

綜合上訴測試,RPi.GPIO能夠被利用到一些時序要求不高、小量數據傳輸、簡單IO操做的項目上。

RPi.GPIO還有其餘的一些用法,若是感興趣能夠下載我寫的 《RPi.GPIO使用手冊》或者到 RPi.GPIO主頁 查看。

相關文章
相關標籤/搜索