打印

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

[复制链接]
223|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
考哥|  楼主 | 2018-7-30 08:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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 设置传输完成中断的情况另当别论。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

461

主题

477

帖子

0

粉丝