原载:http://blog.csdn.net/lxk7280/article/details/26975233?utm_source=tuicool
凭借着OV7620,将已经调好速度控制和角度控制的车子能跑起来了。基础功能实现后就开始对车子优化了。
一个好的人眼睛最重要,同样对于一个好的平衡车,摄像头传感器最重要。因此我决心首先做的是对摄像头的优化。
方针:
OV7620 --> OV7725(鹰眼摄像头) 使用:KEIL 鹰眼摄像头 超核库
OV7620的缺点:
OV7620是1/3”CMOS彩色/黑白图像传感器。它支持连续和隔行两种 扫描方式,VGA与QVGA两种图像格式;最高像素为664×492, 帧速率为30fps。而他的缺点正是在此,帧速率太低。每秒中只能产生30唱图像。可以确定他的
VSYNC信号为30HZ。
帧速率不高为何是缺点:
因为车子跑到一定速度之后,图像变化很快,帧的速率低导致了道路实时性差,不能够及时刷新道路情况。所以会影响智能车的提速。
鹰眼摄像头(OV7725)的优点:
1.高达150HZ的帧频率。
2.硬件二值化。(也有人认为是缺点。)
3.BGA封装:
但是鹰眼的制造商野火,采用捆绑销售,每次买的时候必须购买套装。不过商家也是为了购买者着想,因为很多人不会自己驱动OV7725,只会对例程进行修改,不会移植,这样的购买者买套件确实也不失为一个好方法。
不过博主比较穷,在一番软磨之下,商家给我单卖了一个鹰眼摄像头(OV7725),在此谢谢商家了。
驱动鹰眼的步骤:
1.知道该款摄像头的工作特点和方式。
第一大步:理解时序图。
2.在我介绍OV7620的使用(http://blog.csdn.net/lxk7280/article/details/22207001)的时候,就说了理解时序图是驱动一款摄像头的重中之重。尤其是对于鹰眼这款比较特殊的摄像头。
接下来一个必须理解的地方,否则就驱动不了该款摄像头。
那就是:鹰眼摄像头的一个PCLK信号传来的时候,会传输8个像素点。而不是OV7620的一个PCLK信号,对应1个像素点。
So:如果一行为80个点,那么一个行信号中只会有10个PCLK信号,而不是80个PCLK信号。
示例:采集到:0xFF 0X00 。 对应二值化的像素点。 黑黑黑黑白白白白
为了更好的让自己理解鹰眼摄像头的时序图,我在实验室的示波器上仔细看了下各个信号的波形。如下图:
场信号和行信号波形:
看完这么多关于时序图的波形后,相信大家对鹰眼摄像头的波形都了解了。
接下来开始进攻第二大部分:SCCB的操作。
3. 没有对SCCB进行操作,就没办法操作摄像头。
有人会奇怪为什么使用OV系列的摄像头每次都要进行SCCB的操作呢?难道它自己不会保存上次的操作结果吗?
原因是:OV系列的摄像头的寄存器是EEPROM,不稳定,数据很容易丢失,因此程序每次初始化时我们都要重新写入寄存器设置。
需要修改的寄存器有,PCLK速率,帧率、图像亮度、对比度、色饱和度、镜像等功能。
步骤:
首先给出OV7725的SCCB各个功能对应的寄存器的写入值:
接着,对一些驱动OV7725时需要用到的值进行宏定义。
- #ifndef _OV7725_EAGLE_H_
- #define _OV7725_EAGLE_H_
-
- #include "OV7725_REG.h"
- #define uint8 unsigned char
- #define uint16 unsigned short
-
-
- #define OV7725_HREF_PORT PTA
- #define OV7725_HREF_PIN 14
-
- #define OV7725_VSYNC_PORT PTB
- #define OV7725_VSYNC_PIN 10
-
- #define OV7725_PCLK_PORT PTE
- #define OV7725_PCLK_PIN 3
-
- #define MAX_ROW 20 //定义摄像头图像宽度
- #define MAX_COL 200 //定义摄像头图像高度
-
- typedef struct
- {
- uint8 addr;
- uint8 val;
- } reg_s;
-
-
- #define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( ((a)[0]) ) )
-
- extern uint8 ov7725_eagle_init(uint8 *imgaddr);
- extern void ov7725_eagle_get_img(void);
-
-
- #endif //_OV7725_EAGLE_H_
然后,撰写关于鹰眼摄像头的函数:
- #include "sys.h"
- #include "gpio.h"
- #include "delay.h"
- #include "dma.h"
- #include "ftm.h"
- #include "lptm.h"
- #include "flash.h"
- #include "stdio.h"
- #include "uart.h"
- #include "OV7725_REG.h"
- #include "OV7725_Eagle.h"
- #include "sccb.h"
-
- #define OV7725_EAGLE_Delay_ms(time) DelayMs(time)
-
- volatile extern unsigned int Col_Num,Col;
- volatile extern unsigned char Image[MAX_COL][MAX_ROW];
- volatile extern unsigned char Flag;
-
- uint8 *ov7725_eagle_img_buff;
-
-
- static uint8 ov7725_eagle_reg_init(void);
- static void ov7725_eagle_port_init();
-
- void OV7725_Init()
- {
- while(ov7725_eagle_reg_init() == 0);
- ov7725_eagle_port_init();
- }
-
-
-
-
-
- void ov7725_eagle_port_init()
- {
- unsigned int i;
- GPIO_InitTypeDef GPIO_InitStruct1;
- DMA_InitTypeDef DMA_InitStruct1;
-
- for(i=0;i<8;i++)
- {
- GPIO_InitStruct1.GPIO_Pin = i;
- GPIO_InitStruct1.GPIO_InitState = Bit_SET;
- GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_DISABLE;
- GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStruct1.GPIOx = PTD;
- GPIO_Init(&GPIO_InitStruct1);
- }
-
- GPIO_InitStruct1.GPIO_Pin = OV7725_PCLK_PIN;
- GPIO_InitStruct1.GPIO_InitState = Bit_SET;
- GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_DMA_RISING;
- GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_InitStruct1.GPIOx = OV7725_PCLK_PORT;
- GPIO_Init(&GPIO_InitStruct1);
-
-
- GPIO_InitStruct1.GPIO_Pin = OV7725_HREF_PIN;
- GPIO_InitStruct1.GPIO_InitState = Bit_SET;
- GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_RISING;
- GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_InitStruct1.GPIOx = OV7725_HREF_PORT;
- GPIO_Init(&GPIO_InitStruct1);
-
-
- GPIO_InitStruct1.GPIO_Pin = OV7725_VSYNC_PIN;
- GPIO_InitStruct1.GPIO_InitState = Bit_SET;
- GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_RISING;
- GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_InitStruct1.GPIOx = OV7725_VSYNC_PORT;
- GPIO_Init(&GPIO_InitStruct1);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
-
-
-
-
-
- void PORTB_IRQHandler(void)
- {
- uint8 i=10;
- if((PORTB->ISFR>>i)==1)
- {
-
- Flag = 0;
- PORTB->ISFR|=(1<<10);
- Col = 0;
- Col_Num = 0;
- DMA_SetEnableReq(DMA_CH1,DISABLE);
- NVIC_EnableIRQ(PORTA_IRQn);
- NVIC_DisableIRQ(PORTB_IRQn);
- }
- }
- void PORTA_IRQHandler(void)
- {
- unsigned int Send_Buffer;
- uint8 colour[2] = {254, 0};
- DMA_InitTypeDef DMA_InitStruct1;
- uint8 i=14,j,k;
-
- if((PORTA->ISFR>>i)==1);
- {
- PORTA->ISFR|=(1<<14);
- if(Col_Num++ > 15)
- {
- if(Col_Num%2)
- {
-
- DMA_InitStruct1.Channelx = DMA_CH1;
- DMA_InitStruct1.PeripheralDMAReq =PORTE_DMAREQ;
- DMA_InitStruct1.MinorLoopLength = 24;
- DMA_InitStruct1.TransferBytes = 1;
- DMA_InitStruct1.DMAAutoClose = ENABLE;
- DMA_InitStruct1.EnableState = ENABLE;
-
- DMA_InitStruct1.SourceBaseAddr =(uint32_t)&PTD->PDIR;
- DMA_InitStruct1.SourceMajorInc = 0;
- DMA_InitStruct1.SourceDataSize = DMA_SRC_8BIT;
- DMA_InitStruct1.SourceMinorInc = 0;
-
- DMA_InitStruct1.DestBaseAddr =(uint32_t)Image[Col];
- DMA_InitStruct1.DestMajorInc = 0;
- DMA_InitStruct1.DestDataSize = DMA_DST_8BIT;
- DMA_InitStruct1.DestMinorInc = 1;
- DMA_Init(&DMA_InitStruct1);
-
-
-
- Col ++;
- if(Col==MAX_COL)
- {
- Flag = 1;
- DMA_SetEnableReq(DMA_CH1,DISABLE);
- NVIC_DisableIRQ(PORTA_IRQn);
-
- UART_SendData(UART4,0XFF);
- for(j=0;j<80;j++)
- for(k=0;k<23;k++)
- {
- Send_Buffer = colour[ (Image[j][k] >> 7 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[j][k] >> 6 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[j][k] >> 5 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[j][k] >> 4 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[j][k] >> 3 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[j][k] >> 2 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[j][k] >> 1 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[j][k] >> 0 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- }
-
- NVIC_EnableIRQ(PORTB_IRQn);
- }
- }
- }
- }
- }
-
-
- reg_s ov7725_eagle_reg[] =
- {
-
- {OV7725_COM4 , 0xC1},
- {OV7725_CLKRC , 0x00},
- {OV7725_COM2 , 0x03},
- {OV7725_COM3 , 0xD0},
- {OV7725_COM7 , 0x40},
- {OV7725_HSTART , 0x3F},
- {OV7725_HSIZE , 0x50},
- {OV7725_VSTRT , 0x03},
- {OV7725_VSIZE , 0x78},
- {OV7725_HREF , 0x00},
- {OV7725_SCAL0 , 0x0A},
- {OV7725_AWB_Ctrl0 , 0xE0},
- {OV7725_DSPAuto , 0xff},
- {OV7725_DSP_Ctrl2 , 0x0C},
- {OV7725_DSP_Ctrl3 , 0x00},
- {OV7725_DSP_Ctrl4 , 0x00},
-
- #if (OV7725_EAGLE_W == 80)
- {OV7725_HOutSize , 0x14},
- #elif (OV7725_EAGLE_W == 160)
- {OV7725_HOutSize , 0x28},
- #elif (OV7725_EAGLE_W == 240)
- {OV7725_HOutSize , 0x3c},
- #elif (OV7725_EAGLE_W == 320)
- {OV7725_HOutSize , 0x50},
- #else
-
- #endif
-
- #if (OV7725_EAGLE_H == 60 )
- {OV7725_VOutSize , 0x1E},
- #elif (OV7725_EAGLE_H == 120 )
- {OV7725_VOutSize , 0x3c},
- #elif (OV7725_EAGLE_H == 180 )
- {OV7725_VOutSize , 0x5a},
- #elif (OV7725_EAGLE_H == 240 )
- {OV7725_VOutSize , 0x78},
- #else
-
- #endif
-
- {OV7725_EXHCH , 0x00},
- {OV7725_GAM1 , 0x0c},
- {OV7725_GAM2 , 0x16},
- {OV7725_GAM3 , 0x2a},
- {OV7725_GAM4 , 0x4e},
- {OV7725_GAM5 , 0x61},
- {OV7725_GAM6 , 0x6f},
- {OV7725_GAM7 , 0x7b},
- {OV7725_GAM8 , 0x86},
- {OV7725_GAM9 , 0x8e},
- {OV7725_GAM10 , 0x97},
- {OV7725_GAM11 , 0xa4},
- {OV7725_GAM12 , 0xaf},
- {OV7725_GAM13 , 0xc5},
- {OV7725_GAM14 , 0xd7},
- {OV7725_GAM15 , 0xe8},
- {OV7725_SLOP , 0x20},
- {OV7725_LC_RADI , 0x00},
- {OV7725_LC_COEF , 0x13},
- {OV7725_LC_XC , 0x08},
- {OV7725_LC_COEFB , 0x14},
- {OV7725_LC_COEFR , 0x17},
- {OV7725_LC_CTR , 0x05},
- {OV7725_BDBase , 0x99},
- {OV7725_BDMStep , 0x03},
- {OV7725_SDE , 0x04},
- {OV7725_BRIGHT , 0x00},
- {OV7725_CNST , 0xFF},
- {OV7725_SIGN , 0x06},
- {OV7725_UVADJ0 , 0x11},
- {OV7725_UVADJ1 , 0x02},
-
- };
-
- uint8 ov7725_eagle_cfgnum = ARR_SIZE( ov7725_eagle_reg ) ;
-
-
-
-
-
-
-
- uint8 ov7725_eagle_reg_init(void)
- {
- uint16 i = 0;
- uint8 Sensor_IDCode = 0;
- SCCB_GPIO_init();
-
-
- if( 0 == SCCB_WriteByte ( OV7725_COM7, 0x80 ) )
- {
-
- return 0 ;
- }
-
- OV7725_EAGLE_Delay_ms(50);
-
- if( 0 == SCCB_ReadByte( &Sensor_IDCode, 1, OV7725_VER ) )
- {
-
- return 0;
- }
-
-
- if(Sensor_IDCode == OV7725_ID)
- {
- for( i = 0 ; i < ov7725_eagle_cfgnum ; i++ )
- {
- if( 0 == SCCB_WriteByte(ov7725_eagle_reg[i].addr, ov7725_eagle_reg[i].val) )
- {
-
- return 0;
- }
- }
- }
- else
- {
- return 0;
- }
-
- return 1;
- }
由于鹰眼摄像头的特色,直接导致了图像发送给上位机的时候需要进行一些细操作,才能在上位机上看到相应图像。如:
- for(i=0;i<80;i++)
- for(j=0;j<20;j++)
- {
- Send_Buffer = colour[ (Image[i][j] >> 7 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[i][j] >> 6 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[i][j] >> 5 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[i][j] >> 4 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[i][j] >> 3 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[i][j] >> 2 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[i][j] >> 1 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- Send_Buffer = colour[ (Image[i][j] >> 0 ) & 0x01 ];
- UART_SendData(UART4,Send_Buffer);
- }
接下来就能成功的在上位机上看到相应的图像了。
大概总结:对于每一款摄像头的操作,先对它进行SCCB的写操作,初始化成自己需要的分辨率、模式,等等。
SCCB初始化之后,再进行场中断、行中断、像素中断的函数处理编辑。
最后发送到上位机上,进行显示和处理。很多上位机都可以让用户自己在Visual Stdio上编写自己的算法,直接在上位机上处理,很赞。