周公好,<br /> 又来麻烦你了,最近一周一直在看I2C的相关资料和你们写的源码,也在用开发板做实验,但还是有很多问题不明白,所以这里想详细问下。<br /> 1,首先是这里<br /> void __irq IRQ_I2C(void)<br />{ uint8 sta;<br /><br /> sta = I2STAT; // 读出I2C状态字<br /> switch(sta)<br /> { case 0x08: // 己发送起始条件<br /> if(1==I2C_suba_en) I2DAT = I2C_sla&0xFE; // 指定子地址读时,先写入地址<br /> else I2DAT = I2C_sla; // 否则直接发送从机地址<br /> I2CONCLR = 0x28; // SI=0<br /> break;<br />Question1:为什么else后面不分情况?因为写操作时候(2==I2C_suba_en),也要写从机地址+子地址啊;2==I2C_suba_en和0==I2C_suba_en后面执行的动作肯定应该不一样啊,为什么不分情况,直接就else I2DAT = I2C_sla; ...了呢??<br /> 2 case 0x18: // 已发送SLA+W,并已接收应答<br /> if(0==I2C_suba_en) // 无子地址,则直接发送数据<br /> { if(I2C_num>0)<br /> { I2DAT = *I2C_buf++;<br /> I2CONCLR = 0x28; <br /> I2C_num--;<br /> }<br />Question2:无子地址应该是写了从机地址+子地址后就可以叫无子地址了;在18H这个状态子地址肯定是没有写入到从机的啊,所以应该还有子地址,所以我的疑问是怎么会在case 18H的时候出现无子地址直接发送数据这个语句呢(就是我上面贴出来这句)??<br /> 3 case 0x40: // 己发送SLA+R,并已接收到应答<br /> if(1==I2C_num) // 最后一字节,接收数据后发送非应答信号<br /> { I2CONCLR = 0x2C; // AA=0,接收到数据后产生非应答<br /> }<br /> else // 接收数据并发送应答信号<br /> { I2CONSET = 0x04; // AA=1,接收到数据后产生应答<br /> I2CONCLR = 0x28;<br /> }<br /> break;<br /> case 0x50:<br /> *I2C_buf++ = I2DAT; // 读取数据<br /> I2C_num--;<br /> if(1==I2C_num)<br /> { I2CONCLR = 0x2C; // AA=0,接收到数据后产生非应答<br /> }<br /> else<br /> { I2CONSET = 0x04; // AA=1,接收到数据后产生应答<br /> I2CONCLR = 0x28;<br /> }<br /> break;<br />Question3:40H是从机已经给主机发送了应答位,在case 40H这个语句里为什么没有象case 50H接受数据的语句?我分析是case 40H语句里是能够接受数据的。<br />Question4:为什么最后一字节用if(1==I2C_num)判断而不是if(0==I2C_num)?? |
|