问答

汇集网友智慧,解决技术难题

21ic问答首页 - GD32W515 DCI ov2640摄像头连续捕获模式采集帧率低的问题

ov2640 GD32W515

GD32W515 DCI ov2640摄像头连续捕获模式采集帧率低的问题

OV2640在800*600分辨率,JPG格式输出,日志信息如下:
[12:00:37.591]收←◆[ DEBUG  ]    ov2640 frame count:32768
[12:00:38.653]收←◆[ DEBUG  ]    ov2640 frame count:33792
[12:00:39.716]收←◆[ DEBUG  ]    ov2640 frame count:34816
[12:00:40.780]收←◆[ DEBUG  ]    ov2640 frame count:34816
[12:00:41.842]收←◆[ DEBUG  ]    ov2640 frame count:34816
[12:00:42.907]收←◆[ DEBUG  ]    ov2640 frame count:34816
[12:00:43.971]收←◆[ DEBUG  ]    ov2640 frame count:34816
[12:00:45.035]收←◆[ DEBUG  ]    ov2640 frame count:34816
即,将近1S才采集一帧。
用逻辑分析仪测试VSYNC,周期大概在37ms,也就是说,一秒有将近30帧输出(可先排除OV2640寄存器相关配置问题,通过串口将jpeg输出到上位机,查看图片也没有问题)。
只要DCI有中断回调,则打印日志,日志速率在500K左右(不用考虑日志速率过低导致漏帧问题)。

DCI的关键配置代码片段如下(参考官方ov2640例程):
    // dci相关I/O口配置为166MHZ速率
    // dci配置
    dci_parameter_struct dci_struct;
    dci_struct.capture_mode     = DCI_CAPTURE_MODE_CONTINUOUS;//DCI_CAPTURE_MODE_SNAPSHOT;
    dci_struct.clock_polarity   = DCI_CK_POLARITY_RISING;
    dci_struct.hsync_polarity   = DCI_HSYNC_POLARITY_LOW;
    dci_struct.vsync_polarity   = DCI_VSYNC_POLARITY_LOW;
    dci_struct.frame_rate       = DCI_FRAME_RATE_ALL;
    // dma配置
    dma_multi_data_parameter_struct        dma_multi_struct;
    dma_multi_struct.periph_addr        = (uint32_t)DCI_DATA_ADDRESS;
    dma_multi_struct.memory0_addr       = (uint32_t)(capture[0].image);
    dma_multi_struct.direction          = DMA_PERIPH_TO_MEMORY;
    dma_multi_struct.number             = (FRAME_BUFFER_SIZE)>>2;
    dma_multi_struct.periph_inc         = DMA_PERIPH_INCREASE_DISABLE;
    dma_multi_struct.memory_inc         = DMA_MEMORY_INCREASE_ENABLE;
    dma_multi_struct.periph_width       = DMA_PERIPH_WIDTH_32BIT;
    dma_multi_struct.memory_width       = DMA_MEMORY_WIDTH_32BIT;
    dma_multi_struct.circular_mode      = DMA_CIRCULAR_MODE_DISABLE,
    dma_multi_struct.priority           = DMA_PRIORITY_HIGH;
    dma_multi_struct.critical_value     = DMA_FIFO_4_WORD;
    dma_multi_struct.memory_burst_width = DMA_MEMORY_BURST_SINGLE;
    dma_multi_struct.periph_burst_width = DMA_PERIPH_BURST_SINGLE;

    dci_struct.interface_format         = DCI_INTERFACE_FORMAT_8BITS;

// ov2640的XCLK时钟输入(由于硬件接到PA2,只能用PWM输出16M左右的时钟作为OV2640时钟输入)
    const timer_parameter_struct timer_init_struct={
        .prescaler          = 0,
        .alignedmode        = TIMER_COUNTER_EDGE,
        .counterdirection   = TIMER_COUNTER_UP,
        .period             = 180/32-1,
        .clockdivision      = 0,
        .repetitioncounter  = 0,
    };
    const timer_oc_parameter_struct timer_oc_init_struct={
        .outputstate        = TIMER_CCX_ENABLE,
        .outputnstate       = TIMER_CCXN_DISABLE,
        .ocpolarity         = TIMER_OC_POLARITY_HIGH,
        .ocnpolarity        = TIMER_OCN_POLARITY_HIGH,
        .ocidlestate        = TIMER_OC_IDLE_STATE_LOW,
        .ocnidlestate       = TIMER_OCN_IDLE_STATE_LOW,
    };
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_2);
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_166MHZ, GPIO_PIN_2);

    timer_init(TIMER1,(timer_parameter_struct*)&timer_init_struct);
    timer_channel_output_mode_config(TIMER1,TIMER_CH_2,TIMER_OC_MODE_PWM0);
    timer_channel_output_config(TIMER1,TIMER_CH_2,(timer_oc_parameter_struct*)&timer_oc_init_struct);
    timer_break_disable(TIMER1);
    timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_2,180/32-2);
    timer_channel_output_state_config(TIMER1,TIMER_CH_2,TIMER_CCX_ENABLE);
    timer_enable(TIMER1);



// DCI连续采集使能
    dma_channel_enable(DMA1,DMA_CH7);
    dci_capture_enable();
    dci_enable();


// DCI中断处理代码
/// @brief 拍照中断
/// @param  
void DCI_IRQHandler(void)
{
  int size;
  size = FRAME_BUFFER_SIZE - (dma_transfer_number_get(DMA1,DMA_CH7)<<2);

  dci_interrupt_flag_clear(DCI_INT_EF|DCI_INT_OVR);
  // 看现在是捕获进哪个缓冲区,必须清DMA的标志,否则会导致无法继续捕获
  dma_channel_disable(DMA1,DMA_CH7);
  dma_flag_clear(DMA1,DMA_CH7,DMA_FLAG_FTF|DMA_FLAG_HTF);

  if(capture_active){
    if(capture_windex){
      capture_windex = 0;
      capture_rindex = 1;
    }else{
      capture_windex = 1;
      capture_rindex = 0;
    }
    image_size = size;
    capture_active = 0;
    dma_memory_address_config(DMA1,DMA_CH7,DMA_MEMORY_0,(uint32_t)capture[capture_windex].image);
  }
  dma_transfer_number_config(DMA1,DMA_CH7,(FRAME_BUFFER_SIZE)>>2);
  dma_channel_enable(DMA1,DMA_CH7);
  //
  if(fn_frame_cb)fn_frame_cb(size);
}




回答 +关注 14
846人浏览 1人回答问题 分享 举报
1 个回答

您需要登录后才可以回复 登录 | 注册