|
以你的代碼為例
void i2cwritebyte(unsigned char wdat)//寫入一字節(jié),加入應(yīng)答
{
unsigned char i;
P2=wdat;
for(i=0;i<8;i++)
{
i2csda=0x01&wdat>>7;
wdat=wdat<<1;
i2cscl=1;delayus(4);
i2cscl=0;delayus(4);//最后時(shí)鐘線是低電平,第8個(gè)時(shí)鐘已經(jīng)結(jié)束
}
i2cwack();//應(yīng)答中時(shí)鐘線是高電平,這就是第9 個(gè)時(shí)鐘
}
但是,你的應(yīng)答并不對(duì)
應(yīng)答是要等待SDA出現(xiàn)低電平,而不是簡(jiǎn)單延時(shí)一下
這個(gè)SDA的低電平是24C02給出的
理論上應(yīng)該是:
SCL=1;//時(shí)鐘高電平,保持從機(jī)在第9個(gè)時(shí)鐘
Delay();//延時(shí)
SDA=1;//釋放SDA
while(SDA) ;等待從機(jī)出現(xiàn)應(yīng)答,重點(diǎn)在這里,延時(shí)是不行的,必需得是等待,這是協(xié)議規(guī)定的
但是,在實(shí)際情況中,考慮從機(jī)有故障或者什么的,可能不會(huì)應(yīng)答,while(SDA) ;會(huì)卡死
所以,可以使用:
while((SDA==1)&(k<1000)) //超時(shí)就不再等待應(yīng)答
{
k++;
Delay();
}
而你的程序,本身就是錯(cuò)誤的:
void i2cwack()//寫入應(yīng)答
{
i2csda=1; delayus(4);//執(zhí)行后數(shù)據(jù)線狀態(tài)為低,說(shuō)明從器件的應(yīng)答信號(hào)已發(fā)出
i2cscl=1;delayus(4);//數(shù)據(jù)線狀態(tài)為低
i2cscl=0;delayus(4);//數(shù)據(jù)線狀態(tài)為高
}
應(yīng)該是:
void i2cwack()//寫入應(yīng)答
{
i2csda=1; delayus(4);
i2cscl=1;delayus(4); while(i2csda); //這里要等待,不是延時(shí),重點(diǎn)!重點(diǎn)!重點(diǎn)!可以加入超時(shí)檢測(cè)退出,防止卡死
i2cscl=0;delayus(4);
}
而且,IIC停止讀取之前要加一定不應(yīng)答信號(hào),這個(gè)信號(hào)要由單片機(jī)給出,告訴從機(jī),不要再發(fā)送數(shù)據(jù)了
這個(gè)信號(hào)不是絕對(duì)需要,有的器件你直接停止就可以了,但有的不行,你要給出不應(yīng)答才能正確讀取下一次的數(shù)據(jù)
像你的代碼,能正常就是運(yùn)氣好,因?yàn)橛械腎IC器件硬件電氣性能很好,它的反應(yīng)比單片機(jī)還快,它可能壓根就不需要應(yīng)答
|
|