Skip to content

Instantly share code, notes, and snippets.

@mchalapetr
Last active September 1, 2017 21:16
Show Gist options
  • Save mchalapetr/fc42a35629645b876ce7 to your computer and use it in GitHub Desktop.
Save mchalapetr/fc42a35629645b876ce7 to your computer and use it in GitHub Desktop.
OV7670 control library
/**
* ==========================================================================
* 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);
}
}
/**
* ==========================================================================
* 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();
}
/**
* ==========================================================================
* 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