OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6048|回复: 5

ov7670无法读寄存器

[复制链接]

2

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2015-3-4
在线时间
0 小时
发表于 2015-3-4 21:17:32 | 显示全部楼层 |阅读模式
5金钱
我用的mini板+第三方的摄像头,想先试试SCCB有没有写对,ov7670只接了VCC、GND、SIO_C、SIO_D(SCL和SDA都接了4.7k上拉电阻),把RESET接3.3V(我看文档是低电平复位)。
程序是在别人写的基础上修改了一些。
SIOC接PB2,SIOD接PB3
[mw_shl_code=c,true]void SCCB_Init(void); void SCCB_Start(void); void SCCB_Stop(void); u8 SCCB_ReadByte(void); unsigned char SCCB_WriteByte(unsigned char write_data); u8 SCCB_WR_Reg(u8 SlaveAddr, u8 reg, u8 data); u8 SCCB_RD_Reg(u8 SlaveAddr, u8 reg); #define SCCB_ID 0x42//OV7670的ID #define SCCB_SEND_ACK (0x10) #define SCCB_SEND_NACK (0x11) #define SCCB_STATE_NACK (0x20) #define SCCB_STATE_ACK (0x21) #define SCCB_SCL PBout(2) //SCL #define SCCB_SDA PBout(3) //SDA //SDA方向设置 #define SCCB_SID_IN() {GPIOB->CRL&=0XFFFF0FFF;GPIOB->CRL|=4<<12;} #define SCCB_SID_OUT() {GPIOB->CRL&=0XFFFF0FFF;GPIOB->CRL|=3<<12;}//0011 //IO操作函数 #define SCCB_SDA_READ PBin(3) //输入SDA int main(void) { NVIC_Configuration(); delay_init(); uart_init(9600); //串口初始化为9600 LED_Init(); //初始化与LED连接的硬件接口 SCCB_Init(); SCCB_WR_Reg(SCCB_ID,0x12,0x80); //软复位OV7670 delay_ms(50); while(1) { printf( "Product ID Number MSB (Read only) %x Default=0x76\r\n",(int)SCCB_RD_Reg(SCCB_ID, 0x0a)); delay_ms(3); printf(" Product ID Number LSB (Read only) %x Default=0x60\r\n",(int)SCCB_RD_Reg(SCCB_ID, 0x0b)); delay_ms(3000); LED0=!LED0; } } void SCCB_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;//SCCB,SCL->B2, SDA->B3 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_10;//SCCB,SCL->B2, SDA->B3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); SCCB_SCL=1; delay_us(20); SCCB_SDA=1; delay_us(20); } /********************************************************** 启动子程序 在 SCL 高电平期间 SDA 发生负跳变【从高到低】 **********************************************************/ void SCCB_Start(void) { SCCB_SDA=1; delay_us(200); SCCB_SCL=1; delay_us(200); SCCB_SDA=0; delay_us(200); SCCB_SCL=0; delay_us(200); } /********************************************************** 停止子函数 在 SCL 高电平期间 SDA 发生正跳变 【从低到高】 **********************************************************/ void SCCB_Stop(void) { SCCB_SDA=0; delay_us(200); SCCB_SCL=1; delay_us(200); SCCB_SDA=1; delay_us(200); } //SCCB非应答信号 void noAck(void) { SCCB_SDA=1; delay_us(200); SCCB_SCL=1; delay_us(200); SCCB_SCL=0; delay_us(200); SCCB_SDA=0; delay_us(200); } /********************************************************** //读一字节 ack: SCCB_SEND_ACK 时应答,SCCB_SEND_NACK 时不应答 **********************************************************/ u8 SCCB_ReadByte(void) { u8 i = 0; u8 Read_Data=0; SCCB_SID_IN();//设置SDA为输入 delay_us(200); for(i=0;i<8;i++) // 循环移入8个位 { delay_us(200);//此处延时很关键,否则读取数据失败 SCCB_SCL=1; delay_us(200);//此处延时很关键,否则读取数据失败 Read_Data <<= 1; delay_us(2); if(SCCB_SDA_READ) //读SDA { Read_Data++; } SCCB_SCL=0; delay_us(200);//此处延时很关键,否则读取数据失败 } SCCB_SID_OUT();//设置SDA为输出 delay_us(200); return (Read_Data); } /********************************************************** //向总线写一字节,并返回有无应答 **********************************************************/ unsigned char SCCB_WriteByte(unsigned char write_data) { unsigned char i; for(i=0;i<8;i++) { if((write_data<<i) & 0x80) SCCB_SDA=1; else SCCB_SDA=0; delay_us(200); SCCB_SCL=1; //置时钟线为高,通知被控器开始接收数据位 delay_us(200); SCCB_SCL=0; delay_us(200); } delay_us(10); SCCB_SID_IN(); //设置SDA为输入 delay_us(200); SCCB_SCL=1; delay_ms(3); i=0; while((SCCB_SDA_READ == 1) && (i<250))//如果SCCB_SDA=1,表示被控器无应答或损坏 { i++; //计时开始, if(i==249) //如果计时到了249,器件还没有应答则自动退出 { SCCB_SCL=0; delay_us(200); SCCB_SID_OUT();//设置SDA为输出 return (SCCB_STATE_NACK); } } SCCB_SCL=0; delay_us(200); SCCB_SID_OUT();//设置SDA为输出 return (SCCB_STATE_ACK); } //写寄存器 //返回值:SCCB_STATE_ACK->成功; SCCB_STATE_NACK->失败. u8 SCCB_WR_Reg(u8 SlaveAddr, u8 reg, u8 data) { SCCB_Start();//启动SCCB传输 //res=SCCB_WriteByte(SCCB_ID); //写器件ID 0x42 if(SCCB_STATE_NACK == SCCB_WriteByte(SlaveAddr)) { SCCB_Stop(); return SCCB_STATE_NACK; } delay_us(100); //res=SCCB_WriteByte(reg); if(SCCB_STATE_NACK == SCCB_WriteByte(reg)) { SCCB_Stop(); return SCCB_STATE_NACK; } delay_us(100); //res=SCCB_WriteByte(data); if(SCCB_STATE_NACK == SCCB_WriteByte(data)) { SCCB_Stop(); return SCCB_STATE_NACK; } SCCB_Stop(); return SCCB_STATE_ACK; } //读寄存器 //返回值:读到的寄存器值 u8 SCCB_RD_Reg(u8 SlaveAddr, u8 reg) { u8 val=0; SCCB_Start();//启动SCCB传输 if(SCCB_STATE_NACK == SCCB_WriteByte(SlaveAddr)) { SCCB_Stop(); return SCCB_STATE_NACK; } delay_us(100); if(SCCB_STATE_NACK == SCCB_WriteByte(reg)) { SCCB_Stop(); return SCCB_STATE_NACK; } SCCB_Stop(); delay_us(100); //设置寄存器地址后,才是读 SCCB_Start(); if(SCCB_STATE_NACK == SCCB_WriteByte(SlaveAddr | 0x01)) //发送读命令 { SCCB_Stop(); return SCCB_STATE_NACK; } delay_us(100); val = SCCB_ReadByte(); //读取数据 noAck();//发送NACK命令 SCCB_Stop(); return val; } [/mw_shl_code]
按照文档读0x0a应该返回0x76读0x0b返回0x60,可是我得到的不是0x00就是0x32,应该是没读成功。
然后我烧了原子哥的摄像头例程,(因为没有fifo,所以接法同上)显示init_error消息
我的程序或者接线方法有什么问题吗?或者有什么办法可以测试摄像头是否好用?

最佳答案

查看完整内容[请看2#楼]

PB3当gpio用的时候,要先禁止JTAG!!!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-3-4 21:17:33 | 显示全部楼层
PB3当gpio用的时候,要先禁止JTAG!!!
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
164
金钱
164
注册时间
2015-8-27
在线时间
22 小时
发表于 2015-10-14 14:13:21 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
我用PC13模拟SCCB_SDA为什么读到的ID和寄存器一直是0xFF,好几天一直没解决这个问题。
回复

使用道具 举报

0

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2014-11-26
在线时间
23 小时
发表于 2015-11-2 14:08:21 | 显示全部楼层
回复【3楼】wangyueming:
---------------------------------
不知道你解决没,我现在也遇到这个问题了
回复

使用道具 举报

9

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
164
金钱
164
注册时间
2015-8-27
在线时间
22 小时
发表于 2015-11-2 17:49:00 | 显示全部楼层
回复【4楼】.wolf:
---------------------------------
解决了,首先你需要采用模拟IIC的模式,然后你要检查你定义的SDA输入输出是否正确,然后你根据手册一点点的检查你的程序,观察你的时序是确,甚至Delay()函数都不要放过,我当时是因为SCCB_Stop()函数中一个Delay函数被注释掉了,导致SCL和SDA的时序出现了问题,结果就是读不出正确的ID号。
回复

使用道具 举报

2

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2015-3-4
在线时间
0 小时
 楼主| 发表于 2015-11-3 20:04:03 | 显示全部楼层
回复【5楼】wangyueming:
---------------------------------
我也因为同样的原因(模拟IIC)出过问题,不过当时是在写MPU6050的程序。不过这个问题确实是jtag造成的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 18:54

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表