目录
STM32 OV2640将数据缓存至SRAM
流程设计
流程如下:
-
初始化OV2640后,初始化DCMI和DMA,DCMI的初始化代码与原子开发板的代码一致,这里主要是区分在DMA的初始化上:
ram_campic = (u16 *)my_malloc(SRAMEX, (lcddev.width * lcddev.height * 4)); DCMI2LCD_DMA_Init((u32)ram_campic, (lcddev.width * lcddev.height) * 4, DMA_MemoryDataSize_HalfWord, DMA_MemoryInc_Enable);
RGB565是16个比特,2个字节,因此采用半字传输,总量为
(lcddev.width * lcddev.height) * 2
,存储器地址递增,初始化代码内部定义外设宽度为32bit,即一次4个字节,半字传输需要传2次,所以总数是4倍。 循环查询帧接收flag,如果查到则停止DCMI(这一步冗余,因为在DCMI中断和DMA中断中已经停止了DCMI,而中断的到达时刻要远快于查询),则将该帧打印至LCD或后续通过UDP发送出去
重新启动DMA后等待稳定后启动DCMI
-
中断处理:
- 当DMA循环完一次之后,立即停止DMA,之后停止DCMI,清除中断标记并将flag置位,如果顺序相反,则DCMI停止的过程中DMA依然在工作,因此新的一帧图像会将上一帧图像的起始部分覆盖,所以DMA收齐一帧后立即停止。
- 当一帧传输结束后触发DCMI中断,此时部分帧图像数据依然在DMA的FIFO中,此时停止DCMI,等待DMA传输完成后将flag置位,这样可以确保DMA将一帧图像完整的传输结束。
- 由于一帧传完后DCMI和DMA均停止,中断标记清除,因此主程序while循环将检测到flag并进行处理,结束后重新启动DMA和DCMI
问题汇总
SRAM数据缓存不完整
这个问题表现在外部即LCD打印SRAM的数据时会有大片的黑屏或错位,产生原因是DMA的访问速度过快,部分数据没有及时存储而被抛弃。解决方法是减小FSMC的写地址和数据的时间:
FSMC_ReadWriteTimingStructure.FSMC_AddressSetupTime = 1; //地址建立时间,修改前为15
FSMC_ReadWriteTimingStructure.FSMC_AddressHoldTime = 0x00; //地址保持时间,模式A未用到
FSMC_ReadWriteTimingStructure.FSMC_DataSetupTime = 3; //数据保持时间,0x18个HCLK,6* 24 ns,改之前0x18
FSMC_ReadWriteTimingStructure.FSMC_BusTurnAroundDuration = 0x00;
FSMC_ReadWriteTimingStructure.FSMC_CLKDivision = 0x00;
FSMC_ReadWriteTimingStructure.FSMC_DataLatency = 0x00;
FSMC_ReadWriteTimingStructure.FSMC_AccessMode = FSMC_AccessMode_A; //模式A
LCD打点过程中部分屏幕黑屏
如果SRAM的时序没有问题,则这个问题的原因是DMA的数据传输的数据量不足,因此调整传输量即可。
边缘图像小范围错位
这个问题的原因是由于DMA和DCMI的停止顺序没有控制好造成的,即上面提到的DCMI停止的过程中DMA依然在传输数据,因此将下一帧的部分数据替到了上一帧的开始位置,调整开关DMA和DCMI的顺序即可解决
屏幕花屏
大范围斜纹花屏的原因是打点函数的x、y和摄像头的扫描顺序不一致造成的,即摄像头行扫描的数据被按列打点,而列坐标范围无法覆盖到行坐标,因此出现斜纹,调整打点的扫描方向或打点顺序即可。