以下内容皆是个人学习过程中的总结,记录一下整个过程,用于后期复习,如有不对之处,麻烦各位大佬指出~

(喜欢的朋友麻烦点个关注~~~ 后期还会进行持续更新)

OV2640概述:

OV2640是OV (OmniVision)公司生产的- -颗1/4 寸的CMOS UXGA (1632*1232) 图像
传感器。该传感器体积小、工作电压低,提供单片UXGA摄像头和影像处理器的所有功能。通
过SCCB总线控制,可以输出整帧、子采样、缩放和取窗口等方式的各种分辨率8/10位影像
数据。该产品UXGA图像最高达到15帧/秒(SVGA可达30帧,CIF 可达60帧)。用户可以完
全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、对比
度、色度等都可以通过SCCB接口编程。OmmiVision 图像传感器应用独有的传感器技术,通
过减少或消除光学或电子缺陷如固定图案噪声、拖尾、浮散等,提高图像质量,得到清晰的稳
定的彩色图像。

OV2640的特点有:
● 高灵 敏度、低电压适合嵌入式应用
● 标准的SCCB接口,兼容IIC接口
● 支持RawRGB、RGB(RGB565/RGB555). GRB422、YUV(422/420)和YCbCr (422)
   输出格式
● 支持UXGA、SXGA、SVGA以及按比例缩小到从SXGA到40*30的任何尺寸
● 支持自动曝光控制、自动增益控制、自动白平衡、自动消除灯光条纹、自动黑电平校
   准等自动控制功能。同时支持色饱和度、色相、伽马、锐度等设置。
● 支持闪光灯
● 支持图像缩放、平移和窗口设置
● 支持图像压缩,即可输出JPEG图像数据.
● 自带嵌入式微处理器

OV2640引脚及功能框图:

OV2640传感器采用BGA封装,它的前端是采光窗口,引脚都在背面引出,引脚的分布见下图

图中的非彩色部分是电源相关的引脚,彩色部分是主要的信号引脚,介绍如下表 451

下面我们配合图 453中的OV2640功能框图讲解这些信号引脚。

(1)    控制寄存器

标号处的是OV2640的控制寄存器,它根据这些寄存器配置的参数来运行,而这些参数是由外部控制器通过SIO_C和SIO_D引脚写入的,SIO_C与SIO_D使用的通讯协议跟I2C十分类似,在STM32中我们完全可以直接用I2C硬件外设来控制。

(2)    通信、控制信号及时钟

标号处包含了OV2640的通信、控制信号及外部时钟,其中PCLK、HREF及VSYNC分别是像素同步时钟、行同步信号以及帧同步信号,这与液晶屏控制中的信号是很类似的。RESETB引脚为低电平时,用于复位整个传感器芯片,PWDN用于控制芯片进入低功耗模式。注意最后的一个XCLK引脚,它跟PCLK是完全不同的,XCLK是用于驱动整个传感器芯片的时钟信号,是外部输入到OV2640的信号;而PCLK是OV2640输出数据时的同步信号,它是由OV2640输出的信号。XCLK可以外接晶振或由外部控制器提供,若要类比XCLK之于OV2640就相当于HSE时钟输入引脚与STM32芯片的关系,PCLK引脚可类比STM32的I2C外设的SCL引脚。

(3)    感光矩阵

标号处的是感光矩阵,光信号在这里转化成电信号,经过各种处理,这些信号存储成由一个个像素点表示的数字图像。

(4)    数据输出信号

标号处包含了DSP处理单元,它会根据控制寄存器的配置做一些基本的图像处理运算。这部分还包含了图像格式转换单元及压缩单元,转换出的数据最终通过Y0-Y9引脚输出,一般来说我们使用8根据数据线来传输,这时仅使用Y2-Y9引脚,OV2640与外部器件的连接方式见上图          ​​                        

一、SCCB总线

外部控制器对OV2640寄存器的配置参数是通过SCCB总线传输过去的,而SCCB总线跟I2C十分类似,所以在STM32驱动中我们直接使用片上I2C外设与它通讯。SCCB与标准的I2C协议的区别是它每次传输只能写入或读取一个字节的数据,这是因为SCCB最主要是阉割了IIC的连续读写的功能,即每读写完一个字节就主机必须发送一个NA信号,而I2C协议是支持突发读写的,即在一次传输中可以写入多个字节的数据(EEPROM中的页写入时序即突发写)。关于SCCB协议的完整内容可自行百度搜索查看,下面我们简单介绍下。

1.1、SCCB简介

SCCB是欧姆尼图像技术公司(OmniVision)开发的一种总线,应用于OV系列图像传感器上,所以一般使用OV的图像传感器都离不开SCCB总线协议。可以通俗地讲SCCB有两种工作模式,一主多从,一主一从模式。

一主机多从 也即3线操作:(通过控制使能端SCCB_E控制选中的从机)

一主一从 也即2线操作:(默认SCCB_E被拉低)

1.2、SCCB管脚定义

SCCB IIC 方向 描述
SIO_E \ 主机发出 低电平有效,总线空闲时主机驱动此引脚为1,驱动为0时表示开始传输或者挂起模式
SIO_C SCL 主机发出 总线空闲时主机驱动此引脚为1;
当驱动SIO_E为0时,主机驱动此引脚为0或1;当挂起时主机驱动SIO_C为0;
SIO_D只能在SIO_C为0时发生变化。
SIO_D SDA 双向传输              当总线空闲时保持浮动,状态不固定(0、1或高阻态)相当于数据位!                                                                                                        

1.3、SCCB时序

SCCB_E为低电平时传输有效,SIO_C为高电平时SIO_D读取数据(SIO_C为低电平时SIO_D改变)

1.3.1、开始传输的时序

开始传输开始于SCCB_E下降沿。在SCCB_E下降沿前,主机必须将SIO_D置1,这样可以避免读取传送之前产生的未知总线状态。
在SCCB_E下降沿之前,SIO_D必须有tPRC时长的高电平,tPRC至少要15ns
tPRA是SCCB_E下降沿之后SIO_D保持高电平的时间,tPRA至少要1.25us

//SCCB起始信号
//当时钟为高的时候,数据线的高到低,为SCCB起始信号
//在激活状态下,SDA和SCL均为低电平
void SCCB_Start(void)
{SCCB_SDA_OUT();        //数据线为输出模式SCCB_SDA=1;          //数据线高电平SCCB_SCL=1;            //在时钟高的时候数据线由高至低delay_us(50);SCCB_SDA=0;        //在时钟高的时候数据线由高至低delay_us(50);SCCB_SCL=0;          //数据线恢复低电平,单操作函数必要delay_us(50);
}

1.3.2、结束传输的时序

SCCB_E上升沿时表示结束传输,两个时间规定为tPSA和tPSC
tPSC为SCCB_E上升沿之后SIO_D维持高电平的时间,tPSC至少15ns
tPSA为SCCB_E之前SIO_D高电平的时间,tPSA至少0ns

//SCCB停止信号
//当时钟为高的时候,数据线的低到高,为SCCB停止信号
//空闲状况下,SDA,SCL均为高电平
void SCCB_Stop(void)
{SCCB_SDA_OUT();        //数据线为输出模式SCCB_SDA=0;         //数据线低电平delay_us(50);     SCCB_SCL=1;   delay_us(50); SCCB_SDA=1;  delay_us(50);
}  

1.3.3、产生NA时序(用于读数据)

//SCCB_D先拉高,再把SCCB_C拉高,后把SCCB_C拉低,最后把SCCB_D拉低
void SCCB_No_Ack(void)
{SCCB_SDA_OUT();delay_us(50);SCCB_SDA=1;   SCCB_SCL=1;    delay_us(50);SCCB_SCL=0;   delay_us(50);SCCB_SDA=0;   delay_us(50);
}

1.3.4、读时序

//SCCB 读取一个字节
//在SCL的上升沿,数据锁存
//返回值:读到的数据
u8 SCCB_RD_Byte(void)
{u8 temp=0,j;    SCCB_SDA_IN();        //设置SDA为输入  for(j=8;j>0;j--)    //循环8次接收数据{               delay_us(50);SCCB_SCL=1;temp=temp<<1;if(SCCB_READ_SDA)temp++;   delay_us(50);SCCB_SCL=0;}  SCCB_SDA_OUT();     //设置SDA为输出    return temp;
} 

1.3.5、写时序

//SCCB,写入一个字节
//返回值:0,成功;1,失败.
u8 SCCB_WR_Byte(u8 dat)
{u8 j,res;   for(j=0;j<8;j++) //循环8次发送数据{if(dat&0x80)SCCB_SDA=1;  //高位先发送else SCCB_SDA=0;dat<<=1;delay_us(50);SCCB_SCL=1;      //高电平时写入delay_us(50);SCCB_SCL=0;        //低电平时 改变SDA   }             SCCB_SDA_IN();     //设置SDA为输入 delay_us(50);SCCB_SCL=1;            //接收第九位,以判断是否发送成功delay_us(50);if(SCCB_READ_SDA)res=1;  //SDA=1发送失败,返回1else res=0;         //SDA=0发送成功,返回0SCCB_SCL=0;      SCCB_SDA_OUT();        //设置SDA为输出    return res;
}   

1.4、SCCB传输规则

一个基本传输单元称作一个相
一个相包含总共9比特,前8比特为数据,第9比特为 Don’t-Care bit (不关心比特),该第9比特的数据取决于传输任务是读还是写如果是写操作则don’t care,如果为读操作为NA。一个传输任务的最大相个数是3。
总结如下:
每一个单元组成:8位数据+don’t care/NA
如果是主机发送数据,即进行写操作,第九位就为don’t care(不关心比特)
如果是从机发送数据,即为读操作,第九位就为NA.

相1:主机向从机发送从机的ID号,SCCB协议支持一个主机和多个从机,因此这一个相目的是区分不同的从机,但如果我们只连接了一个从机时,也必须执行这样一个流程。实际上ID Address有8bit,其中bit7-bit1为从机的ID号,大小为0-127,一共能区分128个从机。OV2640的ID号为0x60。而bit0是用来区分对从机是写数据还是读数据,bit0=0代表写数据,bit0=1代表读数据,由于我们要向从机写数据,因此bit0应为0(0x60=01100000写入数据)。而相1中紧跟在ID Address这8位数据后的第九位是一个Don’t care bit(图中打X的位)。对于OV2640来说,从机在接收到主机送来的8bit数据后,将在SCL=1的期间,在SDA引脚输出低电平。在这期间,主机就可以读取SDA上的电平并进行判断,如果读取到低电平,表示从机已经顺利接收到了相1中的前8bit数据。说明数据传输成功,否则说明传输失败。

相2:主机向从机发送将要写入数据的寄存器的编号,寄存器的编号在OV传感器的数据手册上都能找到。寄存器的编号是一个8bit的数据。同样地,相2的第9bit也是一个Don’t care bit(图中打X的位),对该位的说明与相1相同
相3:前面两个相指定了数据传输的从机ID以及要写入数据的寄存器的编号,这时候在第三个相就可以向前面指定的寄存器写入数据了。bit7-bit0是我们希望写入寄存器的数据。而第9bit也是一个Don’t care bit(图中打X的位),对该位的说明与相1相同。
虽然每个相写入的数据不同,但其时序都是相同的,并且第九bit都是Don’t care bit

1.4.1、写寄存器值

写寄存器分三个阶段:写器件地址,写寄存器地址,写数据

//写寄存器
//返回值:0,成功;1,失败.
u8 SCCB_WR_Reg(u8 reg,u8 data)
{u8 res=0;SCCB_Start();                    //启动SCCB传输if(SCCB_WR_Byte(SCCB_ID))res=1;  //写器件ID   delay_us(100);if(SCCB_WR_Byte(reg))res=1;        //写寄存器地址      delay_us(100);if(SCCB_WR_Byte(data))res=1;   //写数据    SCCB_Stop();     return    res;
}   

1.4.2、读寄存器值

读寄存器分两次两个阶段

第一个阶段:写器件地址,写要读的寄存器地址
第二个阶段:写器件地址+1(表示读命令),读取数据,最后在发送NA信号

//读寄存器
//返回值:读到的寄存器值
u8 SCCB_RD_Reg(u8 reg)
{u8 val=0;SCCB_Start();                //启动SCCB传输SCCB_WR_Byte(SCCB_ID);        //写器件ID   delay_us(100);     SCCB_WR_Byte(reg);         //写寄存器地址      delay_us(100);      SCCB_Stop();   delay_us(100);    //设置寄存器地址后,才是读SCCB_Start();SCCB_WR_Byte(SCCB_ID|0X01);    //发送读命令   delay_us(100);val=SCCB_RD_Byte();            //读取数据SCCB_No_Ack();SCCB_Stop();return val;
}

二、SCCB代码部分

2.1、sccb.c

#include "sys.h"
#include "sccb.h"
#include "delay.h"//初始化SCCB接口
void SCCB_Init(void)
{               GPIO_InitTypeDef  GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//使能GPIOD时钟//GPIOF9,F10初始化设置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;//PD6,7 推挽输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  //PD6,7 推挽输出GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIO_SetBits(GPIOD,GPIO_Pin_6|GPIO_Pin_7);}            //SCCB起始信号
//当时钟为高的时候,数据线的高到低,为SCCB起始信号
//在激活状态下,SDA和SCL均为低电平
void SCCB_Start(void)
{SCCB_SDA_OUT();    SCCB_SDA=1;     //数据线高电平      SCCB_SCL=1;     //在时钟线高的时候数据线由高至低delay_us(50);  SCCB_SDA=0;delay_us(50);    SCCB_SCL=0;       //数据线恢复低电平,单操作函数必要
}//SCCB停止信号
//当时钟为高的时候,数据线的低到高,为SCCB停止信号
//空闲状况下,SDA,SCL均为高电平
void SCCB_Stop(void)
{SCCB_SDA_OUT();    SCCB_SDA=0;delay_us(50);    SCCB_SCL=1;   delay_us(50); SCCB_SDA=1;  delay_us(50);
}
//产生NA信号
void SCCB_No_Ack(void)
{delay_us(50);SCCB_SDA=1;  SCCB_SCL=1;    delay_us(50);SCCB_SCL=0;   delay_us(50);SCCB_SDA=0;   delay_us(50);
}
//SCCB,写入一个字节
//返回值:0,成功;1,失败.
u8 SCCB_WR_Byte(u8 dat)
{u8 j,res;   for(j=0;j<8;j++) //循环8次发送数据{if(dat&0x80)SCCB_SDA=1; else SCCB_SDA=0;dat<<=1;delay_us(50);SCCB_SCL=1;   delay_us(50);SCCB_SCL=0;          }             SCCB_SDA_IN();     //设置SDA为输入 delay_us(50);SCCB_SCL=1;            //接收第九位,以判断是否发送成功delay_us(50);if(SCCB_READ_SDA)res=1;  //SDA=1发送失败,返回1else res=0;         //SDA=0发送成功,返回0SCCB_SCL=0;      SCCB_SDA_OUT();        //设置SDA为输出    return res;
}
//SCCB 读取一个字节
//在SCL的上升沿,数据锁存
//返回值:读到的数据
u8 SCCB_RD_Byte(void)
{u8 temp=0,j;    SCCB_SDA_IN();        //设置SDA为输入  for(j=8;j>0;j--)    //循环8次接收数据{               delay_us(50);SCCB_SCL=1;temp=temp<<1;if(SCCB_READ_SDA)temp++;   delay_us(50);SCCB_SCL=0;}  SCCB_SDA_OUT();     //设置SDA为输出    return temp;
}
//写寄存器
//返回值:0,成功;1,失败.
u8 SCCB_WR_Reg(u8 reg,u8 data)
{u8 res=0;SCCB_Start();                    //启动SCCB传输if(SCCB_WR_Byte(SCCB_ID))res=1;  //写器件ID   delay_us(100);if(SCCB_WR_Byte(reg))res=1;        //写寄存器地址      delay_us(100);if(SCCB_WR_Byte(data))res=1;   //写数据    SCCB_Stop();     return    res;
}
//读寄存器
//返回值:读到的寄存器值
u8 SCCB_RD_Reg(u8 reg)
{u8 val=0;SCCB_Start();                //启动SCCB传输SCCB_WR_Byte(SCCB_ID);        //写器件ID   delay_us(100);     SCCB_WR_Byte(reg);         //写寄存器地址      delay_us(100);      SCCB_Stop();   delay_us(100);    //设置寄存器地址后,才是读SCCB_Start();SCCB_WR_Byte(SCCB_ID|0X01);    //发送读命令   delay_us(100);val=SCCB_RD_Byte();            //读取数据SCCB_No_Ack();SCCB_Stop();return val;
}

2.1、sccb.h

#ifndef __SCCB_H_
#define __SCCB_H_
#include "sys.h"//IO方向设置
#define SCCB_SDA_IN()  {GPIOD->MODER&=~(3<<(7*2));GPIOD->MODER|=0<<7*2;}    //PD7 输入
#define SCCB_SDA_OUT() {GPIOD->MODER&=~(3<<(7*2));GPIOD->MODER|=1<<7*2;}    //PD7 输出//IO操作函数
#define SCCB_SCL            PDout(6)        //SCL
#define SCCB_SDA            PDout(7)        //SDA    #define SCCB_READ_SDA      PDin(7)         //输入SDA
#define SCCB_ID             0X60            //OV2640的ID///
void SCCB_Init(void);
void SCCB_Start(void);
void SCCB_Stop(void);
void SCCB_No_Ack(void);
u8 SCCB_WR_Byte(u8 dat);
u8 SCCB_RD_Byte(void);
u8 SCCB_WR_Reg(u8 reg,u8 data);
u8 SCCB_RD_Reg(u8 reg);#endif

STM32F407--驱动OV2640采集图像数据,通过W5500传输至上位机---第一篇:OV2640简介及SCCB协议相关推荐

  1. (一)CCD传感器1000帧(可调)采集,fpga主控,sdram存储 68013usb2.0传输到上位机保存显示:项目介绍

    这是一个关于ccd图像采集到上位机的项目,从设计pcb到开发上位机,开发了很久.期间遇到了各种大大小小的坑,特此记录一下. 功能说明: 自己设置的帧率,通过上位机下发到fpga中,fpga控制ccd采 ...

  2. dtu无线 服务器端,4G DTU将数据无线方式上传上位机软件。服务器PC端扩展功能

    原标题:4G DTU将数据无线方式上传上位机软件.服务器PC端扩展功能 方案需求 工业生产很多生产商喜欢利用颜色检测工具来完成颜色评定和分析,一定要对色灯箱和测色仪这些颜色检测分析仪器才能正确的得到颜 ...

  3. 详细介绍如何从0开始写一个数据通信,将数据从单片机发送到上位机(或者虚拟示波器)进行数据或图像显示,以及常见问题或注意事项解答,本文主要以匿名上位机为例,适合新手和小白

      本文主要内容:详细介绍如何从0开始写一个数据通信,将数据从单片机发送到上位机(或者虚拟示波器)进行数据或图像显示,帮助我们调节一些参数,比如电机PID的调节.波形融合等,以及在我们写通信协议的时候 ...

  4. FPGA驱动FT601实现USB3.0相机HDMI视频采集 提供工程源码和QT上位机源码

    目录 1.前言 2.FT601芯片解读和时序分析 FT601功能和硬件电路 FT601读时序解读 FT601写时序解读 3.我这儿的 FT601 USB3.0通信方案 4.详细设计方案 5.vivad ...

  5. 采集温度数据,用串口传输到上位机

    这里写目录标题 一.实验要求 二.I2C总线通信协议 (一)概念 (二)I2C总线特征 (三)I2C总线协议 (四)I2C的两种方式--硬件I2C和软件I2C 三.AHT20采集温度并上传上位机 四. ...

  6. 多目千兆网工业相机同步采集(FPGA+DDR+千兆网+上位机)

    简介 公司新开发4目千兆网工业相机,4个sensor完全同步拍照,通过千兆网传输到电脑PC.满足某些需要使用多个相机但是空间窄小.无法使用多条网线.需要完全同步拍照等特殊需求.可用于航拍多摄像头,立体 ...

  7. (二)CCD传感器1000帧(可调)采集,fpga主控,sdram存储 68013usb2.0传输到上位机保存显示:fpga逻辑程序

    fpga这部分是花了大部分时间调试的,总结出来:比较难调试,调试方式单一 概述 fpga控制ccd传感器和ad转换芯片,从而获得ccd上所有阵列的电压数据,之后将数据存储在sdram中,然后控制680 ...

  8. 基于STM32根据DL/T 645-2007通讯协议利用RS485进行抄表并将电压等数据利用HC-05蓝牙实时传输至上位机显示

    RS485通讯类似串口通讯,本作品是利用金升阳RS485模块,MCU是STM32F103C8T6最小系统板,电能表是正泰单相电能表,RS485 A端接电能表 A端,B端接B端,RX接MCU的RX,TX ...

  9. Hadoop实战——MapReduce实现主播的播放量等数据的统计及TopN排序(第一篇)

    本次实战项目一共分三篇教学(二三篇后续更新) 第一篇:对主播文本数据的清洗,从大量数据中获取我们所需要的数据(如播放量,时长等) 第二篇:对清洗后的数据进行统计求和处理操作,按照主播id号依次整齐显示 ...

最新文章

  1. python笔记2(函数 面向对象 文件编程 上下文管理器)
  2. linux系统中离线安装python3.7过程记录
  3. 分数化成有限小数的方法_人教版六年级数学上册6.2百分数的换算微课视频辅导|课后练习...
  4. 安装oracle11g时,Enterprise Manager配置成功,出现以下警告……
  5. 【业务知识】企业数字档案馆总体架构图
  6. linux 高性能服务排查方式
  7. SAP Cloud for Customer Price-计价简介 1
  8. B+树索引和哈希索引
  9. luogu2320 鬼谷子的钱袋
  10. 【干货】2020十大消费新机遇.pdf(附下载链接)
  11. 实现一个二叉树层级遍历_算法总结:左神class5—二叉树递归和非递归实现遍历(后序用一个栈彩蛋)...
  12. 菜鸟的mybatis实战教程
  13. 超好用的开源 IP 地址管理系统,告别传统 Excel 统计方式!
  14. 测试5g网速的软件排行榜,2021网络测速app排行榜-手机网速测试软件推荐
  15. PT、CT、CVT各是什么意思?
  16. (MATLAB)错误使用 xlsread (line 260) 无法激活 Excel 工作表
  17. C++常见的预定义宏
  18. 百度图片时看到一张很眼熟,竟然是自己发的,这收录效率!
  19. 拜占庭将军问题OM算法详解(m=1,m=2)
  20. 验证arp的reply回答机制

热门文章

  1. linux ipv6内核编译,linux ipv6内核设置
  2. input输入框限制只能输入数字
  3. 关于10月11日中午余姚高铁区域水情
  4. git clone: error:RPC failed;result=18,HTTP code = 200 MiB | 2.00 KiB/s解决办法
  5. 鸿蒙系统注册谷歌账号
  6. UI进阶之多线程(GCD)
  7. 名帖117 文徵明 小楷《草堂十志》
  8. python的ols模型_pythonstatsmodels中缺少OLS回归模型的截取
  9. mes android开发平台,牛工厂MES系统专用手持移动安卓系统RFID终端PAD扫描枪-生产管理数据采集配套二次开发软件...
  10. 出租车收费计算方法_如何以正确的方式对网站收费