|
OV7670的SCCB總線這個(gè)讓我日夜思念的問題今天終于解決了,我在他身上付出了近5天的努力,工作的路上在想,吃飯的時(shí)候在想,上廁所在想,晚上睡不著在想,除了晚上DOTA的時(shí)候不想外,幾乎總在想這個(gè)問題,SCCB很想IIC總線,IIC總線我早在去年的時(shí)候就做過了,不是很難,就是主機(jī)發(fā)送數(shù)據(jù)包,從機(jī)應(yīng)答就好了,于是我搭起來電路板,問題來了,我的MCU是5V而攝像頭要求電源電壓和IO不能超過3V,怎么辦呢?找手冊(cè),手冊(cè)里寫的是最低工作電壓是3.7V,不行,電壓太高,會(huì)燒掉他的,一籌莫展,怎么辦?正好我手頭還有幾片AVR的高速單片機(jī),于是開始用他們,終于電源電壓的問題解決了,自以為問題不大,他的工作電壓可以達(dá)到2.8V,于是接上,就開始向里面寫程序,怎么調(diào)也不行,任憑我怎樣調(diào)試,始終讀不回?cái)?shù)據(jù),數(shù)據(jù)是標(biāo)志和OV7670的握手是否成功的關(guān)鍵,我使用模擬的辦法來寫的程序,因?yàn)槟鞘遣恍枰艽笥布_銷的,但是占了很多的CPU時(shí)間,于是我就考慮是不是時(shí)序在高速狀態(tài)下錯(cuò)誤或者超過400KHZ呢?有可能啊,于是就加了很多延時(shí),結(jié)果不僅失望,還是扯,沒有回應(yīng),愁死了,于是就向賣家要技術(shù)資料,那孫子說只能給數(shù)據(jù)手冊(cè),另外還要加錢,我不干,有上網(wǎng)上找資料,他媽的都是用ARM做的,人家多是基于LINUX的代碼根本不通用,我這水平也看不懂,轉(zhuǎn)了一大圈有回到了自己的代碼上,究竟是什么問題導(dǎo)致的,沒有示波器,邏輯分析儀,只有一塊萬用表,還是單位的,很郁悶,也不知道程序究竟是個(gè)什么波形,用軟件模擬后,時(shí)序肯定沒問題,但就是讀出數(shù)據(jù),而且數(shù)據(jù)老是錯(cuò),我的第一個(gè)轉(zhuǎn)折開始考慮供電電壓,我發(fā)現(xiàn)一個(gè)規(guī)律:每當(dāng)我不接0V7670時(shí)在PC上顯示的數(shù)據(jù)始終是正確的,一接上就出現(xiàn)亂碼,或者錯(cuò)誤嗎,是干擾嗎?沒有高頻的干擾源,我用的還是內(nèi)部晶振,電源加了兩個(gè)濾波器,這信息讓我測量了一下MCU的VCC電壓,結(jié)果出現(xiàn)了驚人的巧合,當(dāng)我不接7670時(shí)電源電壓是2,8V,此時(shí)數(shù)據(jù)發(fā)送正常,一旦接上后就變成了2,6V,已經(jīng)達(dá)到了MCU的低電壓器檢測的門檻,MCU要復(fù)位了,呵呵問題找到了,兇手是電源電壓,但是我沒有專用的穩(wěn)壓芯片所以不敢吧3.3V的電壓接到VCC,昨天終于鼓起勇氣拿起烙鐵,VCC=3.4V,MCU正常工作,至于7670我那時(shí)候不知道他什么狀態(tài),因?yàn)榈腎O和VCC電壓都大于他手冊(cè)上的電壓,硬著頭皮向里面寫程序,每一次的實(shí)驗(yàn)我都揪心啊,結(jié)果還是不行,我那個(gè)郁悶啊!怎么這么操蛋呢?第二個(gè)轉(zhuǎn)折點(diǎn):既然模擬不行我用硬件,開始用硬件做,昨天用了一上午時(shí)間看手冊(cè),學(xué)會(huì)了寄存的設(shè)置和編程,昨天下午調(diào)試,今天上午實(shí)驗(yàn)成功,數(shù)據(jù)被讀出來了,看來7670對(duì)握手是很苛刻的!。!下面上程序
#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;//發(fā)送完畢標(biāo)志
}
void USART_INT()//初始化串口
{
//UCSRA默認(rèn)
UCSRB=0x48;//使能發(fā)送完畢中斷,禁能數(shù)據(jù)寄存器空中斷,使能發(fā)送模式,關(guān)閉接收,關(guān)閉接收中斷
UCSRC=0x86;//禁止奇偶效驗(yàn),數(shù)據(jù)位8,停止位1,工作在異步模式
UBRRH=0x00;//
UBRRL=51;//波特率9600,8MHZ,
SREG=0x80;//開啟全局中斷
}
void send_byte(uchar buffer)//向PC發(fā)送數(shù)據(jù)
{
while(0==get_bit(UCSRA,5));//數(shù)據(jù)寄存器里的數(shù)據(jù)是不是為空如果是就寫數(shù)據(jù)
UDR=buffer;
while(TXEND);//是否發(fā)送完畢?
TXEND=1;//上一幀已經(jīng)發(fā)送準(zhǔn)備下一幀的發(fā)送
}
/*void ov7670_int()//7670初始化函數(shù)
{
}*/
////***********SCCB-----OX7670************************//////////
void delay1ms(uint z)
{
uint j,k;
for(k=z;k;k--)
{
for(j=2666;j;j--) ; //此處j不得小于27否則讀不出數(shù)據(jù)
}
}
void int_twi_sccb()
{
TWBR=50;//設(shè)置SCL的時(shí)鐘頻率在19。230khz
}
void send_model_sccb()//主發(fā)送模式程序
{
TWCR=0xa4;//插入開始新號(hào)使能總線,使能START
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//檢測起始信號(hào)是否發(fā)送?
while((TWSR&0xf8)!=0x08)
{send_byte(0xf4);
send_byte(0x01);
send_byte(0xf4);//出錯(cuò)
}
send_byte(0xf4);
send_byte(0x10);
send_byte(0xf4);//START信號(hào)的正確響應(yīng)碼
TWDR=0x42;//寫操作SCCB的器件寫地址0X42
TWCR=0x84;//重啟啟動(dòng)數(shù)據(jù)的發(fā)送
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//檢測數(shù)據(jù)信號(hào)是否發(fā)送?
while((TWSR&0XF8)!=0x18)
{send_byte(0xf4);
send_byte(0x02);
send_byte(0xf4);
}
send_byte(0xf4);
send_byte(0x20);
send_byte(0xf4);//發(fā)送完畢有ACK應(yīng)答響應(yīng)碼
TWDR=0x0b;//寫操作SCCB的寄存器地址0x0a
TWCR=0x84;//重啟啟動(dòng)數(shù)據(jù)的發(fā)送
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//檢測數(shù)據(jù)信號(hào)是否發(fā)送?
while((TWSR&0XF8)!=0x28)
{
send_byte(0xf4);
send_byte(0x03);//出錯(cuò)
send_byte(0xf4);
}
send_byte(0xf4);
send_byte(0x30);
send_byte(0xf4);//發(fā)送完畢有ACK應(yīng)答響應(yīng)碼
TWCR=0x94;//STOP信號(hào)
}
uchar incept_model_sccb()//主接收模式程序
{
uchar date;
TWCR=0xa4;//插入開始新號(hào)使能總線,使能START
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//檢測起始信號(hào)是否發(fā)送?
while((TWSR&0XF8)!=0x08)
{send_byte(0xf4);
send_byte(0x04);//出錯(cuò)
send_byte(0xf4);
}
send_byte(0xf4);
send_byte(0x40);
send_byte(0xf4);//START信號(hào)的正確響應(yīng)碼
TWDR=0x43;//寫操作SCCB的器件寫地址0X43
TWCR=0x84;//重啟啟動(dòng)數(shù)據(jù)的發(fā)送
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//檢測數(shù)據(jù)信號(hào)是否發(fā)送?
while((TWSR&0XF8)!=0x40)
{send_byte(0xf4);
send_byte(0x05);//出錯(cuò)
send_byte(0xf4);
}
send_byte(0xf4);
send_byte(0x50);
send_byte(0xf4);//發(fā)送完畢有ACK應(yīng)答響應(yīng)碼
TWCR=0x84;//啟動(dòng)數(shù)據(jù)的接收
send_byte(0xf4);
send_byte(0xcc);
send_byte(0xf4);
while(0==get_bit(TWCR,7));//檢測數(shù)據(jù)信號(hào)是否發(fā)送?
date=TWDR;
while((TWSR&0XF8)!=0x58)
{send_byte(0xf4);
send_byte(0x06);
send_byte(0xf4);}//出錯(cuò)
send_byte(0xf4);
send_byte(0x60);
send_byte(0xf4);//發(fā)送完畢有NACK應(yīng)答響應(yīng)碼
TWCR=0x94;//STOP信號(hào)
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);
}
|
|