找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12191|回复: 1
打印 上一主题 下一主题
收起左侧

基于OV7670摄像头的SCCB总线的实现

[复制链接]
跳转到指定楼层
楼主
ID:26188 发表于 2015-6-23 14:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
     OV7670的SCCB总线这个让我日夜思念的问题今天终于解决了,我在他身上付出了近5天的努力,工作的路上在想,吃饭的时候在想,上厕所在想,晚上睡不着在想,除了晚上DOTA的时候不想外,几乎总在想这个问题,SCCB很想IIC总线,IIC总线我早在去年的时候就做过了,不是很难,就是主机发送数据包,从机应答就好了,于是我搭起来电路板,问题来了,我的MCU是5V而摄像头要求电源电压和IO不能超过3V,怎么办呢?找手册,手册里写的是最低工作电压是3.7V,不行,电压太高,会烧掉他的,一筹莫展,怎么办?正好我手头还有几片AVR的高速单片机,于是开始用他们,终于电源电压的问题解决了,自以为问题不大,他的工作电压可以达到2.8V,于是接上,就开始向里面写程序,怎么调也不行,任凭我怎样调试,始终读不回数据,数据是标志和OV7670的握手是否成功的关键,我使用模拟的办法来写的程序,因为那是不需要很大硬件开销的,但是占了很多的CPU时间,于是我就考虑是不是时序在高速状态下错误或者超过400KHZ呢?有可能啊,于是就加了很多延时,结果不仅失望,还是扯,没有回应,愁死了,于是就向卖家要技术资料,那孙子说只能给数据手册,另外还要加钱,我不干,有上网上找资料,他妈的都是用ARM做的,人家多是基于LINUX的代码根本不通用,我这水平也看不懂,转了一大圈有回到了自己的代码上,究竟是什么问题导致的,没有示波器,逻辑分析仪,只有一块万用表,还是单位的,很郁闷,也不知道程序究竟是个什么波形,用软件模拟后,时序肯定没问题,但就是读出数据,而且数据老是错,我的第一个转折开始考虑供电电压,我发现一个规律:每当我不接0V7670时在PC上显示的数据始终是正确的,一接上就出现乱码,或者错误吗,是干扰吗?没有高频的干扰源,我用的还是内部晶振,电源加了两个滤波器,这信息让我测量了一下MCU的VCC电压,结果出现了惊人的巧合,当我不接7670时电源电压是2,8V,此时数据发送正常,一旦接上后就变成了2,6V,已经达到了MCU的低电压器检测的门槛,MCU要复位了,呵呵问题找到了,凶手是电源电压,但是我没有专用的稳压芯片所以不敢吧3.3V的电压接到VCC,昨天终于鼓起勇气拿起烙铁,VCC=3.4V,MCU正常工作,至于7670我那时候不知道他什么状态,因为的IO和VCC电压都大于他手册上的电压,硬着头皮向里面写程序,每一次的实验我都揪心啊,结果还是不行,我那个郁闷啊!怎么这么操蛋呢?第二个转折点:既然模拟不行我用硬件,开始用硬件做,昨天用了一上午时间看手册,学会了寄存的设置和编程,昨天下午调试,今天上午实验成功,数据被读出来了,看来7670对握手是很苛刻的!!!!下面上程序
#include<iom16v.h>
#define uchar unsigned char
#define uint unsigned int
#define set_bit(a,b)  a|=(1<<b)
#define clr_bit(a,b)  a&=(1<<b)
#define get_bit(a,b)  a&(1<<b)
#pragma interrupt_handler TX_end:14
uchar TXEND;
void TX_end()
{

TXEND=0;//发送完毕标志
}
void USART_INT()//初始化串口
{

//UCSRA默认
UCSRB=0x48;//使能发送完毕中断,禁能数据寄存器空中断,使能发送模式,关闭接收,关闭接收中断
UCSRC=0x86;//禁止奇偶效验,数据位8,停止位1,工作在异步模式
UBRRH=0x00;//
UBRRL=51;//波特率9600,8MHZ,

SREG=0x80;//开启全局中断
}

void send_byte(uchar buffer)//向PC发送数据
{
   while(0==get_bit(UCSRA,5));//数据寄存器里的数据是不是为空如果是就写数据
  
    UDR=buffer;


while(TXEND);//是否发送完毕?
TXEND=1;//上一帧已经发送准备下一帧的发送

}
/*void ov7670_int()//7670初始化函数
{


}*/


////***********SCCB-----OX7670************************//////////
void delay1ms(uint z)
{
uint j,k;
    for(k=z;k;k--)
                       {                           
                      for(j=2666;j;j--) ;  //此处j不得小于27否则读不出数据
        }
               

}

void int_twi_sccb()
{
TWBR=50;//设置SCL的时钟频率在19。230khz
}

void send_model_sccb()//主发送模式程序
{
    TWCR=0xa4;//插入开始新号使能总线,使能START
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//检测起始信号是否发送?
while((TWSR&0xf8)!=0x08)
{send_byte(0xf4);
     send_byte(0x01);
     send_byte(0xf4);//出错
}
send_byte(0xf4);
send_byte(0x10);
send_byte(0xf4);//START信号的正确响应码


TWDR=0x42;//写操作SCCB的器件写地址0X42
TWCR=0x84;//重启启动数据的发送
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//检测数据信号是否发送?
while((TWSR&0XF8)!=0x18)
{send_byte(0xf4);
send_byte(0x02);
send_byte(0xf4);
     }

send_byte(0xf4);
send_byte(0x20);
send_byte(0xf4);//发送完毕有ACK应答响应码


TWDR=0x0b;//写操作SCCB的寄存器地址0x0a
TWCR=0x84;//重启启动数据的发送
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//检测数据信号是否发送?
while((TWSR&0XF8)!=0x28)
{
send_byte(0xf4);
send_byte(0x03);//出错
send_byte(0xf4);
     }

send_byte(0xf4);
send_byte(0x30);
send_byte(0xf4);//发送完毕有ACK应答响应码


TWCR=0x94;//STOP信号





}
uchar incept_model_sccb()//主接收模式程序
{
     uchar date;
TWCR=0xa4;//插入开始新号使能总线,使能START
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//检测起始信号是否发送?
while((TWSR&0XF8)!=0x08)
{send_byte(0xf4);
send_byte(0x04);//出错
send_byte(0xf4);
     }

send_byte(0xf4);
send_byte(0x40);
send_byte(0xf4);//START信号的正确响应码


TWDR=0x43;//写操作SCCB的器件写地址0X43
TWCR=0x84;//重启启动数据的发送
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//检测数据信号是否发送?
while((TWSR&0XF8)!=0x40)
{send_byte(0xf4);
send_byte(0x05);//出错
send_byte(0xf4);
     }

send_byte(0xf4);
send_byte(0x50);
send_byte(0xf4);//发送完毕有ACK应答响应码


TWCR=0x84;//启动数据的接收
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//检测数据信号是否发送?
date=TWDR;
while((TWSR&0XF8)!=0x58)
{send_byte(0xf4);
send_byte(0x06);
send_byte(0xf4);}//出错

send_byte(0xf4);
send_byte(0x60);
send_byte(0xf4);//发送完毕有NACK应答响应码


TWCR=0x94;//STOP信号


return(date);
}

void main()
{

uchar inceptdate;
DDRC=0xff;
PORTC=0xff;
USART_INT();
int_twi_sccb();


send_model_sccb();
delay1ms(2);
inceptdate=incept_model_sccb();

send_byte(0xf4);
send_byte(inceptdate);
send_byte(0xf4);
while(1);


}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:177825 发表于 2017-3-22 15:12 | 只看该作者
我也想用iic写ov的程序,我看资料上面可以用但是就只提了一句。。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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