| 
 
| 我在调试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
 
 
 
 | 
 |