STM32F407VG驱动无FIFO的OV7670简单显示图像学习

显示效果图 

OV7670模块

  我用的OV7670是在某宝上买的花几块钱买的,如下图所示:

OV7670的接线

  ov7670的接线是按照STM32F407VG开发板上预留的DMCI接口来接的,具体可以参照开发板的资料原理图说明,也可以直接按照下面的接线把ov7670接上STM32.

  关于STM32驱动OV7670模块网上的教程有很多,这里我用的是普中科技的STM32F407VG,屏幕用的是它自带的ILI9481,屏幕的驱动代码我是直接使用普中科技官方的,具体的代码大家可以自己去找,下面我主要讲解一下我的代码构成:

DCMI驱动代码

  DCMI是一种数字摄像头接口,是一个并行接口,能够接收外部8为、10位、12位或者14位CMOS摄像头模块发出的高速数据流。

#include "system.h"
#include "dcmi.h" 
#include "uart.h"

extern u8 ov_frame;  						//帧率
u32 datanum=0;
u32 HSYNC=0;
u32 VSYNC=0;
u8 ov_rev_ok = 0;

extern void jpeg_data_process(void);	//JPEG数据处理函数
DCMI_InitTypeDef DCMI_InitStructure;


void DMA2_Stream1_IRQHandler(void)
{        
	if(DMA_GetFlagStatus(DMA2_Stream1,DMA_FLAG_TCIF1)==SET)//DMA2_Steam1,传输完成标志
	{  
		DMA_Cmd(DMA2_Stream1, DISABLE);	
		
		DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1);//清除传输完成中断
		
		ov_rev_ok= 1; //数据获取完毕标志位位
		
	}    														 
}  



void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc)
{ 
	DMA_InitTypeDef  DMA_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
	DMA_DeInit(DMA2_Stream1);
	while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置 
	
  /* 配置 DMA Stream */
  DMA_InitStructure.DMA_Channel = DMA_Channel_1;  //通道1 DCMI通道 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DCMI->DR; ;//外设地址为:DCMI->DR
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DMA_Memory0BaseAddr;//DMA 存储器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式
  DMA_InitStructure.DMA_BufferSize = DMA_BufferSize;//数据传输量 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc;//存储器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据长度:32位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize;//存储器数据长度 
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式  DMA_Mode_Normal
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; //FIFO模式        
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;//使用全FIFO 
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//外设突发单次传输
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//存储器突发单次传输
  DMA_Init(DMA2_Stream1, &DMA_InitStructure);//初始化DMA Stream
		
	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);	//根据指定的参数初始化VIC寄存器、
	
} 

//DCMI初始化
void My_DCMI_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);
	
	RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI,ENABLE);//使能DCMI时钟
	
  	//PA4/6初始化设置
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_6;//PA4/6   复用功能输出 HSYNC PIXCLK
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能输出
  	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
	
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6;// PB6/7   复用功能输出 VSYNC D5 
  	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
	
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_11;//PC6/7/8/9 复用功能输出 D0 D1 D2 D3
  	GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化	

  	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_6;//PE4/5/6  复用功能输出  D4 D6 D7
  	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化	

	GPIO_PinAFConfig(GPIOA,GPIO_PinSource4,GPIO_AF_DCMI); //PA4,AF13  DCMI_HSYNC
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_DCMI); //PA6,AF13  DCMI_PCLK  
 	GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_DCMI); //PB7,AF13  DCMI_VSYNC 
 	GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_DCMI); //PC6,AF13  DCMI_D0  
 	GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_DCMI); //PC7,AF13  DCMI_D1 
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_DCMI); //PC8,AF13  DCMI_D2
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_DCMI); //PC9,AF13  DCMI_D3
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_DCMI); //PC11,AF13  DCMI_D4 
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_DCMI); //PB6,AF13  DCMI_D5 
	GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_DCMI); //PE5,AF13  DCMI_D6
	GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_DCMI); //PE6,AF13  DCMI_D7

	DCMI_DeInit();//清除原来的设置 
 
  DCMI_InitStructure.DCMI_CaptureMode=DCMI_CaptureMode_SnapShot;//快照模式 DCMI_CaptureMode_SnapShot
	DCMI_InitStructure.DCMI_CaptureRate=DCMI_CaptureRate_All_Frame;//全帧捕获
	DCMI_InitStructure.DCMI_ExtendedDataMode= DCMI_ExtendedDataMode_8b;//8位数据格式  
	DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;//DCMI_HSPolarity_High;//HSYNC 低电平有效
	DCMI_InitStructure.DCMI_PCKPolarity= DCMI_PCKPolarity_Falling;//PCLK 下升沿有效
	DCMI_InitStructure.DCMI_SynchroMode= DCMI_SynchroMode_Hardware;//硬件同步HSYNC,VSYNC
	DCMI_InitStructure.DCMI_VSPolarity=DCMI_VSPolarity_High;//VSYNC 低电平有效
	DCMI_Init(&DCMI_InitStructure);

	DCMI_ITConfig(DCMI_IT_FRAME,ENABLE);//开启帧中断 
	DCMI_ITConfig(DCMI_IT_LINE,ENABLE); //开启行中断
	DCMI_ClearITPendingBit(DCMI_IT_VSYNC);
	DCMI_ITConfig(DCMI_IT_VSYNC,ENABLE); //开启场中断	
	DCMI_Cmd(ENABLE);	//DCMI使能

  NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;	//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;		//子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化NVIC寄存器、
} 

//DCMI,启动传输
void DCMI_Start(void)
{ 
	DMA_Cmd(DMA2_Stream1, ENABLE);//开启DMA2,Stream1 
	DCMI_CaptureCmd(ENABLE);//DCMI捕获使能  
}

//DCMI,关闭传输
void DCMI_Stop(void)
{ 
	DCMI_CaptureCmd(DISABLE);//DCMI捕获使关闭	
	while(DCMI->CR&0X01);		//等待传输结束  	
	DMA_Cmd(DMA2_Stream1,DISABLE);//关闭DMA2,Stream1
} 

//DCMI中断服务函数
void DCMI_IRQHandler(void)
{
	if(DCMI_GetITStatus(DCMI_IT_LINE)==SET)//捕获到行
	{
		DCMI_ClearITPendingBit(DCMI_IT_LINE);//清除中断	
		ov_frame++;
	}
	
	if(DCMI_GetITStatus(DCMI_IT_FRAME)==SET)//捕获到帧
	{	
		DCMI_ClearITPendingBit(DCMI_IT_FRAME);//清除中断
	}
	
	if(DCMI_GetITStatus(DCMI_IT_VSYNC)==SET)//捕获到场
	{	
		DCMI_ClearITPendingBit(DCMI_IT_VSYNC);//清除中断
	}
	
} 


//DCMI设置显示窗口
//sx,sy;LCD的起始坐标
//width,height:LCD显示范围.
void DCMI_Set_Window(u16 sx,u16 sy,u16 width,u16 height)
{
	DCMI_Stop(); 
	DMA_Cmd(DMA2_Stream1,ENABLE);	//开启DMA2,Stream1 
	DCMI_CaptureCmd(ENABLE);//DCMI捕获使能 
	
}
   
SCCB通信协议

  SCCB协议是主要用于OV系列图像传感器,它是简化版的I2C协议,专为图像传感器设计。

#include "sccb.h"
#include "delay.h"
#include "uart.h"
#include "tftlcd.h"


/*
 *无FIFO的ov7670需要输入时钟
 *时钟为84MHz
 *分频为4MHz
 *PB5
 */
void ov7670_MCLK_Init(void)
{
	   //1.配置GPIO
     GPIO_InitTypeDef  GPIO_InitStructure;
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
	   //2.配置GPIO的复用
	   GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_TIM3);
	   //3.配置定时器
	   TIM_TimeBaseInitTypeDef TIM_TimeInitStructure;
	   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	   TIM_TimeInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	   TIM_TimeInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	   TIM_TimeInitStructure.TIM_Period=12-1; 
	   TIM_TimeInitStructure.TIM_Prescaler=1-1;
		 TIM_TimeBaseInit(TIM3,&TIM_TimeInitStructure);
		 //4.配置PWM
		 TIM_OCInitTypeDef TIM_OCInitStucture;
		 TIM_OCInitStucture.TIM_OCMode=TIM_OCMode_PWM1;     //PWM1模式
		 TIM_OCInitStucture.TIM_OCPolarity=TIM_OCPolarity_Low;    //极性
		 TIM_OCInitStucture.TIM_OutputState=TIM_OutputState_Enable; 
		 TIM_OC2Init(TIM3,&TIM_OCInitStucture); //初始化通道2
		 //5.使能预装载
		 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
		 //6.允许PWM输出
		 TIM_CtrlPWMOutputs(TIM3,ENABLE);
		 TIM_ARRPreloadConfig(TIM3,ENABLE);//使能预装载寄存器
     //7.允许定时器计时
		 TIM_Cmd(TIM3,ENABLE);
		 //8.设置占空比
		 TIM_SetCompare2(TIM3,10);

}

/*******************************
SCCB总线
时钟线PD6,数据线PD7
******************************/
//初始化SCCB接口 
void SCCB_Init(void)
{				
  	GPIO_InitTypeDef  GPIO_InitStructure;

//  	RCC_AHB1PeriphClockCmd(OV7670_SCCB_RCC, ENABLE);
		
//  	RCC_AHB1PeriphClockCmd(OV7670_XCLK_RCC, ENABLE);
		ov7670_MCLK_Init();    //初始化输入时钟
	//STM32F4时钟输出XCLK
//  	GPIO_InitStructure.GPIO_Pin = OV7670_XCLK_Pin;
//  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//  	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//50MHz

//  	GPIO_Init(OV7670_XCLK_GPIO, &GPIO_InitStructure);
	
//  	RCC_MCO1Config(RCC_MCO1Source_HSI,STM32_MCO1_DIV);
	
  	//GPIOF9,F10初始化设置
  	GPIO_InitStructure.GPIO_Pin = OV7670_SCCB_Pin;//PD6,7 推挽输出
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  //PD6,7 推挽输出
  	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  	GPIO_Init(OV7670_SCCB_GPIO, &GPIO_InitStructure);//初始化
 
	GPIO_SetBits(OV7670_SCCB_GPIO,OV7670_SCCB_Pin);
	SCCB_SDA_OUT();	   
}			 		 

//SCCB起始信号
//当时钟为高的时候,数据线的高到低,为SCCB起始信号
//在激活状态下,SDA和SCL均为低电平
void SCCB_Start(void)
{
    SCCB_SDA=1;     //数据线高电平	 
    delay_us(500); 
    SCCB_SCL=1;	    //在时钟线高的时候数据线由高至低
    delay_us(500);  
    SCCB_SDA=0;
    delay_us(500);	 
    SCCB_SCL=0;	    //数据线恢复低电平,单操作函数必要	
    delay_us(500);   
}

//SCCB停止信号
//当时钟为高的时候,数据线的低到高,为SCCB停止信号
//空闲状况下,SDA,SCL均为高电平
void SCCB_Stop(void)
{
    SCCB_SDA=0;
    delay_us(500);	 
    SCCB_SCL=1;	
    delay_us(500); 
    SCCB_SDA=1;	
    delay_us(500);
}  
//产生NA信号
void SCCB_No_Ack(void)
{
	delay_us(500);
	SCCB_SDA=1;	
  delay_us(500); 
	SCCB_SCL=1;	
	delay_us(500);
	SCCB_SCL=0;	
	delay_us(500);
	SCCB_SDA=0;	
	delay_us(500);
}
//SCCB,写入一个字节
//返回值:0,成功;1,失败. 
u8 SCCB_WR_Byte(u8 dat)
{
	u8 j,res;	 
	for(j=0;j<8;j++) //循环8次发送数据
	{
		if(dat&0x80)SCCB_SDA=1;	
		else SCCB_SDA=0;
		dat<<=1;
		delay_us(500);
		SCCB_SCL=1;	
		delay_us(500);
		SCCB_SCL=0;		   
	}			 
	SCCB_SDA_IN();		//设置SDA为输入 
	delay_us(500);
	SCCB_SCL=1;			//接收第九位,以判断是否发送成功
	delay_us(500);
	if(SCCB_READ_SDA)res=1;  //SDA=1发送失败,返回1
	else res=0;         //SDA=0发送成功,返回0
	SCCB_SCL=0;		 
	//printf("res=%d\r\n",res);
	SCCB_SDA_OUT();		//设置SDA为输出    
	return res;  
}	 
//SCCB 读取一个字节
//在SCL的上升沿,数据锁存
//返回值:读到的数据
u8 SCCB_RD_Byte(void)
{
	u8 temp=0,j;    
	SCCB_SDA_IN();		//设置SDA为输入  
	for(j=8;j>0;j--) 	//循环8次接收数据
	{		     	  
		delay_us(500);
		SCCB_SCL=1;
		temp=temp<<1;
		if(SCCB_READ_SDA)temp++;   
		delay_us(500);
		SCCB_SCL=0;
	}	
	SCCB_SDA_OUT();		//设置SDA为输出    
	return temp;
} 							    
//写寄存器
//返回值:0,成功;1,失败.
u8 SCCB_WR_Reg(u8 reg,u8 data)
{
	u8 res=0;
	SCCB_Start(); 					//启动SCCB传输
	if(SCCB_WR_Byte(SCCB_ID))res=1;	//写器件ID	
	delay_us(100);
  	if(SCCB_WR_Byte(reg))res=1;		//写寄存器地址
	delay_us(100);
  	if(SCCB_WR_Byte(data))res=1; 	//写数据	 
  	SCCB_Stop();
  	return	res;
}		  					    
//读寄存器
//返回值:读到的寄存器值
u8 SCCB_RD_Reg(u8 reg)
{
	u8 val=0;
	SCCB_Start(); 				//启动SCCB传输
	if(0==SCCB_WR_Byte(0x42))
	{
			SCCB_Stop();
  		delay_us(500);
	}  
	 if(0==SCCB_WR_Byte(reg))
	 {
	 	  SCCB_Stop();  
	    delay_us(500);	 
	 }
    SCCB_Stop();			  
	 delay_us(100);	   
	//设置寄存器地址后,才是读
	SCCB_Start();
	if(0==SCCB_WR_Byte(SCCB_ID|0X01))	//发送读命令
	{	  
		 SCCB_Stop();
	   delay_us(100);	 
	}
  	val=SCCB_RD_Byte();		 	//读取数据
		delay_us(500);
  	SCCB_No_Ack();
		delay_us(500);
  	SCCB_Stop();
  	return val;
}















OV7670的一些配置

  包括初始化、白平衡设置、色度设置、亮度设置、对比度设置等。

#include "ov7670.h"
#include "ov7670config.h"	  
#include "delay.h"
#include "uart.h"			 
#include "sccb.h"	
#include "led.h"
#include "tftlcd.h"
#include "dcmi.h"

uint16_t camera_buffer[PIC_WIDTH*PIC_HEIGHT]={0};





//初始化OV7670
//返回0:成功
//返回其他值:错误代码
u8 OV7670_Init(void)
{
	u16 i=0;
	u16 reg=0;
	//设置IO     	   
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
	//GPIOG9,15初始化设置pow和reset
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_15;//PG9,8推挽输出
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //推挽输出
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
	
 	OV7670_PWDN=0;	//POWER ON
	delay_ms(100);
	OV7670_RST=0;	//复位OV7670
	delay_ms(100);
	OV7670_RST=1;	//结束复位 
	SCCB_Init();        		//初始化SCCB 的IO口
	
 	SCCB_WR_Reg(0X12, 0x80);	//软复位OV7670
	delay_ms(50); 
	


 	//初始化配置 OV7670寄存器,采用QVGA分辨率(320*240)  
	for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0]);i++)
	{
		SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);
	} 
	
	//裁剪摄像头照片尺寸,参数:起始坐标x、y;长度、高度;裁剪长高不可大于上面设置的分辨率
	OV7670_Window_Set(PIC_START_X,PIC_START_Y,PIC_WIDTH,PIC_HEIGHT);
	
	/* 白平衡设置,默认值0 */
	OV7670_Light_Mode(0);
	/* 色度设置,默认值2 */
	OV7670_Color_Saturation(2);
	/* 亮度设置,默认值2 */
	OV7670_Brightness(2);
	/* 对比度设置,默认值2 */
	OV7670_Contrast(2);
	
	My_DCMI_Init();
	/* DCMI DMA设置,数据指向照片数组camera_buffer */
	DCMI_DMA_Init((uint32_t)&camera_buffer,sizeof(camera_buffer)/4,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Enable);//DCMI DMA 

  	return 0x00; 	//返回0初始化成功
} 

//OV7670功能设置
//白平衡设置
//0:自动
//1:太阳sunny
//2,阴天cloudy
//3,办公室office
//4,家里home
void OV7670_Light_Mode(u8 mode)
{
	u8 reg13val=0XE7;//默认就是设置为自动白平衡
	u8 reg01val=0;
	u8 reg02val=0;
	switch(mode)
	{
		case 1://sunny
			reg13val=0XE5;
			reg01val=0X5A;
			reg02val=0X5C;
			break;	
		case 2://cloudy
			reg13val=0XE5;
			reg01val=0X58;
			reg02val=0X60;
			break;	
		case 3://office
			reg13val=0XE5;
			reg01val=0X84;
			reg02val=0X4c;
			break;	
		case 4://home
			reg13val=0XE5;
			reg01val=0X96;
			reg02val=0X40;
			break;	
	}
	SCCB_WR_Reg(0X13,reg13val);//COM8设置 
	SCCB_WR_Reg(0X01,reg01val);//AWB蓝色通道增益 
	SCCB_WR_Reg(0X02,reg02val);//AWB红色通道增益 
}				  
//色度设置
//0:-2
//1:-1
//2,0
//3,1
//4,2
void OV7670_Color_Saturation(u8 sat)
{
	u8 reg4f5054val=0X80;//默认就是sat=2,即不调节色度的设置
 	u8 reg52val=0X22;
	u8 reg53val=0X5E;
 	switch(sat)
	{
		case 0://-2
			reg4f5054val=0X40;  	 
			reg52val=0X11;
			reg53val=0X2F;	 	 
			break;	
		case 1://-1
			reg4f5054val=0X66;	    
			reg52val=0X1B;
			reg53val=0X4B;	  
			break;	
		case 3://1
			reg4f5054val=0X99;	   
			reg52val=0X28;
			reg53val=0X71;	   
			break;	
		case 4://2
			reg4f5054val=0XC0;	   
			reg52val=0X33;
			reg53val=0X8D;	   
			break;	
	}
	SCCB_WR_Reg(0X4F,reg4f5054val);	//色彩矩阵系数1
	SCCB_WR_Reg(0X50,reg4f5054val);	//色彩矩阵系数2 
	SCCB_WR_Reg(0X51,0X00);			//色彩矩阵系数3  
	SCCB_WR_Reg(0X52,reg52val);		//色彩矩阵系数4 
	SCCB_WR_Reg(0X53,reg53val);		//色彩矩阵系数5 
	SCCB_WR_Reg(0X54,reg4f5054val);	//色彩矩阵系数6  
	SCCB_WR_Reg(0X58,0X9E);			//MTXS 
}
//亮度设置
//0:-2
//1:-1
//2,0
//3,1
//4,2
void OV7670_Brightness(u8 bright)
{
	u8 reg55val=0X00;//默认就是bright=2
  	switch(bright)
	{
		case 0://-2
			reg55val=0XB0;	 	 
			break;	
		case 1://-1
			reg55val=0X98;	 	 
			break;	
		case 3://1
			reg55val=0X18;	 	 
			break;	
		case 4://2
			reg55val=0X30;	 	 
			break;	
	}
	SCCB_WR_Reg(0X55,reg55val);	//亮度调节 
}
//对比度设置
//0:-2
//1:-1
//2,0
//3,1
//4,2
void OV7670_Contrast(u8 contrast)
{
	u8 reg56val=0X40;//默认就是contrast=2
  	switch(contrast)
	{
		case 0://-2
			reg56val=0X30;	 	 
			break;	
		case 1://-1
			reg56val=0X38;	 	 
			break;	
		case 3://1
			reg56val=0X50;	 	 
			break;	
		case 4://2
			reg56val=0X60;	 	 
			break;	
	}
	SCCB_WR_Reg(0X56,reg56val);	//对比度调节 
}
//特效设置
//0:普通模式    
//1,负片
//2,黑白   
//3,偏红色
//4,偏绿色
//5,偏蓝色
//6,复古	    
void OV7670_Special_Effects(u8 eft)
{
	u8 reg3aval=0X04;//默认为普通模式
	u8 reg67val=0XC0;
	u8 reg68val=0X80;
	switch(eft)
	{
		case 1://负片
			reg3aval=0X24;
			reg67val=0X80;
			reg68val=0X80;
			break;	
		case 2://黑白
			reg3aval=0X14;
			reg67val=0X80;
			reg68val=0X80;
			break;	
		case 3://偏红色
			reg3aval=0X14;
			reg67val=0Xc0;
			reg68val=0X80;
			break;	
		case 4://偏绿色
			reg3aval=0X14;
			reg67val=0X40;
			reg68val=0X40;
			break;	
		case 5://偏蓝色
			reg3aval=0X14;
			reg67val=0X80;
			reg68val=0XC0;
			break;	
		case 6://复古
			reg3aval=0X14;
			reg67val=0XA0;
			reg68val=0X40;
			break;	 
	}
	SCCB_WR_Reg(0X3A,reg3aval);//TSLB设置 
	SCCB_WR_Reg(0X68,reg67val);//MANU,手动U值 
	SCCB_WR_Reg(0X67,reg68val);//MANV,手动V值 
}	
//设置图像输出窗口
//对QVGA设置。
void OV7670_Window_Set(u16 sx,u16 sy,u16 width,u16 height)
{
	u16 endx;
	u16 endy;
	u8 temp; 
	
	if ((sx+width) > 320)
	{
		width = 320 - sx;
	}
	
	if ((sy+height) > 240)
	{
		height = 240 - sy;
	}
	
	sx += 176;
	sy += 12;
	
	endx=sx+width*2;	//HREF
 	endy=sy+height*2;	//VREF
	if(endx>784)
	{
		endx-=784;
	}
	
	temp=SCCB_RD_Reg(0X32);				//读取Href之前的值
	temp&=0XC0;
	temp|=((endx&0X07)<<3)|(sx&0X07);
	SCCB_WR_Reg(0X32,temp);
	SCCB_WR_Reg(0X17,sx>>3);			//设置Href的start高8位
	SCCB_WR_Reg(0X18,endx>>3);			//设置Href的end的高8位
	
	temp=SCCB_RD_Reg(0X03);				//读取Vref之前的值
	temp&=0XF0;
	temp|=((endy&0X03)<<2)|(sy&0X03);
	SCCB_WR_Reg(0X03,temp);				//设置Vref的start和end的最低2位
	SCCB_WR_Reg(0X19,sy>>2);			//设置Vref的start高8位
	SCCB_WR_Reg(0X1A,endy>>2);			//设置Vref的end的高8位


}

























主函数(main)设置

  主函数的设置包括显示图像的函数即txxs函数。

void txxs(uint16_t *camera_buf, uint16_t length_w, uint16_t length_h) {
    uint16_t y, x;
    uint16_t color;

    for (y = 0; y < length_h; y++) {
        for (x = 0; x < length_w; x++) {
            
            color = camera_buf[y * length_w + x]; //直接从camera_buf中读取当前像素的颜色值
            LCD_Fill(x, y, x + 1, y + 1, color); //LCD_Fill接受 RGB565格式的颜色值
						
    }
}
		
int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);
	UART1_init(115200);
	LED_init();
	KEY_Init();					//按键初始化 
	My_EXTI_Init();
	TFTLCD_Init();
	FRONT_COLOR=RED;
	while(OV7670_Init())//OV7725初始化成功
	{
		LCD_ShowString(30,30,200,16,16,"error");	
	}
	{
		if (ov_rev_ok)
		{
			txxs(camera_buffer, PIC_WIDTH, PIC_HEIGHT);
			ov_rev_ok = 0;
		}
		else
		{
		  DCMI_Start();
		}
	}
}

希望这篇文章可以帮助到正在学习O7670的同学!当然完成这个显示大家也可以进行颜色的识别,大家可以在网上寻找教程,我这个就不多说了。

在Ubuntu中使用VSCode配置OpenCV并编写孔明棋的步骤大致如下: 1. 安装OpenCV:首先需要在Ubuntu系统中安装OpenCV库。可以通过以下命令在终端中安装OpenCV: ``` sudo apt-get install libopencv-dev ``` 2. 安装VSCode和C/C++扩展:如果尚未安装VSCode,可以访问其官方网站下载并安装。安装完成后,需要安装C/C++扩展,以便在VSCode中编写和运行C/C++代码。 3. 创建项目文件夹:在合适的位置创建一个新的文件夹作为项目目录。 4. 创建C/C++源文件:在项目目录中创建孔明棋的源代码文件,例如`kongmingqi.cpp`。 5. 配置VSCode的`tasks.json`:需要配置一个编译任务来编译C++代码。右键点击项目目录中的`.vscode`文件夹(如果不存在则创建一个),选择“在终端中打开”,然后输入`code .`打开VSCode,并创建或修改`tasks.json`文件,加入如下配置: ```json { "version": "2.0.0", "tasks": [ { "label": "C++ build", "type": "shell", "command": "g++", "args": [ "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}", "-std=c++11", "-I/usr/include/opencv4" ], "group": { "kind": "build", "isDefault": true }, "presentation": { "echo": true, "reveal": "always", "focus": false, "panel": "shared", "showReuseMessage": true, "clear": false }, "problemMatcher": [ "$gcc" ] } ] } ``` 6. 配置VSCode的`c_cpp_properties.json`:确保你的C++环境路径配置正确。这可以在VSCode的设置中通过“C/Cpp: Edit Configurations (UI)”命令来完成。 7. 编写孔明棋代码:在`kongmingqi.cpp`中编写孔明棋的逻辑代码。 8. 构建和运行:在VSCode中按下`Ctrl+Shift+B`启动构建任务,然后可以通过在终端中运行编译后的可执行文件来运行孔明棋。 请注意,孔明棋的实现细节取决于具体的游戏规则和你打算如何实现它。你需要编写相应的算法来实现棋盘的布局、棋子的移动规则以及游戏的胜负判断逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值