我正在一个嵌入式系统(ARM核)上尝试从Python访问GPIO,它运行的是用Buildroot构建的linux (内核4.1.15)。
我希望我的代码阻止等待GPIO2上的引脚更改(也就是说,我不想通过反复调用"read“来轮询引脚)。我试图在边缘触发模式下使用"epoll“执行此操作:
见用于epoll的Python文档。使用select.EPOLLET标志进行边缘触发。另见用于epoll的Linux文档。
为了简单起见,我已经使用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秒睡眠,然后在下一次迭代时,轮询()立即返回,不阻塞。它应该会阻塞,因为我的输入只在每2秒一个上升的边缘运行。
为什么没有“轮询()”阻塞?
====编辑:====
最初,当我尝试使用“select.EPOLLET”时,代码导致了一个奇怪的错误:
OverflowError: can't convert negative value to unsigned int但是,我发现我意外地使用了myPoll = select.poll()而不是epoll()。密码现在修好了。
发布于 2017-11-30 19:23:50
我决定通过查看/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.6V左右,似乎是噪声触发了设备上的输入电路。
当我切换到正确的信号生成器输出并在GPIO引脚上得到一个干净的信号时,我开始获得预期的中断数,python代码正确工作(即在输入的上升边缘之间正确地阻塞了轮询())。
https://stackoverflow.com/questions/47564734
复制相似问题