我在调试I2C中断方式的接收数据流程时碰到如下问题 如上图波形,在一个接收流程完成后,Stop condition没有成功发送. 流程如下 Start[主] SlaveAddr[主] Ack SubAddr[主] Ack Stop[主] RepeatStart[主] SlaveAddr[主] Ack Data Nack[主] Stop[主](此Stop未成功发送) 下面是UCOSII下的I2C程序文件,请帮我看下是什么问题造成的,谢谢!!
//File : I2CDev.C //Created by : Kuang Hao #include "Config.h" //tI2C_COMM_CB _I2CCommCtrlBlock; tI2C_CB _I2CCtrlBlock[I2C_BUS_COUNT]; static void __InitI2CGPIO(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_StructInit(&GPIO_InitStruct); //* KEYBOARD //* P2.0 I2C0_CLKOUT //* P2.1 I2C0_DOUT GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStruct.GPIO_Direction = GPIO_PinOutput; GPIO_InitStruct.GPIO_Type = GPIO_Type_PushPull; GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Enable; GPIO_InitStruct.GPIO_Alternate = GPIO_OutputAlt2; GPIO_Init(GPIO2, &GPIO_InitStruct); //* EEPROM //* P2.2 I2C1_CLKOUT //* P2.3 I2C1_DOUT GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStruct.GPIO_Direction = GPIO_PinOutput; GPIO_InitStruct.GPIO_Type = GPIO_Type_PushPull; GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Enable; GPIO_InitStruct.GPIO_Alternate = GPIO_OutputAlt2; GPIO_Init(GPIO2, &GPIO_InitStruct); }
static void __InitI2CCB(void) { //* Init I2C communication contrl block _I2CCtrlBlock[0].CommCb.bAddr = 0; _I2CCtrlBlock[0].CommCb.iSize = 0; _I2CCtrlBlock[0].CommCb.pData = (void *)0; _I2CCtrlBlock[0].CommCb.bDirection = I2C_MODE_TRANSMITTER; _I2CCtrlBlock[1].CommCb.bAddr = 0; _I2CCtrlBlock[1].CommCb.iSize = 0; _I2CCtrlBlock[1].CommCb.pData = (void *)0; _I2CCtrlBlock[1].CommCb.bDirection = I2C_MODE_TRANSMITTER; //* Init I2C contrl block _I2CCtrlBlock[0].I2Cx = I2C0; _I2CCtrlBlock[0].pEventSem = OSSemCreate(1); _I2CCtrlBlock[0].pEventMB = OSMboxCreate((void *)0); _I2CCtrlBlock[1].I2Cx = I2C1; _I2CCtrlBlock[1].pEventSem = OSSemCreate(1); _I2CCtrlBlock[1].pEventMB = OSMboxCreate((void *)0);
} // * KEYBOARD -- I2C0 // * EEPROM -- I2C1 void InitI2C(u16 I2C0Addr, u16 I2C1Addr) { I2C_InitTypeDef I2C_Struct; //* InitI2CContrlBlock __InitI2CCB(); //* GPIO0 Config __InitI2CGPIO(); //* I2C0 Configuration I2C_Struct.I2C_GeneralCall = I2C_GeneralCall_Disable; I2C_Struct.I2C_Ack = I2C_Ack_Enable; I2C_Struct.I2C_CLKSpeed = 100000; I2C_Struct.I2C_OwnAddress = I2C0Addr; I2C_Init(I2C0, &I2C_Struct); //* I2C1 Configuration //* we keep the same config as I2C0 for the other I2C_Struct members //* We change just the address I2C_Struct.I2C_OwnAddress = I2C1Addr; I2C_Init(I2C1, &I2C_Struct); I2C_Cmd(I2C0, ENABLE); I2C_Cmd(I2C1, ENABLE); I2C_ITConfig(I2C1, ENABLE); I2C_ITConfig(I2C0, ENABLE); } // ****************************************************************************************************** // * 参数 : [IN]tI2C_CB *I2C_CBx, // * [IN]INT8U bSlaveAddr, // * 从设备地址 // * [IN]INT16U iSubAddr, // * 从设备子地址 // * [IN]INT8U *bData, // * 待传输的数据 // * [IN]INT32U iDataSize // * 传输的数据长度 // * [IN]INT8U bDirection // * 传输的数据的方向 // * // * I2C_MODE_TRANSMITTER // * // * I2C_MODE_RECEIVER // * 返回 : [OUT]INT32U // * 写入的数据长度. // * 创建 : Kuanghao // ****************************************************************************************************** static INT8U __WriteI2CByte(tI2C_CB *I2C_CBx, INT8U bSlaveAddr, INT8U *bData, INT32U iDataSize, INT8U bDirection ) { INT8U bErr = OS_NO_ERR; INT8U Msg = 0; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; cpu_sr = cpu_sr; #endif OS_ENTER_CRITICAL(); I2C_CBx->CommCb.bAddr = bSlaveAddr & 0xFE; //* 存储发送地址 I2C_CBx->CommCb.iSize = iDataSize; //* 存储写字节数 I2C_CBx->CommCb.pData = bData; //* 存储写的数据的指针 I2C_CBx->CommCb.bDirection = bDirection; OS_EXIT_CRITICAL(); I2C_GenerateStart(I2C_CBx->I2Cx, ENABLE); Msg = (INT8U)OSMboxPend(I2C_CBx->pEventMB, I2C_COMM_TIMEOUT_TICKS, &bErr); if(bDirection == I2C_MODE_TRANSMITTER) { if((Msg == MBOX_I2C_WRITE_DATA) & (bErr == OS_NO_ERR)) return (iDataSize - I2C_CBx->CommCb.iSize); } else { if((Msg == MBOX_I2C_READ_DATA) & (bErr == OS_NO_ERR)) return (iDataSize - I2C_CBx->CommCb.iSize); } return FALSE; } // ****************************************************************************************************** // * 参数 : [IN]tI2C_CB *I2C_CBx, // * [IN]const INT8U *pData, // * 写入的数据(包含子地址数据) // * [IN]INT8U bSlaveAddr, // * 从设备地址 // * [IN]INT32U iDataSize // * 传输的数据长度,不包括子地址长度. // * 返回 : [OUT]INT32U 写入的数据长度. // * 创建 : Kuanghao // * 注意 : 数据区内包含子地址. // ****************************************************************************************************** INT32U WriteI2CData(tI2C_CB *I2C_CBx, INT8U bSlaveAddr, // * 从设备地址 INT8U *pData, // * 写入的数据 INT32U iDataSize // * 传输的数据长度,不包括子地址长度. ) { INT8U bErr = OS_NO_ERR; OSSemPend(I2C_CBx->pEventSem, I2C_COMM_TIMEOUT_TICKS, &bErr); // * 写数据 if(!__WriteI2CByte(I2C_CBx, bSlaveAddr, pData, iDataSize, I2C_MODE_TRANSMITTER)) // * 写失败 return (iDataSize - I2C_CBx->CommCb.iSize);// return write data size; OSSemPost(I2C_CBx->pEventSem); return (iDataSize - I2C_CBx->CommCb.iSize); }
// ****************************************************************************************************** // * 参数 : [IN]tI2C_CB *I2C_CBx, // * [OUT]INT8U *pData, // * 读取的数据 // * [IN]INT8U bSlaveAddr, // * 从设备地址 // * [IN]INT16U iSubAddr, // * 从设备子地址 // * [IN]INT8U bSubAddrLen, // * 子地址长度 0 ~ 2 // * [IN]INT32U iDataSize // * 传输的数据长度,不包括子地址长度. // * 返回 : [OUT]INT32U 读出的数据长度. // * 创建 : Kuanghao // ****************************************************************************************************** INT32U ReadI2CData(tI2C_CB *I2C_CBx, INT8U bSlaveAddr, // * 从设备地址 INT16U iSubAddr, // * 从设备子地址 INT8U bSubAddrLen, // * 子地址长度 0 ~ 2 INT8U *pData, // * 读取的数据 INT32U iDataSize // * 传输的数据长度,不包括子地址长度. ) { INT8U bErr = OS_NO_ERR; INT8U bSubAddr[2]; INT8U bWriteSub = TRUE; OSSemPend(I2C_CBx->pEventSem, I2C_COMM_TIMEOUT_TICKS, &bErr); switch(bSubAddrLen) { case 0: // * 无子地址 bWriteSub = FALSE; break; case 1: bSubAddr[0] = (INT8U)iSubAddr; break; case 2: bSubAddr[0] = (INT8U)(iSubAddr >> 8); bSubAddr[1] = (INT8U)iSubAddr; break; default: break; } if(bWriteSub) { // * 写子地址 if(!__WriteI2CByte(I2C_CBx, bSlaveAddr, bSubAddr, bSubAddrLen, I2C_MODE_TRANSMITTER)) // * 写失败 return -1; } // * 对于无子地址器件此处为正常Start 对于有子地址器件此处为ReStart. // * 读数据 if(!__WriteI2CByte(I2C_CBx, bSlaveAddr, pData, iDataSize, I2C_MODE_RECEIVER)) // * 读失败 return (iDataSize - I2C_CBx->CommCb.iSize); // return read data size; OSSemPost(I2C_CBx->pEventSem); return (iDataSize - I2C_CBx->CommCb.iSize); }
void I2CIRQService(tI2C_CB *I2C_CBx) { switch (I2C_GetLastEvent(I2C_CBx->I2Cx)) { // * 在主模式下产生Start condition EV5 case I2C_EVENT_MASTER_MODE_SELECT: // * 传输I2C设备地址 I2C_Send7bitAddress(I2C_CBx->I2Cx, I2C_CBx->CommCb.bAddr, I2C_CBx->CommCb.bDirection); break; // * 在主模式下设备地址字节发送成功 EV6 case I2C_EVENT_MASTER_MODE_SELECTED: //* Clear EV6 by set again the PE bit I2C_CBx->I2Cx->CR |= 0x20; if (I2C_CBx->CommCb.bDirection == I2C_MODE_TRANSMITTER) { //* 写I2C // * 传输设备子地址 I2C_SendData(I2C_CBx->I2Cx, *I2C_CBx->CommCb.pData++);//EV8 just after EV6 I2C_CBx->CommCb.iSize--; } else { //* 读I2C数据 if(I2C_CBx->CommCb.iSize == 1) // * 接收数据为1个. I2C_AcknowledgeConfig(I2C_CBx->I2Cx, DISABLE); else I2C_AcknowledgeConfig(I2C_CBx->I2Cx, ENABLE); } break; // * 在主模式下已传输完成(子地址/数据) case I2C_EVENT_MASTER_BYTE_TRANSMITTED: // EV8 if(I2C_CBx->CommCb.iSize > 0) { I2C_SendData(I2C_CBx->I2Cx, *I2C_CBx->CommCb.pData++); I2C_CBx->CommCb.iSize--; } else { I2C_GenerateSTOP(I2C_CBx->I2Cx, ENABLE); //* 数据传输完毕,发送Stop condition // Post message tx over.. OSMboxPost(I2C_CBx->pEventMB, (void *)MBOX_I2C_WRITE_DATA); } break; // * 在主模式下已接收完成 case I2C_EVENT_MASTER_BYTE_RECEIVED: // EV7 *I2C_CBx->CommCb.pData++ = I2C_ReceiveData(I2C_CBx->I2Cx); I2C_CBx->CommCb.iSize--; if(I2C_CBx->CommCb.iSize == 1) { I2C_AcknowledgeConfig(I2C_CBx->I2Cx, DISABLE); //* 最后一个数据接收到后发送NACK // *下次发送非应答信号 } if(I2C_CBx->CommCb.iSize == 0) { //* Send STOP Condition I2C_GenerateSTOP(I2C_CBx->I2Cx, ENABLE); OSMboxPost(I2C_CBx->pEventMB, (void *)MBOX_I2C_READ_DATA); } break; default: break; } }
//File : I2CDev.h //Created by : Kuang Hao #ifndef _I2CDEV_H_ #define _I2CDEV_H_
//* I2C通信控制块 typedef struct { INT8U bAddr; //* 存储发送地址 INT32U iSize; //* 存储写字节数 INT8U *pData; //* 存储写的数据的指针 INT8U bDirection; //* 数据传输方向 } tI2C_COMM_CB; //* I2C控制块 typedef struct { I2C_TypeDef *I2Cx; OS_EVENT *pEventSem; // * Semaphore OS_EVENT *pEventMB; // * Message box tI2C_COMM_CB CommCb; } tI2C_CB;
#define I2C_COMM_TIMEOUT_TICKS OS_TICKS_PER_SEC #define I2C_BUS_COUNT 2 #define I2C_OWN_ADDR_0 0xA2 #define I2C_OWN_ADDR_1 0xA2
#define MBOX_I2C_WRITE_SUB 1 #define MBOX_I2C_WRITE_DATA 2 #define MBOX_I2C_READ_DATA 3
#define I2C_EEPROM_ADDR 0xA0 //* CAT1025器件从地址
extern tI2C_CB _I2CCtrlBlock[I2C_BUS_COUNT]; #define I2C_CB0 &_I2CCtrlBlock[0] #define I2C_CB1 &_I2CCtrlBlock[1] static void __InitI2CGPIO(void); static void __InitI2CCB(void); static INT8U __WriteI2CByte(tI2C_CB *I2C_CBx, INT8U bSlaveAddr, INT8U *bData, INT32U iDataSize, INT8U bDirection); void InitI2C(u16 I2C0Addr, u16 I2C1Addr); INT32U WriteI2CData(tI2C_CB *I2C_CBx, INT8U bSlaveAddr, // * 从设备地址 INT8U *pData, // * 写入的数据 INT32U iDataSize // * 传输的数据长度,不包括子地址长度. ); INT32U ReadI2CData(tI2C_CB *I2C_CBx, INT8U bSlaveAddr, // * 从设备地址 INT16U iSubAddr, // * 从设备子地址 INT8U bSubAddrLen, // * 子地址长度 0 ~ 2 INT8U *pData, // * 读取的数据 INT32U iDataSize // * 传输的数据长度,不包括子地址长度. ); void I2CIRQService(tI2C_CB *I2C_CBx); #endif
|
|