cancel
Showing results for 
Search instead for 
Did you mean: 

DCMI to memory DMA transfer

khouja_houssem
Associate II
Posted on October 29, 2013 at 08:43

Hi,

I am trying to receive datas from a camera module through DCMI interface and send each 8bits received to UART. The problem is that I can only receive one word (NDTR=1) and the program only enters the DMA interrupt is once. Can someone help me with that. Here is my code:

/* Includes ------------------------------------------------------------------*/
#include ''stm32f4xx.h''
#include ''stm32f4_discovery.h''
#include ''main.h''
#include ''dcmi_ov56h''
__IO uint32_t TimingDelay;
RCC_ClocksTypeDef RCC_Clocks;
EXTI_InitTypeDef EXTI_InitStructure;
uint32_t DCMI_PendingData[1];
/* Private function prototypes -----------------------------------------------*/
uint8_t DCMI_OV9655Config(void);
void DCMI_Config(void);
void USART1_Config(void);
int main(void)
{
/* SysTick end of count event each 10ms */
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);
// MCO1_Init(); //PA8
TIM1_Configuration(); //24Mhz CLK
I2C2_Config();
DCMI_Config();
USART1_Config();
DCMI_OV5642_ReadID();
Delay(10);
QVGA_Init();
/* Activate HSYNC */
DCMI_SingleRandomWrite(OV5642_DEVICE_WRITE_ADDRESS,0x471B,0x03); 
/* Start Image capture and Display on the LCD *****************************/
/* Enable DMA transfer */
DMA_Cmd(DMA2_Stream1, ENABLE);
/* Enable DCMI interface */
DCMI_Cmd(ENABLE); 
/* Start Image capture */ 
DCMI_CaptureCmd(ENABLE); 
while (1)
{
} 
} 
void DMA2_Stream1_IRQHandler(void)
{
/* Test on DMA Stream Transfer Complete interrupt */
if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1))
{
// USART_SendData(USART1, (uint8_t) *DCMI_PendingData);
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
}
} 
/**
* @brief Configures the DCMI to interface with the OV9655 camera module.
* @param None
* @retval None
*/
void DCMI_Config(void)
{
DCMI_InitTypeDef DCMI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable DCMI GPIOs clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE | 
RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE); 
/* Enable DCMI clock */
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
/* Connect DCMI pins to AF13 ************************************************/
/* PCLK */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI); 
/* D0-D7 */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI); //D0
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI); //D1
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI); //D2
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI); //D3
GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI); //D4
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI); //D5
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI); //D6
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI); //D7
/* VSYNC */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
/* HSYNC */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
/* DCMI GPIO configuration **************************************************/
/* D0 D1(PC6/7) */
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);
/* D2..D4(PE0/1/4) D6/D7(PE5/6) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 
| GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* D5(PB6), VSYNC(PB7) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* PCLK(PA6) HSYNC(PA4)*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* DCMI configuration *******************************************************/ 
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);
/* Enable DMA2 clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
/* DMA2 Stream1 Configuration */ 
DMA_DeInit(DMA2_Stream1);
DMA_InitStructure.DMA_Channel = DMA_Channel_1; 
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DCMI_PendingData;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
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;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
/* Enable the DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Stream1, DMA_IT_TC | DMA_IT_FE, ENABLE); 
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the DCMI Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DCMI_ITConfig(DCMI_IT_LINE | DCMI_IT_OVF | DCMI_IT_ERR | DCMI_IT_VSYNC | DCMI_IT_LINE | DCMI_IT_FRAME, ENABLE);
}

4 REPLIES 4
Posted on October 29, 2013 at 16:57

Doing one byte at a time is going to FAIL as a solution, if not in implementation, reconsider.

DMA would need to be circular to get multiple TC interrupts without reconfiguring the DMA controller each time.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
khouja_houssem
Associate II
Posted on October 30, 2013 at 15:37

Thank you CLIVE1 for the answer.

Maybe I will be sending each 4 bytes received before getting the next word.

But I still didn't get to that phase, I changed the DMA mode to circular, and I tryed to use a bigger buffer (uint8_t frame_buffer[160*80*2]) to see if I am receiving more than one word but I am only getting one word of the datas everytime (I also enabled DMA_memoryInc). The NDTR register always contains 1 which confirms that I am only receiving one data.

I am maybe having a problem with the DMA configuration but I am not sure. I hope you can help.
Posted on October 30, 2013 at 17:21

I don't have any investments in screens/cameras.

If you aren't getting any data, you might want to confirm the interface is clocking.

There are other DCMI examples, and posts on the forum.

If the camera interface is clocking at 8-14 MHz (or whatever), you're not going to be able to stuff bytes over a serial or USB-FS interface at a fast enough rate. You're going to want to capture a single frame, then transmit it over the slower interface while ignoring subsequent frames until that completes.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
michaelmccartyeng
Associate II
Posted on October 30, 2013 at 18:18

The way I do it is to dcmi->DMA transfer then on TC of that i have a state machine that i set into ''caputred image'' state, from there it does a DMA->Uart transfer to shoot the image out of the uart port. As soon as I start the DMA->Uart transfer I start an image capture on a second buffer (double buffering). So the instant the DMA->Uart transfer is finished the next image is ready to be transmitted. 

The only good reason to go through each line int and parse the data is to do some processing on the stm32 itself. For instance if you wanted it to follow color or something.