AnsweredAssumed Answered

DCMI camera interface program with DMA with STM32f4-discovery board

Question asked by moodaeng on Jul 23, 2012
Latest reply on Aug 19, 2013 by yesilkaya.seccad
Hi, 
      I am now trying to integrate my STM32Discovery board with OV7670 camera module without using any external ram from LCD. However I found a problem and I cannot get any data. I have tested it in many ways from counting the number of HCLK line per VSYNC to see the camera-output signal from my oscilloscope. I found the problem that everytime I enable camera-capture ( DCMI_CaptureCmd(Enable) )  It always generate  overflow interrupt (  DCMI_GetFlagStatus(DCMI_FLAG_OVFRI) == SET ).  I suspect that my DMA procedure is incorrect. Could someone help me to trace my code to find errors?  
Note: I set my  OV7670 output resolution to 320x240 QVGA. 

First i declare memory to store the data from camera

int8_t frame_buffer[320*240]; //store frame data in here



Here is the code that I initialize my GPIO

and also enable interrupt for debugging purpose..


int8_t frame_buffer[320*240];
 
 
EXTI_InitTypeDef EXTI_InitStructure;
 
void DCMI_GPIO_Configure()
{
    GPIO_InitTypeDef GPIO_InitStructure;
 
 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB
            | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE, ENABLE);
 
 
    /* B7: VSYNC*/
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
    /* A4: HSYNC*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
    /* A6: PCLK*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
    /* C6: data0*/
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
    /* C7: data1*/
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
    /* E0: data2*/
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI);
    /* E1: data3*/
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI);
    /* E4: data4*/
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI);
    /* B6: data5*/
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
    /* E5: data6*/
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI);
    /* E6: data7*/
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI);
 
 
    /* DCMI GPIO configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1
            | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
 
 
    NVIC_InitTypeDef NVIC_InitStructure;
 
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
 
 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}



Here is my DCMI configuration part.

void DCMI_Configure(void)
{
      DCMI_InitTypeDef DCMI_InitStructure;
      DMA_InitTypeDef  DMA_InitStructure;
 
      /*** Configures the DCMI to interface with the OV2640 camera module ***/
      /* Enable DCMI clock */
      RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
 
      /* DCMI configuration */
      //bit[14]: DCMI_Enable
      //bit[13:12]: reserved
      DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b; //bit[11:10]: 8bit-data/pclk
      DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_1of4_Frame;   //bit[9:8]:   Frame Capture Rate Control
      DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;  //LOW?HIGH?          //bit[7]:     VSYNC active @low
      DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;           //bit[6]:     HSYNC active @high
      DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;       //bit[5]:     PCLK at Rising Edge
      DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;     //bit[4]:     use hardware VSYNC/HSYNC
      //DCMI_JPEGCmd(ENABLE/DISABLE) bit[3]: JPEG Mode
      //bit[2]: Crop mode
      DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;     //bit[1]:     capture mode 0:continue(หลังจาก Captureแล้ว CaptureCmd ยัง Enable) 1:snapshot
                                                                             //bit[0]:     capture 0:disable/1:enable
      //ตั้งค่าทั้งหมดให้ DCMI
      DCMI_Init(&DCMI_InitStructure);
 
      //----- mask interrupt for DCMI -----
      DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);
      DCMI_ITConfig(DCMI_IT_LINE, ENABLE);
      DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);
      DCMI_ITConfig(DCMI_IT_OVF, ENABLE);
      DCMI_ITConfig(DCMI_IT_ERR, ENABLE);
 
 
 
      /* Configures the DMA2 to transfer Data from DCMI */
      /* Enable DMA2 clock */
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
      /* DMA2 Stream1 Configuration */
      DMA_DeInit(DMA2_Stream1);
 
      DMA_StructInit(&DMA_InitStructure);
 
      DMA_InitStructure.DMA_Channel = DMA_Channel_1;
      DMA_InitStructure.DMA_PeripheralBaseAddr =  (uint32_t)(DCMI_BASE + 0x28);
      DMA_InitStructure.DMA_Memory0BaseAddr =  (uint32_t)&frame_buffer[0];
      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
      DMA_InitStructure.DMA_BufferSize = 0xFFFF;
      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
      DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
      DMA_InitStructure.DMA_Priority = DMA_Priority_High;
      DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
      DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
      DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
      DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 
      /* DMA2 IRQ channel Configuration */
      DMA_Init(DMA2_Stream1, &DMA_InitStructure);
 
}



and Here is my main.c


void main()
{      
 
......
       DCMI_GPIO_Configure()
       DCMI_Configure(void)
      .....
 
        DMA_Cmd(DMA2_Stream1, ENABLE);
    DCMI_Cmd(ENABLE);
    DCMI_CaptureCmd(ENABLE);
 
    int z = 0;
    while(1);
 
 
}



and this is the way I debug my code using interrupt .


int count = 0;
int start = 0;
 
void DCMI_IRQHandler(void)
{
    if(DCMI_GetFlagStatus(DCMI_FLAG_VSYNCRI) == SET)
    {
        if(start == 0)
        {
            start = 1;
        }
        else
        {
            start = 0;
        }
    }
    else if(DCMI_GetFlagStatus(DCMI_FLAG_LINERI) == SET)
    {
        if(start == 1)
        {
            count++;
        }
        else
        {
            if(count != 0)
            {
                //printf("count: %d \n\n", count); //just dor counting the number of line
            }
            count = 0;
        }
    }
    else if(DCMI_GetFlagStatus(DCMI_FLAG_FRAMERI) == SET)
    {
        printf("DCMI_FLAG_FRAMERI \n\n");
    }
    else if(DCMI_GetFlagStatus(DCMI_FLAG_ERRRI) == SET)
    {
        printf("DCMI_FLAG_ERRRI \n\n");
    }
    else if(DCMI_GetFlagStatus(DCMI_FLAG_OVFRI) == SET)
    {
        printf("DCMI_FLAG_OVFRI \n\n");  //********** Unfortunately.. my code always comes here
    }
 
 
    DCMI_ClearFlag(DCMI_FLAG_VSYNCRI);
    DCMI_ClearFlag(DCMI_FLAG_LINERI);
    DCMI_ClearFlag(DCMI_FLAG_FRAMERI);
    DCMI_ClearFlag(DCMI_FLAG_ERRRI);
    DCMI_ClearFlag(DCMI_FLAG_OVFRI);
 
}



So my first thought is DMA error. I am not sure how to fix it. Everything seems correct. 
The reason that I don't want to use LCD and connect as external ram because I would like to only save the data to SD card and make my system as small as possible. I don't need to display an image to a user. 


:)

Outcomes