2012-07-22 05:15 PM
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 cameraint8_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
2013-01-28 06:42 AM
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??
2013-01-28 06:43 AM
2013-01-28 07:08 AM
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.2013-01-28 10:09 AM
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.
2013-01-28 10:36 AM
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.2013-01-28 11:23 AM
Yeah, my bad. I attached some images that would help you to understand the problem then I shall proceed after new commends
________________ Attachments : Ekran_Al_nt_s_1.PNG : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1Ft&d=%2Fa%2F0X0000000bl0%2Fn7d.M6l71FEs8Lcc3qPqk1y1L3eT5z5XPKQAFOHSo8I&asPdf=falseEkran_Al_nt_s_2.PNG : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1IX&d=%2Fa%2F0X0000000bkx%2F3xDf6XwNQjYs37FJ4n_R8wgYZl7pNCZPT49VVNaU4uY&asPdf=falseEkran_Al_nt_s_3.PNG : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1GS&d=%2Fa%2F0X0000000bku%2Fk654TnPDmFYu.9fCjrHqN0n6gMBH5EyYcHh_N_iF0Xk&asPdf=false2013-01-28 11:43 AM
extern uint8_t frame_buffer[];
resolved the problem, thanks a lot!2013-02-03 04:36 AM
2013-08-19 01:12 AM