1.硬件二值化,二值化效果理想(个人看法不一样)
2.一次传输8个像素,速度可达150帧每秒
3.成像质量、低照度好的OV7725
由于某宙捕食者摄像头停产,不得不换用市面上认为用于智能车比赛较好的摄像头——鹰眼(我也是偷懒的人,能用别人的坚决不自己写)。
我在驱动鹰眼的时候和山外哥一样,并未使用行中断,而是采用场中断+DMA的方式,可能与大家习惯使用行场中断+DMA采集图像的方式存在差异,不过原理并没有太多区别。
注意:①在K60与PCLK、VSYNC连接的IO处加下拉150Ω的电阻进行阻抗匹配,可以有效减少干扰。不过我在测试的时候并没有加,图像也很稳定,并没有异常。
②鹰眼使用3.3V供电,存在因电池电量不够出现图像上下错位的情况。
(忽略图片中的行中断内容)采用场信号上升沿触发中断,开启DMA,根据PCLK的下降沿触发,传输图像。
①需要采集图像时,开场中断
②判断场中断来了,初始化DMA传输,并启动DMA传输
③每个PCLK下降沿来了都触发DMA传输,把摄像头的输出的值读取到内存数组里。
④DMA停止传输时触发中断,中断里面设置图像采集结束标志,图像采集完毕。
OV7725摄像头的寄存器是EEPRON,有一定单片机基础的同学都知道,其不稳定,数据易丢失,因此程序每次初始化时我们都需要重新写入寄存器设置。下面定义摄像头的各寄存器地址:
#ifndef _OV7725_REG_H_
#define _OV7725_REG_H_
#define OV7725_ID 0x21
#define OV7725_GAIN 0x00
#define OV7725_BLUE 0x01
#define OV7725_RED 0x02
#define OV7725_GREEN 0x03
#define OV7725_BAVG 0x05
#define OV7725_GAVG 0x06
#define OV7725_RAVG 0x07
#define OV7725_AECH 0x08
#define OV7725_COM2 0x09
#define OV7725_PID 0x0A
#define OV7725_VER 0x0B
#define OV7725_COM3 0x0C
#define OV7725_COM4 0x0D
#define OV7725_COM5 0x0E
#define OV7725_COM6 0x0F
#define OV7725_AEC 0x10
#define OV7725_CLKRC 0x11
#define OV7725_COM7 0x12
#define OV7725_COM8 0x13
#define OV7725_COM9 0x14
#define OV7725_COM10 0x15
#define OV7725_REG16 0x16
#define OV7725_HSTART 0x17
#define OV7725_HSIZE 0x18
#define OV7725_VSTRT 0x19
#define OV7725_VSIZE 0x1A
#define OV7725_PSHFT 0x1B
#define OV7725_MIDH 0x1C
#define OV7725_MIDL 0x1D
#define OV7725_LAEC 0x1F
#define OV7725_COM11 0x20
#define OV7725_BDBase 0x22
#define OV7725_BDMStep 0x23
#define OV7725_AEW 0x24
#define OV7725_AEB 0x25
#define OV7725_VPT 0x26
#define OV7725_REG28 0x28
#define OV7725_HOutSize 0x29
#define OV7725_EXHCH 0x2A
#define OV7725_EXHCL 0x2B
#define OV7725_VOutSize 0x2C
#define OV7725_ADVFL 0x2D
#define OV7725_ADVFH 0x2E
#define OV7725_YAVE 0x2F
#define OV7725_LumHTh 0x30
#define OV7725_LumLTh 0x31
#define OV7725_HREF 0x32
#define OV7725_DM_LNL 0x33
#define OV7725_DM_LNH 0x34
#define OV7725_ADoff_B 0x35
#define OV7725_ADoff_R 0x36
#define OV7725_ADoff_Gb 0x37
#define OV7725_ADoff_Gr 0x38
#define OV7725_Off_B 0x39
#define OV7725_Off_R 0x3A
#define OV7725_Off_Gb 0x3B
#define OV7725_Off_Gr 0x3C
#define OV7725_COM12 0x3D
#define OV7725_COM13 0x3E
#define OV7725_COM14 0x3F
#define OV7725_COM16 0x41
#define OV7725_TGT_B 0x42
#define OV7725_TGT_R 0x43
#define OV7725_TGT_Gb 0x44
#define OV7725_TGT_Gr 0x45
#define OV7725_LC_CTR 0x46
#define OV7725_LC_XC 0x47
#define OV7725_LC_YC 0x48
#define OV7725_LC_COEF 0x49
#define OV7725_LC_RADI 0x4A
#define OV7725_LC_COEFB 0x4B
#define OV7725_LC_COEFR 0x4C
#define OV7725_FixGain 0x4D
#define OV7725_AREF1 0x4F
#define OV7725_AREF6 0x54
#define OV7725_UFix 0x60
#define OV7725_VFix 0x61
#define OV7725_AWBb_blk 0x62
#define OV7725_AWB_Ctrl0 0x63
#define OV7725_DSP_Ctrl1 0x64
#define OV7725_DSP_Ctrl2 0x65
#define OV7725_DSP_Ctrl3 0x66
#define OV7725_DSP_Ctrl4 0x67
#define OV7725_AWB_bias 0x68
#define OV7725_AWBCtrl1 0x69
#define OV7725_AWBCtrl2 0x6A
#define OV7725_AWBCtrl3 0x6B
#define OV7725_AWBCtrl4 0x6C
#define OV7725_AWBCtrl5 0x6D
#define OV7725_AWBCtrl6 0x6E
#define OV7725_AWBCtrl7 0x6F
#define OV7725_AWBCtrl8 0x70
#define OV7725_AWBCtrl9 0x71
#define OV7725_AWBCtrl10 0x72
#define OV7725_AWBCtrl11 0x73
#define OV7725_AWBCtrl12 0x74
#define OV7725_AWBCtrl13 0x75
#define OV7725_AWBCtrl14 0x76
#define OV7725_AWBCtrl15 0x77
#define OV7725_AWBCtrl16 0x78
#define OV7725_AWBCtrl17 0x79
#define OV7725_AWBCtrl18 0x7A
#define OV7725_AWBCtrl19 0x7B
#define OV7725_AWBCtrl20 0x7C
#define OV7725_AWBCtrl21 0x7D
#define OV7725_GAM1 0x7E
#define OV7725_GAM2 0x7F
#define OV7725_GAM3 0x80
#define OV7725_GAM4 0x81
#define OV7725_GAM5 0x82
#define OV7725_GAM6 0x83
#define OV7725_GAM7 0x84
#define OV7725_GAM8 0x85
#define OV7725_GAM9 0x86
#define OV7725_GAM10 0x87
#define OV7725_GAM11 0x88
#define OV7725_GAM12 0x89
#define OV7725_GAM13 0x8A
#define OV7725_GAM14 0x8B
#define OV7725_GAM15 0x8C
#define OV7725_SLOP 0x8D
#define OV7725_DNSTh 0x8E
#define OV7725_EDGE0 0x8F
#define OV7725_EDGE1 0x90
#define OV7725_DNSOff 0x91
#define OV7725_EDGE2 0x92
#define OV7725_EDGE3 0x93
#define OV7725_MTX1 0x94
#define OV7725_MTX2 0x95
#define OV7725_MTX3 0x96
#define OV7725_MTX4 0x97
#define OV7725_MTX5 0x98
#define OV7725_MTX6 0x99
#define OV7725_MTX_Ctrl 0x9A
#define OV7725_BRIGHT 0x9B
#define OV7725_CNST 0x9C
#define OV7725_UVADJ0 0x9E
#define OV7725_UVADJ1 0x9F
#define OV7725_SCAL0 0xA0
#define OV7725_SCAL1 0xA1
#define OV7725_SCAL2 0xA2
#define OV7725_SDE 0xA6
#define OV7725_USAT 0xA7
#define OV7725_VSAT 0xA8
#define OV7725_HUECOS 0xA9
#define OV7725_HUESIN 0xAA
#define OV7725_SIGN 0xAB
#define OV7725_DSPAuto 0xAC
#endif
摄像头初始化配置表单:
reg_s ov7725_eagle_reg[] =
{
//寄存器,寄存器值次 50 75 112 150
{OV7725_COM4 , 0xC1},//0xc1;0x41;0x81;0xc1
{OV7725_CLKRC , 0x00},//0x02;0x00;0x00;0x00
{OV7725_COM2 , 0x03},
{OV7725_COM3 , 0xD0},
{OV7725_COM7 , 0x40},
{OV7725_COM10 , 0x20},
{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 (CAMERA_W == 80)
{OV7725_HOutSize , 0x14},
#elif (CAMERA_W == 160)
{OV7725_HOutSize , 0x28},
#elif (CAMERA_W == 240)
{OV7725_HOutSize , 0x3c},
#elif (CAMERA_W == 320)
{OV7725_HOutSize , 0x50},
#else
#endif
#if (CAMERA_H == 60 )
{OV7725_VOutSize , 0x1E},
#elif (CAMERA_H == 120 )
{OV7725_VOutSize , 0x3c},
#elif (CAMERA_H == 180 )
{OV7725_VOutSize , 0x5a},
#elif (CAMERA_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 , 0x90},
{OV7725_SIGN , 0x06},
{OV7725_UVADJ0 , 0x11},
{OV7725_UVADJ1 , 0x02},
};
OV77寄存器初始化函数:
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 ;
}
LPLD_SYSTICK_DelayMs(50);
if( 0 == SCCB_ReadByte( &Sensor_IDCode, 1, OV7725_VER ) ) /* 读取摄像头传感器 ID号*/
{
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;
}
SCCB配置:
#include "common.h"
#include "SCCB.h"
static void SCCB_delay(uint16 i);
/*!
* @brief SCCB延迟函数
*/
static void SCCB_delay(volatile uint16 time)
{
while(time)
{
time--;
}
}
/*!
* @brief SCCB管脚配置
*/
void SCCB_GPIO_init(void)
{
GPIO_InitTypeDef ptb;
/********用户可修改值 开始***********/
ptb.GPIO_PTx = PTA;
ptb.GPIO_Pins = GPIO_Pin25 | GPIO_Pin26;
/********用户可修改值 结束***********/
ptb.GPIO_Dir = DIR_OUTPUT;
ptb.GPIO_Output = OUTPUT_H;
ptb.GPIO_PinControl = NULL;
LPLD_GPIO_Init(ptb);
}
/*!
* @brief SCCB起始信号
*/
static uint8 SCCB_Start(void)
{
SDA_H();
SCL_H();
SCCB_DELAY();
SDA_DDR_IN();
if(!SDA_IN())
{
SDA_DDR_OUT();
return 0; /* SDA线为低电平则总线忙,退出 */
}
SDA_DDR_OUT();
SDA_L();
SCCB_DELAY();
SCL_L();
if(SDA_IN())
{
SDA_DDR_OUT();
return 0; /* SDA线为高电平则总线出错,退出 */
}
//SDA_DDR_OUT();
//SDA_L();
//SCCB_delay();
return 1;
}
/*!
* @brief SCCB停止信号
*/
static void SCCB_Stop(void)
{
SCL_L();
//SCCB_DELAY();
SDA_L();
SCCB_DELAY();
SCL_H();
SCCB_DELAY();
SDA_H();
SCCB_DELAY();
}
/*!
* @brief SCCB应答信号
*/
static void SCCB_Ack(void)
{
SCL_L();
SCCB_DELAY();
SDA_L();
SCCB_DELAY();
SCL_H();
SCCB_DELAY();
SCL_L();
SCCB_DELAY();
}
/*!
* @brief SCCB无应答信号
*/
static void SCCB_NoAck(void)
{
SCL_L();
SCCB_DELAY();
SDA_H();
SCCB_DELAY();
SCL_H();
SCCB_DELAY();
SCL_L();
SCCB_DELAY();
}
/*!
* @brief SCCB 等待应答
* @return 应答结果(0表示无应答,1表示有应答)
*/
static int SCCB_WaitAck(void)
{
SCL_L();
//SDA_H();
SDA_DDR_IN();
SCCB_DELAY();
SCL_H();
SCCB_DELAY();
if(SDA_IN()) //应答为高电平,异常,通信失败
{
SDA_DDR_OUT();
SCL_L();
return 0;
}
SDA_DDR_OUT();
SCL_L();
return 1;
}
/*!
* @brief SCCB 发送的数据
* @param SendByte 需要发送的数据
*/
static void SCCB_SendByte(uint8 SendByte)
{
uint8 i = 8;
while(i--)
{
if(SendByte & 0x80) //SDA 输出数据
{
SDA_H();
}
else
{
SDA_L();
}
SendByte <<= 1;
SCCB_DELAY();
SCL_H(); //SCL 拉高,采集信号
SCCB_DELAY();
SCL_L(); //SCL 时钟线拉低
//SCCB_DELAY();
}
//SCL_L();
}
/*!
* @brief 接收SCCB总线的数据
* @return 接收到的数据
*/
static int SCCB_ReceiveByte(void)
{
uint8 i = 8;
uint8 ReceiveByte = 0;
//SDA_H();
//SCCB_DELAY();
SDA_DDR_IN();
while(i--)
{
ReceiveByte <<= 1;
SCL_L();
SCCB_DELAY();
SCL_H();
SCCB_DELAY();
if(SDA_IN())
{
ReceiveByte |= 0x01;
}
}
SDA_DDR_OUT();
SCL_L();
return ReceiveByte;
}
/******************************************************
* 函数名:SCCB_WriteByte
* 描述 :写一字节数据
* 输入 :- WriteAddress: 待写入地址 - SendByte: 待写入数据 - DeviceAddress: 器件类型
* 输出 :返回为:=1成功写入,=0失败
**********************************/
static int SCCB_WriteByte_one( uint16 WriteAddress , uint8 SendByte );
int SCCB_WriteByte( uint16 WriteAddress , uint8 SendByte ) //考虑到用sccb的管脚模拟,比较容易失败,因此多试几次
{
uint8 i = 0;
while( 0 == SCCB_WriteByte_one ( WriteAddress, SendByte ) )
{
i++;
if(i == 20)
{
return 0 ;
}
}
return 1;
}
int SCCB_WriteByte_one( uint16 WriteAddress , uint8 SendByte )
{
if(!SCCB_Start())
{
return 0;
}
SCCB_SendByte( DEV_ADR ); /* 器件地址 */
if( !SCCB_WaitAck() )
{
SCCB_Stop();
return 0;
}
SCCB_SendByte((uint8)(WriteAddress & 0x00FF)); /* 设置低起始地址 */
SCCB_WaitAck();
SCCB_SendByte(SendByte);
SCCB_WaitAck();
SCCB_Stop();
return 1;
}
/******************************************************
* 函数名:SCCB_ReadByte
* 描述 :读取一串数据
* 输入 :- pBuffer: 存放读出数据 - length: 待读出长度 - ReadAddress: 待读出地址 - DeviceAddress: 器件类型
* 输出 :返回为:=1成功读入,=0失败
********/
static int SCCB_ReadByte_one(uint8 *pBuffer, uint16 length, uint8 ReadAddress);
int SCCB_ReadByte(uint8 *pBuffer, uint16 length, uint8 ReadAddress)
{
uint8 i = 0;
while( 0 == SCCB_ReadByte_one(pBuffer, length, ReadAddress) )
{
i++;
if(i == 30)
{
return 0 ;
}
}
return 1;
}
int SCCB_ReadByte_one(uint8 *pBuffer, uint16 length, uint8 ReadAddress)
{
if(!SCCB_Start())
{
return 0;
}
SCCB_SendByte( DEV_ADR ); /* 器件地址 */
if( !SCCB_WaitAck() )
{
SCCB_Stop();
return 0;
}
SCCB_SendByte( ReadAddress ); /* 设置低起始地址 */
SCCB_WaitAck();
SCCB_Stop();
if(!SCCB_Start())
{
return 0;
}
SCCB_SendByte( DEV_ADR + 1 ); /* 器件地址 */
if(!SCCB_WaitAck())
{
SCCB_Stop();
return 0;
}
while(length)
{
*pBuffer = SCCB_ReceiveByte();
if(length == 1)
{
SCCB_NoAck();
}
else
{
SCCB_Ack();
}
pBuffer++;
length--;
}
SCCB_Stop();
return 1;
}
void ov7725_eagle_port_init()//注意先初始化数据口在初始化DMA
{
//数据口初始化:PTB0~PTB7
pte_init.GPIO_PTx = PTB;
pte_init.GPIO_Dir = DIR_INPUT;
pte_init.GPIO_Pins = GPIO_Pin0_7;
pte_init.GPIO_PinControl = IRQC_DIS | INPUT_PULL_DIS;
LPLD_GPIO_Init(pte_init);
dma_init();
LPLD_DMA_DisableReq(CAMERA_DMA_CH);
disable_irq(PORTA_IRQn); //关闭PTA的中断
DMA0->INT |= 0x1u<<0; //清除中断标志位
LPLD_GPIO_ClearIntFlag(PORTA);
LPLD_DMA_EnableIrq(dma_init_struct);
//行信号接口初始化:PTA28-H;‘’并未使用行信号产生中断--hl‘’
h_init.GPIO_PTx = PTA;
h_init.GPIO_Dir = DIR_INPUT;
h_init.GPIO_Pins = GPIO_Pin28;
h_init.GPIO_PinControl = IRQC_DIS|INPUT_PULL_DOWN;
//h_init.GPIO_Isr = coms_isr;
LPLD_GPIO_Init(h_init);
//场信号接口初始化:PTA29-V
v_init.GPIO_PTx = PTA;
v_init.GPIO_Dir = DIR_INPUT;
v_init.GPIO_Pins = GPIO_Pin29;
v_init.GPIO_PinControl = IRQC_RI|INPUT_PULL_DOWN;
v_init.GPIO_Isr = ov7725_eagle_vsync;
LPLD_GPIO_Init(v_init);
// PCLK信号接口初始化:PTA27-PCLK
p_init.GPIO_PTx = PTA;
p_init.GPIO_Pins = GPIO_Pin27;
p_init.GPIO_Dir = DIR_INPUT;
p_init.GPIO_PinControl = IRQC_DMAFA | INPUT_PULL_DOWN|INPUTPF_EN;
LPLD_GPIO_Init(p_init);
}
void dma_init()
{
//DMA参数配置
dma_init_struct.DMA_CHx = CAMERA_DMA_CH; //CH0通道
dma_init_struct.DMA_Req = PORTA_DMAREQ; //PORTA为请求源
dma_init_struct.DMA_MajorLoopCnt = CAMERA_DMA_NUM; //主循环计数值
dma_init_struct.DMA_MinorByteCnt = 1; //次循环一次传输字节的个数
dma_init_struct.DMA_SourceAddr = (uint32)&PTB->PDIR; //源地址:PTB0~7
dma_init_struct.DMA_DestAddr = (uint32)ov7725_eagle_img_buff;//目的地址:存放图像的数组
dma_init_struct.DMA_DestAddrOffset = 1; //目的地址偏移:每次读入增加1
dma_init_struct.DMA_AutoDisableReq = TRUE; //自动禁用请求
dma_init_struct.DMA_MajorCompleteIntEnable=TRUE; //使能DMA主循环完成中断
(DMA0->TCD[CAMERA_DMA_CH].CSR =0|DMA_CSR_BWC(3)); //每读一次,eDMA暂停4个周期
dma_init_struct.DMA_Isr=ov7725_eagle_dma;
//初始化DMA
LPLD_DMA_Init(dma_init_struct);
}
void ov7725_eagle_vsync(void)
{
if(LPLD_GPIO_IsPinxExt(PORTA, GPIO_Pin29))//很关键,必须判断是否为PTA29上的中断
{
//场中断需要判断是场结束还是场开始
if(ov7725_eagle_img_flag==IMG_START) //需要开始采集图像
{
ov7725_eagle_img_flag=IMG_GATHER; //标记图像采集中
disable_irq(PORTA_IRQn);
#if 1
PORTA->ISFR =1<<27;
LPLD_DMA_EnableReq(CAMERA_DMA_CH); //使能通道CHn 硬件请求
PORTA->ISFR =1<<27;
LPLD_DMA_LoadDstAddr(CAMERA_DMA_CH,(uint32)ov7725_eagle_img_buff);
//LPLD_GPIO_Toggle_b(PTC,0);
#else
PORTA->ISFR =1<<27;
//dma_init();
DMA0->INT |= 0x1u<<0;//清除中断标志位
(DMA0->TCD[CAMERA_DMA_CH].CITER_ELINKNO=(((uint16_t)(((uint16_t)(CAMERA_DMA_NUM))<TCD[CAMERA_DMA_CH].BITER_ELINKNO=(((uint16_t)(((uint16_t)(CAMERA_DMA_NUM))<TCD[CAMERA_DMA_CH].SADDR=(uint32)&PTB->PDIR);
(DMA0->TCD[CAMERA_DMA_CH].DADDR=(uint32)ov7725_eagle_img_buff);
LPLD_DMA_EnableReq(CAMERA_DMA_CH);
#endif
}
else //图像采集错误
{
disable_irq(PORTA_IRQn); //关闭PTA的中断
ov7725_eagle_img_flag = IMG_FAIL; //标记图像采集失败
}
}
}
void ov7725_eagle_dma()
{
ov7725_eagle_img_flag = IMG_FINISH ;
}
因为摄像头传输回来的数据是并不是一个像素一个字节,而是八个像素一个字节,所以无论是发送到上位机观察图像还是屏幕显示图像,都必须先解压图像。
void img_extract(void *dst, void *src, uint32_t srclen)
{
uint8_t colour[2] = {255, 0}; //0 和 1 分别对应的颜色
uint8_t * mdst = dst;
uint8_t * msrc = src;
//注:山外的摄像头 0 表示 白色,1表示 黑色
uint8_t tmpsrc;
while(srclen --)
{
tmpsrc = *msrc++;
*mdst++ = colour[ (tmpsrc >> 7 ) & 0x01 ];
*mdst++ = colour[ (tmpsrc >> 6 ) & 0x01 ];
*mdst++ = colour[ (tmpsrc >> 5 ) & 0x01 ];
*mdst++ = colour[ (tmpsrc >> 4 ) & 0x01 ];
*mdst++ = colour[ (tmpsrc >> 3 ) & 0x01 ];
*mdst++ = colour[ (tmpsrc >> 2 ) & 0x01 ];
*mdst++ = colour[ (tmpsrc >> 1 ) & 0x01 ];
*mdst++ = colour[ (tmpsrc >> 0 ) & 0x01 ];
}
}
以上完成了基础的配置,调用下面两个初始化函数和采集图像函数,就可以正常使用这款摄像头。
uint8 ov7725_eagle_init(uint8 *imgaddr)
{
ov7725_eagle_img_buff = imgaddr;
while(ov7725_eagle_reg_init() == 0);
ov7725_eagle_port_init();
return 0;
}
void ov7725_eagle_get_img()
{
ov7725_eagle_img_flag = IMG_START; //开始采集图像
LPLD_GPIO_ClearIntFlag(PORTA);
enable_irq(PORTA_IRQn); //允许PTA的中断
while(ov7725_eagle_img_flag != IMG_FINISH) //等待图像采集完毕
{
if(ov7725_eagle_img_flag == IMG_FAIL) //假如图像采集错误,则重新开始采集
{
ov7725_eagle_img_flag = IMG_START; //开始采集图像
LPLD_GPIO_ClearIntFlag(PORTA);
enable_irq(PORTA_IRQn); //允许PTA的中断
}
}
}
对于摄像头的使用,一般来讲都是按照上续步骤,注意处理好各中断就好。根据上位机的不同,先发送不同的命令后传输数据。后续出稳定的图像后,可以更改OV7725初始化配置表单中的数值来调节帧率、像素等。
附上两张在屏幕上显示的照片。