** 1 **
** 前言 **
前段时间做了一块STM32H563的开发板。
其实这块板子还设置了其他更多的内容。
有一个板载OV2640接口用以进行图像捕获。
从STM32F407移植摄像头代码,但是一直不能使用。
利用板载DCMI接口使用DMA传输,但是发现DMA数据迟迟没有获取。
于是就开启了漫长的Debug之旅~
** 2 **
** 硬件问题? **
最开始怀疑的是硬件问题,因为板子是自己设计的并且是自己手焊的,难免会出现部分地方虚焊的现象。或者因为走线过于抽象导致信号出现问题等等。
但是我后来还制作了一块STM32H5的核心板,利用杜邦线的解法也无法使用,而且用万用表仔细检查过每一个引脚,依旧无法解决问题。
所以暂时初步排除是硬件问题。
** 3 **
** 代码问题 **
于是着重检查代码部分。由于DMA检查起来较为复杂,我们首先通过轮询的方式检查摄像头是否能够工作。
OVMode = OV2640_Init(); if(OVMode==0) { OV2640_RGB565_Mode(); OV2640_OutSize_Set(240, 240); DCMI->IER = 0x0; __HAL_DCMI_ENABLE_IT(&hdcmi, DCMI_IT_FRAME); __HAL_DCMI_ENABLE(&hdcmi); DCMI->CR |= DCMI_CR_CAPTURE; // 启动捕获模式 //HAL_DMA_Start(hdcmi.DMA_Handle, (uint32_t)&hdcmi.Instance->DR, (uint32_t)frame_buffer, 240*240);// HAL_DCMI_Start_DMA(&hdcmi,DCMI_MODE_CONTINUOUS,(uint32_t *)frame_buffer,240*240); HAL_GPIO_WritePin(GPIOD,GPIO_PIN_8,1); }
由于HAL库好像没有不使用DMA启动DCMI的函数,因此,我们查看参考手册,使用寄存器启动DCMI。
在DCMI的控制寄存器部分,第0位是启用捕获。因此只需要让第0位置1即可。
DCMI->CR |= DCMI_CR_CAPTURE; // 启动捕获模式
开启捕获模式之后 ,发现DR即数据寄存器的值有,但是不更新。SR在0,1到3之间跳跃。
查看SR寄存器的定义,大体讲的是VSYNC和HSYNC的状态。这是时钟同步,并没有什么问题、
CR寄存器的值是0x4029
这些对应控制寄存器:使能DCMI,PCKPOL位上升沿使能,JPEG模式使能。以及开启捕获使能。
这些也是没有问题的。
于是也不清楚到底发生了什么事情。
直到突然发现一件事。但是在手册中找到一句重要的话。
开启DCMI的时候,需要确保寄存器配置正常,既然控制寄存器配置是正常的,那么肯定是其他哪里有不正常的地方。
于是把除了CubeMX生成的代码之外的都给删掉。然后就莫名其妙的解决了问题。
** 3 **
** 接踵而来 **
不过,随着代码的运行又出现了运行,代码会运行着一会之后,DR的值又不更新了。
我们比较代码,发现RISR的第二位(x=0x1B)出现了异常。查看参考手册关于第二位的描述。
参考手册中描述到:如果这一位置1,则代表着数据FIFO已损坏。通过设置DCMI_ICR寄存器的OVR_ISC位来清除该位。
if (hdcmi.Instance->RISR & 0x02){ hdcmi.Instance->ICR = 0x02;//清除损坏位}
在代码中添加清楚这一位的代码。
这样子直到一帧捕获完全数据一直在更新。
RIS寄存器中,第0位代表着数据捕获标记位,在ICR的设置,清楚标志位。
if (hdcmi.Instance->RISR & 0x01) { hdcmi.Instance->ICR = 0x01;//清除捕获位 DCMI->CR |= DCMI_CR_CAPTURE; // 启动捕获模式 }
这样子就实现了轮询式代码实现。这说明我们摄像头是没有问题的,硬件也是没有问题的。启动流程和使用方法出现了问题。
下期再实现DMA的功能和屏幕显示。