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

树莓派连接OV5642 SPI摄像头MicroPython代码报EIO错误求助

树莓派OV5642 SPI摄像头MicroPython代码I2C读取错误排查

我编写了用于树莓派连接OV5642 SPI摄像头的MicroPython代码,运行后出现I/O错误。已确认摄像头连接正常(官方CircuitPython代码可正常运行),怀疑是对readfrom_into的调用理解有误,寻求解决提示。

我的MicroPython代码

import machine
import time as utime
from OV5642_reg import *

OV5642=1

BMP =0
JPEG=1
RAW =2

OV5642_CHIPID_HIGH=0x300a
OV5642_CHIPID_LOW=0x300b

class ArducamClass(object):
    def __init__(self,Type):
        self.CameraMode=JPEG
        self.CameraType=Type
        self.SPI_CS = machine.Pin(5, mode=machine.Pin.OUT, value=1)
        self.I2cAddress=0x3c
        self.spi = machine.SPI(0, baudrate=4000000,polarity=0,phase=0,bits=8, sck=machine.Pin(2), mosi=machine.Pin(3), miso=machine.Pin(4))
        self.i2c = machine.I2C(0, scl=machine.Pin(9), sda=machine.Pin(8), freq=1000000)
        print(self.i2c.scan())
        self.Spi_write(0x07,0x80)
        utime.sleep(0.1)
        self.Spi_write(0x07,0x00)
        utime.sleep(0.1)

    def Camera_Detection(self):
        while True:
            if self.CameraType==OV5642:
                self.I2cAddress=0x3c
                self.wrSensorReg16_8(0xff,0x01)
                id_h=self.rdSensorReg16_8(OV5642_CHIPID_HIGH)
                id_l=self.rdSensorReg16_8(OV5642_CHIPID_LOW)
                if((id_h==0x56)and(id_l==0x42)):
                    print('CameraType is OV5642')
                    break
                else:
                    print('Can\'t find OV5642 module')
            utime.sleep(1)
            
    def Set_Camera_mode(self,mode):
        self.CameraMode=mode

    def wrSensorReg16_8(self,addr,val):
        buffer=bytearray(3)
        buffer[0]=(addr>>8)&0xff
        buffer[1]=addr&0xff
        buffer[2]=val
        self.iic_write(buffer)    

    def rdSensorReg16_8(self,addr):
        buffer=bytearray(2)
        rt=bytearray(1)
        buffer[0]=(addr>>8)&0xff
        buffer[1]=addr&0xff
        self.iic_write(buffer)
        self.iic_readinto(rt)
        return rt[0]

    def iic_write(self, buf, *, start=0, end=None):
        if end is None:
            end = len(buf)
        self.i2c.writeto(self.I2cAddress, buf[start:end])

    def iic_readinto(self, buf, *, start=0, end=None):
        if end is None:
            end = len(buf)
            print(buf[start:end])
            print(self.I2cAddress)
        self.i2c.readfrom_into(self.I2cAddress, buf[start:end])

    def Spi_write(self,address,value):
        maskbits = 0x80
        buffer=bytearray(2)
        buffer[0]=address | maskbits
        buffer[1]=value
        self.SPI_CS.value(0)
        self.spi_write(buffer)
        self.SPI_CS.value(1)

    def spi_write(self, buf, *, start=0, end=None):
            if end is None:
                end = len(buf)
            self.spi.write(buf[start:end])


mycam = ArducamClass(OV5642)
mycam.Camera_Detection()

运行错误信息

Traceback (most recent call last):
  File "<stdin>", line 89, in <module>
  File "<stdin>", line 33, in Camera_Detection
  File "<stdin>", line 58, in rdSensorReg16_8
  File "<stdin>", line 71, in iic_readinto
OSError: [Errno 5] EIO

解决提示

  1. 修正I2C读取逻辑
    MicroPython中分开调用writeto和readfrom_into会发送停止位,而OV5642读取寄存器要求使用重复起始位。改用writeto_then_readfrom方法自动处理该流程:
def rdSensorReg16_8(self, addr):
    buffer = bytearray(2)
    buffer[0] = (addr >> 8) & 0xff
    buffer[1] = addr & 0xff
    rt = bytearray(1)
    self.i2c.writeto_then_readfrom(self.I2cAddress, buffer, rt)
    return rt[0]

同时可删除原有的iic_readinto方法。

  1. 降低I2C频率
    代码中I2C频率设为1MHz,部分传感器无法稳定支持。将初始化时的freq=1000000改为freq=400000(标准高速模式),提升兼容性。

  2. 验证I2C地址
    确认self.i2c.scan()输出包含0x3c,若没有,检查接线或确认OV5642的实际I2C地址(部分硬件配置下为0x3d)。

  3. 简化调试
    临时在rdSensorReg16_8中加入打印,确认寄存器地址和读取结果:

print(f"Reading register: {hex(addr)}")
print(f"Read value: {hex(rt[0])}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:13:36