void sccb_isda () //设置输入为高阻
{
//sbit SCCB_SDA = P0^4; // 数 据 线
//sbit SCCB_SCL = P0^6; // 时 钟 线
P0M1=0x04; /* 0001 0000 <第五位>*/
P0M0=0x40; /* 0100 0000 <第五位>*/
}
void sccb_osda () //设置输入为高阻
{
//sbit SCCB_SDA = P0^4; // 数 据 线
//sbit SCCB_SCL = P0^6; // 时 钟 线
P0M1=0x00; /* 0000 0000 */
P0M0=0x14; /* 0001 1000 */
}
//SCCB起始信号
//当时钟为高的时候,数据线的高到低,为SCCB起始信号
//在激活状态下,SDA和SCL均为低电平
void SCCB_Start(void)
{
sccb_osda (); //设定为输出模式
SCCB_SCL=1; // 在 时 钟 线 高 的 时 候 数 据 线 由 高 至 低
SCCB_SDA=1; //数据线电平拉高
Delay_US (5); //持续时间最少1.5US
SCCB_SDA=0; // 数据线电平置为低
Delay_US (5); //持续时间最少1.5US
SCCB_SCL=0; //数据线恢复低电平,单操作函数必要
}
//SCCB停止信号
//当时钟为高的时候,数据线的低到高,为SCCB停止信号
//空闲状况下,SDA,SCL均为高电平
void SCCB_Stop(void)
{
sccb_osda (); //设定为输出模式
SCCB_SCL=0;
SCCB_SDA=0;
Delay_US (5);
SCCB_SCL=1;
Delay_US (50); //持续时间最少1.5US
SCCB_SDA=1;
Delay_US (50);
}
//产生NA信号
void SCCB_No_Ack(void)
{
sccb_osda (); //设定为输出模式
SCCB_SDA=1;
SCCB_SCL=1;
Delay_US (50);
SCCB_SCL=0;
SCCB_SDA=0;
}
//SCCB,写入一个字节
//返回值:0,成功;1,失败.
INT8U SCCB_WR_Byte(INT8U dat)
{
INT8U j,res;
sccb_osda (); //设定为输出模式
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;
}
Delay_US (10);
sccb_isda (); /*设定为输入模式*/
SCCB_SCL=1; //接收第九位,以判断是否发送成功
Delay_US (5000);
if(SCCB_SDA)res=1; //SDA=1发送失败,返回1
else res=0; //SDA=0发送成功,返回0
Delay_US (10);
SCCB_SCL=0;
return res;
}
//SCCB 读取一个字节
//在SCL的上升沿,数据锁存
//返回值:读到的数据
INT8U SCCB_RD_Byte(void)
{
INT8U temp=0,j;
/*设定为输入模式*/
sccb_isda ();
for(j=8;j>0;j--) //循环8次接收数据
{
Delay_US (10);
SCCB_SCL=1;
temp=temp<<1;
Delay_US (10);
if(SCCB_SDA==1)temp++;
else temp|=0x00;
Delay_US (10);
SCCB_SCL=0;
}
return temp;
}
//写寄存器
//返回值:0,成功;1,失败.
INT8U SCCB_WR_Reg(INT8U reg,INT8U Data)
{
INT8U res=0; //返回值的记录
SCCB_Start(); //启动SCCB传输
if(SCCB_WR_Byte(SCCB_ID))res=1; //写器件ID 判断是否写入成功
/*如果写入成功返回【0】,如果写入不成功则是返回【1】*/
Delay_US (300);
if(SCCB_WR_Byte(reg))res=2; //写寄存器地址
Delay_US (300);
if(SCCB_WR_Byte(Data))res=3; //写数据
SCCB_Stop();
return res;
}
//读寄存器
//返回值:读到的寄存器值 ///////////////////////
INT8U SCCB_RD_Reg(INT8U reg)
{
INT8U val=0;
INT8U flag=0;
SCCB_Start(); //启动SCCB传输
Delay_US (50);
if(SCCB_WR_Byte(0X42))return 0x21; //表示写入数据
Delay_US (50);
if(SCCB_WR_Byte(reg)) return 0x22; //地址是否错误
Delay_US (300);
SCCB_Stop();
Delay_US (100);
//设置寄存器地址后,才是读
SCCB_Start();
Delay_US (100);
// do{
// flag = SCCB_WR_Byte(0X43); // 发 送 读 命 令
/*写入成功返回【0】*/
/*写入失败返回【1】*/
/*判断 什么时候返回0;否则一直写下去*/
// }while(flag!=0);
if(SCCB_WR_Byte(0X43))return 0x23; /*发送读取寄存器的指令*/
Delay_US (300);
val=SCCB_RD_Byte(); //读取数据
SCCB_No_Ack();
SCCB_Stop();
return val;
}
/*复位SCCB总线*/
/*返回值类型:对应上表*/
/*返回:错误,正确 0,1,*/
INT8U Init_SCCB (void)
{
if(SCCB_WR_Reg(0x12,0x80)) /*0X12通用控制位 0X80复位总线 返回0表示写入成功*/
return SCCB_INIT_ERROR; //复位SCCB; //
else
return SCCB_INIT_OK ; //复位SCCB 返回0表示初始化成功
}
INT8U Init_OVCamer (void)
{
INT8U temp=0;
if(Init_SCCB ()!=0) /*复位SCCB总线*/
{
return SCCB_ERROR ; /*错误直接返回【3】*/
}
/*读取产品型号 */
temp=SCCB_RD_Reg(0x0B);
//if(SCCB_RD_Reg(0x0a)!=0x73)
//return ID_ERROR; /*错误返回【4】*/
//return SCCB_RD_Reg(0x0a);
//temp=temp;
//if(SCCB_RD_Reg(0x0a)!=0x76)
//{
//return OV_RETURN1; //0x76
//}
return temp;//SCCB_OK; /*正确返回【0】*/
}
这是代码
问题是:每次到了读取器件ID 都是返回一个写入不成功。这是为什么呢?摄像头是没有问题的,我在STM32上用一点问题也没有!temp=SCCB_RD_Reg(0x0B);
这一句的返回值有21H 22H 23H
21H:表示-设定为写入,错误
22H:表示-写入地址, 错误
23H:表示-设定为读取,错误
有老师做过这种东西么?求教! |