hpdell 发表于 2016-5-12 21:00:11

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

本帖最后由 hpdell 于 2016-5-13 10:17 编辑

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

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

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

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

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


/* Private define ------------------------------------------------------------*/
#define LCD_REG(*(volatile uint16_t *)(0x6C000000))/* RS = 0 disp RegADDR*/
#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("\r\nOV2640_SENSOR_MID:%#X",err);
returnerr ;
}

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

/* 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, OV2640_160x120_JPEG);
    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, OV2640_176x144_JPEG);
    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, OV2640_320x240_JPEG);
//    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, OV2640_352x288_JPEG);
    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, OV2640_QQVGA_160x120);
   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, OV2640_QVGA_320x240);
   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, OV2640_480x272);
   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, OV2640_480x320);
   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, OV2640_VGA_640x480);
   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, OV2640_SVGA_800x600);
   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, OV2640_SXGA_1600x1200);
   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;
}


/**
* @briefInitializes the DCMI MSP.
* @paramNone
* @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);
}
}


/**
* @briefStarts the camera capture in continuous mode. 在连续模式下启动相机捕获。
* @parambuff: 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; // 字体颜色
tFont.BackColor = CL_MASK; // 透明色
tFont.Space = 10;

LCD_ClrScr(CL_BLUE);

LCD_DispStr( 30, 10,(const u8 *)"SWSSTM32F429IIT6 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);   //色彩饱和度
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("\r\nCAMERA Init Success ... ...\r\n");


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)
{

}
}



//**********************************************************************************************
/**
* @briefConverts a line to an ARGB8888 pixel format.
* @parampSrc: Pointer to source buffer
* @parampDst: Output color
* @paramxSize: Buffer width
* @paramColorMode: 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.AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d_eval.LayerCfg.InputAlpha = 0xFF;
hdma2d_eval.LayerCfg.InputColorMode = CM_RGB565;
hdma2d_eval.LayerCfg.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("\r\nHAL DMA2_Init Error ... ...");
}
}


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

/**
* @briefCamera line evnet callback
* @paramNone
* @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("\r\nDCMI OUT ... %d", counter);   // 串口打应 正常还有此处,我已经把他屏蔽的了,但是程序运行时串口还是会有输出,不知道是何故 ??????????????????????????????????
}
else
{
    tmp = 0;
    tmp2 = 0;
    counter = 0;
}
}


/**
* @briefFrame event callback   帧事件回调
* @paramhdcmi: pointer to the DCMI handle
* @retval None
*/
void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
{      
BSP_CAMERA_FrameEventCallback();
}



wtliu 发表于 2016-5-13 10:01:15

先好好看看OV2640 显示的数据手册,主要可能是时序问题。

hpdell 发表于 2016-5-13 10:15:15

本帖最后由 hpdell 于 2016-5-13 15:25 编辑

wtliu 发表于 2016-5-13 10:01
先好好看看OV2640 显示的数据手册,主要可能是时序问题。
我使用标准库时是没有任何问题的,

现在应该是这个hal的库不怎么会用,可能哪里设置不对或者是hal库的函数调用不对吧,再或者是配置不对吧,

myfocus-2048857 发表于 2016-5-13 17:47:13

【正点原子探索者STM32F407开发板例程连载+教学】第40章 OV2640摄像头实验实验
http://www.openedv.com/posts/list/43372.htm

hpdell 发表于 2016-5-13 22:06:17

myfocus-2048857 发表于 2016-5-13 17:47
【正点原子探索者STM32F407开发板例程连载+教学】第40章 OV2640摄像头实验实验
http://www.openedv.com/pos ...

他的这个是标准库的,目前这个 HAL的库与标准库的差别很大啊,

myfocus-2048857 发表于 2016-5-14 01:04:09

hpdell 发表于 2016-5-13 22:06
他的这个是标准库的,目前这个 HAL的库与标准库的差别很大啊,

学习了:标准库、HAL库

colin2135 发表于 2016-5-14 09:05:28

1.把摄像头改成彩条输出,改两个寄存器就可以了。

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

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

Ljmp 发表于 2016-5-14 14:47:31

;P;P;P去找找ov2640历程基本可以搞定!!!

xmshao 发表于 2016-5-14 15:59:58

那可能是哪里时序有点小差异导致的

hpdell 发表于 2016-5-14 20:02:49

本帖最后由 hpdell 于 2016-5-14 20:34 编辑

colin2135 发表于 2016-5-14 09:05
1.把摄像头改成彩条输出,改两个寄存器就可以了。

2.debug模式下,看看图像的buffer,彩条模式下,buffer的 ...
你好,貌似找到了,正在研究中,多谢多谢啊,貌似是在 21里面
页: [1] 2
查看完整版本: 使用stm32f429 cube/HAL库 驱动 OV2640 显示不成功 ???