STM32F407 摄像头实验 图片缓冲区的确定

2019-07-21 02:18发布

      1、在STM32F407在发送到上位机,用串口调试助手显示的时候,需要给摄像头采集过来的数据申请一个缓冲区。由于DCMI的 DMA发送数据是使用循环模式,缓冲区地址自动增长,当地址指针达到缓冲区的末尾就会返回缓冲区的首地址,重新开始执行。
STM32F407 DCMI DMA的设置如下:
DMA_InitStructure.DMA_Channel = DMA_Channel_1;  //通道1 DCMI通道 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&DCMI->DR;//外设地址为CMI->DR
  DMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;//DMA 存储器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式
  DMA_InitStructure.DMA_BufferSize = DMA_BufferSize;//数据传输量 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc;//存储器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据长度:32位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize;//存储器数据长度 
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式 
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; //FIFO模式        
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;//使用全FIFO 
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//外设突发单次传输
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//存储器突发单次传输
  DMA_Init(DMA2_Stream1, &DMA_InitStructure);//初始化DMA Stream
           2、DCMI的中断函数是帧中断,即每捕获到一帧数据,产生一次中断,处理一次数据,
DCMI 中断函数:
数据缓冲区的定义:
#define jpeg_buf_size 31*1024   //定义JPEG数据缓存jpeg_buf的大小(*4字节)
__align(4) u32 jpeg_buf[jpeg_buf_size]; //JPEG数据缓存buf
volatile u32 jpeg_data_len=0; //buf中的JPEG有效数据长度 
volatile u8 jpeg_data_ok=0; //JPEG数据采集完成标志 

 void DCMI_IRQHandler(void)
{
        if(DCMI_GetITStatus(DCMI_IT_FRAME)==SET)//捕获到一帧图像
       {
              jpeg_data_process(); //jpeg数据处理
              DCMI_ClearITPendingBit(DCMI_IT_FRAME);//清除帧中断
              LED1=!LED1;
             ov_frame++;  
     }

数据处理函数:
void jpeg_data_process(void)
{
        if(ov2640_mode)//只有在JPEG格式下,才需要做处理.
        {
                   if(jpeg_data_ok==0) //jpeg数据还未采集完?
                  {
                         DMA_Cmd(DMA2_Stream1, DISABLE);//停止当前传输 
                        while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置  
                       jpeg_data_len=jpeg_buf_size-DMA_GetCurrDataCounter(DMA2_Stream1);//得到此次数据传输的长度

                      jpeg_data_ok=1; //标记JPEG数据采集完按成,等待其他函数处理
                  }
                if(jpeg_data_ok==2) //上一次的jpeg数据已经被处理了
                {
                       DMA2_Stream1->NDTR=jpeg_buf_size;
                       DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);//传输长度为jpeg_buf_size*4字节
                      DMA_Cmd(DMA2_Stream1, ENABLE); //重新传输
                      jpeg_data_ok=0; //标记数据未采集
               }
       }

事实上,没处理一次函数,都会重新配置DMA的传输数据流:
 DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);//传输长度为jpeg_buf_size*4字节  
而每一次传输的数据长度都是一帧数据,并不是jpeg_buf_size(31*1024个字)。如果将数据缓冲区设置为jpeg_buf[jpeg_buf_size],缓冲区满的时候存放的是整个图片的数据。每发送一帧数据,缓冲区指针移动一帧数据所占有的空间。当整个图片的数据发送完毕,指针再回到缓冲区的首地址继续执行,如此往复。如果将缓冲区设置为一帧数据的大小,执行过程就是:发送第一帧数据,缓冲区的指针从开始移动到缓冲区的结束为止,发送第二帧数据的时候,再回到缓冲区的首地址继续执行。事实上,缓冲区存储的就是一帧数据。通过串口调试助手可以发现,一帧数据的长度为1088字,有的时候会达到1288字,为确保实验的准确性,可以将图片的缓冲区大小设置为1400字。通过调试发现,和缓冲区设置为 u32 jpeg_buf[jpeg_buf_size]的时候,串口调试助手显示的结果是一样的。如果DCMI DMA 设置传输完成中断的情况另当别论。



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
3条回答
yefeng159
2019-07-21 12:38
这个跟图片大小没有关系,缓冲区存储的只是一帧的数据量,即使图片很大,DCMI捕获的是一帧数据,把这帧数据放在缓冲区,再游串口2发送给串口调试助手,显示图片。由于在void jpeg_data_process(void)里面第二次开启DMA的时候,重新配置传输的数据流,DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);跟上一次DMA传输没有关系,只是在传输过程中当前的数据在缓冲区覆盖前一帧的数据。
#define jpeg_buf_size 31*1024    //定义JPEG数据缓存jpeg_buf的大小(*4字节)
  __align(4) u32 jpeg_buf[jpeg_buf_size];

按照这样的设定,存储区储存的是整个图片的数据

#define jpeg_buf_size 1400    //定义JPEG数据缓存jpeg_buf的大小(*4字节)
  __align(4) u32 jpeg_buf[jpeg_buf_size];
按照这样的设定,存储区存储的是图片的一帧的数据

两者的方运行结果是一样的。

一周热门 更多>