如下疑問 :
關(guān)于程序中這個讀字節(jié)的子函數(shù) uchar read_byte() ,讀取EEPROM內(nèi)數(shù)據(jù)時,用了 “ k=(k<<1)|sda; ”,然后循環(huán)8次,這里是如何得到一個字節(jié)數(shù)據(jù)的,沒弄明白。
我理解是k左移之后(不管k初值是什么),低位補0,而sda要么是0000 0000,要么是0000 0001,是固定的,所以進行按位或之后的k要么是0000 0000,要么是0000 0001,這個也是固定的,不管循環(huán)多少次,每次得到的k都是0000 0000,或者是0000 0001,怎么就讀取到內(nèi)部的0x55這個數(shù)據(jù)了呢? 而且實際運行用P1點亮LED也是正確的。
感謝指點!
以下是單片機代碼(注釋是自己寫的,有錯誤的地方還請不吝指正):
#include <reg52.h>
#include <intrins.h>
sbit scl=P2^1;
sbit sda=P2^0;
typedef unsigned char uchar;
typedef unsigned int uint;
void delayms(uchar z)
{
int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void delayus()
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
void start() //開始信號
{
sda=1;
scl=1;
delayus(); //根據(jù)時序圖,scl和sda都為1的時候要保持4.7us以上。
sda=0; //在scl為高電平的狀態(tài)下,sda產(chǎn)生下降沿
delayus(); //根據(jù)時序圖,數(shù)據(jù)拉低后保持4us以上。
scl=0; //根據(jù)時序圖,將scl拉低,后面開始字節(jié)傳輸。
delayus();
}
void stop() //停止信號
{
sda=0;
scl=1;
delayus(); //根據(jù)時序圖,scl和sda分別為1、0的時候要保持4us以上。
sda=1; //在scl為高電平的狀態(tài)下,sda產(chǎn)生上升沿
delayus(); //根據(jù)時序圖,數(shù)據(jù)拉高后保持4.7us以上。
sda=0; //根據(jù)時序圖,將sda拉低。
delayus();
}
void respons() //應答信號
{
uchar i;
sda=1; //不管之前sda是什么狀態(tài),先釋放sda
delayus();
scl=1; //將scl拉高,用于sda響應。
delayus();
while((sda==1)&&(i<250)) i++;
scl=0;
delayus();
}
void write_byte(uchar date) //寫字節(jié),可以用來寫 器件地址 或 內(nèi)存地址 或 數(shù)據(jù)。
{
uchar i,temp;
temp=date;
scl=0;
for(i=0;i<8;i++) //總共8位(器件地址是7位+1位讀寫位,內(nèi)存地址是8位),所以需要循環(huán)8次。
{
temp=temp<<1; //將器件地址進行左移,左移之后會溢出,因為IIC是從MSB開始寫,所以要左移。
sda=CY; //每當有數(shù)據(jù)溢出1,CY都會置1,溢出0,會置0,賦給sda,就得到了本次移出來的地址數(shù)據(jù)
delayus();
scl=1;
delayus(); //延時,給從機時間讀取sda信號。
scl=0; //傳輸完一位后就將SCL拉低,下一次循環(huán)時sda才允許發(fā)生變化。
}
scl=0;
delayus();
sda=1;
delayus();
}
uchar read_byte() //字節(jié)讀取
{
uchar j,k;
scl=0;
delayus();
sda=1;
delayus();
for(j=0;j<8;j++)
{
scl=1;
delayus();
k=(k<<1)|sda; //k的初值不管是什么,左移之后LSB都是0
scl=0;
delayus();
}
return k;
}
void init()
{
sda=1;
scl=1;
delayus();
}
void main() // 主程序思路為先往24C02中寫0x55,然后再讀出來并且賦值給P1
{
init();
start();
write_byte(0xa0); //尋址,并且下一步為寫。
respons(); //從機響應,疑問:respons函數(shù)中,沒有響應時超時后也會繼續(xù),那主機往哪里寫?
write_byte(22); //寫存儲地址,指定后面要往存儲器的第22個地址去寫數(shù)據(jù)。24c02總共256個字節(jié)地址,所以0~255都可以。
respons();
write_byte(0x55); //往存儲器的第22個地址中寫入數(shù)據(jù)0x55
respons();
stop();
delayms(100); //進入24C02的寫周期,需>10ms
/*下面一段參考24c02的隨機讀時序來寫,將上面剛剛寫進第22個地址的數(shù)據(jù)讀出來賦值給P1*/
start();
write_byte(0xa0); //尋址,并且下一步為寫
respons(); //從機響應
write_byte(22); //指定要訪問的地址為22
respons();
start(); //由寫變?yōu)樽x,所以要重新開始一下
write_byte(0xa1); //尋址,并且下一步為讀
respons();
P1=read_byte();
stop();
while(1); //主程序?qū)、讀完之后,將讀到的數(shù)據(jù)給P1,然后讓程序停在這里。
}
|