cancel
Showing results for 
Search instead for 
Did you mean: 

DCMI camera interface program with DMA with STM32f4-discovery board

theparitt
Associate II
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
28 REPLIES 28
chtatasever
Associate II
Posted on January 28, 2013 at 15:42

Hi, I declared uint8_t frame_buffer[320*240] in where we configure DMA etc. in OV7670.c, do you guys have any idea how can I use frame_buffer variable in main.c ? I will flash leds according to pixel values of array.. what would you think about it??

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

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
Up vote any posts that you find helpful, it shows what's working..
chtatasever
Associate II
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.  

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
Up vote any posts that you find helpful, it shows what's working..
chtatasever
Associate II
Posted on January 28, 2013 at 20:43

extern uint8_t frame_buffer[];

resolved the problem, thanks a lot!

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

yesil_kaya76
Associate II
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