在收ACK信号时必须等待!!!因为从机也做处理(比较地址)后才返回ACK信号. 下面2个例程都是用模拟的I2C做的.
51例程(51读写铁电EEPROM): //I2C收发一体化ACK读写函数 bit I2CAck(unsigned char val) { unsigned char i; SDA = val & 1;//写入1位ACK数据 _nop_();_nop_();_nop_();_nop_();_nop_();//延时4.7uS SCL = 1;//拉高I2C时钟 _nop_();_nop_();_nop_();_nop_();_nop_();//延时4.7uS CY = SDA;//读回1位ACK数据 if (val <= 1) {//需要从机应答信号 for (i = 255; i > 0; i --) { if (!(CY = SDA)) break;//收到从机应答信号立即退出 } } SCL = 0;//拉低I2C时钟 return CY;//返回读回ACK数据 }
LabWindows例程(打印机并口直接读写EEPROM):
void CVIFUNC I2C_WriteAck(unsigned char ack) { if (ack) { I2C_ClrSDA();//给从机ACK信号 } else { I2C_SetSDA();//给从机nACK信号 } I2C_SetSCL();//拉高时钟信号,拉高时钟(必须在SDA=1时) I2C_ClrSCL();//拉低时钟信号,防止START信号产生 I2C_ClrSDA();//给从机ACK信号 }
HRESULT CVIFUNC I2C_GetAck(void) { HRESULT __result = S_FALSE; int i; for (i = 0; i < I2C_waitAckDelay; i ++) { if (I2C_GetSDA() == 0) //释放数据总线读数据总线 { __result = S_OK; break; } } I2C_SetSCL();//拉高时钟(必须在SDA=1时)??? I2C_ClrSCL();//拉低时钟 I2C_ClrSDA();//保证SDA=SCL=0///pwy(拉低SDA便于发送停止喜欢) return __result;//SDA=1,SCL=0 } 相关链接:https://bbs.21ic.com/club/bbs/showEssence.asp?id=8532
|