现在想用2103驱动摄像头并对所得图片进行图像分析,但是一直驱动不了摄像头,7670是带fifo的,我这里有STM32的例程,仿照实现SCCB时序,对0v7670的寄存器进行设置,代码感觉没什么问题,一直不能对寄存器设置和读取。我是 用一般gpio做为SDA,和SCL的这个有什么特殊要求吗,比如必须上拉
附上仿写的代码:
//初始化OV7670
//返回0:成功
//返回其他值:错误代码
uint8 OV7670_Init(void)
{
uint8 temp;
uint16 i=0;
PINSEL1=0x00000000; //16~31设置为gpio口
IO0DIR=0x01f00000; //p020,p021,p022,p023,p024设置为gpio输出
SCCB_Init(); //初始化SCCB 的IO口
if(SCCB_WR_Reg(0x12,0x80))
return 1; //复位SCCB
delay_ms(50);
//读取产品型号
temp=SCCB_RD_Reg(0x0b);
if(temp!=0x73)
return 2;
temp=SCCB_RD_Reg(0x0a);
if(temp!=0x76)
return 2;
//初始化序列
for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0]);i++)
{
SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);
delay_ms(2);
}
return 0; //ok
}
//初始化SCCB接口
//CHECK OK
void SCCB_Init(void)
{
PINSEL0= 0x00000000;
IO0DIR|= 0x00000030; //p0.4,p0.5设置为输出
}
//SCCB起始信号
//当时钟为高的时候,数据线的高到低,为SCCB起始信号
//在激活状态下,SDA和SCL均为低电平
void SCCB_Start(void)
{
IO0SET=SCCB_SDA; //数据线高电平
IO0SET=SCCB_SCL; //在时钟线高的时候数据线由高至低
delay_us(50);
IO0CLR=SCCB_SDA;
delay_us(50);
IO0CLR=SCCB_SCL; //数据线恢复低电平,单操作函数必要
}
//SCCB停止信号
//当时钟为高的时候,数据线的低到高,为SCCB停止信号
//空闲状况下,SDA,SCL均为高电平
void SCCB_Stop(void)
{
IO0CLR=SCCB_SDA;
delay_us(50);
IO0SET=SCCB_SCL;
delay_us(50);
IO0SET=SCCB_SDA;
delay_us(50);
}
//产生NA信号
void SCCB_No_Ack(void)
{
delay_us(50);
IO0SET=SCCB_SDA;
IO0SET=SCCB_SCL;
delay_us(50);
IO0CLR=SCCB_SCL;
delay_us(50);
IO0CLR=SCCB_SDA;
delay_us(50);
}
//SCCB,写入一个字节
//返回值:0,成功;1,失败.
uint8 SCCB_WR_Byte(uint8 dat)
{
uint8 j,res;
for(j=0;j<8;j++) //循环8次发送数据
{
if(dat&0x80)IO0SET=SCCB_SDA;
else IO0CLR=SCCB_SDA;
dat<<=1;
delay_us(50);
IO0SET=SCCB_SCL;
delay_us(50);
IO0CLR=SCCB_SCL;
}
SCCB_SDA_IN(); //设置SDA为输入
delay_us(50);
IO0SET=SCCB_SCL; //接收第九位,以判断是否发送成功
delay_us(50);
if(SCCB_READ_SDA)
res=1; //SDA=1发送失败,返回1
else res=0; //SDA=0发送成功,返回0 (低电平的应答信号)
IO0CLR=SCCB_SCL;
SCCB_SDA_OUT(); //设置SDA为输出
return res;
}
//SCCB 读取一个字节
//在SCL的上升沿,数据锁存
//返回值:读到的数据
uint8 SCCB_RD_Byte(void)
{
uint8 temp=0,j;
SCCB_SDA_IN(); //设置SDA为输入
for(j=8;j>0;j--) //循环8次接收数据
{
delay_us(50);
IO0SET=SCCB_SCL;
temp=temp<<1;
if(SCCB_READ_SDA)temp++;
delay_us(50);
IO0CLR=SCCB_SCL;
}
SCCB_SDA_OUT(); //设置SDA为输出
return temp;
}
//写寄存器
//返回值:0,成功;1,失败.
uint8 SCCB_WR_Reg(uint8 reg,uint8 data)
{
uint8 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;
}
//读寄存器
//返回值:读到的寄存器值
uint8 SCCB_RD_Reg(uint8 reg)
{
uint8 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;
}
自己调试了下,程序是运行到
if(temp!=0x73)
return 2;
这里跳出去的,说明没有读到寄存器值 |