3.1.2 GPIO应用
开发板预置了 GPIO Python 库 Hobot.GPIO,用户可以通过如下命令导入GPIO库。
sunrise@ubuntu:~$ sudo python3
Python 3.8.10 (default, Mar 15 2022, 12:22:08)
Type "help", "copyright", "credits" or "license" for more information.
>>> import Hobot.GPIO as GPIO
>>> GPIO.VERSION
'0.0.2'
>>> GPIO.model
'RDK_X5'
设置引脚编码方式
开发板的引脚编码有 4 种模式:
- BOARD:物理引脚序号,与开发板的丝印序号一一对应。
- BCM:根据博通SoC制定的GPIO命名规则。
- CVM: 使用字符串代替数字,对应于CVM / CVB连接器的信号名称。
- SOC: 对应的编号是芯片内部的 GPIO 管脚序号。
本文推荐用户使用BOARD编码模式,设置编码的方式如下:
注意:编码每次只能设置一次,如果想要重新设置,需要GPIO.cleanup()后重新设置
GPIO.setmode(GPIO.BOARD)
# or
GPIO.setmode(GPIO.BCM)
# or
GPIO.setmode(GPIO.CVM)
# or
GPIO.setmode(GPIO.SOC)
查询编码方式:
GPIO.getmode()
程序会输出 BOARD, BCM, CVM, SOC or None 其中的一种结果。
警告信息
以下几种情况下运行代码,会有警告日志输出,但并不会影响正常功能:
- 用户尝试使用的GPIO,已在其他应用程序中使用;
- 在设置模式和通道之前,尝试调用
GPIO.cleanup清理管脚;
如要屏蔽警告信息,可通过如下命令实现:
GPIO.setwarnings(False)
管脚配置
GPIO管脚在使用之前,需要进行相应的配置,具体如下:
设置为输入的方式如下:
GPIO.setup(channel, GPIO.IN)
设置为输出的方式如下:
GPIO.setup(channel, GPIO.OUT)
也可以为输出通道指定一个初始值,例如:
GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)
另外,工具支持同时设置多个输出通道,例如:
# set gpio(18,12,13) to output
channels = [18, 12, 13]
GPIO.setup(channels, GPIO.OUT)
输入操作
要读取通道的值,请使用:
GPIO.input(channel)
命令返回值为 0 或者 1。 0 代表 GPIO.LOW, 1 代表 GPIO.HIGH。
输出操作
要设置通道的输出值,请使用:
GPIO.output(channel, state)
其中 state 可以是 GPIO.LOW 或 GPIO.HIGH。
清理管脚占用
在程序推出前,推荐进行通道清理动作,请使用:
GPIO.cleanup()
如果只想清理特定通道,请使用:
# 清除单个通道
GPIO.cleanup(channel)
# 清除一组通道
GPIO.cleanup( (channel1, channel2) )
GPIO.cleanup( [channel1, channel2] )
查看管脚状态
此功能允许您检查对应 GPIO 通道的功能:
GPIO.gpio_function(channel)
该函数返回 IN 或 OUT。
边沿检测与中断
边沿是电信号从低到高(上升沿)或从高到低(下降沿)的变化,这种改变可以看作是一种事件的发生,这种事件可以用来触发CPU中断信号。
在RDK Ultra平台上,40pin上只有特定几个管脚才能作为中断管脚使用,它们在BOARD编码模式下的编号为:13、16、18、22、27、28、32、33、37
管脚定义请参考 管脚配置与定义
GPIO库提供了三种方法来检测输入事件:
wait_for_edge() 函数
此函数阻塞调用线程,直到检测到对应的边缘变化。函数调用如下:
GPIO.wait_for_edge(channel, GPIO.RISING)
其中,第二个参数指定要检测的边沿,取值范围为GPIO.RISING、GPIO.FALLING 或 GPIO.BOTH。如果要指定等待时间,可以选择设置超时:
# 超时以毫秒为单位
GPIO.wait_for_edge(channel, GPIO.RISING, timeout=500)
在超时时间内外部信号发生变化,函数返回检测的通道号;如果发生超时,函数返回None。
event_detected() 函数
此函数可用于定期检查自上次调用以来是否发生了事件。该函数可以按如下方式设置和调用:
# 在通道GPIO上设置上升沿检测
GPIO.add_event_detect(channel, GPIO.RISING)
if GPIO.event_detected(channel):
print("Rising edge event detected")
您可以检测 GPIO.RISING、GPIO.FALLING 或 GPIO.BOTH 的事件。
检测到边沿事件时运行回调函数
此功能可用于注册回调函数,回调函数运行在独立的处理线程中,使用说明如下:
# define callback function
def callback_fn(channel):
print("Callback called from channel %s" % channel)
# enable rising detection
GPIO.add_event_detect(channel, GPIO.RISING, callback=callback_fn)
如有需要,也可以添加多个回调,方法如下:
def callback_one(channel):
print("First Callback")
def callback_two(channel):
print("Second Callback")
GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, callback_one)
GPIO.add_event_callback(channel, callback_two)
由于所有回调函数运行在同一线程上,因此不同的回调是按顺序运行的,而不是同时运行。
为了通过将多个事件合并为一个事件来防止多次调用回调函数,可以选择设置去抖动时间:
# bouncetime unit is ms
GPIO.add_event_detect(channel, GPIO.RISING, callback=callback_fn, bouncetime=200)