引言
本系统着眼于经济型视频监控系统,可应用于工业自动化设备、汽车安全驾驶、医疗设施或大楼供水、供电等系统的监控,应用前景广阔、成本低廉、系统简洁。
1 芯片简介
1.1 STM32F407简介
本系统采用的处理器是意法半导体公司的STM32F407,该处理器以32位CortexM4为内核,具有浮点运算功能的低端高速ARM,其内部集成了大量可供立即使用的资源,如TFT液晶显示器接口(Flexible Stactic Memory Control,FSMC)、摄像头接口(Camera Interface)、DMA控制器[1]等,方便且实用。
1.2 OV7670简介
OV7670是OmniVision公司基于CMOS VGA的图像传感器,可通过SCCB总线控制输出整帧、子采集、取窗口等操作,其VGA图像最高可达到30 fps[2]。其对外重要接口有:XCLK(时钟输入)、HREF(输出行同步信号)、VSYNC(输出场同步信号)、PCLK(输出像素时钟)、RESET(复位输入信号)、PWDN、SIO_C(SCCB总线时钟信号)、SIO_D(SCCB总线数据信号)、D0~D7(摄像头输出数据信号)。
本系统采用的OV7670不带FIFO,由STM32F407直接通过SCCB总线读取数据,并显示在LCD上。
2 硬件和软件实现
2.1 硬件实现
本系统硬件电路实现简单,微处理器与系统主要外设连接如图1所示,主要涉及STM32F407与TFT液晶模块连接以及与OV7670图像传感器的连接,接口电路如图2、图3所示。
图1 微处理器与系统主要外设连接
图2 TFT液晶显示器与STM32F407接口电路
STM32F407与TFT液晶模块连接时,仅需将该模块考虑成一个SRAM即可,具体连接方式见图2。唯一需要注意的是,液晶模块RS和CS端与STM32F407的FSMC控制器的连接,本系统中RS连接FSMC_A0(PF0),CS连接FSMC_NE4(PG12),这些连接直接关系到软件初始化时相关寄存器地址设置。
如图3所示,STM32F407与OV7670连接时,OV7670的XLCK PC9可以选择STM32F407的MCO1或MCO2引脚,同时PCI SOIC和SOID PC2引脚可以连接至I2C总线,也可以根据软件设计定义其他I/O引脚(本系统采用了这种方案),OV7670的其他端口连接至DCMI相应接口即可。
图3 OV7670与STM32F407接口电路
2.2 软件实现
本系统的软件设计关键点在于系统时钟的配置、TFT液晶模块初始化、OV7670图像传感器初始化、SCCB总线时序模拟。软件程序流程图如图4所示。
图4 系统软件流程
系统时钟配置由RCC_Config()函数完成,函数内部结构如下:
RCC_DeInit();//复位RCC配置至系统默认状态
RCC_HSEConfig(RCC_HSE_ON);//打开外部时钟
if(RCC_WaitForHSEStartUp() == SUCCESS) {//等待外部时钟稳定
RCC_PLLCmd(DISABLE); //关闭锁相环时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//将系统时钟配置成相关时钟
RCC_HCLKConfig(RCC_SYSCLK_Div1);//HCLK为系统时钟
RCC_PCLK1Config(RCC_HCLK_Div4);//PCLK1时钟为系统时钟的4分频
RCC_PCLK2Config(RCC_HCLK_Div2);//PCLK2时钟为系统时钟的2分频
RCC_PLLConfig(RCC_PLLSource_HSE,12,240,2,8);//将系统时钟配置成120 MHz
RCC_PLLCmd(ENABLE);//开启锁相环时钟
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET){}//等待锁相环时钟输出稳定
}
TFT液晶模块初始化关键点在于FSMC控制器的配置和寄存器地址的计算。STM32F407的FSMC使用了AHB3提供的时钟信号,因而需要使能AHB3时钟以及FSMC控制器复用的其他I/O端口所在时钟信号。寄存器地址则需要根据液晶模块的RS和CS端与FSMC接口的具体连接方式计算。由于STM32F4系列微处理器的FSMC控制器对外设备地址映射从0x60000000开始到0x9FFFFFFF结束,共有4个BANK组成,每个BANK大小为256 MB,每个BANK又分为4个小块,每块大小为64 MB。
在TFT液晶初始化程序中选择了BANK1,且CS连接FSMC_NE4(PG12),故TFT液晶模块的寄存器起始地址为0x6C000000;RS连接FSMC_A0(PF0),故TFT液晶模块的RAM为0x6C000000+20×2=0x6C000002。如果在TFT液晶初始化程序中选择了BANK1,且CS连接FSMC_NE1(PD7),TFT液晶模块的寄存器起始地址为0x60000000;RS连接FSMC_A18(PD13),TFT液晶模块的RAM为0x60000000+218×2=0x60080000。
依次类推可以计算其他连接方法时,液晶模块的寄存器起始地址和RAM地址。代码如下:
#define LCD_RAM*(vu16*)((u32)0x6c000002)//定义RAM基地址
#define LCD_REG*(vu16*)((u32)0x6c000000)//定义REG基地址
OV7670图像传感器初始化关键点有两个,首先是微处理器的DCMI接口及DMA部分的配置,这些配置主要体现在DCMI接口、DMA控制器以及图像传感器用到的其他I/O端口所在时钟总线使能方面;其次是OV7670本身寄存器配置方面。由于篇幅所限,现将一些重要的函数列出,并给出重要注释,仅供参考。
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);//DCMI
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);//DMA2
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|
RCC_AHB1Periph_GPIOB|
RCC_AHB1Periph_GPIOC|
RCC_AHB1Periph_GPIOE, ENABLE);
……
RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_5);
unsigned charSCCB_Write(unsigned charm_data){//SCCB总线写数据操作
unsigned charj,tem,K;
K=m_data;
for(j=0;j<8;j++) { //循环8次发送数据
if((K&0x80)==0x80){
SCCB_SID_H();//SCCB总线SID置高
}
else {
SCCB_SID_L();//SCCB总线SID置低
}
Delay_us(10);
SCCB_SIC_H();//SCCB总线SCL置高
Delay_us(5);
K<<=1;
SCCB_SIC_L();//SCCB总线SCL置高
Delay_us(1);
}
Delay_us(2);
SCCB_DATA_IN;
Delay_us(2);
SCCB_SIC_H();
Delay_us(2);
if(SCCB_SID_STATE)
tem=0;//SDA=1发送失败
else
tem=1;//SDA=0发送成功,返回1
SCCB_SIC_L();
Delay_us(2);
SCCB_DATA_OUT;
return tem;
}
unsigned charOV_WriteReg(unsigned charregID, unsigned charregDat){//通过SCCB总线写入OV7670寄存器数据
SCCB_Start();//发送SCCB总线开始传输命令
if(SCCB_Write(0x42)==0){//写地址
SCCB_Stop();//发送SCCB总线停止传输命令
return 0;//错误返回
}
Delay_us(10);
if(SCCB_Write(regID)==0){//寄存器ID
SCCB_Stop();//发送SCCB总线停止传输命令
return 0;//错误返回
}
Delay_us(10);
if(SCCB_Write(regDat)==0){//写数据到寄存器
SCCB_Stop();//发送SCCB总线停止传输命令
return 0;//错误返回
}
SCCB_Stop();//发送SCCB总线停止传输命令
return 1;//成功返回
}
void OV7670_HW(unsigned inthstart,unsigned int vstart,unsigned int hstop,unsigned int vstop){//通过计算显示区域设置OV7670寄存器
u8 v;
OV_WriteReg(0x17,(hstart>>3)&0xff);//HSTART
OV_WriteReg(0x18,(hstop>>3)&0xff);//HSTOP
OV_ReadReg(0x32,&v);
v=(v&0xc0)|((hstop&0x7)<<3)|(hstart&0x7);
OV_WriteReg(0x32,v);//HREF
OV_WriteReg(0x19,(vstart>>2)&0xff);//VSTART开始高8位
OV_WriteReg(0x1a,(vstop>>2)&0xff);//VSTOP结束高8位
OV_ReadReg(0x03,&v);
v=(v&0xf0)|((vstop&0x3)<<2)|(vstart&0x3);
OV_WriteReg(0x03,v);//VREF
OV_WriteReg(0x11,0x00);
图5 图像效果
}
SCCB总线时序模拟可以根据SCCB标准中定义的时序进行程序编写,这一部分为大家所熟知,不再赘述。
结语
通过以上程序编写、软件和硬件的调试,最终得到比较满意的结果,如图5所示。
虽然视频图像显示有点模糊,且画面略有顿挫感,但是可以通过软件、硬件的再优化提升画面效果,同时也为STM32F407和OV7670在视频监控系统中的应用提供思路。