Skip to main content
theparitt
Associate III
July 23, 2012
Question

DCMI camera interface program with DMA with STM32f4-discovery board

  • July 23, 2012
  • 28 replies
  • 6417 views
Posted on July 23, 2012 at 02:15

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. :) #ask-smarter-questions #dcmi-dma-stm32f4-sicovery-camera
This topic has been closed for replies.

28 replies

chtatasever
Visitor II
January 28, 2013
Posted on January 28, 2013 at 15:43

Tesla DeLorean
Guru
January 28, 2013
Posted on January 28, 2013 at 16:08

Provided you allocated it as a global variable you should be able to use the data once the DMA operation completes. Regular array or pointer access should suffice.

I'm not sure blinking LEDs 70K times is going to be very helpful. You'd presumably be better off loading it in a standard bitmap format you can use on a PC. Or output via a LCD panel.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
chtatasever
Visitor II
January 28, 2013
Posted on January 28, 2013 at 19:09

When I declare it as a regular array I'm getting identifier ''frame_buffer'' is undefined error. Well, actually I'm going to calculate mean of the pixels to detect objects that in sight of camera(8-bits depth 1=black 255=white) so leds are not very important. How about making it a global variable, how can I? or is it possible that using  if(s) and some loops to alert obstacles in OV7670.c file, OV7670 doesn't even have a void main function.. thanks.  

Tesla DeLorean
Guru
January 28, 2013
Posted on January 28, 2013 at 19:36

You're talking about code I can't see, in a project I don't have.

If the frame buffer is defined in a different module you'll need to refer to it using an 'extern' prototype.
Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
chtatasever
Visitor II
January 28, 2013
Posted on January 28, 2013 at 20:43

extern uint8_t frame_buffer[];

resolved the problem, thanks a lot!

chtatasever
Visitor II
February 3, 2013
Posted on February 03, 2013 at 13:36

yesil_kaya76
Associate
August 19, 2013
Posted on August 19, 2013 at 10:12

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6cp&d=%2Fa%2F0X0000000bs0%2FkUzBKU8CO7.vS4Ke8ew4gazdaP0fq3I8TDpgyJuADEM&asPdf=false