【STM32】--二值化算法利用摄像头OV7670识别物体,获取坐标

#include "sys.h"
#include "ov7670.h"
#include "ov7670config.h"	  
#include "delay.h"
#include "usart.h"			 
#include "sccb.h"	
#include "lcd.h" 
extern u8 ov_sta;	//在exit.c里面定义
extern u8 ov_frame;	//在timer.c里面定义	
extern u32 Xpos, Ypos;
u32 times;
void camera_refresh(u8 dire) 
{ 
	u32 x ,y;
 	u16 color;	 
	
	if(ov_sta == 2)
	{
		LCD_Scan_Dir(dire);		//从上到下,从左到右 
		LCD_SetCursor(0x00,0x0000);	//设置光标位置 
		LCD_WriteRAM_Prepare();     //开始写入GRAM	
		OV7670_RRST=0;				//开始复位读指针 
		OV7670_RCK=0;
		OV7670_RCK=1;
		OV7670_RCK=0;
		OV7670_RRST=1;				//复位读指针结束 
		OV7670_RCK=1;  
		for(x = 0; x < 240; x++) 
		for(y = 0; y < 319; y++) //320时有杂的像素点
		{
			OV7670_RCK=0;
			color=GPIOC->IDR&0XFF;	//读数据
			OV7670_RCK=1; 
			color<<=8;  
			OV7670_RCK=0;
			color|=GPIOC->IDR&0XFF;	//读数据
			OV7670_RCK=1; 
			if(y < 320)
			{
				if(color > 0x5000)//测定0x5500时最佳
				{
					color = 0xffff;
				}
				else
				{
					color = 0x0000;
					times++;
					if(times >= 3000 && x > 10 && y < 310)//重要:去除杂像素点,
					{
							times = 0;
							Xpos = x;
							Ypos = y;
							printf("小球坐标是:(%d, %d)",Xpos,Ypos);						
					}
				}
			}
			else
			{
				color = 0xa06b;
			}
					 
			LCD->LCD_RAM=color;			   
		}   							 
		EXTI_ClearITPendingBit(EXTI_Line7);  //清除LINE8上的中断标志位
		ov_sta=0;					//开始下一次采集
 		ov_frame++; 
		LCD_Scan_Dir(DFT_SCAN_DIR);	//恢复默认扫描方向 
	} 
}


//摄像机边界定位
void cameraPosition(u8 dire)
{
	u32 x ,y;
 	u16 color;	 
	u32 Xpos1, Ypos1, Xpos2, Ypos2;
	if(ov_sta == 2)
	{
		LCD_Scan_Dir(dire);		//扫描方向
		LCD_SetCursor(0xf0,0x0000);	//设置光标位置 
		LCD_WriteRAM_Prepare();     //开始写入GRAM	
		OV7670_RRST=0;				//开始复位读指针 
		OV7670_RCK=0;
		OV7670_RCK=1;
		OV7670_RCK=0;
		OV7670_RRST=1;				//复位读指针结束 
		OV7670_RCK=1;  
		for(x = 0; x < 240; x++) 
		for(y = 0; y < 319; y++) //320时有杂的像素点
		{
			OV7670_RCK=0;
			color=GPIOC->IDR&0XFF;	//读数据
			OV7670_RCK=1; 
			color<<=8;  
			OV7670_RCK=0;
			color|=GPIOC->IDR&0XFF;	//读数据
			OV7670_RCK=1; 
			if(color > 0x4500)//测定0x5500时最佳
			{
				color = 0xffff;
			}
			else
			{
				color = 0x0000;
				
				times++;
				if((times <= 2500) && (x - y > 1))//重要:去除杂像素点,
				{
						if(times == 500)
					{
						Xpos1 = x;
						Ypos1 = y;
						printf("该点的x,y坐标是:%d,%d  ", Xpos1, Ypos1);
					}
					if(times == 1500)
					{
						Xpos2 = x;
						Ypos2 = y;
						printf("该点的x,y坐标是:%d, %d ", Xpos2, Ypos2);
					}
				
				}
			}
			LCD->LCD_RAM=color;
			   
		}   							 
		EXTI_ClearITPendingBit(EXTI_Line7);  //清除LINE8上的中断标志位
		ov_sta = 0;
 		ov_frame++; 
		LCD_Scan_Dir(L2R_U2D);
	} 
}



//初始化OV7670
//返回0:成功
//返回其他值:错误代码
u8 OV7670_Init(void)
{
	u8 temp;
	u16 i=0;
	 
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG, ENABLE);	 //使能相关端口时钟
 

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8; 	//PA8 输入 上拉
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);


	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;				 // 端口配置
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);	


	GPIO_InitStructure.GPIO_Pin  = 0xff; //PC0~7 输入 上拉
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
 	GPIO_Init(GPIOC, &GPIO_InitStructure);



   	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 	GPIO_Init(GPIOD, &GPIO_InitStructure);
	GPIO_SetBits(GPIOD,GPIO_Pin_6);

	   
 
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_14|GPIO_Pin_15;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 	GPIO_Init(GPIOG, &GPIO_InitStructure);
	GPIO_SetBits(GPIOG,GPIO_Pin_14|GPIO_Pin_15);	

    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);	//SWD

 	SCCB_Init();        		//初始化SCCB 的IO口	   	  
 	if(SCCB_WR_Reg(0x12,0x80))return 1;	//复位SCCB	  
	delay_ms(50); 
	//读取产品型号
 	temp=SCCB_RD_Reg(0x0b);   
	if(temp!=0x73)return 2;  
 	temp=SCCB_RD_Reg(0x0a);   
	if(temp!=0x76)return 2;
	//初始化序列	  
	for(i=0;i784)endy-=784;
	temp=SCCB_RD_Reg(0X03);				//读取Vref之前的值
	temp&=0XF0;
	temp|=((endx&0X03)<<2)|(sx&0X03);
	SCCB_WR_Reg(0X03,temp);				//设置Vref的start和end的最低2位
	SCCB_WR_Reg(0X19,sx>>2);			//设置Vref的start高8位
	SCCB_WR_Reg(0X1A,endx>>2);			//设置Vref的end的高8位

	temp=SCCB_RD_Reg(0X32);				//读取Href之前的值
	temp&=0XC0;
	temp|=((endy&0X07)<<3)|(sy&0X07);
	SCCB_WR_Reg(0X17,sy>>3);			//设置Href的start高8位
	SCCB_WR_Reg(0X18,endy>>3);			//设置Href的end的高8位
}

























 

你可能感兴趣的:(竞赛项目)