如题:我现在用STM32F407+OV7670+DCMI+DMA 要保存VGA(640*480) YUV的一帧图像到SRAM(外扩2M)。
我遇到的问题:
1.DMA传输的 DMA_BufferSize 最大65536个单位(65536*4 < 640*480*2),所以不能像320*240那样一次性就能保存到外扩的SRAM里
2.DCMI为了方便测试我用了DCMI_CaptureMode_SnapShot方式
3.我测试发现,当DCMI需要DMA传输640*480*2个字节,假设DMA的传输DMA_BufferSize=640个字节,那么DMA2_Stream1_IRQHandler 里的 DMA_IT_TCIF1中断就会发生480*2次。 也就是说DMA会按照DMA_BufferSize的大小把DCMI的数据全部传输完成,就是循环的覆盖DMA_Memory0BaseAddr里的数据,我想利用这点,在DMA2_Stream1_IRQHandler 中断里及时把数据copy出去
4.我采用DMA_BufferSize=320,(实际每次DMA传输数据时320*4字节),这正好是一行像素的数据,但是在DMA2_Stream1_IRQHandler 里的DMA_IT_TCIF1中断里
读取这一行的数据时出错,经过我测试后发现:在中断里使用 memcpy函数把320*4=1280字节由DMA缓存区(DMA_Memory0BaseAddr )复制到其他SRAM 数据区时引起中断函数占用超时,使DMA停止工作。之所得到这个结论是因为我用memcpy复制数据量很少时,比如100个字节,这是DMA_IT_TCIF1的中断就能持续进行(当然数据没有读完整100<1280).
5.现在怎么把DMA的数据及时的copy出来这就是问题。
6.我发现设置DCMI_ITConfig(DCMI_IT_LINE, ENABLE);时,即使采用DCMI_CaptureMode_SnapShot方式,当一帧图像都传输完成时,DCMI_IRQHandler里仍然持续有DCMI_IT_LINE
中断发生,这是这么回事?但是DCMI_IT_FRAME信号就一次(前提是开启了这个中断)。
7.我觉得DCMI的DCMI_IT_LINE中断和DMA没有关系,各是各的。DMA只是把数据都传输出来而已。
8.有人说DMA用双缓冲,这个好像很难哦,还有说在DCMI_IT_LINE中断里copy DMA的buffer,我没测试成功
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
我测试了下,还是不行,
不明白为什么设置为1,设置为1不就是一直在那一个字节上循环覆盖吗?
我的结构体的设置对不对?
DMA_DeInit(DMA2_Stream1);
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DMA_BUF ;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 1;//76800;(这里设置为1?)
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE);
---------------------------------
这里DMA仅仅负责搬运。
不停的将DCMI->DR的数据,搬运到目标地址,一次搬运长度是1.
如果你用外部SRAM,确实应该用目标地址自增,这个忘记了。。。
LCD是可以自己地址自增的。。。SRAM得你设置地址自增才行。
然后传输完一帧要中断,重新设置传输量。
中断你可以采用DCMI的帧中断,到里面再次去设置DMA。
一周热门 更多>