AnsweredAssumed Answered

STM32F4 DIS CAM on the STM32F4 Discovery Board

Question asked by fabianS on Jul 29, 2015
Latest reply on Aug 5, 2015 by fabianS
Hello,
I am currently trying to get the STM32F4 DIS Cam to work with my Discovery Board. First I want to take a Snapshot with the Camera, save it in the RAM and then transfer the Data to my PC via UART.
Resolution of the Picture is QQVGA (160x120 Pixel), everything greater than that would be too large for the RAM.

Here is my Code so far.

main:

01.int main(void)
02.{
03.    long i;
04.    for(i=0;i<38400;i++)
05.    {
06.        picbuffer[i]='A';
07.    }
08.    for(i=0;i<320;i++)
09.    {
10.        pic_buf[i]='B';
11.    }
12.  
13.    SystemInit();
14.  
15.    /*Systick end of count event alle 10ms
16.     * Delay Funktion, ProzessorClock auf 1Mhz*/
17.    RCC_GetClocksFreq(&RCC_Clocks);
18.    SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);
19.    EXTI_Setup();
20.    USART_Setup();
21.    DCMI_Control_IO_Init();
22.    int a,b;
23.  
24.    if (DCMI_OV9655Config() == 0x00)
25.    {
26.        //DMA für Kamera aktivieren
27.        DMA_Cmd(DMA2_Stream1, ENABLE);
28.        //Kamera Interface aktivieren
29.        DCMI_Cmd(ENABLE);
30.        //Aufnahme starten
31.        DCMI_CaptureCmd(ENABLE);
32.  
33.        while(1)
34.        {
35.            //Delay(50);
36.            if(picbuffer[38399]!='A')
37.            {
38.                DCMI_CaptureCmd(DISABLE);
39.                send_string(bmp_header,54);
40.                Delay(100);
41.  
42.                for(a=0;a<120;a++)
43.                {
44.                    for(b=0;b<320;b++)
45.                    {
46.                        pic_buf[b]=picbuffer[a*320+b];
47.                    }
48.                    send_string(pic_buf,320);
49.                    Delay(100);
50.                }
51.                DCMI_CaptureCmd(ENABLE);
52.                Keypress=0;
53.            }
54.        }
55.    }else
56.    {
57.        while(1);
58.    }
59.}

and my other functions:
001.void EXTI0_IRQHandler()
002.{
003.    Keypress=1;
004.    EXTI_ClearITPendingBit(EXTI_Line0);
005.}
006.  
007.//USART Funktionen
008.void send_string(unsigned char string[], int len)
009.{
010.    DMA_InitTypeDef DMA_InitStructure;
011.    int i;
012.    if(!DMA_GetFlagStatus(DMA1_Stream3,DMA_FLAG_TCIF3))
013.    {
014.        for(i=0;i<len;i++)
015.        {
016.            send_buffer[i]=string[i];
017.        }
018.            /*DMA übertragung auf passende Stringlänge stellen um nur
019.            benötigte Anzahl Zeichen zu senden. */
020.            DMA_Cmd(DMA1_Stream3, DISABLE);
021.            DMA_DeInit(DMA1_Stream3);
022.            DMA_StructInit(&DMA_InitStructure);
023.            DMA_InitStructure.DMA_BufferSize = len;
024.            DMA_InitStructure.DMA_Channel = DMA_Channel_4;
025.            DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
026.            DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
027.            DMA_InitStructure.DMA_Memory0BaseAddr = &send_buffer;
028.            DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
029.            DMA_InitStructure.DMA_PeripheralDataSize =  DMA_PeripheralDataSize_Byte;
030.            DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
031.            DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_BASE+0x04;
032.            DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
033.            DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
034.            DMA_Init(DMA1_Stream3, &DMA_InitStructure);
035.            DMA_ITConfig(DMA1_Stream3, DMA_IT_TC,ENABLE);
036.            DMA_Cmd(DMA1_Stream3, ENABLE);
037.  
038.  
039.    }else
040.    {
041.  
042.    }
043.}
044.  
045.void DMA1_Stream3_IRQHandler()
046.{
047.    if(DMA_GetFlagStatus(DMA1_Stream3,DMA_FLAG_TCIF3))
048.    {
049.        DMA_ClearFlag(DMA1_Stream3,DMA_FLAG_TCIF3);
050.    }
051.}
052.  
053.void USART_Setup()
054.{
055.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
056.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
057.    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
058.  
059.  
060.    //USART3 PD8 - TX || PD9 - RX
061.    USART_InitTypeDef USART_InitStructure;
062.    GPIO_InitTypeDef GPIO_InitStructure;
063.    NVIC_InitTypeDef NVIC_InitStructure;
064.  
065.    //Configure Pins
066.    GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);
067.    GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);
068.  
069.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
070.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
071.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
072.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;
073.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
074.    GPIO_Init(GPIOD, &GPIO_InitStructure);
075.  
076.    //Configure USART
077.    USART_InitStructure.USART_BaudRate = 19200;
078.    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
079.    USART_InitStructure.USART_StopBits = USART_StopBits_1;
080.    USART_InitStructure.USART_Parity = USART_Parity_No;
081.    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
082.    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
083.  
084.    USART_Init(USART3, &USART_InitStructure);
085.    USART_Cmd(USART3, ENABLE);
086.  
087.    USART_DMACmd(USART3,USART_DMAReq_Tx, ENABLE);
088.    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;
089.    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
090.    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
091.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
092.    NVIC_Init(&NVIC_InitStructure);
093.    NVIC_EnableIRQ(DMA1_Stream3_IRQn);
094.}
095.  
096.//I2C1 Setup, benötigt um die Kamera zu steuern
097.void I2C1_Setup()
098.{
099.    //Init Structures
100.    GPIO_InitTypeDef GPIO_InitStructure;
101.    I2C_InitTypeDef  I2C_InitStruct;
102.  
103.    //Anschalten der Taktsignale für Peripherals
104.    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
105.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
106.  
107.    //Einstellen der Pins auf Alternate Function
108.    GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
109.    GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
110.  
111.    //Init Pins
112.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
113.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
114.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
115.    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
116.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
117.    GPIO_Init(GPIOB, &GPIO_InitStructure);
118.  
119.    //Init I2C
120.    I2C_DeInit(I2C1); //mögliche Konfigurationen löschen
121.  
122.    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
123.    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
124.    I2C_InitStruct.I2C_OwnAddress1 = 0xFE;
125.    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
126.    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
127.    I2C_InitStruct.I2C_ClockSpeed = 30000;
128.    I2C_Init(I2C1, &I2C_InitStruct);
129.    I2C_Cmd(I2C1, ENABLE); //I2C1 aktivieren
130.}
131.  
132.//DCMI Setup, Schnittstelle der Kamera
133.void DCMI_Setup()
134.{
135.    //Init Structures
136.    DCMI_InitTypeDef DCMI_InitStructure;
137.    GPIO_InitTypeDef GPIO_InitStructure;
138.    DMA_InitTypeDef  DMA_InitStructure;
139.  
140.    //Anschalten der Taktsignale
141.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE);
142.    RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
143.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
144.  
145.    //Einstellen der Pins auf Alternate Function
146.    //Picture Clock
147.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
148.    //D0-D7, 8 Bit Kamera
149.    GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
150.    GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
151.    GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI);
152.    GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI);
153.    GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI);
154.    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
155.    GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI);
156.    GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI);
157.    //VSYNC
158.    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
159.    //HSYNC
160.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
161.  
162.    //Init Pins
163.    //D0|D1
164.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
165.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
166.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
167.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
168.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
169.    GPIO_Init(GPIOC, &GPIO_InitStructure);
170.    //D2|D3|D4|D6|D7
171.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
172.    GPIO_Init(GPIOE, &GPIO_InitStructure);
173.    //D5|VSYNC
174.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
175.    GPIO_Init(GPIOB, &GPIO_InitStructure);
176.    //PCLK|HSYNC
177.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;
178.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
179.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
180.    GPIO_Init(GPIOA, &GPIO_InitStructure);
181.  
182.    //DMCI Setup
183.    DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
184.    DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
185.    DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
186.    DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
187.    DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;
188.    DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
189.    DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
190.  
191.    DCMI_Init(&DCMI_InitStructure);
192.  
193.    //DMA Setup
194.    /*DMA_StructInit(&DMA_InitStructure);
195.    DMA_InitStructure.DMA_Channel = DMA_Channel_1;
196.    DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
197.    DMA_InitStructure.DMA_Memory0BaseAddr = &picbuffer;
198.    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
199.    DMA_InitStructure.DMA_BufferSize = 1;
200.    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
201.    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
202.    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
203.    DMA_InitStructure.DMA_PeripheralDataSize =  DMA_PeripheralDataSize_Word;
204.    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
205.    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
206.    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
207.    //DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
208.    //DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
209.    //DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;*/
210.  
211.    DMA_InitStructure.DMA_Channel = DMA_Channel_1;
212.    DMA_InitStructure.DMA_PeripheralBaseAddr =  (uint32_t)(DCMI_BASE + 0x28);
213.    DMA_InitStructure.DMA_Memory0BaseAddr =  (uint32_t)picbuffer;
214.    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
215.    DMA_InitStructure.DMA_BufferSize = 9600; //160*120/2
216.    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
217.    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
218.    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
219.    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
220.    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// First take one picture
221.    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
222.    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
223.    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
224.    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
225.    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
226.  
227.  
228.    DMA_Init(DMA2_Stream1, &DMA_InitStructure);
229.  
230.  
231.  
232.}
233.  
234.//EXTI Setup, Kamera Auslöser
235.void EXTI_Setup()
236.{
237.    //Init Structures
238.    GPIO_InitTypeDef    GPIO_InitStructure;
239.    NVIC_InitTypeDef    NVIC_InitStructure;
240.    EXTI_InitTypeDef    EXTI_InitStructure;
241.  
242.    //Anschalten der Taktsignale
243.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
244.    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
245.  
246.    //GPIO Konfiguration
247.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
248.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
249.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
250.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
251.    GPIO_Init(GPIOA, &GPIO_InitStructure);
252.  
253.    //Interrupt Line Konfigurieren
254.    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
255.  
256.    //Interrupt Konfiguration
257.    EXTI_InitStructure.EXTI_Line = EXTI_Line0;
258.    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
259.    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
260.    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
261.    EXTI_Init(&EXTI_InitStructure);
262.  
263.    //Interrupt Einstellen
264.    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
265.    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
266.    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
267.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
268.    NVIC_Init(&NVIC_InitStructure);
269.}
270.  
271.//CAM Setup
272.uint8_t DCMI_OV9655Config()
273.{
274.    //I2C aktivieren
275.    I2C1_Setup();
276.    //Überprüfen ob Modul da ist
277.    if (DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS,0x12, 0x80))
278.    {
279.        return (0xFF);
280.    }
281.    //Bildgröße einstellen
282.    DCMI_OV9655_QQVGASizeSetup();
283.    //Modus auf RGB565
284.    DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS, OV9655_COM7, 0x63);
285.    DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS, OV9655_COM15, 0x10);
286.    //Href Signal invertieren?
287.    DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS, OV9655_COM10, 0x08);
288.  
289.    //DCMI aktivieren
290.    DCMI_Setup();
291.  
292.    return 0;
293.}
294.  
295./* Bewegungssensor auf dem Discovery Board auf Reset,
296. * würde sonst eine Leitung permanent auf low ziehen */
297.void LIS302DL_Reset(void)
298.{
299.  uint8_t ctrl = 0;
300.  
301.  LIS302DL_InitTypeDef  LIS302DL_InitStruct;
302.  LIS302DL_InterruptConfigTypeDef LIS302DL_InterruptStruct;
303.  
304.  /* Set configuration of LIS302DL*/
305.  LIS302DL_InitStruct.Power_Mode = LIS302DL_LOWPOWERMODE_ACTIVE;
306.  LIS302DL_InitStruct.Output_DataRate = LIS302DL_DATARATE_100;
307.  LIS302DL_InitStruct.Axes_Enable = LIS302DL_X_ENABLE | LIS302DL_Y_ENABLE | LIS302DL_Z_ENABLE;
308.  LIS302DL_InitStruct.Full_Scale = LIS302DL_FULLSCALE_2_3;
309.  LIS302DL_InitStruct.Self_Test = LIS302DL_SELFTEST_NORMAL;
310.  LIS302DL_Init(&LIS302DL_InitStruct);
311.  
312.  /* Set configuration of Internal High Pass Filter of LIS302DL*/
313.  LIS302DL_InterruptStruct.Latch_Request = LIS302DL_INTERRUPTREQUEST_LATCHED;
314.  LIS302DL_InterruptStruct.SingleClick_Axes = LIS302DL_CLICKINTERRUPT_Z_ENABLE;
315.  LIS302DL_InterruptStruct.DoubleClick_Axes = LIS302DL_DOUBLECLICKINTERRUPT_Z_ENABLE;
316.  LIS302DL_InterruptConfig(&LIS302DL_InterruptStruct);
317.  
318.  /* Required delay for the MEMS Accelerometre: Turn-on time = 3/Output data Rate
319.                                                             = 3/100 = 30ms */
320.  Delay(30);
321.  
322.  /* Configure Click Window */
323.  ctrl = 0xC0;
324.  LIS302DL_Write(&ctrl, LIS302DL_CLICK_CTRL_REG3_ADDR, 1);
325.}
326.  
327.//Funktionen für Delay
328.void SysTick_Handler(void)
329.{
330.  TimingDelay_Decrement();
331.}
332.void TimingDelay_Decrement(void)
333.{
334.  if (TimingDelay != 0x00)
335.  {
336.    TimingDelay--;
337.  }
338.}
339.void Delay(uint32_t nTime)
340.{
341.  TimingDelay = nTime;
342.  
343.  while (TimingDelay != 0);
344.}

Some of this code is taken from the official STM code samples for the Discovery CAM and BB expansions.

The problem is, that, if i use Snapshot mode for the Camera i only get 100 or 200 Bytes stored in my RAM, the rest stays at 'A'. If I use continuous mode i only get random data.

Outcomes