You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派Zero W与MCP3008 SPI通信报错:Too many open files: /dev/spidev0.0

问题描述

我尝试通过SPI将MCP3008与树莓派Zero W连接以读取通道数据,使用Adafruit Blinka库实现。运行一段时间后出现错误:[Errno 24] Too many open files: '/dev/spidev0.0'。

我的Python代码如下:

import wiringpi
from time import sleep
wiringpi.wiringPiSetup()
import busio
import digitalio
import board

import adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn

class Readspi(Node):
    def execute(self):
        try:
            input_io = self.get_input_params()
            clock = int(input_io['clock'])
            miso = int(input_io["miso"])
            mosi = int(input_io["mosi"])
            channel = int(input_io['channel'])
            spi = busio.SPI(clock, mosi, miso)
            cs = digitalio.DigitalInOut(board.D5)
            mcp = MCP.MCP3008(spi, cs)
            temp_value = AnalogIn(mcp, channel)
            new_value = temp_value.value
            print(type(new_value), " ", new_value)
            spi.deinit()
        except Exception as exception:
            self.set_next_node_params([str(exception), ])
            print("fail")
问题分析与解决

核心原因

错误[Errno 24] Too many open files是因为每次调用execute方法时,虽然调用了spi.deinit(),但CS引脚的DigitalInOut对象没有被正确释放,导致系统文件句柄持续泄漏,积累到一定数量后触发报错。另外,wiringpi.wiringPiSetup()的初始化放在全局区域,若execute被多次调用,可能也会引发资源冲突。

修复步骤

  1. 正确释放CS引脚资源
    在spi.deinit()之后,需要调用cs.deinit()来释放CS引脚的文件句柄,避免泄漏。
  2. 优化资源初始化逻辑
    将SPI和MCP3008的初始化移到类的初始化方法(__init__)中,而不是每次execute都重新创建。这样可以避免重复打开/关闭SPI设备,减少资源消耗。
  3. 移除不必要的wiringpi初始化
    代码中使用了Adafruit Blinka库的busio和digitalio,与wiringpi属于不同的GPIO控制框架,同时使用可能引发冲突,建议移除wiringpi相关代码。

修复后的代码

import busio
import digitalio
import board

import adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn

class Readspi(Node):
    def __init__(self):
        # 初始化SPI和MCP3008,只执行一次
        input_io = self.get_input_params()
        clock = int(input_io['clock'])
        miso = int(input_io["miso"])
        mosi = int(input_io["mosi"])
        self.channel = int(input_io['channel'])
        
        self.spi = busio.SPI(clock, mosi, miso)
        self.cs = digitalio.DigitalInOut(board.D5)
        self.mcp = MCP.MCP3008(self.spi, self.cs)

    def execute(self):
        try:
            temp_value = AnalogIn(self.mcp, self.channel)
            new_value = temp_value.value
            print(type(new_value), " ", new_value)
        except Exception as exception:
            self.set_next_node_params([str(exception), ])
            print("fail")
        # 类销毁时自动释放资源
    def __del__(self):
        self.cs.deinit()
        self.spi.deinit()

额外建议

  • 检查系统文件句柄限制:可以通过ulimit -n命令查看当前用户的文件句柄上限,若需要可临时调整为更大的值(如ulimit -n 1024),但修复代码泄漏才是根本解决办法。
  • 确保树莓派已启用SPI:通过raspi-config进入Interfacing Options,确认SPI已开启。

内容的提问来源于stack exchange,提问作者Ax111_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:50:21