STM32学习笔记---SCCB摄像头协议

介绍

SCCB(OmniVision serial camera control bus),即串行摄像机控制总线。OmniVision 公司已经定义和采纳的SCCB总线是一种三线结构的串行总线,用于完成对绝大多数OmniVision 系列图像传芯片功能的控制。它与IIC协议类似,但是不完全相同。
SCCB协议有两线也有三线的,两线的只能有一个主机一个从机,三线的可以有一个主机多个从机。在STM32的例程里用的是两线的,以下的时序是三线,在使用两线时只需要忽略SCCB_E就可以了,其他时序都是一样的。

与IIC的区别

1、SCCB是简化的I2C协议,SIO-l是串行时钟输入线,SIO-O是串行双向数据线,分别相当于I2C协议的SCL和SDA。
2、SCCB的总线时序与I2C基本相同,它的响应信号ACK被称为一个传输单元的第9位,分为Don’t care和NA。Don’t care位由从机产生;NA位由主机产生,由于SCCB不支持多字节的读写,NA位必须为高电平。
3、SCCB没有重复起始的概念,因此在SCCB的读周期中,当主机发送完片内寄存器地址后,必须发送总线停止条件。不然在发送读命令时,从机将不能产生Don’t care响应信号。
4、SCCB的写周期直接使用I2C总线协议的写周期时序;而SC-CB的读周期,则增加一个总线停止条件。
5、SCCB总线通信协议只支持100Kb/s或400Kb/s的传输速度。

引脚介绍

SCCB_E:输出(主机发出,单向),低电平有效,总线空闲时主机驱动此引脚为1,驱动为0时表示开始传输。
SIO_C:输出(主机发出,单向),总线空闲时主机驱动此引脚为1;当驱动SIO_E为0时,主机驱动此引脚为0或1;当挂起时主机驱动SIO_C为0,相当于时钟线。
SIO_D:IO口(双向),用于传输数据,当总线空闲时保持浮动,当系统挂起时保持低电平。
PWDN:输出(主机发出,单向),挂起引脚,当从机接受PWDN为0时,系统进入挂起状态。

具体时序图

1、如何传输一相数据

SCCB 3线时序图—总图
STM32学习笔记---SCCB摄像头协议_第1张图片
在不进行传输时 SCCB_E 与 SIO_C 处于高电平,SIO_D 处于高阻态

SCCB 3线时序图—开始时序图
STM32学习笔记---SCCB摄像头协议_第2张图片
将SIO_D和SIO_C拉高
将SCCB_E拉低
1.25us后将SIO_D拉低
50us后将SIO_C拉低
完成起始信号

SCCB 3线时序图—结束时序图
STM32学习笔记---SCCB摄像头协议_第3张图片
拉低SIO_D、拉高SIO_C
拉高SIO_D
0~1ns后拉高SCCB_E
SCCB_E维持高电平15ns
完成结束时序

先发送起始信号,而后 SIO_D 的数据在SIO_C处于低电平时改变,在SIO_C处于高电平时被传输,如此发送一相数据后,紧跟着发送结束信号,完成一相数据的传输。

2、发送什么样的数据

首先要说的是,一相包含9bit数据,8bit的数据和1bit的控制位。对OV摄像头寄存器进行配置的写操作需要三相,对其进行读取的读操作需要四相。

先介绍一下配置寄存器的 写操作:(最重要也是最有用的)
STM32学习笔记---SCCB摄像头协议_第4张图片
STM32学习笔记---SCCB摄像头协议_第5张图片
写操作需要传输三相数据,第一相为OV摄像头设备ID地址,第二相为所要配置的寄存器地址,第三相为所要写入的数据。尤其需要重视的是,设备ID地址只占7位,从D7到D1,第一相写设备ID地址的第8位数据是读写控制位R/W,0表示写,1表示读。
STM32学习笔记---SCCB摄像头协议_第6张图片
之后是配置寄存器的 读操作:
读操作由二相写操作和二相读操作构成,先进行二相写操作,向从机发送要读的寄存器地址,而后进行二相读操作,从机会把寄存器的值放在读操作的第二相中。二相写操作,其数据传输时序与三相写操作相同;二相读操作,所要注意的是,在读取数据后,主机要在第9个时钟低电平期间拉高数据线SIO_D,发送不应答信号NA。
STM32学习笔记---SCCB摄像头协议_第7张图片
STM32学习笔记---SCCB摄像头协议_第8张图片
不关心位:
写数据操作的一相数据的第9位为不关心位,它的目的是保证数据的完整性,其值为0表示数据发送成功,由从机发出,主机接收。
NA位
读数据操作的一相数据的第9位为NA位,其值应该为1,主机发出。

硬件连接

1、一个主机一个从机
STM32学习笔记---SCCB摄像头协议_第9张图片
2、一个主机多个从机
此时应该与IIC一样,各从机并联,并保持SIO_D的电阻,该电阻保证了总线争用时不会发生短路。
STM32学习笔记---SCCB摄像头协议_第10张图片

挂起模式(低功耗)

有的摄像头具有挂起模式功能,对于OV系列来说挂起功能由引脚PWDN控制,在主机将PWDN拉低,随后50ns将SCCB_E、SIO_D、SIO_C 三个拉低,从机进入挂起状态。之后的唤醒需要先拉高SCCB_E、SIO_D、SIO_C ,50ns之后拉高PWDN。
STM32学习笔记---SCCB摄像头协议_第11张图片

STM32程序

#define SCCB_SCL    		PDout(3)	 	//SCL
#define SCCB_SDA    		PGout(13) 		//SDA	 

#define SCCB_SDA_IN()  {GPIOG->CRH&=0XFF0FFFFF;GPIOG->CRH|=0X00800000;}
#define SCCB_SDA_OUT() {GPIOG->CRH&=0XFF0FFFFF;GPIOG->CRH|=0X00300000;}

#define SCCB_SCL    		PDout(3)	 	//SCL
#define SCCB_SDA    		PGout(13) 		//SDA	 

#define SCCB_READ_SDA    	PGin(13)  
#define SCCB_ID   			0X42 

//初始化SCCB接口
//CHECK OK
void SCCB_Init(void)
{											   
	RCC->APB2ENR|=1<<8;//使能PORT G时钟   
  	RCC->APB2ENR|=1<<5;//使能PORT D时钟
	//PORTG13 IN	
	GPIOG->CRH&=0XFF0FFFFF;
	GPIOG->CRH|=0X00800000;    
	GPIOG->ODR|=1<<13; 	
	//PD3 OUT  
	GPIOD->CRL&=0XFFFF0FFF;
	GPIOD->CRL|=0X00003000;    
	GPIOD->ODR|=1<<3;  
	SCCB_SDA_OUT();	   
}			 

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

//SCCB停止信号
//当时钟为高时,数据线由低到高,为停止信号
//在空闲状态下,SDA与SCL均为高电平
void SCCB_Stop(void)
{
    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表示成功
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();
	delay_us(50);
	SCCB_SCL=1;//接收第9位,判断是否发送成功
	delay_us(50);
	if(SCCB_READ_SDA)res=1;  //SDA=1发送失败
	else res=0;         //SDA=0发送成功
	SCCB_SCL=0;		 
	SCCB_SDA_OUT();
	return res;  
}	 
//SCCB 读取一个字节
//在SCL的上升沿,数据锁存
//返回值:读到的数据
u8 SCCB_RD_Byte(void)
{
	u8 temp=0,j;    
	SCCB_SDA_IN();
	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();
	return temp;
} 							    
//写寄存器
//返回值:0成功
u8 SCCB_WR_Reg(u8 reg,u8 data)
{
	u8 res=0;
	SCCB_Start(); //起始信号
	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_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(); //发送NA
  	SCCB_Stop(); //停止信号  
  	return val;
}

你可能感兴趣的:(软件代码,STM32笔记)