实际我给的例程是PC的并口模拟I2C协议,用什么语言并不重要.<br /><br />楼主的类似以下的程序全部有问题~~~<br />while(i--)<br />{ <br /> I2CStart();<br /> I2CSendByte(ControlByte&0xfe);//指定芯片,此次必定为写<br /> if(!WaitAck()) //涵数返回一个1为成功<br /> continue; //结束写操作,并i-1后,再来一次<br />//...<br /> if(errorflag==error) //经过写完后,如果最后errorflag标志为1,则表示有错误<br /> continue; //结束写操作,并i-1后,再来一次<br /><br />等等都有问题.<br />I2C的通讯状态很规矩,每个状态都有详细的定义.<br />gccavr中的定义很规范(atmel称I2C为TWI)<br />enum enum_TWIState<br />{<br />/* Master */<br /> TW_START = 0x08,<br /> TW_REP_START= 0x10,<br />/* Master Transmitter */<br /> TW_MT_SLA_ACK= 0x18,<br /> TW_MT_SLA_NACK= 0x20,<br /> TW_MT_DATA_ACK= 0x28,<br /> TW_MT_DATA_NACK= 0x30,<br /> TW_MT_ARB_LOST= 0x38,<br />/* Master Receiver */<br /> TW_MR_ARB_LOST= 0x38,<br /> TW_MR_SLA_ACK= 0x40,<br /> TW_MR_SLA_NACK= 0x48,<br /> TW_MR_DATA_ACK= 0x50,<br /> TW_MR_DATA_NACK= 0x58,<br />/* Slave Transmitter */<br /> TW_ST_SLA_ACK= 0xA8,<br /> TW_ST_ARB_LOST_SLA_ACK= 0xB0,<br /> TW_ST_DATA_ACK= 0xB8,<br /> TW_ST_DATA_NACK= 0xC0,<br /> TW_ST_LAST_DATA= 0xC8,<br />/* Slave Receiver */<br /> TW_SR_SLA_ACK= 0x60,<br /> TW_SR_ARB_LOST_SLA_ACK= 0x68,<br /> TW_SR_GCALL_ACK= 0x70,<br /> TW_SR_ARB_LOST_GCALL_ACK= 0x78,<br /> TW_SR_DATA_ACK= 0x80,<br /> TW_SR_DATA_NACK= 0x88,<br /> TW_SR_GCALL_DATA_ACK= 0x90,<br /> TW_SR_GCALL_DATA_NACK= 0x98,<br /> TW_SR_STOP= 0xA0,<br />/* Misc */<br /> TW_NO_INFO= 0xF8,<br /> TW_BUS_ERROR= 0x00,<br /> TW_READ= 1,<br /> TW_WRITE= 0<br />};<br /><br />不管I2C出现的任何错误,主机都应该发送I2CStop(),而不应该像楼主用continue重试.<br /><br />因为从机是根据主机的节拍即时钟进行工作即状态转移的,主机发现的错误从机并不知晓.<br /><br />所以正确地容错应该是主机发送I2CStop()停止从机的工作后,使从机的状态归零.<br />然后再I2CStart()重新通讯.<br /><br /><br />再者I2C的调试实际很简单,应该在发送I2CStart()和从地址后,在接收应答处<br />设置个断点.<br />若裸奔应该在此处加个LedOn()或LedOff()看看到底收到从机的应答信号ACK否.<br /><br />若收不到就应该检查时序,否则一切都白搭~~~<br /><br />建议I2C用状态机,虽然在模拟I2C上很少使用,但它能使通讯更可靠~~~ <br /> 相关链接:<a href='https://bbs.21ic.com/club/bbs/showEssence.asp?id=9000&page=1'>https://bbs.21ic.com/club/bbs/showEssence.asp?id=9000&page=1</a>
|