-
-
Save andrecurvello/3b87c40becc21a50fa37598626f3c2be to your computer and use it in GitHub Desktop.
OV7670 control library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* ========================================================================== | |
* main.c | |
* (c) 2014-2015, Petr Machala | |
* | |
* Description: | |
* OptRec sensor system main file. | |
* Optimized for 32F429IDISCOVERY board. | |
* | |
* License: | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
* ========================================================================== | |
*/ | |
#include "stm32f4xx.h" | |
#include "ov7670_control.h" | |
#include "lcd_ili9341.h" | |
#include "lcd_fonts.h" | |
#include "lcd_spi.h" | |
#include "fmc_sdram.h" | |
#include <stdio.h> | |
/* Main program loop */ | |
int main(void){ | |
// System initialization | |
SystemInit(); | |
FMC_SDRAM_Init(); | |
Camera_Init(); | |
LCD_ILI9341_Init(); | |
LCD_ILI9341_Rotate(LCD_ILI9341_Orientation_Portrait_2); | |
// OV7670 configuration | |
LCD_ILI9341_Fill(ILI9341_COLOR_WHITE); | |
LCD_ILI9341_Puts_center(120, "Configuring camera", &LCD_Font_11x18, ILI9341_COLOR_BLACK, ILI9341_COLOR_WHITE); | |
LCD_ILI9341_DrawRectangle(70, 150, 170, 150+18, ILI9341_COLOR_BLACK); | |
if (OV7670_Config() != 0){ | |
LCD_ILI9341_Puts_center(200, "Failed", &LCD_Font_11x18, ILI9341_COLOR_RED, ILI9341_COLOR_WHITE); | |
LCD_ILI9341_Puts_center(225, "Push reset button", &LCD_Font_7x10, ILI9341_COLOR_BLACK, ILI9341_COLOR_WHITE); | |
while(1){ | |
} | |
} | |
// Infinite program loop | |
while(1){ | |
DCMI_CaptureCmd(ENABLE); | |
} | |
} | |
/* DCMI DMA interrupt */ | |
void DMA2_Stream1_IRQHandler(void){ | |
uint32_t n, i, buffer, *lcd_sdram1 = (uint32_t*) SDRAM_LCD_START1, *lcd_sdram2 = (uint32_t*) SDRAM_LCD_START2; | |
// DMA complete | |
if(DMA_GetITStatus(DMA2_Stream1,DMA_IT_TCIF1) == SET){ | |
DMA_Cmd(DMA2_Stream1, DISABLE); | |
//Wait for SPI to be ready | |
while (SPI_I2S_GetFlagStatus(ILI9341_SPI, SPI_I2S_FLAG_BSY)); | |
// Modify image to little endian | |
i=0; | |
for (n = 0; n < (IMG_HEIGHT*IMG_WIDTH)/2; n++) { | |
buffer = lcd_sdram1[n]; | |
lcd_sdram2[n] = (((buffer & 0xff000000) >> 8) | ((buffer & 0x00ff0000) << 8) | ((buffer & 0x0000ff00) >> 8) | ((buffer & 0x000000ff) << 8)); | |
} | |
// Prepare LCD for image | |
LCD_ILI9341_Rotate(LCD_ILI9341_Orientation_Landscape_2); | |
LCD_ILI9341_SetCursorPosition(0, 0, IMG_HEIGHT - 1, IMG_WIDTH - 1); | |
LCD_ILI9341_SendCommand(ILI9341_GRAM); | |
// SPI send | |
ILI9341_WRX_SET; | |
ILI9341_CS_RESET; | |
SPI_DMA_init(lcd_sdram2); | |
DMA_Cmd(DMA2_Stream4, ENABLE); | |
// Clear IRQ flag | |
DMA_ClearITPendingBit(DMA2_Stream1,DMA_IT_TCIF1); | |
} | |
} | |
/* LCD SPI interrupt */ | |
void DMA2_Stream4_IRQHandler(void){ | |
static uint8_t n = 0; | |
uint32_t *lcd_sdram2 = (uint32_t*) SDRAM_LCD_START2; | |
// DMA_SPI complete | |
if(DMA_GetITStatus(DMA2_Stream4,DMA_IT_TCIF4) == SET){ | |
DMA_Cmd(DMA2_Stream4, DISABLE); | |
//Wait for SPI to be ready | |
while (SPI_I2S_GetFlagStatus(ILI9341_SPI, SPI_I2S_FLAG_BSY)); | |
switch(n){ | |
case 0: | |
SPI_DMA_init(lcd_sdram2 + IMG_WIDTH*IMG_HEIGHT*BYTES_PER_PX/3/4); | |
DMA_Cmd(DMA2_Stream4, ENABLE); | |
n++; | |
break; | |
case 1: | |
SPI_DMA_init(lcd_sdram2 + 2*IMG_WIDTH*IMG_HEIGHT*BYTES_PER_PX/3/4); | |
DMA_Cmd(DMA2_Stream4, ENABLE); | |
n++; | |
break; | |
case 2: | |
ILI9341_CS_SET; | |
DMA_Cmd(DMA2_Stream1, ENABLE); | |
DCMI_CaptureCmd(ENABLE); | |
n=0; | |
break; | |
} | |
// Clear IRQ flag | |
DMA_ClearITPendingBit(DMA2_Stream4,DMA_IT_TCIF4); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* ========================================================================== | |
* ov7670_control.c | |
* (c) 2014-2015, Petr Machala | |
* | |
* Description: | |
* OV7670 camera configuration and control file. | |
* Optimized for 32F429IDISCOVERY board. | |
* | |
* License: | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
* ========================================================================== | |
*/ | |
#include "ov7670_control.h" | |
const uint8_t OV7670_reg [OV7670_REG_NUM][2] = { | |
{0x12, 0x80}, //Reset registers | |
// Image format | |
{0x12, 0x14}, //QVGA size, RGB mode | |
{0x40, 0xd0}, //RGB565 | |
{0xb0, 0x84}, //Color mode | |
// Hardware window | |
{0x11, 0x80}, //PCLK settings | |
{0x32, 0x80}, //HREF | |
{0x17, 0x17}, //HSTART | |
{0x18, 0x05}, //HSTOP | |
{0x03, 0x0a}, //VREF | |
{0x19, 0x02}, //VSTART | |
{0x1a, 0x7a}, //VSTOP | |
// Scalling numbers | |
{0x70, 0x3a}, //X_SCALING | |
{0x71, 0x35}, //Y_SCALING | |
{0x72, 0x11}, //DCW_SCALING | |
{0x73, 0xf0}, //PCLK_DIV_SCALING | |
{0xa2, 0x02}, //PCLK_DELAY_SCALING | |
// Matrix coefficients | |
{0x4f, 0x80}, {0x50, 0x80}, | |
{0x51, 0x00}, {0x52, 0x22}, | |
{0x53, 0x5e}, {0x54, 0x80}, | |
{0x58, 0x9e}, | |
// Gamma curve values | |
{0x7a, 0x20}, {0x7b, 0x10}, | |
{0x7c, 0x1e}, {0x7d, 0x35}, | |
{0x7e, 0x5a}, {0x7f, 0x69}, | |
{0x80, 0x76}, {0x81, 0x80}, | |
{0x82, 0x88}, {0x83, 0x8f}, | |
{0x84, 0x96}, {0x85, 0xa3}, | |
{0x86, 0xaf}, {0x87, 0xc4}, | |
{0x88, 0xd7}, {0x89, 0xe8}, | |
// AGC and AEC parameters | |
{0xa5, 0x05}, {0xab, 0x07}, | |
{0x24, 0x95}, {0x25, 0x33}, | |
{0x26, 0xe3}, {0x9f, 0x78}, | |
{0xa0, 0x68}, {0xa1, 0x03}, | |
{0xa6, 0xd8}, {0xa7, 0xd8}, | |
{0xa8, 0xf0}, {0xa9, 0x90}, | |
{0xaa, 0x94}, {0x10, 0x00}, | |
// AWB parameters | |
{0x43, 0x0a}, {0x44, 0xf0}, | |
{0x45, 0x34}, {0x46, 0x58}, | |
{0x47, 0x28}, {0x48, 0x3a}, | |
{0x59, 0x88}, {0x5a, 0x88}, | |
{0x5b, 0x44}, {0x5c, 0x67}, | |
{0x5d, 0x49}, {0x5e, 0x0e}, | |
{0x6c, 0x0a}, {0x6d, 0x55}, | |
{0x6e, 0x11}, {0x6f, 0x9f}, | |
{0x6a, 0x40}, {0x01, 0x40}, | |
{0x02, 0x60}, {0x13, 0xe7}, | |
// Additional parameters | |
{0x34, 0x11}, {0x3f, 0x00}, | |
{0x75, 0x05}, {0x76, 0xe1}, | |
{0x4c, 0x00}, {0x77, 0x01}, | |
{0xb8, 0x0a}, {0x41, 0x18}, | |
{0x3b, 0x12}, {0xa4, 0x88}, | |
{0x96, 0x00}, {0x97, 0x30}, | |
{0x98, 0x20}, {0x99, 0x30}, | |
{0x9a, 0x84}, {0x9b, 0x29}, | |
{0x9c, 0x03}, {0x9d, 0x4c}, | |
{0x9e, 0x3f}, {0x78, 0x04}, | |
{0x0e, 0x61}, {0x0f, 0x4b}, | |
{0x16, 0x02}, {0x1e, 0x00}, | |
{0x21, 0x02}, {0x22, 0x91}, | |
{0x29, 0x07}, {0x33, 0x0b}, | |
{0x35, 0x0b}, {0x37, 0x1d}, | |
{0x38, 0x71}, {0x39, 0x2a}, | |
{0x3c, 0x78}, {0x4d, 0x40}, | |
{0x4e, 0x20}, {0x69, 0x00}, | |
{0x6b, 0x3a}, {0x74, 0x10}, | |
{0x8d, 0x4f}, {0x8e, 0x00}, | |
{0x8f, 0x00}, {0x90, 0x00}, | |
{0x91, 0x00}, {0x96, 0x00}, | |
{0x9a, 0x00}, {0xb1, 0x0c}, | |
{0xb2, 0x0e}, {0xb3, 0x82}, | |
{0x4b, 0x01} | |
}; | |
void PWDN_Init(void){ | |
GPIO_InitTypeDef GPIO_InitDef; | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); | |
// GPIO config | |
// PB4 | |
GPIO_InitDef.GPIO_Pin = PWDN_PIN; | |
GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT; | |
GPIO_InitDef.GPIO_OType = GPIO_OType_PP; | |
GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL; | |
GPIO_InitDef.GPIO_Speed = GPIO_Speed_100MHz; | |
GPIO_Init(PWDN_PORT, &GPIO_InitDef); | |
} | |
void MCO_Init(void){ | |
GPIO_InitTypeDef GPIO_InitStructure; | |
TIM_OCInitTypeDef TIM_OCInitStructure; | |
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; | |
RCC_ClockSecuritySystemCmd(ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); | |
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); | |
// GPIO config | |
// PA9 | |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; | |
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; | |
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; | |
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; | |
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; | |
GPIO_Init(GPIOA, &GPIO_InitStructure); | |
// GPIO AF config | |
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_TIM1); | |
// Time base configuration | |
TIM_TimeBaseStructure.TIM_Prescaler = 0; | |
TIM_TimeBaseStructure.TIM_Period = TIM_PERIOD - 1; | |
TIM_TimeBaseStructure.TIM_ClockDivision = 0; | |
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; | |
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); | |
TIM_ARRPreloadConfig(TIM1, ENABLE); | |
// TIM PWM1 Mode configuration | |
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; | |
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; | |
TIM_OCInitStructure.TIM_Pulse = TIM_DUTY_50; | |
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; | |
// Output Compare PWM Mode configuration | |
TIM_OC2Init(TIM1, &TIM_OCInitStructure); | |
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); | |
// Enable TIM | |
TIM_CtrlPWMOutputs(TIM1, ENABLE); | |
TIM_Cmd(TIM1, ENABLE); | |
} | |
void SCCB_Init(void){ | |
GPIO_InitTypeDef GPIO_InitStructure; | |
I2C_InitTypeDef I2C_InitStructure; | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); | |
// GPIO config | |
// SIOC SIOD | |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; | |
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; | |
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; | |
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; | |
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; | |
GPIO_Init(GPIOB, &GPIO_InitStructure); | |
// GPIO AF config | |
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1); | |
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); | |
// I2C config | |
I2C_DeInit(I2C1); | |
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; | |
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; | |
I2C_InitStructure.I2C_OwnAddress1 = 0x00; | |
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; | |
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; | |
I2C_InitStructure.I2C_ClockSpeed = 100000; | |
I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE); | |
I2C_Init(I2C1,&I2C_InitStructure); | |
I2C_Cmd(I2C1, ENABLE); | |
} | |
uint8_t SCCB_write_reg(uint8_t reg_addr, uint8_t* data){ | |
uint32_t timeout = 0x7FFFFF; | |
// Send start bit | |
I2C_GenerateSTART(I2C1, ENABLE); | |
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB)){ | |
if ((timeout--) == 0){ | |
return 1; | |
} | |
} | |
while( !I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){ | |
if ((timeout--) == 0){ | |
return 1; | |
} | |
} | |
// Send slave address (camera write address) | |
I2C_Send7bitAddress(I2C1, OV7670_WRITE_ADDR, I2C_Direction_Transmitter); | |
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){ | |
if ((timeout--) == 0){ | |
return 1; | |
} | |
} | |
// Send register address | |
I2C_SendData(I2C1, reg_addr); | |
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){ | |
if ((timeout--) == 0){ | |
return 1; | |
} | |
} | |
// Send new register value | |
I2C_SendData(I2C1, *data); | |
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){ | |
if ((timeout--) == 0){ | |
return 1; | |
} | |
} | |
// Send stop bit | |
I2C_GenerateSTOP(I2C1, ENABLE); | |
return 0; | |
} | |
void DCMI_DMA_Init(void){ | |
GPIO_InitTypeDef GPIO_InitStructure; | |
DCMI_InitTypeDef DCMI_InitStructure; | |
DMA_InitTypeDef DMA_InitStructure; | |
NVIC_InitTypeDef NVIC_InitStructure; | |
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); | |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); | |
// GPIO config | |
// HREF PCLK | |
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); | |
// VSYNC | |
GPIO_InitStructure.GPIO_Pin = 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); | |
// D5 | |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; | |
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(GPIOD, &GPIO_InitStructure); | |
// D0 D1 D2 | |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8; | |
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); | |
// D4 D6 D7 | |
GPIO_InitStructure.GPIO_Pin = 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); | |
// D3 | |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; | |
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(GPIOG, &GPIO_InitStructure); | |
// GPIO AF config | |
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI); | |
GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_DCMI); | |
// DCMI config | |
DCMI_DeInit(); | |
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot; | |
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b; | |
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame; | |
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising; | |
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low; | |
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High; | |
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware; | |
DCMI_Init(&DCMI_InitStructure); | |
DCMI_Cmd(ENABLE); | |
// DMA config | |
DMA_DeInit(DMA2_Stream1); | |
DMA_InitStructure.DMA_Channel = DMA_Channel_1; | |
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS; | |
DMA_InitStructure.DMA_Memory0BaseAddr = SDRAM_LCD_START1; | |
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; | |
DMA_InitStructure.DMA_BufferSize = IMG_HEIGHT*IMG_WIDTH*BYTES_PER_PX/4; | |
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_Word; | |
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; | |
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; | |
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; | |
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); | |
DMA_Cmd(DMA2_Stream1, ENABLE); | |
// DMA interrupt | |
DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE); | |
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); | |
} | |
uint8_t OV7670_Config(void){ | |
uint8_t data, i, err; | |
// Configure camera registers | |
for(i=0; i<OV7670_REG_NUM ;i++){ | |
data = OV7670_reg[i][1]; | |
err = SCCB_write_reg(OV7670_reg[i][0], &data); | |
if (err) | |
break; | |
Delay_ms(10); | |
LCD_ILI9341_DrawLine(70+i*100/OV7670_REG_NUM, 150, 70+i*100/OV7670_REG_NUM, 150+18, ILI9341_COLOR_BLACK); | |
} | |
return err; | |
} | |
void Camera_Init(void){ | |
PWDN_Init(); | |
MCO_Init(); | |
SCCB_Init(); | |
DCMI_DMA_Init(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* ========================================================================== | |
* ov7670_control.h | |
* (c) 2014-2015, Petr Machala | |
* | |
* Description: | |
* OV7670 camera configuration and control library. | |
* Optimized for 32F429IDISCOVERY board. | |
* | |
* License: | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
* ========================================================================== | |
*/ | |
#ifndef OV7670_CONTROL_H | |
#define OV7670_CONTROL_H | |
// Includes | |
#include "stm32f4xx.h" | |
#include "stm32f4xx_rcc.h" | |
#include "stm32f4xx_gpio.h" | |
#include "stm32f4xx_i2c.h" | |
#include "stm32f4xx_dma.h" | |
#include "stm32f4xx_dcmi.h" | |
#include "lcd_ili9341.h" | |
#include "fmc_sdram.h" | |
// SCCB write address | |
#define SCCB_REG_ADDR 0x01 | |
// DCMI data register | |
#define DCMI_DR_ADDRESS (uint32_t) 0x50050028 | |
// OV7670 camera settings | |
#define OV7670_REG_NUM 122 | |
#define OV7670_WRITE_ADDR 0x42 | |
// Image settings | |
#define IMG_HEIGHT 320 | |
#define IMG_WIDTH 240 | |
#define BYTES_PER_PX 2 | |
// TIM MCO (XCLK) | |
#define TIM_FREQ 24000000 | |
#define TIM_PERIOD (SystemCoreClock/TIM_FREQ) | |
#define TIM_DUTY_50 (TIM_PERIOD/2) | |
// Camera PWDN | |
#define PWDN_PIN GPIO_Pin_4 | |
#define PWDN_PORT GPIOB | |
#define CAMERA_ON GPIO_ResetBits(PWDN_PORT, PWDN_PIN) | |
#define CAMERA_OFF GPIO_SetBits(PWDN_PORT, PWDN_PIN) | |
/* | |
* Initialize camera | |
*/ | |
extern void Camera_Init(void); | |
/* | |
* OV7670 camera configuration | |
*/ | |
extern uint8_t OV7670_Config(void); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment