程序清单 37 __i2cTryTransfer的具体实现
static INT __i2cTryTransfer (UINT uiChannel, PLW_I2C_ADAPTER pI2cAdapter, PLW_I2C_MESSAGE pI2cMsg, INT iNum) { …… /* * 设置I2C时钟频率,清状态位,使能I2C * 并判断总线状态,若IBB位为0 (总线空闲)继续,否则取消本次传输 */ if (__i2cTransferEnable(uiChannel) != 0) { return (PX_ERROR); } /* * 设置为主模式+传输模式 * 设置完后IBB位自动置1(总线繁忙),开始传输 */ if (__i2cTransferStart(uiChannel) != 0) { return (PX_ERROR); } /* * 完成设备地址发送后,进入收发消息函数 */ for (i = 0; i < iNum; i++, pI2cMsg++) { if (__i2cTransferMsg(uiChannel, pI2cMsg, iNum) != ERROR_NONE) { break; } } /* * generate STOP by clearing MSTA bit * (清除MSTA位使其停止传输) */ __i2cTransferStop(uiChannel); /* * disable the controller * (禁止I2C控制器) */ __i2cTransferDisable(uiChannel); …… }__i2cTransferEnable的具体实现
__i2cTransferEnable函数使能I2C,设置时钟频率。
__i2cTransferStart的具体实现
__i2cTransferStart函数设置I2C控制器为主模式(占用总线)。
__i2cTransferMsg的具体实现
i2cTransferMsg函数判断读/写模式,对应不同操作。如程序清单 38所示。
程序清单 38 __i2cTransferMsg的具体实现
static INT __i2cTransferMsg ( UINT uiChannel, PLW_I2C_MESSAGE pI2cMsg, INT iNUM) { …… if (pI2cMsg->I2CMSG_usFlag & LW_I2C_M_RD) { /* 读取操作 */ /* * do repeat-start * (重复启动) (IEN_MSTA_MTX_RSTA) */ …… /* * send slave address again, but indicate read operation * (发送从机器件地址,���明为读操作) */ …… if (__i2cTransferTxByte(pucData, uiChannel) != 0) { /* 发送从机地址,等待返回ACK */ return -1; } /* * change to receive mode * (设置为接收模式) */ …… /* * 若只有一个字节,设置选择不发送ACK(最后一次传输不发送ACK) */ …… /* * dummy read * (行假读) */ *pucData = readw(REG_I2C_I2DR(uiChannel)); /* * 开始读... */ if (__i2cTransferRxBytes(pI2cMsg->I2CMSG_pucBuffer, uiChannel, pI2cMsg->I2CMSG_usLen) != 0) { return (PX_ERROR); } } else { /* 发送操作 */ /* * Step 2: send slave address + read/write at the LSB * (发送从机地址+读写LSB 设置为写位) */ …… /* * 将从机地址数据写入寄存器,等待ACK返回 */ …… /* * 设定一个长度,循环往寄存器写,等待ACK返回 */ pucData = pI2cMsg->I2CMSG_pucBuffer; for (i = 0; i < pI2cMsg->I2CMSG_usLen; i++) { /* * send device register value * (发送寄存器地址 / 信息) */ if ((iRet = __i2cTransferTxByte(pucData, uiChannel)) != 0) { break; } pucData++; } } …… }__i2cTransferTxByte的具体实现
如程序清单 39,程序清单 310所示。