前段时间搞winCE6.0,发现使用IIC进行读写外围器件时,有个显现比较怪,写正常,而读则需要打印出信息才正确,否则就是一些无规则的数。当时时间不够没彻底解决,这两天仔细研究了下,终于搞清楚这个问题! 是BSP里IIC驱动的BUG! s3c6410_iic_lib.cpp里,HW_Read()是实际的控制IIC读的函数。读过程如下: 1.写器件地址(W)+写读地址。 2.写器件地址(R)+接收数据 中断服务里IIC_IST()判断一个读或写完成的条件 if (bDone) { RETAILMSG(ZONE_INFO, (TEXT("SetEvent DONE/r/n"))); SetEvent(g_hTransferDone); } 发现这里在读一个字节(4字节TRANSMIT)过程中会有三次进入到bDone条件里面,第一次是正常Master_transmit,第二次没有正常Master_receive,也没有正常Master_transmit,第三次是正常Master_receive。 也就是说中间有一次进入中断是假的,是不应该激发bDone事件的! 高亮显示bDone,发现bDone是在IIC_IST()里定义的局部变量BOOL bDone = FALSE;只有在开始传输时被设置为FALSE,传输完后一直是TRUE。 所以第二次中断会让这次条件成立,设置g_hTransferDone,而此时还没到读取要读字节的时候,所以读出的数是pOutBuff本来的数据,但是过一会时间,第三次中断到来,真正读取的数据就会进到pOutBuff里。也就是说,如果设置clock够快,还是能够在返回时读取到正确的数值。 总结: if (bDone) { RETAILMSG(ZONE_INFO, (TEXT("SetEvent DONE/r/n"))); bDone = FALSE; //添加这行 SetEvent(g_hTransferDone); } 添加的行就不会重复执行一次中断完成事件。 另外,示波器抓波形发现读过程中一直没有ACK,4个字节都是一样。 原来是 case Master_receive: 。。。。。 if (g_uIIC_PT==g_uIIC_DATALEN) { //g_pIICReg->IICCON &= ~(1<<7); //注释掉 } 。。。。。 break; 这样波形就对了,有了ACK. 还有,原来读的时候,读两次就可以得到正确的数,由此可以猜想到,IIC寄存器IICDS的写和读是分开的两个寄存器,只是名称一样而已。 |
s3c6410 winCE6.0 IIC驱动BUG
最新推荐文章于 2022-02-25 21:57:21 发布