使用stm32f429 cube/HAL库驱动OV2640显示不成功?

2019-07-14 16:16发布

小弟最近在折腾 使用STM32f429 cube/HAL库  驱动 OV2640 显示不成功 ???

程序可以通过I2C读出 OV2640的ID号,说明 i2c通讯是正常的,还有之前使用 标准库驱动是完全没有任何问题的,所以硬件是完全正确的。

LCD控制器: ILI9486    3.5寸,480*320   lcd 驱动我就不上传了   ,采用16位接口,

代码如下:
大神们帮忙看看问题是出在哪里 ???

#define LCD_35_HEIGHT  480     /* 3.5寸宽屏 高度,单位:像素 */
#define LCD_35_WIDTH   320     /* 3.5寸宽屏 宽度,单位:像素 */


/* Private define ------------------------------------------------------------*/
#define LCD_REG  (*(volatile uint16_t *)(0x6C000000))  /* RS = 0 disp Reg  ADDR*/
#define LCD_RAM  (*(volatile uint16_t *)(0x6C000000 +  (1 << (18 + 1)))) /* FSMC 16位总线模式下,FSMC_A18口线对应物理地址A19 , RS = 1 disp Data ADDR*/




CAMERA_StatusTypeDef CAMERA_Init(CAMERA_ImageFormat_TypeDef  _ImageFormat)
{
CAMERA_StatusTypeDef err;
u16 index=0;
u16 cnt=0;
u16 Xid;

CAMERA_Reset();

err = CAMERA_Read_MID( (u16 * ) & Xid);
if(Xid != CAMERA_OV2640_MID)        // 0X7FA2
{
  printf(" OV2640_SENSOR_MID:%#X",err);
  return  err ;
}

err = CAMERA_Read_PID( (u16 * ) & Xid);
if(Xid != CAMERA_OV2640_PID)        // 0X2642
{
  printf(" OV2640_SENSOR_PID:%#X",err);
  return  err;
}   

  /* Initialize OV2640 */
  switch (_ImageFormat)
  {
    case JPEG_160x120:
    {
   cnt = (sizeof(OV2640_160x120_JPEG)/2);
      for(index=0; index<cnt; index++)
      {
        err = CAMERA_WR_Reg(OV2640_160x120_JPEG[index][0], OV2640_160x120_JPEG[index][1]);
    if(CAMERA_OK != err)
     return err;   
//    BSP_OS_TimeDlyMs(1);
      }
      break;
    }
    case JPEG_176x144:
    {
   cnt = (sizeof(OV2640_176x144_JPEG)/2);
      for(index=0; index<cnt; index++)
      {
        err = CAMERA_WR_Reg(OV2640_176x144_JPEG[index][0], OV2640_176x144_JPEG[index][1]);
    if(CAMERA_OK != err)
     return err;   
//    BSP_OS_TimeDlyMs(1);
      }
      break;
    }
    case JPEG_320x240:
    {
   cnt = (sizeof(OV2640_320x240_JPEG)/2);
       for(index=0; index<cnt; index++)
      {
        CAMERA_WR_Reg(OV2640_320x240_JPEG[index][0], OV2640_320x240_JPEG[index][1]);
//    BSP_OS_TimeDlyMs(1);
      }
      break;
    }
    case JPEG_352x288:
    {
   cnt = (sizeof(OV2640_352x288_JPEG)/2);
      for(index=0; index<cnt; index++)
      {
        err = CAMERA_WR_Reg(OV2640_352x288_JPEG[index][0], OV2640_352x288_JPEG[index][1]);
    if(CAMERA_OK != err)
     return err;   
//    BSP_OS_TimeDlyMs(1);
      }
      break;
    }  
  
  case CAMERA_R160x120:
   {
    cnt = (sizeof(OV2640_QQVGA_160x120)/2);
    for(index=0; index<cnt; index++)
    {
     err = CAMERA_WR_Reg(OV2640_QQVGA_160x120[index][0], OV2640_QQVGA_160x120[index][1]);
     if(CAMERA_OK != err)
      return err;   
//    BSP_OS_TimeDlyMs(1);
    }
    break;
   }   
   
  case CAMERA_R320x240:
   {
    cnt = (sizeof(OV2640_QVGA_320x240)/2);
    for(index=0; index<cnt; index++)
    {
     err = CAMERA_WR_Reg(OV2640_QVGA_320x240[index][0], OV2640_QVGA_320x240[index][1]);
     if(CAMERA_OK != err)
      return err;   
//    BSP_OS_TimeDlyMs(1);
    }
    break;
   }
   
  case CAMERA_R480x272:
   {
    cnt = (sizeof(OV2640_480x272)/2);
    for(index=0; index<cnt; index++)
    {
     err = CAMERA_WR_Reg(OV2640_480x272[index][0], OV2640_480x272[index][1]);
     if(CAMERA_OK != err)
      return err;   
//    BSP_OS_TimeDlyMs(1);
    }
    break;
   }
   
  case CAMERA_R480x320:
   {
    cnt = (sizeof(OV2640_480x320)/2);
    for(index=0; index<cnt; index++)
    {
     err = CAMERA_WR_Reg(OV2640_480x320[index][0], OV2640_480x320[index][1]);
     if(CAMERA_OK != err)
      return err;   
//    BSP_OS_TimeDlyMs(1);
    }
    break;
   }   
   
  case CAMERA_R640x480:
   {
    cnt = (sizeof(OV2640_VGA_640x480)/2);
    for(index=0; index<cnt; index++)
    {
     err = CAMERA_WR_Reg(OV2640_VGA_640x480[index][0], OV2640_VGA_640x480[index][1]);
     if(CAMERA_OK != err)
      return err;   
//    BSP_OS_TimeDlyMs(1);
    }
    break;
   }   
   
  case CAMERA_R800x600:
   {
    cnt = (sizeof(OV2640_SVGA_800x600)/2);
    for(index=0; index<cnt; index++)
    {
     err = CAMERA_WR_Reg(OV2640_SVGA_800x600[index][0], OV2640_SVGA_800x600[index][1]);
     if(CAMERA_OK != err)
      return err;   
//    BSP_OS_TimeDlyMs(1);
    }
    break;
   }   
   
  case CAMERA_R1600x1200:
   {
    cnt = (sizeof(OV2640_SXGA_1600x1200)/2);
    //初始化 OV2640,采用SXGA分辨率(1600*1200)  
    for(index=0;index<cnt;index++)
    {
     err = CAMERA_WR_Reg(OV2640_SXGA_1600x1200[index][0], OV2640_SXGA_1600x1200[index][1]);
     if(CAMERA_OK != err)
      return err;   
//    BSP_OS_TimeDlyMs(1);
    }     
    break;   
   }
   
  default:
   {
     break;   
   }
  }
return CAMERA_OK;
}




/* DCMI init function */
CAMERA_StatusTypeDef BSP_CAMERA_Init(CAMERA_ImageFormat_TypeDef _ImageFormat)
{
DCMI_HandleTypeDef *phdcmi;
CAMERA_StatusTypeDef ret = CAMERA_ERROR;

  /* Get the DCMI handle structure */
  phdcmi = &hdcmi_eval;


// HAL_DCMI_DeInit(phdcmi);  //清除原来的设置

  /*** Configures the DCMI to interface with the camera module ***/
  /* DCMI configuration */
  phdcmi->Init.CaptureRate      = DCMI_CR_ALL_FRAME;  
  phdcmi->Init.HSPolarity       = DCMI_HSPOLARITY_LOW;
  phdcmi->Init.SynchroMode      = DCMI_SYNCHRO_HARDWARE;
  phdcmi->Init.VSPolarity       = DCMI_VSPOLARITY_LOW;
  phdcmi->Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
  phdcmi->Init.PCKPolarity      = DCMI_PCKPOLARITY_RISING;
  phdcmi->Instance              = DCMI;   

  /* DCMI Initialization */
  DCMI_MspInit();  

  switch(_ImageFormat)
  {
    case BMP_QQVGA:
    {
      /* DCMI configuration */
      phdcmi->Init.VSPolarity       = DCMI_VSPOLARITY_HIGH;
      HAL_DCMI_Init(phdcmi);
      break;
    }
  
    case BMP_QVGA:
    {
      /* DCMI configuration */
      HAL_DCMI_Init(phdcmi);
      break;
    }
  
    default:
    {
      /* DCMI configuration */
      phdcmi->Init.VSPolarity       = DCMI_VSPOLARITY_LOW;   //DCMI_VSPolarity_High;
      HAL_DCMI_Init(phdcmi);
      break;
    }
  }

ret = CAMERA_Init( _ImageFormat);   // 此函数里面实现 读取 ID, 设置图片分辨率等
current_resolution = _ImageFormat;
return ret;
}


/**
  * @brief  Initializes the DCMI MSP.
  * @param  None
  * @retval None
  */
static void DCMI_MspInit(void)   //HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
{
  static DMA_HandleTypeDef hdma_eval;
  GPIO_InitTypeDef GPIO_InitStruct;
  DCMI_HandleTypeDef *_phdcmi = &hdcmi_eval;

  if(_phdcmi->Instance == DCMI)   //如果不使用 HAL_DCMI_MspInit 这个函数,那么此处需要屏蔽
  {
  /*** Enable peripherals and GPIO clocks ***/
  /* Enable DCMI clock */
  __DCMI_CLK_ENABLE();
//    __HAL_RCC_DCMI_CLK_ENABLE();
  
  /* Enable DMA2 clock */
  __DMA2_CLK_ENABLE();   
  
  __GPIOA_CLK_ENABLE();
  __GPIOH_CLK_ENABLE();
  __GPIOI_CLK_ENABLE();  
  
    /**DCMI GPIO Configuration
    PH9     ------> DCMI_D0
    PH10    ------> DCMI_D1
    PH11    ------> DCMI_D2
    PH12    ------> DCMI_D3   
    PH14    ------> DCMI_D4
  PI4     ------> DCMI_D5
    PI6     ------> DCMI_D6
    PI7     ------> DCMI_D7
    PH8     ------> DCMI_HSYNC
    PA6     ------> DCMI_PIXCK
    PI5     ------> DCMI_VSYNC
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_14;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
  
    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);   
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  /*** Configure the DMA ***/
  /* Set the parameters to be configured */
  hdma_eval.Init.Channel             = DMA_CHANNEL_1;
  hdma_eval.Init.Direction           = DMA_PERIPH_TO_MEMORY;   //外设到存储器模式
  hdma_eval.Init.PeriphInc           = DMA_PINC_DISABLE;     //外设非增量模式
  hdma_eval.Init.MemInc              = DMA_MINC_ENABLE;      //存储器增量模式
  hdma_eval.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;    //外设数据长度:32位
  hdma_eval.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;   //DMA_MDATAALIGN_WORD;    //存储器数据长度
  hdma_eval.Init.Mode                = DMA_CIRCULAR;       // 使用循环模式
  hdma_eval.Init.Priority            = DMA_PRIORITY_HIGH;     //高优先级
  hdma_eval.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;   // ???
//  hdma_eval.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;     //FIFO模式   
  hdma_eval.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;  //使用全FIFO
  hdma_eval.Init.MemBurst            = DMA_MBURST_SINGLE;     //外设突发单次传输
  hdma_eval.Init.PeriphBurst         = DMA_PBURST_SINGLE;     //存储器突发单次传输
  hdma_eval.Instance = DMA2_Stream1;
    __HAL_LINKDMA(_phdcmi, DMA_Handle, hdma_eval);
  /*** Configure the NVIC for DCMI and DMA ***/
  /* NVIC configuration for DCMI transfer complete interrupt */
    HAL_NVIC_SetPriority(DCMI_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(DCMI_IRQn);
  
  /* NVIC configuration for DMA2D transfer complete interrupt */
  HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
  
//  HAL_DMA_Init(&hdma_dcmi);
  /* Configure the DMA stream */
  HAL_DMA_Init(_phdcmi->DMA_Handle);
  }
}


/**
  * @brief  Starts the camera capture in continuous mode. 在连续模式下启动相机捕获。
  * @param  buff: pointer to the camera output buffer
  * @retval None
  */
void BSP_CAMERA_ContinuousStart(uint8_t *buff)
{
  /* Start the camera capture */
  HAL_DCMI_Start_DMA(&hdcmi_eval, DCMI_MODE_CONTINUOUS, (uint32_t )buff, CAMERA_GetSize(current_resolution));  
}


//RGB565测试
//RGB数据直接显示在LCD上面
CAMERA_StatusTypeDef DCMI_RGB565_LcdTest(void)
{
CAMERA_StatusTypeDef err;

tFont.FontCode = FC_ST_16; // 字体代码 16点阵
tFont.FrontColor = CL_WHITE; // 字体颜 {MOD}
tFont.BackColor = CL_MASK; // 透明 {MOD}
tFont.Space = 10;  

LCD_ClrScr(CL_BLUE);

LCD_DispStr( 30, 10,  (const u8 *)"SWS  STM32F429IIT6 LQFP-176",  &tFont);
LCD_DispStr( 30, 34,  (const u8 *)"OV2640 RGB565 Mode",  &tFont);
LCD_DispStr( 30, 58,  (const u8 *)"KEY0 Contrast",  &tFont);      //对比度
LCD_DispStr( 30, 82,  (const u8 *)"KEY1 Saturation",  &tFont);     // {MOD}彩饱和度
LCD_DispStr( 30, 106, (const u8 *)"KEY2 Effects",  &tFont);      //特效  
LCD_DispStr( 30, 130, (const u8 *)"KEY_UP FullSize / Scale",  &tFont); //1:1尺寸(显示真实尺寸)/全尺寸缩放
bsp_DelayMS(500);


/* 初始化OV2640摄像头及读取摄像头芯片ID,确定摄像头正常连接 */
if(CAMERA_OK == BSP_CAMERA_Init(CAMERA_R480x320))
{
   /* Wait 1s before Camera snapshot */
   HAL_Delay(1000);
  
  err = CAMERA_RGB565_Mode();       //RGB565模式
  if( CAMERA_OK != err )
   return err;  
  
  printf(" CAMERA Init Success ... ... ");
  
  
  CAMERA_SetImageOutPixelSize(DCMI_OUT_SIZE_X, DCMI_OUT_SIZE_Y);
  
  //在屏幕中间显示
  LCD_SetCursor_B((MAX_X - DCMI_OUT_SIZE_X) / 2, DCMI_OUT_SIZE_X + ((MAX_X - DCMI_OUT_SIZE_X) / 2) - 1,   //图像输出320,输出范围要与此“OV2640_OutSize_Set(320, 240); ”的设置一致
          (MAX_Y - DCMI_OUT_SIZE_Y) / 2, DCMI_OUT_SIZE_Y + ((MAX_Y - DCMI_OUT_SIZE_Y) / 2) - 1);  //图像输出240,   
//  CAMERA_SetImageOutSize (DCMI_OUT_SIZE_X/2, DCMI_OUT_SIZE_Y/2);
  
  
  DCMI_FrameBuf = mymalloc(SRAMEX, 1288) ;      // 申请外部SRAM内存地址
   /* Start the Camera Capture 启动相机捕捉  */
   BSP_CAMERA_ContinuousStart((uint8_t *) & DCMI_FrameBuf);
}
while(1)
{

}
}



//**********************************************************************************************
/**
  * @brief  Converts a line to an ARGB8888 pixel format.
  * @param  pSrc: Pointer to source buffer
  * @param  pDst: Output color
  * @param  xSize: Buffer width
  * @param  ColorMode: Input color mode   
  * @retval None
  */
static void DCMI_LCD_LL_ConvertLineToARGB8888(void *pSrc, void *pDst)
{
  /* Enable DMA2D clock */
  __HAL_RCC_DMA2D_CLK_ENABLE();
  
  /* Configure the DMA2D Mode, Color Mode and output offset */
  hdma2d_eval.Init.Mode         = DMA2D_M2M_PFC;
  hdma2d_eval.Init.ColorMode    = DMA2D_ARGB8888;
  hdma2d_eval.Init.OutputOffset = 0;     
  
  /* Foreground Configuration */
  hdma2d_eval.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
  hdma2d_eval.LayerCfg[1].InputAlpha = 0xFF;
  hdma2d_eval.LayerCfg[1].InputColorMode = CM_RGB565;
  hdma2d_eval.LayerCfg[1].InputOffset = 0;
  
  hdma2d_eval.Instance = DMA2D;
  
  /* DMA2D Initialization */
  if(HAL_DMA2D_Init(&hdma2d_eval) == HAL_OK)
  {
    if(HAL_DMA2D_ConfigLayer(&hdma2d_eval, 1) == HAL_OK)
    {
      if (HAL_DMA2D_Start(&hdma2d_eval, (uint32_t)pSrc, (uint32_t)pDst, LCD_35_WIDTH, 1) == HAL_OK)
      {
        /* Polling For DMA transfer */  
        HAL_DMA2D_PollForTransfer(&hdma2d_eval, 10);
      }
    }
  }
  else
  {
    /* FatFs Initialization Error */
//    Error_Handler();
  printf(" HAL DMA2_Init Error ... ...");
  }
}


//*******************************************************************************************

/**
  * @brief  Camera line evnet callback
  * @param  None
  * @retval None
  */
void BSP_CAMERA_LineEventCallback(void)
{
  static uint32_t tmp, tmp2, counter;
  
  if(LCD_35_HEIGHT > counter)
  {
    DCMI_LCD_LL_ConvertLineToARGB8888((uint32_t *)(DCMI_FrameBuf + tmp), (uint32_t *)(LCD_RAM + tmp2));
    tmp  = tmp +  LCD_35_WIDTH * sizeof ( uint16_t );
    tmp2 = tmp2 + LCD_35_WIDTH * sizeof ( uint32_t );
    counter ++;
  
  printf(" DCMI OUT ... %d", counter);     // 串口打应 正常  还有此处,我已经把他屏蔽的了,但是程序运行时串口还是会有输出,不知道是何故 ??????????????????????????????????
  }
  else
  {
    tmp = 0;
    tmp2 = 0;
    counter = 0;
  }
}


/**
  * @brief  Frame event callback   帧事件回调
  * @param  hdcmi: pointer to the DCMI handle  
  * @retval None
  */
void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
{        
  BSP_CAMERA_FrameEventCallback();
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
13条回答
davidliu9518
2019-07-15 07:54
1.把摄像头改成彩条输出,改两个寄存器就可以了。

2.debug模式下,看看图像的buffer,彩条模式下,buffer的值和大小都是一样的,看看是否顺利得到数据了。

3.我在其他论坛有个关于CUBE库获取OV2640的JPEG图像的例子,有源码,地址不方便贴了,百度一下【f446RE开发板试用】教你用HAL库DCMI捕捉OV2640

一周热门 更多>