本人是参加第八届的飞思卡尔摄像头组,由于学校不允许大二参加,所以我到了大三才第一次参加,也可以说是最后一次吧,所以想把自己调试的感想及时的写下!
刚开始也是和别人一样,买了一个OV7620 然后就开始看资料,卖家说这个摄像头支持3.3V和5V。由于刚开始听某些学长说他比赛的时候因为接了个LCD12864(当然这个液晶是5V供电的),用了一个判忙的引脚而让LCD上的5V电给烧了两块K60。第一块不知道为什么,第二块发现及时,但待发现时那个判忙的引脚已经烧坏了。这样一来,为了安全我还是果断的接了3.3V的电源,是K60板子直供的(其实是没有3.3V的,只有3V左右)。
我将摄像头的驱动写好了之后怎么测都有竖着的噪点,当时很奇怪,找不不到什么原因,因为时序里更不找不出这些黑斑的原因啊!我不知道尝试了多少次,这个比赛的所有工作就停留在了这里,也因此而干扰了整个组的进度。经过两天的调试渐渐的发现摄像头出来的值几乎没有200以上的,即使图片里白的地方一没有200以上的,最大的好像是180不到,当时觉得奇怪,并开始有点怀疑电压的问题了。后来到网上查了好长时间,发现有人说3.3V的电压时可以的不过噪点有点多,不过不大碍事。我想着想着就直接接了5V的上去了。后来的第一幅图像让我惊了,原理一直有噪点的图像一下子清晰多了。
3.3V时候的图像:
5V时的图像:
看看,擦别大吧!
那时候有遇到了另外的一种情况,但不是图像不清晰的问题,是图像会错开的问题,就如下图:
这个也找了好长的时间,后来有个学长看了一下说我开了场中断的时候虽然没有使能中断,但此时有场脉冲信号过来,检测到之后还是会置位标志位的。如是就将我开始捕捉图像之前加了个清标志位的语句,然后就将图像稳定了下来。
程序代码如下:
主函数:
/*这个程序只做参考,不能直接复制使用,因为有些函数没贴出来!!*/
#include "common.h"
#include "include.h"
extern bool image_finish_flag;
extern u8 line[DMA_NUM];
extern u8 line_num;
extern u8 image[ROW][COLUMN];
extern u8 steer_d,engine_d;
void uart_sent_Image();
void main(void)
{
//u8 temp; ///
UART_Init();
Motor_Init();
OV7620_Init();
// Encoder_Init(); //编码器初始化
// PIT_Init(CAPTURE_CYCLE);
// gpio_init (PORTD,12,GPO,0);
while(1)
{
/* GPIO_TURN(PORTD,12);*/
switch(uart_getchar(UART5))
{
case 0xff: {
PORTB_ISFR |= (1<<22);
PORTC_ISFR |= 1; //去掉标志位 可以固定一下图像 (学长加的)
enable_irq(PORTC_IRQ_NUM); //使能帧同步中断
while(!image_finish_flag);
image_finish_flag = 0;
DMA_DIS(DMA_CH4);
uart_sent_Image(); //用串口将图像发到上位机
delayus();
disable_irq(PORTC_IRQ_NUM); //这里显得有点多余,这个是调试的时候检测的
memset(image,0,120*80);
};break;
case '+': {
//set_steer(++steer_d);
set_engine(++engine_d);
uart_putchar(UART5,engine_d);
};break;
case '-': {
//set_steer(--steer_d);
set_engine(--engine_d);
uart_putchar(UART5,engine_d);
};break;
default: break;
}
}
}
相关中断:
/*==============================================================================
摄像头中断的时候要关掉其他所有的中断
==============================================================================*/
void PORTC_IRQHandler() //帧同步中断 VSYNC (端口C的中断)
{
u8 n;
n = 0;
if(PORTC_ISFR & (1<<n))
{
PORTC_ISFR |= (1<<n);
disable_irq(PORTC_IRQ_NUM); //失能帧同步中断
line_num= 0;
skip_line = 0;
//add_even=0;
// exti_init(PORTB,22,rising_down); //行同步中断 HSYNC (端口B的中断)
PORTC_ISFR |= 1;
PORTB_ISFR |= (1<<22);
enable_irq(PORTB_IRQ_NUM); //使能行同步中断
}
}
void PORTB_IRQHandler() //行同步中断 HSYNC (端口B的中断)
{
u8 n;
n = 22;
if(PORTB_ISFR & (1<<n))
{
PORTB_ISFR |= (1<<n);
PORTC_ISFR |= 1;
if(ROW>line_num)
{
disable_irq(PORTB_IRQ_NUM); //失能行同步中断
PORTC_ISFR |= (1<<22);
delayus(); //等待4us 去掉消隐区( 由于时间不准所以图像会有抖动 )
DMA_EN(DMA_CH4); //使能DMA 通道CH4 硬件请求
}
else
{
disable_irq(PORTB_IRQ_NUM);
image_finish_flag = 1;
}
}
}
void DMA_CH4_IRQHandler()
{
DMA_IRQ_CLEAN(DMA_CH4); //清除DMA中断标志位
DMA_DIS(DMA_CH4); //失能DMA通道
// memcpy(&image[line_num][0],line,COLUMN);
zoom_memcpy(&image[line_num][0],line,COLUMN,SKIP_dot); //这个函数是对应的缩小的赋值函数(就是跳一个点赋值一个点)
line_num++; //记录为当前行数加1
// exti_init(PORTB,22,rising_down);
enable_irq(PORTB_IRQ_NUM); //使能行同步中断
PORTB_ISFR |= (1 << 22); //防止出现行错误
}