GD32H759I-EVAL开发板还带了一个DCI接口摄像头,下面试试摄像头功能,在LCD上显示摄像头内容。
摄像头接口如下:
1712397184333.jpg
参考了例程重新整理了一下摄像头驱动。首先初始化GPIO接口,然后就是DCI外设初始化,通过DMA方式将DCI的摄像头数据传到SDRAM地址0XC1000000。
下面是DCI的初始化:
  1. /*!
  2.     \brief      configure the DCI to interface with the camera module
  3.     \param[in]  none
  4.     \param[out] none
  5.     \retval     none
  6. */
  7. void dci_config(void)
  8. {
  9.     dci_parameter_struct dci_struct;
  10.     dma_single_data_parameter_struct  dma_single_struct;
  11.    
  12.     rcu_periph_clock_enable(RCU_GPIOA);
  13.     rcu_periph_clock_enable(RCU_GPIOB);
  14.     rcu_periph_clock_enable(RCU_GPIOC);
  15.     rcu_periph_clock_enable(RCU_GPIOE);
  16.     rcu_periph_clock_enable(RCU_GPIOH);
  17.     rcu_periph_clock_enable(RCU_GPIOG);
  18.     rcu_periph_clock_enable(RCU_DCI);

  19.     /* DCI GPIO AF configuration */
  20.     /* configure DCI_PIXCLK(PE3), DCI_VSYNC(PB7), DCI_HSYNC(PA4) */
  21.     gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_3);
  22.     gpio_af_set(GPIOB, GPIO_AF_13, GPIO_PIN_7);
  23.     gpio_af_set(GPIOA, GPIO_AF_13, GPIO_PIN_4);

  24.     gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
  25.     gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_3);
  26.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
  27.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);

  28.     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
  29.     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4);

  30.     /* configure  DCI_D0(PC6), DCI_D1(PH10) DCI_D2(PC8), DCI_D3(PC9), DCI_D4(PE4), DCI_D5(PB6), DCI_D6(PE5), DCI_D7(PE6) */
  31.     gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_6);
  32.     gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_8);
  33.     gpio_af_set(GPIOC, GPIO_AF_13, GPIO_PIN_9);
  34.     gpio_af_set(GPIOB, GPIO_AF_13, GPIO_PIN_6);
  35.     gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_4);
  36.     gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_5);
  37.     gpio_af_set(GPIOE, GPIO_AF_13, GPIO_PIN_6);
  38.     gpio_af_set(GPIOH, GPIO_AF_13, GPIO_PIN_10);

  39.     gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
  40.     gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10);

  41.     gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
  42.     gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
  43.     gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
  44.     gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
  45.     gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
  46.     gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
  47.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
  48.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);

  49.     gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
  50.     gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4);
  51.     gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
  52.     gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_5);
  53.     gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
  54.     gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);

  55.     /* DCI configuration */
  56.     dci_struct.capture_mode = DCI_CAPTURE_MODE_CONTINUOUS;
  57.     dci_struct.clock_polarity =  DCI_CK_POLARITY_RISING;
  58.     dci_struct.hsync_polarity = DCI_HSYNC_POLARITY_LOW;
  59.     dci_struct.vsync_polarity = DCI_VSYNC_POLARITY_LOW;
  60.     dci_struct.frame_rate = DCI_FRAME_RATE_ALL;
  61.     dci_struct.interface_format = DCI_INTERFACE_FORMAT_8BITS;
  62.     dci_init(&dci_struct);

  63.     /* DCI DMA configuration */
  64.     rcu_periph_clock_enable(RCU_DMA1);
  65.     rcu_periph_clock_enable(RCU_DMAMUX);

  66.     dma_single_data_para_struct_init(&dma_single_struct);
  67.     dma_deinit(DMA1, DMA_CH7);
  68.     dma_single_struct.request = DMA_REQUEST_DCI;
  69.     dma_single_struct.periph_addr = (uint32_t)DCI_DATA_ADDRESS;
  70.     dma_single_struct.memory0_addr = (uint32_t)0xC1000000;
  71.     dma_single_struct.direction = DMA_PERIPH_TO_MEMORY;
  72.     dma_single_struct.number = 38400;
  73.     dma_single_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  74.     dma_single_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  75.     dma_single_struct.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;
  76.     dma_single_struct.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
  77.     dma_single_struct.priority = DMA_PRIORITY_HIGH;
  78.     dma_single_data_mode_init(DMA1, DMA_CH7, &dma_single_struct);
  79.    
  80.     /* DMA interrupt and channel enable */
  81.     dma_interrupt_enable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
  82.     dma_channel_enable(DMA1, DMA_CH7);
  83.     /* enable DMA1 channel 7 */
  84.     nvic_irq_enable(DMA1_Channel7_IRQn, 0U, 1U);
  85. }
  1. /*!
  2.     \brief      ckout0 initialization
  3.     \param[in]  none
  4.     \param[out] none
  5.     \retval     none
  6. */
  7. void ckout0_init(void)
  8. {
  9.     rcu_periph_clock_enable(RCU_GPIOA);
  10.    
  11.     gpio_af_set(GPIOA, GPIO_AF_CKOUT, GPIO_PIN_8);
  12.     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8);
  13.     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);

  14.     rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL, RCU_CKOUT0_DIV2);
  15. }

  16. /*!
  17.     \brief      DCI camera outsize set
  18.     \param[in]  width: outsize width
  19.     \param[in]  height: outsize height
  20.     \param[out] none
  21.     \retval     0x00 or 0xFF
  22. */
  23. uint8_t ov2640_outsize_set(uint16_t width, uint16_t height)
  24. {
  25.     uint16_t outh;
  26.     uint16_t outw;
  27.     uint8_t temp;
  28.    
  29.     if(width % 4) {
  30.         return 0xFF;
  31.     }
  32.     if(height % 4) {
  33.         return 0xFF;
  34.     }
  35.     outw = width / 4;
  36.     outh = height / 4;
  37.    
  38.     dci_byte_write(0xFF, 0x00);
  39.     dci_byte_write(0xE0, 0x04);
  40.     dci_byte_write(0x5A, outw & 0xFF);
  41.     dci_byte_write(0x5B, outh & 0xFF);
  42.    
  43.     temp = (outw >> 8) & 0x03;
  44.     temp |= (outh >> 6) & 0x04;
  45.    
  46.     dci_byte_write(0x5C, temp);
  47.     dci_byte_write(0xE0, 0x00);
  48.    
  49.     return 0;
  50. }

整个初始化如下:
  1. /*!
  2.     \brief      DCI camera initialization
  3.     \param[in]  none
  4.     \param[out] none
  5.     \retval     0x00 or 0xFF
  6. */
  7. uint8_t dci_ov2640_init(void)
  8. {
  9.     uint8_t i;
  10.    
  11.     sccb_config();
  12.     dci_config();
  13.     ckout0_init();
  14.    
  15.     delay_1ms(100);
  16.    
  17.     /* OV2640 reset */
  18.     if(dci_byte_write(0xFF, 0x01) != 0) {
  19.         return 0xFF;
  20.     }
  21.     if(dci_byte_write(0x12, 0x80) != 0) {
  22.         return 0xFF;
  23.     }
  24.     delay_1ms(10);
  25.     for(i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++)
  26.     {
  27.         if(0 != dci_byte_write(ov2640_svga_init_reg_tbl[i][0], ov2640_svga_init_reg_tbl[i][1]))
  28.         {
  29.             return 0xFF;
  30.         }
  31.     }

  32.     delay_1ms(100);
  33.     for(i = 0; i < (sizeof(ov2640_rgb565_reg_tbl) / 2); i++)
  34.     {
  35.         if(0 != dci_byte_write(ov2640_rgb565_reg_tbl[i][0], ov2640_rgb565_reg_tbl[i][1]))
  36.         {
  37.             return 0xFF;
  38.         }
  39.     }
  40.     delay_1ms(100);
  41.     ov2640_outsize_set(320, 240);
  42.    
  43.     dci_ov2640_id_read(&ov2640id);

  44.     return 0;
  45. }

DMA中断函数如下:
  1. /*!
  2.     \brief      this function handles DMA1_Channel7_IRQ interrupt request
  3.     \param[in]  none
  4.     \param[out] none
  5.     \retval     none
  6. */
  7. void DMA1_Channel7_IRQHandler(void)
  8. {
  9.     if(dma_interrupt_flag_get(DMA1, DMA_CH7, DMA_INT_FLAG_FTF))
  10.     {
  11.         int i = 0, x = 0, y = 0;
  12.         dma_channel_disable(DMA1, DMA_CH7);
  13.         dma_interrupt_flag_clear(DMA1, DMA_CH7, DMA_INT_FLAG_FTF);
  14.         dma_channel_enable(DMA1, DMA_CH7);
  15.     }
  16. }
main中调用lcd显示初始化和摄像头初始化和捕捉图像如下:
1712397281237.jpg
  1. int main(void)
  2. {
  3.     /* enable the CPU cache */
  4.     SCB_EnableICache();/* enable i-cache */
  5.     SCB_EnableDCache();/* enable d-cache */
  6.     nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
  7.    
  8.     /* configure systick */
  9.     systick_config();
  10.    
  11.     init_cycle_counter(true);
  12.    
  13.     gpio_config();
  14.     usart_config();
  15.     /* output a message on hyperterminal using printf function */
  16.     printf("\r\n GD32H759 Board example.\r\n");
  17.    
  18.     gd_eval_lcd_init();
  19.     lcd_font_set(&LCD_DEFAULT_FONT);
  20.     lcd_layer_set(LCD_LAYER_BACKGROUND);
  21.     lcd_vertical_string_display(10,0,(uint8_t *)" GD32H759 Camera");
  22.    
  23.     lcd_layer_set_window(LCD_LAYER_FOREGROUND, 80,15,320, 240,0xC1000000);
  24.    
  25.     /* camera initialization */
  26.     dci_ov2640_init();
  27.     dci_enable(); /* DCI enable */
  28.     dci_capture_enable();
  29.    
  30.     while(1)
  31.     {
  32.         
  33. //        GPIO_TG(LED2_GPIO_PORT) = LED2_PIN;
  34. //        delay_1ms(100);
  35. //        GPIO_TG(LED1_GPIO_PORT) = LED1_PIN;
  36. //        delay_1ms(100);
  37.         if(gpio_input_bit_get(TAMPER_KEY_GPIO_PORT, TAMPER_KEY_PIN) == RESET)
  38.         {
  39.             printf("\r\n TAMPER_KEY Press.\r\n");
  40.         }
  41.         if(gpio_input_bit_get(WAKEUP_KEY_GPIO_PORT, WAKEUP_KEY_PIN) == RESET)
  42.         {
  43.             printf("\r\n WAKEUP_KEY Press.\r\n");
  44.         }
  45.         if(gpio_input_bit_get(USER_KEY_GPIO_PORT, USER_KEY_PIN) == RESET)
  46.         {
  47.             printf("\r\n USER_KEY Press.\r\n");
  48.         }
  49.     }
  50. }

这里重新初始化lcd显示的Layer1为摄像头尺寸320*240分辨率。并且显存直接设置成摄像头的数据区地址0xC1000000.
  1. lcd_layer_set_window(LCD_LAYER_FOREGROUND, 80,15,320, 240,0xC1000000);

编译下载之后就可以在lcd上看到摄像头的内容了。
image.png

工程:
GDH7_Demo.zip (1.22 MB, 下载次数: 7)
全部回复 0
暂无评论,快来抢沙发吧