OV7670的SCCB协议

前记:
  众说周知,SCCB协议与IIC协议十分相似,不过IIC是PHILIPS的专利,所以OmnVision在IIC的基础上做了点小改动,然后你懂的。SCCB最主要是阉割了IIC的连续读写的功能,即每读写完一个字节就主机必须发送一个NA信号。

SCCB协议介绍

SCCB(Serial Camera Control Bus)是和I2C相同的一个协议,即串行摄像机控制总线。 SCCB协议有两线也有三线,两线为SIO_C与SIO_D,三线为SIO_E、SIO_C与SIO_D。2线的SCCB总线只能是一个主器件对一个从器件控制,但3线SCCB接口可以对多个从器件控制,因此当只有一个从机(slave device)时用两线,有多个从机时用三线。其中SIO_C只能由主机配置(FPGA),SIO_D是一个三态门,双向数据线,既可以由主机控制,也可以由从机控制。SIO_C和SIO_D分别为SCCB总线的时钟线和数据线。

OV公司为了减少传感器引脚的封装,现在SCCB总线大多采用两线式接口总线。OV7725使用的是两线式接口总线,该接口总线包括SIO_C串行时钟输入线和SIO_D串行双向数据线,分别相当于IIC协议的SCL信号线和SDA信号线。SIO_C的最小时间为10us,即最大频率为100K。一般来说,100K-400K之间都可以。

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

  1. 一主机多从机 也即3线操作:(通过控制使能端SCCB_E控制选中的从机)
  2. 一主一从 也即2线操作:(默认SCCB_E被拉低)

 三、协议的内容与程序实现
②两线SCCB总线协议分析:
<1>传输开始标志:每次传输(无论是读数据还是写数据),都要由主机操作总线,按时序图向SDA和SCL输出规定电平,这样从机在接收到相应电平时会知道数据的传输将要开始。传输开始的标志为:在SCL保持高电平期间,SDA完成高电平到低电平的转变,随后SCL恢复低电平。

          起始:SIO_C为高时,SIO_D由高拉低。

          停止:SIO_C为高时,SIO_D由低拉高

void SCCB_Start(void)
{
    SCCB_SDA=1;       //数据线为输出模式
    SCCB_SCL=1;	      //数据线高电平
    delay_us(50);     
    SCCB_SDA=0;
    delay_us(50);	 //并不是必须为50us,不要太短即可
    SCCB_SCL=0;	     //数据线恢复低电平,单操作函数必要
}

 <2>传输结束标志:
通知从机一次传输过程结束。标志:在SCL为高电平期间,SDA由低电平向高电平的转变

void SCCB_Stop(void)
{
    SCCB_SDA=0;
    delay_us(50);	 
    SCCB_SCL=1;	
    delay_us(50); 
    SCCB_SDA=1;	
    delay_us(50);
} 

 <3>传输相(Transmission Phases):
传输相是每次数据传输的一个基本单元。它由九个bit组成,其中高bit在前。第一位到第八位为bit7-bit0,第九位为Don’t care bit或NA bit。Don’t care bit及NA bit的具体含义将在下面介绍具体的相时介绍。而第九位究竟是Don’t care bit还是NA bit是由传输相的内容决定的,不同的相有不同的规定,也将在下面介绍具体的每一个相时进行说明。
<4>写操作:
每向从机写一个字节数据称为一次写操作,但要向从机写入我们想要的一个字节数据前,还要告诉从机ID号是多少,将要写入数据的寄存器编号(Sub-Address)是多少,因此写操作的一个过程由三个相(Phase)组成。

相1:向从机发送从机的ID号,SCCB协议支持一个主机和多个从机,因此这一个相是为了区分不同的从机,但如果我们只连接了一个从机时,也必须执行这样一个过程。实际上ID Address有8bit,其中bit7-bit1为从机的ID号,大小为0-127,一共能区分128个从机。OV7670的ID号为0x42。而bit0是用来区分该相所在的cycle是向从机写数据还是读数据,bit0=0代表写数据,bit0=1代表读数据,由于我们要向从机写数据,因此bit0应为0。而相1中紧跟在ID Address这8位数据后的第九位是一个Don’t care bit(图中打X的位)。对于OV7670来说,从机在接收到主机送来的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。因此可以把每个相的写入编写成一个函数,如下:
 

u8 SCCB_WR_Byte(u8 dat)//写1个相
{
	u8 j,res;	 
	for(j=0;j<8;j++) //循环发送bit7-bit0
	{
		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;			//将SCL置1,此时如果数据已被从机接收,从机将把SDA置0
	delay_us(50);
	if(SCCB_READ_SDA)res=1;  //SDA置1,说明从机没有成功接收数据
	else res=0;         //发送成功
	SCCB_SCL=0;		 
	SCCB_SDA_OUT();		//设置SDA为输出,为下一个相的输出作准备  
	return res;  
}	

根据上面写操作的说明,每向从机的某一个寄存器写一个字节的数据都要完成3个相的数据传输,将这3个相的数据写入过程编写成一个写寄存器函数。

u8 SCCB_WR_Reg(u8 reg,u8 data)
{
	u8 res=0;
	SCCB_Start(); 					//启动传输的标志
	if(SCCB_WR_Byte(SCCB_ID))res=1;	//写入OV7670传感器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;
}		

<5>读操作:
根据SCCB协议,要从从机的寄存器读取一个字节的数据,需要完成两次数据传输过程:①包含两个相的写过程(2-Phase Write Transmission Cycle)②包含两个相的读过程(2-Phase Read Transmission Cycle)下面分别介绍:
①两相写传输过程:这个过程包含了两个相,均由主机发送给从机。第一个相指明从机的ID号。第二个相指明将要从从机的哪个寄存器读取数据。这些相各个bit的含义与上面写操作介绍过的含义是一致的。
②两相读传输过程:
上面一个传输过程告诉从机做好准备,主机将要读取数据了。而这一个传输过程则是真正的从从机读取数据。它也包含了两个相。

相1:与上面相1的定义是一致的。但需要注意的是,此时是从从机读取数据,因此bit0应设置为1,可以用SCCB_ID|0x01(SCCB_ID是从机ID号的宏)来得到。
相2:从机向主机发送数据。因此应把主机连接SDA的IO口设置为输入模式。读取八个字节后,为了告诉从机已经成功收到数据,主机应向从机发送一个bit的应答信号(NA)。这个信号的时序定义如下:
这个应答信号需要主机将SDA先拉高,然后在SDA高电平期间,将SCL由原来的低电平变为高电平再变为低电平。实现NAbit的代码如下

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);
}

我们可以把相2中读取bit7-bit0的数据封装成一个函数

u8 SCCB_RD_Byte(void)
{
	u8 temp=0,j;    
	SCCB_SDA_IN();		//设置主机SDA连接的IO口为输入
	for(j=8;j>0;j--) 	//循环读取bit7-bit0
	{		     	  
		delay_us(50);
		SCCB_SCL=1;
		temp=temp<<1;
		if(SCCB_READ_SDA)temp++;   //SCCB_READ_SDA是从IO口读到的数据
		delay_us(50);
		SCCB_SCL=0;
	}	
	SCCB_SDA_OUT();		//将主机连接SDA的IO口设置为输出  
	return temp;
} 

有了以上的两个函数,再借助我们先前编写的写一相数据的u8 SCCB_WR_Byte(u8 dat)
函数,我们就可以编写一个完成整个读操作的函数

u8 SCCB_RD_Reg(u8 reg)
{
	u8 val=0;
    //对应两相写操作
	SCCB_Start(); 				//启动传输
	SCCB_WR_Byte(SCCB_ID);  //相1		  
	delay_us(100);	 
  	SCCB_WR_Byte(reg);	   //相2  
	delay_us(100);	  
	SCCB_Stop();             //结束传输
	delay_us(100);	   
	//对应两相读操作
	SCCB_Start();            //启动传输
	SCCB_WR_Byte(SCCB_ID|0X01);	  //相1
	delay_us(100);
  	val=SCCB_RD_Byte();		 //相2
  	SCCB_No_Ack();            //读取完8bit数据后的应答
  	SCCB_Stop();              //结束传输
  	return val;
}

至此我们已经实现了SCCB的读寄存器和写寄存器操作的函数SCCB_RD_Reg和SCCB_WR_Reg。调用这两个函数就可以实现向OV传感器指定寄存器读写数据,从而完成传感器的初始化工作。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、SCCB协议简述 SCCB协议有两线也有三线,两线为SIO_C与SIO_D,三线为SIO_E、SIO_C与SIO_D。 2线的SCCB总线只能是一个主器件对一个从器件控制,但3线SCCB接口可以对多个从器件控制,因此当只有一个从机(slave device)时用两线,有多个从机时用三线。 其中SIO_C只能由主机配置(FPGA),SIO_D是一个三态门,双向数据线,既可以由主机控制,也可以由从机控制。 2、数据传输 当写数据到从机被定义为写传输(write transmission),当从机中读数据被定义为读传输 (read transmission),每一个传输都要有开始和结束来释放总线(start + sotp) 完整的数据传输包括两个或三个阶段,每一个阶段包含9位数据,其中高8位为所要传输的数据,最低位根据器件所处情况有不同的取值: 总结如下: 每一个阶段组成:8位数据+don't care/NA 如果是主机发送数据,即进行写操作,第九位就为don't care 如果是从机发送数据,即为读操作,第九位就为NA. 在进行主器件写操作时,全部阶段的最低位均是Don’t care bit 在进行主器件读操作时,第一阶段的最低位是自由位,第二阶段的最低位为NA,请结合第三部分好好理解 3、SCCB的读写操作 写操作是三个阶段构成一个传输的写,每一阶段都是9位,具体如下 ID地址(7位ID地址+1位读写控制+don't care) + 要写的寄存器地址(8位寄存器地址+don't care) +要写入的数据(8位数据+don't care) 要强调的是ID地址,写为8'h42,读为8'h42 , 8'h42即ID地址的读写控制位为0,8'h43即ID地址的读写控制位为1 总结为: start + ID地址(42)+ 寄存器地址 + 数据 + stop
OV7670是一款CMOS图像传感器,它通过SCCB总线与单片机进行通信。SCCB是一种简化版的I2C总线,它只需要两根线(时钟线和数据线)即可实现设备之间的通信。下面是OV7670通信协议的步骤: 1.初始化SCCB总线,包括设置时钟线和数据线的方向、上拉电阻等参数。 2.写入设备地址和寄存器地址,设备地址为0x42,寄存器地址根据需要进行设置。 3.写入寄存器数据,根据需要进行设置。 4.读取寄存器数据,根据需要进行设置。 5.结束通信。 下面是一个简单的OV7670初始化代码示例: ```c void SCCB_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); SCCB_SDA_H; SCCB_SCL_H; } void SCCB_WriteByte(uint8_t WriteAddress, uint8_t SendByte) { uint8_t i; SCCB_Start(); SCCB_SendByte(WriteAddress); for (i = 0; i < 8; i++) { if (SendByte & 0x80) SCCB_SDA_H; else SCCB_SDA_L; SCCB_SCL_L; SCCB_SCL_H; SendByte <<= 1; } SCCB_Stop(); } void SCCB_ReadByte(uint8_t WriteAddress, uint8_t *pBuffer) { uint8_t i; SCCB_Start(); SCCB_SendByte(WriteAddress); for (i = 0; i < 8; i++) { pBuffer <<= 1; SCCB_SCL_L; if (SCCB_SDA_READ) pBuffer |= 0x01; SCCB_SCL_H; } SCCB_Stop(); } void OV7670_Init(void) { SCCB_Init(); SCCB_WriteByte(0x12, 0x80); // Reset the camera delay_ms(100); SCCB_WriteByte(0x12, 0x00); // Enable the camera delay_ms(100); SCCB_WriteByte(0x3a, 0x04); // UYVY SCCB_WriteByte(0x40, 0xd0); // Set the brightness SCCB_WriteByte(0x3e, 0x00); // Set the sharpness SCCB_WriteByte(0x13, 0xe0); // Set the gamma SCCB_WriteByte(0x00, 0x00); // Set the gain SCCB_WriteByte(0x10, 0x00); // Set the exposure SCCB_WriteByte(0x11, 0x80); // Set the exposure SCCB_WriteByte(0x3d, 0x38); // Set the color matrix SCCB_WriteByte(0x17, 0x16); // Set the horizontal mirror SCCB_WriteByte(0x18, 0x04); // Set the vertical flip SCCB_WriteByte(0x32, 0x80); // Set the test pattern SCCB_WriteByte(0x29, 0x3f); // Set the edge enhancement SCCB_WriteByte(0x33, 0x00); // Set the special effects SCCB_WriteByte(0x3c, 0x78); // Set the brightness SCCB_WriteByte(0x3f, 0x00); // Set the contrast SCCB_WriteByte(0x75, 0x05); // Set the pixel clock SCCB_WriteByte(0x76, 0xe1); // Set the PLL SCCB_WriteByte(0x77, 0x0b); // Set the PLL SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter SCCB_WriteByte(0x3b, 0x0a); // Set the banding filter } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值