一直都据说树莓派功能很强大,这几天就买了个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主页 查看。