|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "tpad.h"
#include "exti.h"
#include "usmart.h"
#include "ov7670.h"
#include "ov7725.h"
#include "hsi.h"
//ALIENTEK精英STM32F103开发板 实验33
//摄像头实验 实验
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司
//传感器名字宏定义
#define OV7725 1
#define OV7670 2
//由于OV7725传感器安装方式原因,OV7725_WINDOW_WIDTH相当于LCD的高度,OV7725_WINDOW_HEIGHT相当于LCD的宽度
//注意:此宏定义只对OV7725有效
#define OV7725_WINDOW_WIDTH 320 // <=320
#define OV7725_WINDOW_HEIGHT 240 // <=240
#define min3v(v1, v2, v3) ((v1)>(v2)? ((v2)>(v3)?(v3) v2)) (v1)>(v3)?(v3) v1)))//
#define max3v(v1, v2, v3) ((v1)<(v2)? ((v2)<(v3)?(v3) v2)) (v1)<(v3)?(v3) v1)))//
const u8*LMODE_TBL[6]={"Auto","Sunny","Cloudy","Office","Home","Night"};//6种光照模式
const u8*EFFECTS_TBL[7]={"Normal","Negative","B&W","Redish","Greenish","Bluish","Antique"}; //7种特效
extern u8 ov_sta; //在exit.c里 面定义
extern u8 ov_frame; //在timer.c里面定义
extern unsigned int shunxu[5][6];
extern u16 n;
extern u16 t;
extern u16 keyc;
u16 color0; //refresh函数颜色顺序判断
u32 h,s2,l;
u16 get_date;
u8 shu=2;
u32 find_x,find_y;
u16 pwm_x=200;
u16 pwm_y=200; //pwm占空比
u16 target_x=120;
u16 target_y=160; //目标位置
float Kp_x=0.18,Ki_x=0.01; //pid参数
float Kp_y=0.18,Ki_y=0.01; //pid参数
int Bias_x, Last_bias_x; //定义目标频率
int Bias_y, Last_bias_y; //定义目标频率
u32 sum_x=0,sum_y=0,i_xy = 0,n_i;
u16 X,Y; //靶子实际坐标
u8 key;
COLOR_RGB Rgb;
COLOR_HSL Hsl1;
RESULT Resu;
TARGET_CONDI Condition={0,200,0,34,20,30,40,40,320,240};
void refresh(u16 color);
static void ReadColor(u16 x,u16 y,COLOR_RGB *Rgb)
{
unsigned short C16;
C16 = LCD_ReadPoint(x,y);
Rgb->red = (unsigned char)((C16&0xf800)>>8);
Rgb->green = (unsigned char)((C16&0x07e0)>>3);
Rgb->blue = (unsigned char)((C16&0x001f)<<3);
}
static void RGBtoHSL(const COLOR_RGB *Rgb, COLOR_HSL *Hsl)
{
int maxVal,minVal,difVal;
int r = Rgb->red;
int g = Rgb->green;
int b = Rgb->blue;
int h,s2,l;
maxVal = max3v(r, g, b);
minVal = min3v(r, g, b);
difVal = maxVal-minVal;
//计算亮度
l = (maxVal+minVal)*240/255/2;
if(maxVal == minVal)//若r=g=b
{
h = 0;
s2 = 0;
}
else
{
//计算色调
if(maxVal==r)
{
if(g>=b)
h = 40*(g-b)/(difVal);
else
h = 40*(g-b)/(difVal) + 240;
}
else if(maxVal==g)
h = 40*(b-r)/(difVal) + 80;
else if(maxVal==b)
h = 40*(r-g)/(difVal) + 160;
//计算饱和度
if(l == 0)
s2 = 0;
else if(l<=120)
s2 = (difVal)*240/(maxVal+minVal);
else
s2 = (difVal)*240/(511 - (maxVal+minVal));
}
Hsl->hue = (unsigned char)(((h>240)? 240 : ((h<0)?0:h)));
Hsl->saturation = (unsigned char)(((s2>240)? 240 : ((s2<0)?0:s2)));
Hsl->luminance = (unsigned char)(((l>240)? 240 : ((l<0)?0:l)));
}
//更新LCD显示(OV7725)
void OV7725_camera_refresh(void)
{
u32 i,j;
u16 color;
if(ov_sta)//有帧中断更新
{
LCD_Scan_Dir(U2D_L2R); //从上到下,从左到右
LCD_Set_Window((lcddev.width-OV7725_WINDOW_WIDTH)/2,(lcddev.height-OV7725_WINDOW_HEIGHT)/2,OV7725_WINDOW_WIDTH,OV7725_WINDOW_HEIGHT);//将显示区域设置到屏幕中央
if(lcddev.id==0X1963)LCD_Set_Window((lcddev.width-OV7725_WINDOW_WIDTH)/2,(lcddev.height-OV7725_WINDOW_HEIGHT)/2,OV7725_WINDOW_HEIGHT,OV7725_WINDOW_WIDTH);//将显示区域设置到屏幕中央
LCD_WriteRAM_Prepare(); //开始写入GRAM
OV7725_RRST=0; //开始复位读指针
OV7725_RCK_L;
OV7725_RCK_H;
OV7725_RCK_L;
OV7725_RRST=1; //复位读指针结束
OV7725_RCK_H;
for(i=0;i<OV7725_WINDOW_HEIGHT;i++)
{
for(j=0;j<OV7725_WINDOW_WIDTH;j++)
{
OV7725_RCK_L;
color=GPIOC->IDR&0XFF; //读数据
OV7725_RCK_H;
color<<=8;
OV7725_RCK_L;
color|=GPIOC->IDR&0XFF; //读数据
OV7725_RCK_H;
LCD->LCD_RAM=color;
}
}
shu++;
ov_sta=0; //清零帧中断标记
ov_frame++;
LCD_Scan_Dir(DFT_SCAN_DIR); //恢复默认扫描方向
}
}
//更新LCD显示(OV7670)
int main(void)
{
u8 i=0;
u8 msgbuf[15];//消息缓存区
u8 tm=0;
u8 lightmode=0,effect=0;
s8 saturation=0,brightness=0,contrast=0;
Stm32_Clock_Init(9); //系统时钟设置
uart_init(72,115200); //串口初始化为115200
delay_init(72); //延时初始化
usmart_dev.init(72); //初始化USMART
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //初始化按键
LCD_Init(); //初始化LCD
EXTIX_Init(); //初始化外部中断输入
TPAD_Init(6); //触摸按键初始化
TIM3_PWM_Init(3999,359);
POINT_COLOR=RED; //设置字体为红色
LCD_ShowString(30,50,200,16,16,"WarShip STM32");
LCD_ShowString(30,70,200,16,16,"OV7725_OV7670 TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2017/11/1");
LCD_ShowString(30,130,200,16,16,"KEY0 ight Mode");
LCD_ShowString(30,150,200,16,16,"KEY1:Saturation");
LCD_ShowString(30,170,200,16,16,"KEY2:Brightness");
LCD_ShowString(30,190,200,16,16,"KEY_UP:Contrast");
LCD_ShowString(30,210,200,16,16,"TPAD:Effects");
LCD_ShowString(30,230,200,16,16,"OV7725_OV7670 Init...");
while(1)//初始化OV7725_OV7670
{
if(OV7725_Init()==0)
{
LCD_ShowString(30,230,200,16,16,"OV7725 Init OK ");
while(1)
{
key=KEY_Scan(0);
if(key==KEY0_PRES)
{
OV7725_Window_Set(OV7725_WINDOW_WIDTH,OV7725_WINDOW_HEIGHT,0);//QVGA模式输出
i=0;
break;
}else if(key==KEY1_PRES)
{
OV7725_Window_Set(OV7725_WINDOW_WIDTH,OV7725_WINDOW_HEIGHT,1);//VGA模式输出
i=0;
break;
}
i++;
if(i==100)LCD_ShowString(30,250,210,16,16,"KEY0 VGA KEY1:VGA"); //闪烁显示提示信息
if(i==200)
{
LCD_Fill(30,250,210,250+16,WHITE);
i=0;
}
delay_ms(5);
}
OV7725_Light_Mode(lightmode);
OV7725_Color_Saturation(saturation);
OV7725_Brightness(brightness);
OV7725_Contrast(contrast);
OV7725_Special_Effects(effect);
OV7725_CS=0;
break;
}else if(OV7670_Init()==0)
{
LCD_ShowString(30,230,200,16,16,"OV7670 Init OK ");
delay_ms(1500);
OV7670_Light_Mode(lightmode);
OV7670_Color_Saturation(saturation);
OV7670_Brightness(brightness);
OV7670_Contrast(contrast);
OV7670_Special_Effects(effect);
OV7670_Window_Set(12,176,240,320);//设置窗口
OV7670_CS=0;
break;
}else
{
LCD_ShowString(30,230,200,16,16,"OV7725_OV7670 Error!!");
delay_ms(200);
LCD_Fill(30,230,239,246,WHITE);
delay_ms(200);
}
}
TIM6_Int_Init(9999,7199); //10Khz计数频率,1秒钟中断
EXTI8_Init(); //使能外部中断8,捕获帧中断
LCD_Clear(BLACK);
while(1)
{
key=KEY_Scan(0);//不支持连按
if(t)
{
switch(keyc)
{
case 1:
refresh(keyc-1);
printf("1");
break;
case 2:
refresh(keyc-1);
printf("2");
break;
case 3:
printf("error!");
}
}
else
LED1=0;
// OV7725_camera_refresh();
// TIM3->CCR1=200+70;
// TIM3->CCR2=200+75;
if(tm)
{
LCD_ShowString((lcddev.width-240)/2+30,(lcddev.height-320)/2+60,200,16,16,msgbuf);
tm--;
}
i++;
if(i==15)//DS0闪烁.
{
i=0;
LED0=!LED0;
}
}
}
void refresh(u16 color)
{
if(shu==3)
{
shu=0;
for(find_y=0;find_y<320;find_y=find_y +4)//寻找测试点
{
for(find_x=0;find_x<240;find_x=find_x +4) //y轴先固定,扫描x轴
{
get_date=LCD_ReadPoint(find_x,find_y);
ReadColor(find_x,find_y,&Rgb); //输入一个点,分别获得颜色值
RGBtoHSL(&Rgb,&Hsl1);// rgb转化为色调,亮度,对比度
if(((Hsl1.hue>=shunxu[color][0])&&(Hsl1.hue<=shunxu[color][1]))&&((Hsl1.saturation>=shunxu[color][2])&&(Hsl1.saturation<=shunxu[color][3]))&&((Hsl1.luminance>=shunxu[color][4])&&(Hsl1.luminance<=shunxu[color][5]))) //????
{
sum_x = sum_x+find_x ;
sum_y = sum_y+find_y ;
i_xy++; //每找到一个点累加一次
n_i=i_xy;
X=sum_x /n_i; ////得到目标x轴坐标
Y=sum_y /n_i; ////得到目标y轴坐标
printf("%d \n",color);
// printf("x:%d y:%d\n",find_x,find_y);
}
// if(((find_x==120)&&(find_y==160)))
// printf("h:%d s:%d l:%d\n",Hsl1.hue,Hsl1.saturation,Hsl1.luminance);
}
}
if(((sum_x==0)&&(sum_y==0))) //如果扫描不到对象,保持舵机静止
{
X=120;Y=160;
}
POINT_COLOR=BLACK;
LCD_Draw_Circle( X,Y,20); //画圆标注
//x轴pid
Bias_x=target_x-X; //计算偏差
pwm_x+=(Ki_x*(Bias_x-Last_bias_x)+Kp_x*Bias_x); //增量式PI控制器
if(pwm_x>=400)pwm_x=400;
if(pwm_x<=0)pwm_x=0;
Last_bias_x=Bias_x; //保存上一次偏差
//y轴pid
Bias_y=target_y-Y; //计算偏差
pwm_y+=(Ki_y*(Bias_y-Last_bias_y)+Kp_y*Bias_y); //增量式PI控制器
Last_bias_y=Bias_y; //保存上一次偏差
if(pwm_y>=400)pwm_y=400;
if(pwm_y<=0)pwm_y=0;
//改变占空比
TIM3->CCR1=pwm_x+70;
TIM3->CCR2=pwm_y+75;
// if(((target_x<121)&&(target_x>119)&&(target_y<161)&&(target_y>159)))
// {
// delay_ms(2000);
// keyc++;
// }
//清零
sum_x =0;
sum_y =0;
i_xy =0;
}
OV7725_camera_refresh(); //摄像头刷新
}
void TIM6_IRQHandler(void)
{
if(TIM6->SR&0X0001)//溢出中断
{
printf("frame:%dfps\r\n",ov_frame); //打印帧率
ov_frame=0;
}
TIM6->SR&=~(1<<0);//清除中断标志位
} |
|