我在嵌入式系统(ARM核心)上试验Python的GPIO访问,该系统运行的是用Buildroot(内核4.1.15)构建的linux。
我希望我的代码BLOCK等待GPIO2上的引脚更改(即我不想通过反复调用“read”来轮询引脚)。我试图在边缘触发模式下使用“epoll”来做到这一点:
见Python docs for epoll。 select.EPOLLET 标志用于获取epoll的边缘触发。另请参阅Linux docs for epoll。
为简单起见,我已经使用sysfs:
从控制台设置了我的GPIO引脚# cat /sys/class/gpio/gpio2/direction
in
# cat /sys/class/gpio/gpio2/edge
rising
这是我的Python代码:
#!/usr/bin/env python
# coding=utf8
from time import sleep
import select
import sys
if __name__ == '__main__':
try:
pinIn = open("/sys/class/gpio/gpio2/value", "r")
except IOError:
print("Error setting up GPIO pin")
sys.exit()
myPoll = select.epoll()
myPoll.register(pinIn.fileno(), select.EPOLLPRI | select.EPOLLET)
while(1):
events = myPoll.poll(4)
print("EPoll result: %s" % (str(events),))
for fd, event_type in events:
print("FD: %d; Events: %d" % (fd, event_type))
if event_type & select.EPOLLIN:
print("-EPOLLIN!")
if event_type & select.EPOLLPRI:
print("-EPOLLPRI!")
if event_type & select.EPOLLERR:
print("-EPOLLERR!")
value = pinIn.read(1)
pinIn.seek(0)
print("--> %s" % (str(value),))
sleep(1)
为了进行测试,我使用来自信号发生器的方波输入引脚,每个周期大约2秒,所以我可以看到引脚何时发生变化。
当我在嵌入式系统上运行时,我得到了这个:
# python3 /usr/sbin/test-gpio-python.py
EPoll result: [(3, 10)]
FD: 3; Events: 10
-EPOLLPRI!
-EPOLLERR!
--> 0
代码在1秒睡眠时休眠,然后在下一次迭代中,poll()立即返回并且不会阻塞。它应该阻止,因为我的输入仅在每2秒一个上升沿运行。
为什么“poll()”阻止?
====编辑:====
最初,当我尝试使用“select.EPOLLET”时,代码导致了一个奇怪的错误:
OverflowError: can't convert negative value to unsigned int
但是,我发现我不小心使用了 myPoll = select.poll()而不是 epoll()。代码现已修复。
答案 0 :(得分:0)
我决定通过查看 / proc / interrupts 来检查中断信息。
在这里,只需几秒钟就可以将边缘设置为"上升"对于GPIO引脚:
# cat /proc/interrupts
...
33: 421 gpio-mxc 2 Edge gpiolib
...
嗯,已经发生了421次中断!
两秒钟后:
# cat /proc/interrupts
...
33: 852 gpio-mxc 2 Edge gpiolib
...
这可以解释它。中断以每秒400左右的速度堆积,绝对比我在Python中处理它们更快。
对示波器的进一步研究表明,信号发生器仅输出约1.6 V,看起来噪声正在触发器件上的输入电路。
当我切换到正确的信号发生器输出并在GPIO引脚上得到一个干净的信号时,我开始得到预期的中断次数,并且python代码正常工作(即poll()在输入的上升沿之间正确阻塞)。