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