”WinForm上位机+OV7670摄像头+STM32+蓝牙“图像采集系统(一)STM32驱动CMOS摄像头OV7670

本文介绍了使用STM32F103ZET6单片机通过SCCB接口初始化OV7670摄像头,设置为320*240_4bits灰度图像输出,利用FIFO进行图像存储和传输。调试过程包括验证SCCB时序、读写寄存器以及中断服务程序设计,以实现图像帧的完整捕获。
摘要由CSDN通过智能技术生成

初衷;将摄像头放在防盗门猫眼位置,访客到来时,给访客拍个照,然后传到房主端显示。 现在只完成了蓝牙传输,和WinForm窗体显示,后面时间来得及的话会陆续完成WiFi传输,和手机端APK显示。


常规思路:图像采集->图像处理->图像传输->图像显示


首先要做的就是图像采集:

系统采用32位单片机STM32F103ZET6,自己LayOut的PCB,中间可以直插FSMC驱动的TFT屏。 摄像头模块用的带FIFO的OV7670,最高输出是640*480@25Hz_16RGB,由于系统采用的是串口蓝牙传输,所以为了节省传输时间,决定只取320*240_4bits灰度图像传输。

OV要把一帧图像存储在FIFO中,等待MCU慢慢地读取,MCU读完一帧图片后,OV才会向FIFO写入新的一帧图片(摄像头VYSNC做FIFO读写中断即可),硬件装置如下图所示。


1、SCCB接口

初始化OV摄像头,需要通过SCCB接口配置其内部的一百多个寄存器。 SCCB就是个两线的接口协议,类似于IIC。SCL是时钟线,SDA是双向数据线。

2、调试心酸经验

刚开始调OV的时候,找了一大堆网友的程序,挨个试验,结果没一个管用的,于是耽搁了一段时间没搞,很是不甘心。 后来想着要理解理解代码,从SCCB协议开始,对照着芯片手册上的Register Map理解。

1) 先确保SCCB的时序正确,对照着DataSheet上的SCCB Timing Diagram检查

2) SCCB时序无误后,检查是否可以正常读写寄存器。先读下图的两个寄存器,地址为0X0A和0X0B,若分别返回0X76和0X73则说明可以正常读寄存器。

然后再去写一个寄存器(不要写成了ReadOnly的寄存器),写完去读它,检查是否和自己写入的值相等。若相等的话,就表示可以正常写了。

3) 在调试过程中,我遇到过几次这样的情况:读出来的数据始终是0XFF,也就是说,每次按位读的时候,SDA总为高电平。很让我苦恼,同样的程序在STM32上可以用,为什么到其他平台上就不能用了呢。后来偶然发现了原因:因为我将SCCB时序程序中的delay_us(50)改成了delay_ms(1)。也就是说,延时变长了就不能正常读写了,切记!

4) 另外,介绍两个需要注意的寄存器,地址分别是0x12 (用来配置输出格式:RGB YUV QVGA等), 0x1e (用来配置输出水平垂直镜像)

5)一帧图像在FIFO内读写的控制,程序如下,作简单解读

 //ov_sta:0,开始一帧数据采集
u8 ov_sta;
 //外部中断5~9服务程序  , 接OV7670_VSYNC
void EXTI9_5_IRQHandler(void)
{ 
 
if(EXTI_GetITStatus(EXTI_Line8)==SET)//是8线的中断
{     
if(ov_sta<2)
{
if(ov_sta==0)
{
OV7670_WRST_0;//复位写指针  
OV7670_WRST_1;
OV7670_WREN_1;//允许写入FIFO
}else 
{
OV7670_WREN_0;//禁止写入FIFO 
OV7670_WRST_0;//复位写指针  
OV7670_WRST_1;
}
ov_sta++;
}
}
EXTI_ClearITPendingBit(EXTI_Line8);  //清除EXTI8线路挂起位 
} 


此IO中断连接OV7670_VSYNC,状态变量ov_sta初始为0,第一个OV7670_VSYNC上升沿来到,表示OV开始输出一帧图像,此时复位FIFO写指针,允许写入FIFO,ov_sta自增至1。第二个OV7670_VSYNC上升沿来到,表示OV此帧图像输出完毕,开始输出下一帧图像,此时进制写入FIFO,ov_sta自增至2。 这样就把一帧图像锁存在FIFO中等待MCU慢慢读取了,ov_sta为2的时候,OV7670_VSYNC的中断服务是不会有任何操作的,因为此时要等待MCU读完FIFO,并将状态变量ov_sta复位,程序如下:

 extern u8 ov_sta;
//更新LCD显示
void camera_refresh(void)
{
u32 i,j;
  u16 color;  
//  ili9320_SetCursor(0,0); 
//  LCD_WriteRAM_Prepare(); 
if(ov_sta==2)
{ 
OV7670_RRST_0;//开始复位读指针 
OV7670_RCK_0;
OV7670_RCK_1;
OV7670_RCK_0;
OV7670_RRST_1;//复位读指针结束 
OV7670_RCK_1;  


for(i=0;i<240;i++)
for(j=0;j<320;j++)
{
OV7670_RCK_0;
color=GPIOC->IDR&0XFF;//读数据
usart1_send_char(color);
delay_ms(20);//留时间给zigbee传输数据
OV7670_RCK_1; 
color<<=8;  
OV7670_RCK_0;
color|=GPIOC->IDR&0XFF;//读数据
usart1_send_char(color);
delay_ms(20);//留时间给zigbee传输数据
OV7670_RCK_1; 


// LCD_WriteRAM(color);
LCD_DrawPoint(239-i,j,color);
}    
EXTI_ClearITPendingBit(EXTI_Line8);  //清除LINE8上的中断标志位
ov_sta=0; //开始下一次采集
} 
} 

  • 46
    点赞
  • 241
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值