void i2cMgr_t::SendAddrRX() { I2C_Send7bitAddress(I2C1, ((CmdToRead->Address) << 1), I2C_Direction_Receiver); Delay.Reset(&Timer); }
/** * @brief Reads a block of data from the EEPROM. * @param pBuffer : pointer to the buffer that receives the data read from * the EEPROM. * @param ReadAddr : EEPROM's internal address to read from. * @param NumByteToRead : pointer to the variable holding number of bytes to * read from the EEPROM. * * @note The variable pointed by NumByteToRead is reset to 0 when all the * data are read from the EEPROM. Application should monitor this * variable in order know when the transfer is complete. * * @note When number of data to be read is higher than 1, this function just * configure the communication and enable the DMA channel to transfer data. * Meanwhile, the user application may perform other tasks. * When number of data to be read is 1, then the DMA is not used. * * @retval None */ void sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead) { /* Set the pointer to the Number of data to be read. This pointer will be used by the DMA Transfer Completer interrupt Handler in order to reset the variable to 0. User should check on this variable in order to know if the DMA transfer has been complete or not. */ sEEDataReadPointer = NumByteToRead; /*!< While the bus is busy */ while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) { } /*!< Send START condition */ I2C_GenerateSTART(sEE_I2C, ENABLE); /*!< Test on EV5 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { } /*!< Send EEPROM address for write */ I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); /*!< Test on EV6 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { } #ifdef sEE_M24C08 /*!< Send the EEPROM's internal address to read from: Only one byte address */ I2C_SendData(sEE_I2C, ReadAddr); #elif defined (sEE_M24C64_32) /*!< Send the EEPROM's internal address to read from: MSB of the address first */ I2C_SendData(sEE_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8)); /*!< Test on EV8 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { } /*!< Send the EEPROM's internal address to read from: LSB of the address */ I2C_SendData(sEE_I2C, (uint8_t)(ReadAddr & 0x00FF)); #endif /*!< sEE_M24C08 */ /*!< Test on EV8 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { } /*!< Send STRAT condition a second time */ I2C_GenerateSTART(sEE_I2C, ENABLE); /*!< Test on EV5 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { } /*!< Send EEPROM address for read */ I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Receiver); /*!< Test on EV6 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { } /* If number of data to be read is 1, then DMA couldn't be used */ if ((uint16_t)(*NumByteToRead) < 2) { /*!< Disable Acknowledgement */ I2C_AcknowledgeConfig(sEE_I2C, DISABLE); /*!< Send STOP Condition */ I2C_GenerateSTOP(sEE_I2C, ENABLE); /*!< Test on EV7 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) { } /*!< Read a byte from the EEPROM */ *pBuffer = I2C_ReceiveData(sEE_I2C); /*!< Decrement the read bytes counter */ (uint16_t)(*NumByteToRead)--; /*!< Enable Acknowledgement to be ready for another reception */ I2C_AcknowledgeConfig(sEE_I2C, ENABLE); } /* DMA could be used for number of data higher than 1 */ else { /* Configure the DMA Rx Channel with the buffer address and the buffer size */ sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint16_t)(*NumByteToRead), sEE_DIRECTION_RX); /* Inform the DMA that the next End Of Transfer Signal will be the last one */ I2C_DMALastTransferCmd(sEE_I2C, ENABLE); /* Enable the DMA Rx Channel */ DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, ENABLE); } }
bool clMPU6050::I2C_BufferRead(u8 slaveAddr, u8* pBuffer, u8 readAddr, u16 NumByteToRead) { // Wait while the bus is busy this->restartTimeoutTimer(); while(I2C_GetFlagStatus(this->i2c, I2C_FLAG_BUSY)){ if(this->getTimeoutTimerTime() > 20*this->timeForOneByte){ return false; } } // Send START condition I2C_GenerateSTART(this->i2c, ENABLE); // Check if START condition has been sent by checking the SB bit in SR 1, // this flag is cleared by reading SR1 and writing to DR, this will be done when sending the slave address. bool startConditionSent = false; this->restartTimeoutTimer(); while(!startConditionSent){ startConditionSent = this->i2c->SR1 && BIT0; if(this->getTimeoutTimerTime() > 20*this->timeForOneByte){ return false; } } // Send MPU6050 address for write I2C_Send7bitAddress(this->i2c, slaveAddr, I2C_Direction_Transmitter); // Wait until the slave has acknowledged the address. To do this, we check the ADDR bit // in SR1. This bit is cleared by subsequently reading SR1 and SR2. this->restartTimeoutTimer(); bool addressHasBeenReceived = false; while(!addressHasBeenReceived){ addressHasBeenReceived = this->i2c->SR1 && BIT1; if(this->getTimeoutTimerTime() > 20*this->timeForOneByte){ return false; } } // Clear ADDR flag by reading SR2; variable is declared as volatile to keep the compiler from optimizing it away. volatile uint16_t tmp = this->i2c->SR2; // Send the MPU6050's internal address to read from I2C_SendData(this->i2c, readAddr); // Wait until the byte transfer has been finished by checking on the BTF bit in SR1. It will // be cleared by the next read operation of the DR register. this->restartTimeoutTimer(); bool byteHasBeenTransmitted = false; while(!byteHasBeenTransmitted){ byteHasBeenTransmitted = this->i2c->SR1 && BIT2; if(this->getTimeoutTimerTime() > 20*this->timeForOneByte){ return false; } } // Send START condition a second time I2C_GenerateSTART(this->i2c, ENABLE); // Check if START condition has been sent by checking the SB bit in SR 1, // this flag is cleared by reading SR1 and writing to DR, this will be done when sending the slave address. startConditionSent = false; this->restartTimeoutTimer(); while(!startConditionSent){ startConditionSent = this->i2c->SR1 && BIT0; if(this->getTimeoutTimerTime() > 20*this->timeForOneByte){ return false; } } // Send MPU6050 address for read I2C_Send7bitAddress(this->i2c, slaveAddr, I2C_Direction_Receiver); // Wait until the slave has acknowledged the address. To do this, we check the ADDR bit // in SR1. This bit is cleared by subsequently reading SR1 and SR2. this->restartTimeoutTimer(); addressHasBeenReceived = false; while(!addressHasBeenReceived){ addressHasBeenReceived = this->i2c->SR1 && BIT1; if(this->getTimeoutTimerTime() > 20*this->timeForOneByte){ return false; } } // Clear ADDR flag by reading SR2: tmp = this->i2c->SR2; I2C_GenerateSTOP(this->i2c, ENABLE); /* // Read in bytes sent by the slave: // If we are about to receive 1 single byte, there is no need to acknowledge it, since the last byte // is not acknowledged. If we will receive more than one byte, every byte except the last one has to be acknowledged // by the master. I2C_AcknowledgeConfig(this->i2c, ENABLE); if(NumByteToRead == 1){ I2C_AcknowledgeConfig(this->i2c, DISABLE); } // While there is data to be read: uint32_t timeoutTime = 20* NumByteToRead * this->timeForOneByte; this->restartTimeoutTimer(); while(NumByteToRead > 0) { // Check for timeout: if(this->getTimeoutTimerTime() > timeoutTime){ return false; } // When we are about to receive the last byte: if(NumByteToRead == 1) { // Disable Acknowledgement: I2C_AcknowledgeConfig(this->i2c, DISABLE); } // Check whether a byte has been received: bool newByteReceived = this->i2c->SR1 && BIT6; if(newByteReceived) { newByteReceived = false; // Read a byte from the MPU6050 *pBuffer = this->i2c->DR; // Point to the location where the next byte will be saved. pBuffer++; // Decrement the read bytes counter. NumByteToRead--; } } // We have received all bytes, send STOP condition. I2C_GenerateSTOP(this->i2c, ENABLE); return true; */ }
/** * @brief Writes more than one byte to the EEPROM with a single WRITE cycle. * * @note The number of bytes (combined to write start address) must not * cross the EEPROM page boundary. This function can only write into * the boundaries of an EEPROM page. * This function doesn't check on boundaries condition (in this driver * the function sEE_WriteBuffer() which calls sEE_WritePage() is * responsible of checking on Page boundaries). * * @param pBuffer : pointer to the buffer containing the data to be written to * the EEPROM. * @param WriteAddr : EEPROM's internal address to write to. * @param NumByteToWrite : pointer to the variable holding number of bytes to * be written into the EEPROM. * * @note The variable pointed by NumByteToWrite is reset to 0 when all the * data are written to the EEPROM. Application should monitor this * variable in order know when the transfer is complete. * * @note This function just configure the communication and enable the DMA * channel to transfer data. Meanwhile, the user application may perform * other tasks in parallel. * * @retval sEE_OK (0) if operation is correctly performed, else return value * different from sEE_OK (0) or the timeout user callback. */ uint32_t sEE_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite) { /* Set the pointer to the Number of data to be written. This pointer will be used by the DMA Transfer Completer interrupt Handler in order to reset the variable to 0. User should check on this variable in order to know if the DMA transfer has been complete or not. */ sEEDataWritePointer = NumByteToWrite; /*!< While the bus is busy */ sEETimeout = sEE_LONG_TIMEOUT; while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send START condition */ I2C_GenerateSTART(sEE_I2C, ENABLE); /*!< Test on EV5 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send EEPROM address for write */ sEETimeout = sEE_FLAG_TIMEOUT; I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); /*!< Test on EV6 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } #ifdef sEE_M24C08 /*!< Send the EEPROM's internal address to write to : only one byte Address */ I2C_SendData(sEE_I2C, WriteAddr); #elif defined(sEE_M24C64_32) /*!< Send the EEPROM's internal address to write to : MSB of the address first */ I2C_SendData(sEE_I2C, (uint8_t)((WriteAddr & 0xFF00) >> 8)); /*!< Test on EV8 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send the EEPROM's internal address to write to : LSB of the address */ I2C_SendData(sEE_I2C, (uint8_t)(WriteAddr & 0x00FF)); #endif /*!< sEE_M24C08 */ /*!< Test on EV8 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /* Configure the DMA Tx Channel with the buffer address and the buffer size */ sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint8_t)(*NumByteToWrite), sEE_DIRECTION_TX); /* Enable the DMA Tx Stream */ DMA_Cmd(sEE_I2C_DMA_STREAM_TX, ENABLE); /* If all operations OK, return sEE_OK (0) */ return sEE_OK; }
void I2C::EventIRQ() { static uint32_t I2C_Status=0; static u8 timeOut=0; I2C_Status = I2C_GetLastEvent(mI2C); switch(I2C_Status)//查询中断事件类型 { case I2C_EVENT_MASTER_MODE_SELECT: //EV5 //SB、BUSY、MSL位置位 if(mState==STATE_SEND_ADW)//发送从机地址+写信号 { #ifdef I2C_USE_DMA if(mUseDma) { mI2C->CR2 &= ~I2C_IT_BUF; //使用DMA,关闭BUF中断 mI2C->CR2 |= I2C_CR2_DMAEN; //使能IIC DMA传输 } #endif I2C_Send7bitAddress(mI2C,mCurrentCmd.slaveAddr,I2C_Direction_Transmitter); mState = STATE_SEND_DATA;//状态设置为需要发送数据(发送寄存器地址) #ifdef I2C_USE_DMA if(mUseDma) { /* I2Cx Common Channel Configuration */ if(mCurrentCmd.cmdType>=I2C_WRITE_BYTE)//写模式 { mDMA_InitStructure.DMA_BufferSize = mCurrentCmd.outDataLen; } else //读模式 设置长度为1 因为发送一个字节后需要再次发送起始信号 { mDMA_InitStructure.DMA_BufferSize = 1; } mDMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)&mCurrentCmd.DataOut[0]; mDMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST; DMA_Init(mDmaTxChannel,&mDMA_InitStructure); DMA_Cmd(mDmaTxChannel, ENABLE); } #endif } else if(mState==STATE_SEND_ADR)//发送从机地址+读信号 { I2C_Send7bitAddress(mI2C,mCurrentCmd.slaveAddr,I2C_Direction_Receiver); mState = STATE_REVEIVE_DATA;//状态设置为需要发送数据(发送寄存器地址) #ifdef I2C_USE_DMA if(mUseDma) { if( mCurrentCmd.cmdType==I2C_READ_BYTE)//接收一个字节,不能使用DMA,使用中断的方式 { mI2C->CR2 |= I2C_IT_BUF; //接收一个字节,打开 BUF中断,不使用DMA mI2C->CR2 &= ~I2C_CR2_DMAEN; //失能IIC DMA传输 } else //接收的字节数大于1,使用DMA { mI2C->CR2|=I2C_CR2_LAST;//使能接收最后一位时发送NACK mI2C->CR2 &= ~I2C_IT_BUF; //使用DMA,关闭BUF中断 mI2C->CR2 |= I2C_CR2_DMAEN; //使能IIC DMA传输 mDMA_InitStructure.DMA_BufferSize = mCurrentCmd.inDataLen; mDMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)mCurrentCmd.pDataIn; mDMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; DMA_Init(mDmaRxChannel,&mDMA_InitStructure); DMA_Cmd(mDmaRxChannel, ENABLE); } } #endif } break; case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED://EV6 //已: I2C_Send7bitAddress(W) 应: I2C_SendData() #ifndef I2C_USE_DMA // I2C->CR1 |= I2C_CR1_PE; I2C_SendData(mI2C,mCurrentCmd.DataOut[0]);//发送寄存器地址或者命令 ++mIndex_Send;//发送计数下标后移 --mCurrentCmd.outDataLen;//需要发送的数据长度减1 #else if(mUseDma==false) { // I2C->CR1 |= I2C_CR1_PE; I2C_SendData(mI2C,mCurrentCmd.DataOut[0]);//发送寄存器地址或者命令 ++mIndex_Send;//发送计数下标后移 --mCurrentCmd.outDataLen;//需要发送的数据长度减1 } #endif break; case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED://EV6 //已: I2C_Send7bitAddress(R) if(mCurrentCmd.cmdType==I2C_READ_BYTE)//只接收一个字节 { I2C_AcknowledgeConfig(mI2C,DISABLE);//关应答 I2C_GenerateSTOP(mI2C,ENABLE);//产生停止信号 } break; case I2C_EVENT_MASTER_BYTE_RECEIVED://EV7 //数据到达,接收数据 if(mState==STATE_REVEIVE_DATA)//防止标志没来得及清掉,重复进入 { #ifdef I2C_USE_DMA if(mUseDma) { if(mCurrentCmd.cmdType==I2C_READ_BYTE)//只接收一个字节 { (*mCurrentCmd.pDataIn) = I2C_ReceiveData(mI2C); //保存接收到的数据 mI2C->CR2 &= ~I2C_IT_BUF; //使用DMA,关闭BUF中断 if(mCurrentCmd.isRecordInterval)//需要记录两次执行相同命令的间隔 mCurrentCmd.pDevice->Updated(); //检查队列是否为空 if(mCmdQueue.Size()>0)//队列不为空 { mCmdQueue.Get(mCurrentCmd);//下一个命令出队 //都要先发送从机地址+写信号 mState = STATE_SEND_ADW;//标志设置为需要发送从机地址+写信号 mIndex_Send = 0;//发送、接收计数下标清零 I2C_AcknowledgeConfig(mI2C,ENABLE); //使能应答 I2C_GenerateSTART(mI2C,ENABLE); //产生启动信号 } else//队列为空, { mState=STATE_READY;//将状态设置为 准备好发送 模式 } } } else { (*mCurrentCmd.pDataIn) = I2C_ReceiveData(mI2C); ++mCurrentCmd.pDataIn;//下标后移 --mCurrentCmd.inDataLen;//需要接收数据计数减一 if(mCurrentCmd.inDataLen==1)//还剩最后一个字节需要接收 { I2C_AcknowledgeConfig(mI2C,DISABLE);//关应答 I2C_GenerateSTOP(mI2C,ENABLE); //产生停止信号 } else if(mCurrentCmd.inDataLen==0)//接收完毕 { if(mCurrentCmd.isRecordInterval)//需要记录两次执行相同命令的间隔 mCurrentCmd.pDevice->Updated(); //检查队列是否为空 if(mCmdQueue.Size()>0)//队列不为空 { mCmdQueue.Get(mCurrentCmd);//下一个命令出队 mState = STATE_SEND_ADW;//标志设置为需要发送从机地址+写信号 mIndex_Send = 0;//发送、接收计数下标清零 I2C_AcknowledgeConfig(mI2C,ENABLE); //使能应答 I2C_GenerateSTART(mI2C,ENABLE); //产生启动信号 } else//队列为空, { mState=STATE_READY;//将状态设置为 准备好发送 模式 } } } #else (*mCurrentCmd.pDataIn) = I2C_ReceiveData(mI2C); ++mCurrentCmd.pDataIn;//下标后移 --mCurrentCmd.inDataLen;//需要接收数据计数减一 if(mCurrentCmd.inDataLen==1)//还剩最后一个字节需要接收 { I2C_AcknowledgeConfig(mI2C,DISABLE);//关应答 I2C_GenerateSTOP(mI2C,ENABLE); //产生停止信号 } else if(mCurrentCmd.inDataLen==0)//接收完毕 { if(mCurrentCmd.recordIntervalNumber)//需要记录两次执行相同命令的间隔 mCurrentCmd.pDevice->Updated(); //检查队列是否为空 if(mCmdQueue.Size()>0)//队列不为空 { mCmdQueue.Get(mCurrentCmd);//下一个命令出队 mState = STATE_SEND_ADW;//标志设置为需要发送从机地址+写信号 mIndex_Send = 0;//发送、接收计数下标清零 I2C_AcknowledgeConfig(mI2C,ENABLE); //使能应答 I2C_GenerateSTART(mI2C,ENABLE); //产生启动信号 } else//队列为空, { mState=STATE_READY;//将状态设置为 准备好发送 模式 } } #endif } break; case I2C_EVENT_MASTER_BYTE_TRANSMITTED: //EV8_2 //已: I2C_SendData() if(STATE_SEND_DATA==mState)//防止标志没来得及清掉,重复进入 { #ifdef I2C_USE_DMA if(mUseDma) { if(0==DMA_GetCurrDataCounter(mDmaTxChannel) && mState == STATE_SEND_DATA)//检查是否发送完毕 { DMA_Cmd(mDmaTxChannel, DISABLE);//关DMA if(mCurrentCmd.cmdType >= I2C_WRITE_BYTE)//处于写模式 单字节或者多字节 { I2C_GenerateSTOP(mI2C,ENABLE);//产生停止信号 if(mCurrentCmd.isRecordInterval)//需要记录两次执行相同命令的间隔 mCurrentCmd.pDevice->Updated(); //判断队列是否为空 if(mCmdQueue.Size()>0)//队列不为空 { mCmdQueue.Get(mCurrentCmd);//下一个命令出队 //都要先发送从机地址+写信号 mState = STATE_SEND_ADW;//标志设置为需要发送从机地址+写信号 mIndex_Send = 0;//发送、接收计数下标清零 I2C_AcknowledgeConfig(mI2C,ENABLE); //使能应答 I2C_GetLastEvent(mI2C);//!!这里再次获取一下状态的原因其实是起延时的作用,等待busy位复位 //因为只有在busy位为0时才可以设置start位才有用,否则可能导致开始信号无法发送的情况 /* Delay::Us(1); */ /* usart1<<"ok\n"; */ I2C_GenerateSTART(mI2C,ENABLE); //产生启动信号 } else//队列为空, { mState=STATE_READY;//将状态设置为 准备好发送 模式 } } else//处于读模式 { mState = STATE_SEND_ADR;//状态设置为 发送从机地址+读 I2C_GenerateSTART(mI2C,ENABLE);//起始信号 } } } else { if(mCurrentCmd.outDataLen>0)//还需要发送数据 { I2C_SendData(mI2C,mCurrentCmd.DataOut[mIndex_Send++]);//发送寄存器地址或者命令 --mCurrentCmd.outDataLen;//需要发送的数据长度减1 } else//数据已经发送完成 { if(mCurrentCmd.cmdType >= I2C_WRITE_BYTE)//处于写模式 单字节或者多字节 { //已经写完,发送停止信号 I2C_GenerateSTOP(mI2C,ENABLE);//产生停止信号 if(mCurrentCmd.isRecordInterval)//需要记录两次执行相同命令的间隔 mCurrentCmd.pDevice->Updated(); //判断队列是否为空 if(mCmdQueue.Size()>0)//队列不为空 { mCmdQueue.Get(mCurrentCmd);//下一个命令出队 mState = STATE_SEND_ADW;//标志设置为需要发送从机地址+写信号 mIndex_Send = 0;//发送、接收计数下标清零 I2C_AcknowledgeConfig(mI2C,ENABLE); //使能应答 I2C_GetLastEvent(mI2C);//!!这里再次获取一下状态的原因其实是起延时的作用,等待busy位复位 //因为只有在busy位为0时才可以设置start位才有用,否则可能导致开始信号无法发送的情况 I2C_GenerateSTART(mI2C,ENABLE); //产生启动信号 } else//队列为空, { mState=STATE_READY;//将状态设置为 准备好发送 模式 } } else//处于读模式 { mState = STATE_SEND_ADR;//状态设置为 发送从机地址+读 I2C_GenerateSTART(mI2C,ENABLE);//起始信号 } } } #else if(mCurrentCmd.outDataLen>0)//还需要发送数据 { I2C_SendData(mI2C,mCurrentCmd.DataOut[mIndex_Send++]);//发送寄存器地址或者命令 --mCurrentCmd.outDataLen;//需要发送的数据长度减1 } else//数据已经发送完成 { if(mCurrentCmd.cmdType >= I2C_WRITE_BYTE)//处于写模式 单字节或者多字节 { //已经写完,发送停止信号 I2C_GenerateSTOP(mI2C,ENABLE);//产生停止信号 if(mCurrentCmd.isRecordInterval)//需要记录两次执行相同命令的间隔 mCurrentCmd.pDevice->Updated(); //判断队列是否为空 if(mCmdQueue.Size()>0)//队列不为空 { mCmdQueue.Get(mCurrentCmd);//下一个命令出队 mState = STATE_SEND_ADW;//标志设置为需要发送从机地址+写信号 mIndex_Send = 0;//发送、接收计数下标清零 I2C_AcknowledgeConfig(mI2C,ENABLE); //使能应答 I2C_GetLastEvent(mI2C);//!!这里再次获取一下状态的原因其实是起延时的作用,等待busy位复位 //因为只有在busy位为0时才可以设置start位才有用,否则可能导致开始信号无法发送的情况 I2C_GenerateSTART(mI2C,ENABLE); //产生启动信号 } else//队列为空, { mState=STATE_READY;//将状态设置为 准备好发送 模式 } } else//处于读模式 { mState = STATE_SEND_ADR;//状态设置为 发送从机地址+读 I2C_GenerateSTART(mI2C,ENABLE);//起始信号 } } #endif } else { ++timeOut; if(timeOut>3) { Soft_Reset(); mState = STATE_ERROR;//状态设置为错误状态 } } break; // case I2C_EVENT_MASTER_BYTE_TRANSMITTING://EV8 /* TRA, BUSY, MSL, TXE flags */ // break; case 0x00030044://接收数据时出现数据溢出错误,DR为读出, I2C_ReceiveData(mI2C); //读出数据,清除BTF标志 break; case 0x00000010: //STOPF :从机收到停止信号,但本程序中并没有考虑从机模式,在这里判定为出错 //(如果总线上没有另外的主机,可能是由于:当主机发送完数据后(主动产生停止信号后)自动进入从机模式 //而此时比如sda和scl线接触不良,将导致产生错误的停止信号,从而出现此中断,故判定为断线,将iic设备关闭) Soft_Reset(); mState = STATE_ERROR;//状态设置为错误状态 break; case 0x00000040: I2C_ReceiveData(mI2C); //读出数据,清除RxNE标志 break; } if(I2C_Status!=I2C_EVENT_MASTER_BYTE_TRANSMITTED)// timeOut=0; if((I2C_Status&0x00010000)==0)//从机模式,主机主动产生停止信号之后便会进入从机模式 { // Soft_Reset(); // mState = STATE_ERROR;//状态设置为错误状态 } }
extern hal_result_t hal_i2c4hal_hid_standby(hal_i2c4hal_port_t port, uint8_t devaddr) { volatile uint16_t tmpSR1 = 0; volatile uint32_t trials = 0; volatile uint32_t timeout = 0; I2C_TypeDef* I2Cx = (hal_i2c4hal_port1 == port) ? (I2C1) : (I2C2); #warning --> ci sono tre i2c errore ........... // While the bus is busy timeout = s_hal_i2c4hal_timeout_long; while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // keep looping till the slave acknowledge his address or maximum number of trials is reached while(1) { /*!< Send START condition */ I2C_GenerateSTART(I2Cx, ENABLE); /*!< Test on EV5 and clear it */ timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } /*!< Send EEPROM address for write */ I2C_Send7bitAddress(I2Cx, devaddr, I2C_Direction_Transmitter); /* Wait for ADDR flag to be set (Slave acknowledged his address) */ timeout = s_hal_i2c4hal_timeout_long; do { /* Get the current value of the SR1 register */ tmpSR1 = (I2Cx)->SR1; /* Update the timeout value and exit if it reach 0 */ if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } /* Keep looping till the Address is acknowledged or the AF (ack failure) flag is set (address not acknowledged at time) */ while((tmpSR1 & (I2C_SR1_ADDR | I2C_SR1_AF)) == 0); /* Check if the ADDR flag has been set */ if (tmpSR1 & I2C_SR1_ADDR) { /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already been read) */ (void)(I2Cx)->SR2; /*!< STOP condition */ I2C_GenerateSTOP(I2Cx, ENABLE); /* Exit the function */ return hal_res_OK; } else { /*!< Clear AF flag */ I2C_ClearFlag(I2Cx, I2C_FLAG_AF); } /* Check if the maximum allowed number of trials has been reached */ if (s_hal_i2c4hal_ackaddress_maxtrials == trials++) { /* If the maximum number of trials has been reached, exit the function */ return s_hal_i2c4hal_timeoutexpired(); } } }
static hal_result_t s_hal_i2c4hal_write(hal_i2c4hal_port_t port, uint8_t devaddr, hal_i2c4hal_regaddr_t regaddr, uint8_t* data, uint16_t size) { hal_result_t res = hal_res_NOK_generic; uint8_t reg1byteadr = 0; volatile uint32_t timeout = 0; I2C_TypeDef* I2Cx = (hal_i2c4hal_port1 == port) ? (I2C1) : (I2C2); // uint8_t usedma = s_stm32i2c4hal_generics.use_dma[port-1]; /////////////////////////////////////// // wait until the bus is not busy anymore timeout = s_hal_i2c4hal_timeout_long; while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // send START condition I2C_GenerateSTART(I2Cx, ENABLE); // test on ev5 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // send address of device I2C_Send7bitAddress(I2Cx, devaddr, I2C_Direction_Transmitter); // test on ev6 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // send address of register inside the device if(1 == regaddr.numofbytes) { reg1byteadr = regaddr.bytes.one; I2C_SendData(I2Cx, reg1byteadr); // test on ev8 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } } else if(2 == regaddr.numofbytes) { reg1byteadr = regaddr.bytes.two & 0xFF00; // msb first I2C_SendData(I2Cx, reg1byteadr); // test on ev8 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } reg1byteadr = regaddr.bytes.two & 0x00FF; // then lsb I2C_SendData(I2Cx, reg1byteadr); // test on ev8 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } } // now we decide if it is dma or direct send // if(1 == size) // { // usedma = 0; // } // // if(0 == usedma) // { s_hal_i2c4hal_write_bytes(I2Cx, data, size); // } // else // { // s_stm32i2c4hal_write_withdma(I2Cx, data, size); // } ///////////////////////////////////////////////////////////// //s_stm32i2c4hal_i2c4hal_waitdevicestandbystate(port, devaddr); return(hal_res_OK); }
/** * @brief Writes a value in a register of the device through I2C. * @param RegisterAddr: The target register address * @param RegisterValue: The target register value to be written * @retval IOE_OK: if all operations are OK. Other value if error. */ uint8_t I2C_WriteDeviceRegister(uint8_t RegisterAddr, uint8_t RegisterValue) { uint32_t read_verif = 0; /* Begin the configuration sequence */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on EV5 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_SB)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Transmit the slave address and enable writing operation */ I2C_Send7bitAddress(IOE_I2C, IOE_ADDR, I2C_Direction_Transmitter); /* Test on EV6 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_ADDR)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Read status register 2 to clear ADDR flag */ IOE_I2C->SR2; /* Test on EV8_1 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_TXE)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Transmit the first address for r/w operations */ I2C_SendData(IOE_I2C, RegisterAddr); /* Test on EV8 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_TXE)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Prepare the register value to be sent */ I2C_SendData(IOE_I2C, RegisterValue); /* Test on EV8_2 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while ((!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_BTF))) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* End the configuration sequence */ I2C_GenerateSTOP(IOE_I2C, ENABLE); #ifdef VERIFY_WRITTENDATA /* Verify (if needed) that the loaded data is correct */ /* Read the just written register*/ read_verif = IOE_I2C_ReadDeviceRegister(RegisterAddr); /* Load the register and verify its value */ if (read_verif != RegisterValue) { /* Control data wrongly transferred */ read_verif = IOE_FAILURE; } else { /* Control data correctly transferred */ read_verif = 0; } #endif /* Return the verifying value: 0 (Passed) or 1 (Failed) */ return read_verif; }
/** * @brief Reads a register of the device through I2C without DMA. * @param RegisterAddr: The target register address (between 00x and 0x24) * @retval The value of the read register (0xAA if Timeout occurred) */ uint8_t I2C_ReadDeviceRegister(uint8_t RegisterAddr) { uint8_t tmp = 0; /* Enable the I2C peripheral */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on EV5 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_SB)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Disable Acknowledgement */ I2C_AcknowledgeConfig(IOE_I2C, DISABLE); /* Transmit the slave address and enable writing operation */ I2C_Send7bitAddress(IOE_I2C, IOE_ADDR, I2C_Direction_Transmitter); /* Test on EV6 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_ADDR)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Read status register 2 to clear ADDR flag */ IOE_I2C->SR2; /* Test on EV8 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_TXE)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Transmit the first address for r/w operations */ I2C_SendData(IOE_I2C, RegisterAddr); /* Test on EV8 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while ((!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_BTF))) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Regenerate a start condition */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on EV5 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_SB)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Transmit the slave address and enable writing operation */ I2C_Send7bitAddress(IOE_I2C, IOE_ADDR, I2C_Direction_Receiver); /* Test on EV6 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_ADDR)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Read status register 2 to clear ADDR flag */ IOE_I2C->SR2; /* Test on EV7 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_RXNE)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* End the configuration sequence */ I2C_GenerateSTOP(IOE_I2C, ENABLE); /* Load the register value */ tmp = I2C_ReceiveData(IOE_I2C); /* Enable Acknowledgement */ I2C_AcknowledgeConfig(IOE_I2C, ENABLE); /* Return the read value */ return tmp; }
/** * @brief Write to the configuration register of the LM75. * @param RegValue: sepecifies the value to be written to LM75 configuration * register. * @retval None */ uint8_t LM75_WriteConfReg(uint8_t RegValue) { uint8_t LM75_BufferTX = 0; LM75_BufferTX = (uint8_t)(RegValue); /* Test on BUSY Flag */ LM75_Timeout = LM75_LONG_TIMEOUT; while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Configure DMA Peripheral */ LM75_DMA_Config(LM75_DMA_TX, (uint8_t*)(&LM75_BufferTX), 1); /* Enable the I2C peripheral */ I2C_GenerateSTART(LM75_I2C, ENABLE); /* Test on SB Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB) == RESET) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Transmit the slave address and enable writing operation */ I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter); /* Test on ADDR Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Transmit the first address for r/w operations */ I2C_SendData(LM75_I2C, LM75_REG_CONF); /* Test on TXE FLag (data sent) */ LM75_Timeout = LM75_FLAG_TIMEOUT; while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF))) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Enable I2C DMA request */ I2C_DMACmd(LM75_I2C,ENABLE); /* Enable DMA TX Channel */ DMA_Cmd(LM75_DMA_TX_CHANNEL, ENABLE); /* Wait until DMA Transfer Complete */ LM75_Timeout = LM75_LONG_TIMEOUT; while (!DMA_GetFlagStatus(LM75_DMA_TX_TCFLAG)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Wait until BTF Flag is set before generating STOP */ LM75_Timeout = LM75_LONG_TIMEOUT; while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF))) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send STOP Condition */ I2C_GenerateSTOP(LM75_I2C, ENABLE); /* Disable DMA TX Channel */ DMA_Cmd(LM75_DMA_TX_CHANNEL, DISABLE); /* Disable I2C DMA request */ I2C_DMACmd(LM75_I2C,DISABLE); /* Clear DMA TX Transfer Complete Flag */ DMA_ClearFlag(LM75_DMA_TX_TCFLAG); return LM75_OK; }
/** * @brief Enables or disables the LM75. * @param NewState: specifies the LM75 new status. This parameter can be ENABLE * or DISABLE. * @retval None */ uint8_t LM75_ShutDown(FunctionalState NewState) { uint8_t LM75_BufferRX[2] ={0,0}; uint8_t LM75_BufferTX = 0; __IO uint8_t RegValue = 0; /* Test on BUSY Flag */ LM75_Timeout = LM75_LONG_TIMEOUT; while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Configure DMA Peripheral */ LM75_DMA_Config(LM75_DMA_RX, (uint8_t*)LM75_BufferRX, 2); /* Enable DMA NACK automatic generation */ I2C_DMALastTransferCmd(LM75_I2C, ENABLE); /* Enable the I2C peripheral */ I2C_GenerateSTART(LM75_I2C, ENABLE); /* Test on SB Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send device address for write */ I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter); /* Test on ADDR Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send the device's internal address to write to */ I2C_SendData(LM75_I2C, LM75_REG_CONF); /* Test on TXE FLag (data sent) */ LM75_Timeout = LM75_FLAG_TIMEOUT; while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF))) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send START condition a second time */ I2C_GenerateSTART(LM75_I2C, ENABLE); /* Test on SB Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send LM75 address for read */ I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Receiver); /* Test on ADDR Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Enable I2C DMA request */ I2C_DMACmd(LM75_I2C,ENABLE); /* Enable DMA RX Channel */ DMA_Cmd(LM75_DMA_RX_CHANNEL, ENABLE); /* Wait until DMA Transfer Complete */ LM75_Timeout = LM75_LONG_TIMEOUT; while (!DMA_GetFlagStatus(LM75_DMA_RX_TCFLAG)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send STOP Condition */ I2C_GenerateSTOP(LM75_I2C, ENABLE); /* Disable DMA RX Channel */ DMA_Cmd(LM75_DMA_RX_CHANNEL, DISABLE); /* Disable I2C DMA request */ I2C_DMACmd(LM75_I2C,DISABLE); /* Clear DMA RX Transfer Complete Flag */ DMA_ClearFlag(LM75_DMA_RX_TCFLAG); /*!< Get received data */ RegValue = (uint8_t)LM75_BufferRX[0]; /*---------------------------- Transmission Phase ---------------------------*/ /*!< Enable or disable SD bit */ if (NewState != DISABLE) { /*!< Enable LM75 */ LM75_BufferTX = RegValue & LM75_SD_RESET; } else { /*!< Disable LM75 */ LM75_BufferTX = RegValue | LM75_SD_SET; } /* Test on BUSY Flag */ LM75_Timeout = LM75_LONG_TIMEOUT; while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Configure DMA Peripheral */ LM75_DMA_Config(LM75_DMA_TX, (uint8_t*)(&LM75_BufferTX), 1); /* Enable the I2C peripheral */ I2C_GenerateSTART(LM75_I2C, ENABLE); /* Test on SB Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB) == RESET) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Transmit the slave address and enable writing operation */ I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter); /* Test on ADDR Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Transmit the first address for r/w operations */ I2C_SendData(LM75_I2C, LM75_REG_CONF); /* Test on TXE FLag (data sent) */ LM75_Timeout = LM75_FLAG_TIMEOUT; while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF))) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Enable I2C DMA request */ I2C_DMACmd(LM75_I2C,ENABLE); /* Enable DMA TX Channel */ DMA_Cmd(LM75_DMA_TX_CHANNEL, ENABLE); /* Wait until DMA Transfer Complete */ LM75_Timeout = LM75_LONG_TIMEOUT; while (!DMA_GetFlagStatus(LM75_DMA_TX_TCFLAG)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Wait until BTF Flag is set before generating STOP */ LM75_Timeout = LM75_LONG_TIMEOUT; while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF))) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send STOP Condition */ I2C_GenerateSTOP(LM75_I2C, ENABLE); /* Disable DMA TX Channel */ DMA_Cmd(LM75_DMA_TX_CHANNEL, DISABLE); /* Disable I2C DMA request */ I2C_DMACmd(LM75_I2C,DISABLE); /* Clear DMA TX Transfer Complete Flag */ DMA_ClearFlag(LM75_DMA_TX_TCFLAG); return LM75_OK; }
/** * @brief Read the configuration register from the LM75. * @param None * @retval LM75 configuration register value. */ uint8_t LM75_ReadConfReg(void) { uint8_t LM75_BufferRX[2] ={0,0}; /* Test on BUSY Flag */ LM75_Timeout = LM75_LONG_TIMEOUT; while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Configure DMA Peripheral */ LM75_DMA_Config(LM75_DMA_RX, (uint8_t*)LM75_BufferRX, 2); /* Enable DMA NACK automatic generation */ I2C_DMALastTransferCmd(LM75_I2C, ENABLE); /* Enable the I2C peripheral */ I2C_GenerateSTART(LM75_I2C, ENABLE); /* Test on SB Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send device address for write */ I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter); /* Test on ADDR Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send the device's internal address to write to */ I2C_SendData(LM75_I2C, LM75_REG_CONF); /* Test on TXE FLag (data sent) */ LM75_Timeout = LM75_FLAG_TIMEOUT; while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF))) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send START condition a second time */ I2C_GenerateSTART(LM75_I2C, ENABLE); /* Test on SB Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send LM75 address for read */ I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Receiver); /* Test on ADDR Flag */ LM75_Timeout = LM75_FLAG_TIMEOUT; while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Enable I2C DMA request */ I2C_DMACmd(LM75_I2C,ENABLE); /* Enable DMA RX Channel */ DMA_Cmd(LM75_DMA_RX_CHANNEL, ENABLE); /* Wait until DMA Transfer Complete */ LM75_Timeout = LM75_LONG_TIMEOUT; while (!DMA_GetFlagStatus(LM75_DMA_RX_TCFLAG)) { if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback(); } /* Send STOP Condition */ I2C_GenerateSTOP(LM75_I2C, ENABLE); /* Disable DMA RX Channel */ DMA_Cmd(LM75_DMA_RX_CHANNEL, DISABLE); /* Disable I2C DMA request */ I2C_DMACmd(LM75_I2C,DISABLE); /* Clear DMA RX Transfer Complete Flag */ DMA_ClearFlag(LM75_DMA_RX_TCFLAG); /*!< Return Temperature value */ return (uint8_t)LM75_BufferRX[0]; }
void Codec_WriteRegister(uint8_t RegisterAddr, uint8_t RegisterValue) //dodane ale zmodyfikowane, nie zwraca info o bledzie { /*!< While the bus is busy */ CODECTimeout = CODEC_LONG_TIMEOUT; while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY)) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback(); } /* Start the config sequence */ I2C_GenerateSTART(CODEC_I2C, ENABLE); /* Test on EV5 and clear it */ CODECTimeout = CODEC_FLAG_TIMEOUT; while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback(); } /* Transmit the slave address and enable writing operation */ I2C_Send7bitAddress(CODEC_I2C, CODEC_I2C_ADDRESS, I2C_Direction_Transmitter); /* Test on EV6 and clear it */ CODECTimeout = CODEC_FLAG_TIMEOUT; while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback(); } /* Transmit the first address for write operation */ I2C_SendData(CODEC_I2C, RegisterAddr); /* Test on EV8 and clear it */ CODECTimeout = CODEC_FLAG_TIMEOUT; while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback(); } /* Prepare the register value to be sent */ I2C_SendData(CODEC_I2C, RegisterValue); /*!< Wait till all data have been physically transferred on the bus */ CODECTimeout = CODEC_LONG_TIMEOUT; while(!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BTF)) { if((CODECTimeout--) == 0) Codec_TIMEOUT_UserCallback(); } /* End the configuration sequence */ I2C_GenerateSTOP(CODEC_I2C, ENABLE); #ifdef VERIFY_WRITTENDATA /* Verify that the data has been correctly written */ result = (Codec_ReadRegister(RegisterAddr) == RegisterValue)? 0:1; #endif /* VERIFY_WRITTENDATA */ /* Return the verifying value: 0 (Passed) or 1 (Failed) */ }
/******************************************************************************* * Function Name : I2C1_EV_IRQHandler * Description : This function handles I2C1 Event interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void I2C1_EV_IRQHandler(void) { switch (I2C_GetLastEvent(I2C1)) { case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */ if(Direction == Transmitter) { /* Master Transmitter ----------------------------------------------*/ /* Send slave Address for write */ I2C_Send7bitAddress(I2C1, I2C2_SLAVE_ADDRESS7, I2C_Direction_Transmitter); } else { /* Master Receiver -------------------------------------------------*/ /* Send slave Address for read */ I2C_Send7bitAddress(I2C1, I2C2_SLAVE_ADDRESS7, I2C_Direction_Receiver); } break; /* Master Transmitter --------------------------------------------------*/ /* Test on I2C1 EV6 and first EV8 and clear them */ case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* Send the first data */ I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx1_Idx++]); break; /* Test on I2C1 EV8 and clear it */ case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* Without BTF, EV8 */ if(Tx1_Idx < (Tx1BufferSize)) { /* Transmit I2C1 data */ I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx1_Idx++]); } else { I2C_TransmitPEC(I2C1, ENABLE); I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE); } break; case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* With BTF EV8-2 */ I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE); /* I2C1 Re-START Condition */ I2C_GenerateSTART(I2C1, ENABLE); break; /* Master Receiver -------------------------------------------------------*/ case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: if(Tx2BufferSize == 1) { /* Disable I2C1 acknowledgement */ I2C_AcknowledgeConfig(I2C1, DISABLE); /* Send I2C1 STOP Condition */ I2C_GenerateSTOP(I2C1, ENABLE); } break; /* Test on I2C1 EV7 and clear it */ case I2C_EVENT_MASTER_BYTE_RECEIVED: /* Store I2C1 received data */ I2C1_Buffer_Rx[Rx1_Idx++] = I2C_ReceiveData (I2C1); /* Disable ACK and send I2C1 STOP condition before receiving the last data */ if(Rx1_Idx == (Tx2BufferSize - 1)) { /* Disable I2C1 acknowledgement */ I2C_AcknowledgeConfig(I2C1, DISABLE); /* Send I2C1 STOP Condition */ I2C_GenerateSTOP(I2C1, ENABLE); } break; default: break; } }
/** * @brief Read from a device connected to I2C - cannot receive less than 2 bytes at a time * @param Pointer to the data string, number of bytes to read, device address, sub address * @retval I2C success/error code */ I2C_Returntype I2C_Read(uint8_t* Data_Pointer,uint8_t Bytes, uint8_t Addr, uint8_t Sub_Addr) {//Reads from an i2c device int8_t n=0; //0xFF as the Sub_Addr disables sub address uint16_t Time=0; if(Sub_Addr!=0xFF) { //0xFF disables this - so we wont setup addr pointer I2C_GenerateSTART( I2C1, ENABLE ); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { Time++; if(Time>I2C_TIMEOUT) return I2C_START_TIMEOUT; } Time=0; I2C_Send7bitAddress( I2C1, Addr, I2C_Direction_Transmitter ); //Address write while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { Time++; if(Time>I2C_TIMEOUT) return I2C_SACK_TIMEOUT; //Checks that the slave acknowledged if(SET==I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)) { I2C_ClearFlag(I2C1, I2C_FLAG_AF); I2C_GenerateSTOP( I2C1, ENABLE ); //Enable the STOP here - so hardware is ready again return I2C_SACK_FAILURE; //Slave did not ack } } Time=0; I2C_SendData( I2C1, Sub_Addr ); //Write sub address register while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { Time++; if(Time>I2C_TIMEOUT) return I2C_TX_TIMEOUT; } //I2C_GenerateSTOP( I2C1, ENABLE ); //This code doesnt _seem_ to be needed //while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)==SET); //Wait for bus to go inactive } Time=0; I2C_GenerateSTART( I2C1, ENABLE ); //Repeated start or the first start while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { Time++; if(Time>I2C_TIMEOUT) return I2C_RSTART_TIMEOUT; //note that if we disable sub addr, then a start error } //becomes a repeated start error Time=0; I2C_Send7bitAddress( I2C1, Addr|0x01, I2C_Direction_Receiver ); //Address to read while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { Time++; if(Time>I2C_TIMEOUT) return I2C_SACK_TIMEOUT; //Checks that the slave acknowledged if(SET==I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)) { I2C_ClearFlag(I2C1, I2C_FLAG_AF); I2C_GenerateSTOP( I2C1, ENABLE ); //Enable the STOP here - so hardware is ready again return I2C_SACK_FAILURE; //Slave did not ack } } //We now auto switch to rx mode if(Bytes>2) { //More than two bytes to receive Time=0; while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) { //Wait for the first byte Time++; if(Time>I2C_TIMEOUT) return I2C_RX_TIMEOUT; } for(;n<((int8_t)Bytes-3);n++) { Time=0; Data_Pointer[n]=I2C_ReceiveData(I2C1); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) { Time++; if(Time>I2C_TIMEOUT) return I2C_RX_TIMEOUT; } } Time=0; while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BTF)!=SET) { //Wait for two bytes to be received - ref man p712 Time++; if(Time>I2C_TIMEOUT) return I2C_RX_TIMEOUT; } I2C_AcknowledgeConfig(I2C1, DISABLE); //Do not ack the last byte Data_Pointer[n++]=I2C_ReceiveData(I2C1); //Third to last byte I2C_GenerateSTOP( I2C1, ENABLE ); //Enable the STOP here Data_Pointer[n++]=I2C_ReceiveData(I2C1); //Read the Penultimate from buffer Time=0; while(I2C_GetFlagStatus(I2C1,I2C_FLAG_RXNE)!=SET) { //Last byte received here with a NACK and STOP Time++; if(Time>I2C_TIMEOUT) return I2C_RX_TIMEOUT; } } else { I2C_AcknowledgeConfig(I2C1, DISABLE); //Do not ack the last byte Time=0; while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BTF)!=SET) { //Wait for two bytes to be received - ref man p713 Time++; if(Time>I2C_TIMEOUT) return I2C_RX_TIMEOUT; } I2C_GenerateSTOP( I2C1, ENABLE ); //Enable the STOP here Data_Pointer[n++]=I2C_ReceiveData(I2C1); //First byte to lowest location } Data_Pointer[n]=I2C_ReceiveData(I2C1); //Clear the buffer (last byte is in it) I2C_AcknowledgeConfig(I2C1, ENABLE); //Re-enable ACK return I2C_SUCCESS; //Exit ok }
/** * @brief Reads a buffer of 2 bytes from the device registers. * @param RegisterAddr: The target register adress (between 00x and 0x24) * @retval The data in the buffer containing the two returned bytes (in halfword). */ uint16_t I2C_ReadDataBuffer(uint32_t RegisterAddr) { uint8_t IOE_BufferRX[2] = {0x00, 0x00}; /* Enable the I2C peripheral */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on EV5 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_SB)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send device address for write */ I2C_Send7bitAddress(IOE_I2C, IOE_ADDR, I2C_Direction_Transmitter); /* Test on EV6 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_ADDR)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Read status register 2 to clear ADDR flag */ IOE_I2C->SR2; /* Test on EV8 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_TXE)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send the device's internal address to write to */ I2C_SendData(IOE_I2C, RegisterAddr); /* Send START condition a second time */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on EV5 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_SB)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send IO Expander address for read */ I2C_Send7bitAddress(IOE_I2C, IOE_ADDR, I2C_Direction_Receiver); /* Test on EV6 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_ADDR)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Disable Acknowledgement and set Pos bit */ I2C_AcknowledgeConfig(IOE_I2C, DISABLE); I2C_NACKPositionConfig(IOE_I2C, I2C_NACKPosition_Next); /* Read status register 2 to clear ADDR flag */ IOE_I2C->SR2; /* Test on EV7 and clear it */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_BTF)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send STOP Condition */ I2C_GenerateSTOP(IOE_I2C, ENABLE); /* Read the first byte from the IO Expander */ IOE_BufferRX[1] = I2C_ReceiveData(IOE_I2C); /* Read the second byte from the IO Expander */ IOE_BufferRX[0] = I2C_ReceiveData(IOE_I2C); /* Enable Acknowledgement and reset POS bit to be ready for another reception */ I2C_AcknowledgeConfig(IOE_I2C, ENABLE); I2C_NACKPositionConfig(IOE_I2C, I2C_NACKPosition_Current); /* return the data */ return ((uint16_t) IOE_BufferRX[0] | ((uint16_t)IOE_BufferRX[1]<< 8)); }
/** * @brief Main program * @param None * @retval None */ int main(void) { /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f10x_xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f10x.c file */ /* System clocks configuration ---------------------------------------------*/ RCC_Configuration(); /* GPIO configuration ------------------------------------------------------*/ GPIO_Configuration(); /* Enable I2C1 and I2C2 ----------------------------------------------------*/ I2C_Cmd(I2C1, ENABLE); I2C_Cmd(I2C2, ENABLE); /* I2C1 configuration ------------------------------------------------------*/ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = ClockSpeed; I2C_Init(I2C1, &I2C_InitStructure); /* I2C2 configuration ------------------------------------------------------*/ I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit; I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS10; I2C_Init(I2C2, &I2C_InitStructure); /*----- Transmission Phase -----*/ /* Send I2C1 START condition */ I2C_GenerateSTART(I2C1, ENABLE); /* Test on I2C1 EV5 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /* Send Header to I2C2 for write */ I2C_SendData(I2C1, HeaderAddressWrite); /* Test on I2C1 EV9 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_ADDRESS10)); /* Send I2C2 slave Address for write */ I2C_Send7bitAddress(I2C1, I2C2_SLAVE_ADDRESS7, I2C_Direction_Transmitter); /* Test on I2C2 EV1 and clear it */ while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED)); /* Test on I2C1 EV6 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* Send data */ while (RxIdx < BufferSize) { /* Send I2C1 data */ I2C_SendData(I2C1, I2C1_Buffer_Tx[TxIdx++]); /* Test on I2C2 EV2 and clear it */ while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_BYTE_RECEIVED)); /* Store received data on I2C2 */ I2C2_Buffer_Rx[RxIdx++] = I2C_ReceiveData(I2C2); /* Test on I2C1 EV8 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); } /* Send I2C1 STOP Condition */ I2C_GenerateSTOP(I2C1, ENABLE); /* Test on I2C2 EV4 and clear it */ while(!I2C_CheckEvent(I2C2, I2C_EVENT_SLAVE_STOP_DETECTED)); /* Clear I2C2 STOPF flag: read operation to I2C_SR1 followed by a write operation to I2C_CR1 */ (void)(I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF)); I2C_Cmd(I2C2, ENABLE); /* Check the corectness of written data */ TransferStatus = Buffercmp(I2C1_Buffer_Tx, I2C2_Buffer_Rx, BufferSize); /* TransferStatus = PASSED, if the transmitted and received data are equal */ /* TransferStatus = FAILED, if the transmitted and received data are different */ while (1) { } }
/** * @brief Reads a block of data from the MPU6050. * @param slaveAddr : slave address MPU6050_DEFAULT_ADDRESS * @param pBuffer : pointer to the buffer that receives the data read from the MPU6050. * @param readAddr : MPU6050's internal address to read from. * @param NumByteToRead : number of bytes to read from the MPU6050 ( NumByteToRead >1 only for the Mgnetometer readinf). * @return None */ void MPU6050_I2C_BufferRead( u8 slaveAddr, u8* pBuffer, u8 readAddr, u16 NumByteToRead ) { /* ENTR_CRT_SECTION(); */ /* While the bus is busy */ while( I2C_GetFlagStatus( MPU6050_I2C, I2C_FLAG_BUSY ) ) ; /* Send START condition */ I2C_GenerateSTART( MPU6050_I2C, ENABLE ); /* Test on EV5 and clear it */ while( !I2C_CheckEvent( MPU6050_I2C, I2C_EVENT_MASTER_MODE_SELECT ) ) ; /* Send MPU6050 address for write */ I2C_Send7bitAddress( MPU6050_I2C, slaveAddr, I2C_Direction_Transmitter ); /* Test on EV6 and clear it */ while( !I2C_CheckEvent( MPU6050_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) ) ; /* Clear EV6 by setting again the PE bit */ I2C_Cmd( MPU6050_I2C, ENABLE ); /* Send the MPU6050's internal address to write to */ I2C_SendData( MPU6050_I2C, readAddr ); /* Test on EV8 and clear it */ while( !I2C_CheckEvent( MPU6050_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) ) ; /* Send STRAT condition a second time */ I2C_GenerateSTART( MPU6050_I2C, ENABLE ); /* Test on EV5 and clear it */ while( !I2C_CheckEvent( MPU6050_I2C, I2C_EVENT_MASTER_MODE_SELECT ) ) ; /* Send MPU6050 address for read */ I2C_Send7bitAddress( MPU6050_I2C, slaveAddr, I2C_Direction_Receiver ); /* Test on EV6 and clear it */ while( !I2C_CheckEvent( MPU6050_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) ) ; /* While there is data to be read */ while( NumByteToRead ) { if( NumByteToRead == 1 ) { /* Disable Acknowledgement */ I2C_AcknowledgeConfig( MPU6050_I2C, DISABLE ); /* Send STOP Condition */ I2C_GenerateSTOP( MPU6050_I2C, ENABLE ); } /* Test on EV7 and clear it */ if( I2C_CheckEvent( MPU6050_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED ) ) { /* Read a byte from the MPU6050 */ *pBuffer = I2C_ReceiveData( MPU6050_I2C ); /* Point to the next location where the byte read will be saved */ pBuffer++; /* Decrement the read bytes counter */ NumByteToRead--; } } /* Enable Acknowledgement to be ready for another reception */ I2C_AcknowledgeConfig( MPU6050_I2C, ENABLE ); /* EXT_CRT_SECTION(); */ }
static hal_result_t s_i2c4hal_read(hal_i2c4hal_port_t port, uint8_t devaddr, hal_i2c4hal_regaddr_t regaddr, uint8_t* data, uint16_t size) { hal_result_t res = hal_res_NOK_generic; uint8_t reg1byteadr = 0; volatile uint32_t timeout = 0; I2C_TypeDef* I2Cx = (hal_i2c4hal_port1 == port) ? (I2C1) : (I2C2); // uint8_t usedma = s_stm32i2c4hal_generics.use_dma[port-1]; // wait until the bus is not busy anymore timeout = s_hal_i2c4hal_timeout_long; while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // send START condition I2C_GenerateSTART(I2Cx, ENABLE); // test on ev5 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // send address of device I2C_Send7bitAddress(I2Cx, devaddr, I2C_Direction_Transmitter); // test on ev6 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // send address of register to read inside the device if(1 == regaddr.numofbytes) { reg1byteadr = regaddr.bytes.one; I2C_SendData(I2Cx, reg1byteadr); // test on ev8 and clear it (ev8 is I2C_EVENT_MASTER_BYTE_TRANSMITTING ...) timeout = s_hal_i2c4hal_timeout_flag; #if 0 while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET) #else while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) #endif { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } } else if(2 == regaddr.numofbytes) { reg1byteadr = regaddr.bytes.two & 0xFF00; // msb first I2C_SendData(I2Cx, reg1byteadr); // test on ev8 and clear it timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } reg1byteadr = regaddr.bytes.two & 0x00FF; // then lsb I2C_SendData(I2Cx, reg1byteadr); // test on ev8 and clear it (ev8 is I2C_EVENT_MASTER_BYTE_TRANSMITTING ...) timeout = s_hal_i2c4hal_timeout_flag; #if 0 while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET) #else while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) #endif { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } } // send START condition a second time I2C_GenerateSTART(I2Cx, ENABLE); // test on ev5 timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // send address for read I2C_Send7bitAddress(I2Cx, devaddr, I2C_Direction_Receiver); //#warning --> w/ I2C_GetFlagStatus() the eeprom does not work. with I2C_CheckEvent() it works // wait on addr flag to be set //while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET) //{ //} timeout = s_hal_i2c4hal_timeout_flag; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if(0 == (timeout--)) return s_hal_i2c4hal_timeoutexpired(); } // if(1 == size) // { // usedma = 0; // } // if(0 == usedma) // { s_hal_i2c4hal_read_bytes(I2Cx, data, size); // } // else // { // s_stm32i2c4hal_read_withdma(I2Cx, data, size); // } return(hal_res_OK); }
/** * @brief Writes a value in a register of the device through I2C. * @param DeviceAddr: The address of the IOExpander, could be : IOE_1_ADDR * or IOE_2_ADDR. * @param RegisterAddr: The target register address * @param RegisterValue: The target register value to be written * @retval IOE_OK: if all operations are OK. Other value if error. */ uint8_t I2C_WriteDeviceRegister(uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t RegisterValue) { uint8_t read_verif = 0; uint8_t IOE_BufferTX = 0; /* Get Value to be written */ IOE_BufferTX = RegisterValue; /* Configure DMA Peripheral */ IOE_DMA_Config(IOE_DMA_TX, (uint8_t*)(&IOE_BufferTX)); /* Enable the I2C peripheral */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on SB Flag */ IOE_TimeOut = TIMEOUT_MAX; while (I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_SB) == RESET) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Transmit the slave address and enable writing operation */ I2C_Send7bitAddress(IOE_I2C, DeviceAddr, I2C_Direction_Transmitter); /* Test on ADDR Flag */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Transmit the first address for r/w operations */ I2C_SendData(IOE_I2C, RegisterAddr); /* Test on TXE FLag (data dent) */ IOE_TimeOut = TIMEOUT_MAX; while ((!I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_BTF))) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Enable I2C DMA request */ I2C_DMACmd(IOE_I2C,ENABLE); /* Enable DMA TX Channel */ DMA_Cmd(IOE_DMA_TX_STREAM, ENABLE); /* Wait until DMA Transfer Complete */ IOE_TimeOut = TIMEOUT_MAX; while (!DMA_GetFlagStatus(IOE_DMA_TX_STREAM,IOE_DMA_TX_TCFLAG)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Wait until BTF Flag is set before generating STOP */ IOE_TimeOut = 2 * TIMEOUT_MAX; while ((!I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_BTF))) { } /* Send STOP Condition */ I2C_GenerateSTOP(IOE_I2C, ENABLE); /* Disable DMA TX Channel */ DMA_Cmd(IOE_DMA_TX_STREAM, DISABLE); /* Disable I2C DMA request */ I2C_DMACmd(IOE_I2C,DISABLE); /* Clear DMA TX Transfer Complete Flag */ DMA_ClearFlag(IOE_DMA_TX_STREAM,IOE_DMA_TX_TCFLAG); #ifdef VERIFY_WRITTENDATA /* Verify (if needed) that the loaded data is correct */ /* Read the just written register*/ read_verif = I2C_ReadDeviceRegister(DeviceAddr, RegisterAddr); /* Load the register and verify its value */ if (read_verif != RegisterValue) { /* Control data wrongly transfered */ read_verif = IOE_FAILURE; } else { /* Control data correctly transfered */ read_verif = 0; } #endif /* Return the verifying value: 0 (Passed) or 1 (Failed) */ return (read_verif); }
/** * @brief Reads a block of data from the EEPROM. * @param pBuffer : pointer to the buffer that receives the data read from * the EEPROM. * @param ReadAddr : EEPROM's internal address to start reading from. * @param NumByteToRead : pointer to the variable holding number of bytes to * be read from the EEPROM. * * @note The variable pointed by NumByteToRead is reset to 0 when all the * data are read from the EEPROM. Application should monitor this * variable in order know when the transfer is complete. * * @note When number of data to be read is higher than 1, this function just * configures the communication and enable the DMA channel to transfer data. * Meanwhile, the user application may perform other tasks. * When number of data to be read is 1, then the DMA is not used. The byte * is read in polling mode. * * @retval sEE_OK (0) if operation is correctly performed, else return value * different from sEE_OK (0) or the timeout user callback. */ uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead) { /* Set the pointer to the Number of data to be read. This pointer will be used by the DMA Transfer Completer interrupt Handler in order to reset the variable to 0. User should check on this variable in order to know if the DMA transfer has been complete or not. */ sEEDataReadPointer = NumByteToRead; /*!< While the bus is busy */ sEETimeout = sEE_LONG_TIMEOUT; while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send START condition */ I2C_GenerateSTART(sEE_I2C, ENABLE); /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send EEPROM address for write */ I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); /*!< Test on EV6 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } #ifdef sEE_M24C08 /*!< Send the EEPROM's internal address to read from: Only one byte address */ I2C_SendData(sEE_I2C, ReadAddr); #elif defined (sEE_M24C64_32) /*!< Send the EEPROM's internal address to read from: MSB of the address first */ I2C_SendData(sEE_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8)); /*!< Test on EV8 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send the EEPROM's internal address to read from: LSB of the address */ I2C_SendData(sEE_I2C, (uint8_t)(ReadAddr & 0x00FF)); #endif /*!< sEE_M24C08 */ /*!< Test on EV8 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF) == RESET) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send STRAT condition a second time */ I2C_GenerateSTART(sEE_I2C, ENABLE); /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send EEPROM address for read */ I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Receiver); /* If number of data to be read is 1, then DMA couldn't be used */ /* One Byte Master Reception procedure (POLLING) ---------------------------*/ if ((uint16_t)(*NumByteToRead) < 2) { /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */ sEETimeout = sEE_FLAG_TIMEOUT; while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_ADDR) == RESET) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Disable Acknowledgment */ I2C_AcknowledgeConfig(sEE_I2C, DISABLE); /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ (void)sEE_I2C->SR2; /*!< Send STOP Condition */ I2C_GenerateSTOP(sEE_I2C, ENABLE); /* Wait for the byte to be received */ sEETimeout = sEE_FLAG_TIMEOUT; while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_RXNE) == RESET) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Read the byte received from the EEPROM */ *pBuffer = I2C_ReceiveData(sEE_I2C); /*!< Decrement the read bytes counter */ (uint16_t)(*NumByteToRead)--; /* Wait to make sure that STOP control bit has been cleared */ sEETimeout = sEE_FLAG_TIMEOUT; while(sEE_I2C->CR1 & I2C_CR1_STOP) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Re-Enable Acknowledgment to be ready for another reception */ I2C_AcknowledgeConfig(sEE_I2C, ENABLE); } else/* More than one Byte Master Reception procedure (DMA) -----------------*/ { /*!< Test on EV6 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /* Configure the DMA Rx Channel with the buffer address and the buffer size */ sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint16_t)(*NumByteToRead), sEE_DIRECTION_RX); /* Inform the DMA that the next End Of Transfer Signal will be the last one */ I2C_DMALastTransferCmd(sEE_I2C, ENABLE); /* Enable the DMA Rx Stream */ DMA_Cmd(sEE_I2C_DMA_STREAM_RX, ENABLE); } /* If all operations OK, return sEE_OK (0) */ return sEE_OK; }
/** * @brief Reads a buffer of 2 bytes from the device registers. * @param DeviceAddr: The address of the device, could be : IOE_1_ADDR * or IOE_2_ADDR. * @param RegisterAddr: The target register address (between 00x and 0x24) * @retval A pointer to the buffer containing the two returned bytes (in halfword). */ uint16_t I2C_ReadDataBuffer(uint8_t DeviceAddr, uint8_t RegisterAddr) { uint8_t tmp= 0; uint8_t IOE_BufferRX[2] = {0x00, 0x00}; /* Configure DMA Peripheral */ IOE_DMA_Config(IOE_DMA_RX, (uint8_t*)IOE_BufferRX); /* Enable DMA NACK automatic generation */ I2C_DMALastTransferCmd(IOE_I2C, ENABLE); /* Enable the I2C peripheral */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on SB Flag */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_SB)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send device address for write */ I2C_Send7bitAddress(IOE_I2C, DeviceAddr, I2C_Direction_Transmitter); /* Test on ADDR Flag */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send the device's internal address to write to */ I2C_SendData(IOE_I2C, RegisterAddr); /* Test on TXE FLag (data dent) */ IOE_TimeOut = TIMEOUT_MAX; while ((!I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_BTF))) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send START condition a second time */ I2C_GenerateSTART(IOE_I2C, ENABLE); /* Test on SB Flag */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_GetFlagStatus(IOE_I2C,I2C_FLAG_SB)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send IOExpander address for read */ I2C_Send7bitAddress(IOE_I2C, DeviceAddr, I2C_Direction_Receiver); /* Test on ADDR Flag */ IOE_TimeOut = TIMEOUT_MAX; while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Enable I2C DMA request */ I2C_DMACmd(IOE_I2C,ENABLE); /* Enable DMA RX Channel */ DMA_Cmd(IOE_DMA_RX_STREAM, ENABLE); /* Wait until DMA Transfer Complete */ IOE_TimeOut = 2 * TIMEOUT_MAX; while (!DMA_GetFlagStatus(IOE_DMA_RX_STREAM, IOE_DMA_RX_TCFLAG)) { if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback()); } /* Send STOP Condition */ I2C_GenerateSTOP(IOE_I2C, ENABLE); /* Disable DMA RX Channel */ DMA_Cmd(IOE_DMA_RX_STREAM, DISABLE); /* Disable I2C DMA request */ I2C_DMACmd(IOE_I2C,DISABLE); /* Clear DMA RX Transfer Complete Flag */ DMA_ClearFlag(IOE_DMA_RX_STREAM,IOE_DMA_RX_TCFLAG); /* Reorganize received data */ tmp = IOE_BufferRX[0]; IOE_BufferRX[0] = IOE_BufferRX[1]; IOE_BufferRX[1] = tmp; /* return a pointer to the IOE_Buffer */ return (*(__IO uint16_t *) IOE_BufferRX); }
/** * @brief Wait for EEPROM Standby state. * * @note This function allows to wait and check that EEPROM has finished the * last operation. It is mostly used after Write operation: after receiving * the buffer to be written, the EEPROM may need additional time to actually * perform the write operation. During this time, it doesn't answer to * I2C packets addressed to it. Once the write operation is complete * the EEPROM responds to its address. * * @param None * @retval sEE_OK (0) if operation is correctly performed, else return value * different from sEE_OK (0) or the timeout user callback. */ uint32_t sEE_WaitEepromStandbyState(void) { __IO uint16_t tmpSR1 = 0; __IO uint32_t sEETrials = 0; /*!< While the bus is busy */ sEETimeout = sEE_LONG_TIMEOUT; while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /* Keep looping till the slave acknowledge his address or maximum number of trials is reached (this number is defined by sEE_MAX_TRIALS_NUMBER define in stm322xg_eval_i2c_ee.h file) */ while (1) { /*!< Send START condition */ I2C_GenerateSTART(sEE_I2C, ENABLE); /*!< Test on EV5 and clear it */ sEETimeout = sEE_FLAG_TIMEOUT; while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /*!< Send EEPROM address for write */ I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); /* Wait for ADDR flag to be set (Slave acknowledged his address) */ sEETimeout = sEE_LONG_TIMEOUT; do { /* Get the current value of the SR1 register */ tmpSR1 = sEE_I2C->SR1; /* Update the timeout value and exit if it reach 0 */ if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); } /* Keep looping till the Address is acknowledged or the AF flag is set (address not acknowledged at time) */ while((tmpSR1 & (I2C_SR1_ADDR | I2C_SR1_AF)) == 0); /* Check if the ADDR flag has been set */ if (tmpSR1 & I2C_SR1_ADDR) { /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already been read) */ (void)sEE_I2C->SR2; /*!< STOP condition */ I2C_GenerateSTOP(sEE_I2C, ENABLE); /* Exit the function */ return sEE_OK; } else { /*!< Clear AF flag */ I2C_ClearFlag(sEE_I2C, I2C_FLAG_AF); } /* Check if the maximum allowed number of trials has bee reached */ if (sEETrials++ == sEE_MAX_TRIALS_NUMBER) { /* If the maximum number of trials has been reached, exit the function */ return sEE_TIMEOUT_UserCallback(); } } }
/* * 函数名:I2C_EE_BufferRead * 描述 :从EEPROM里面读取一块数据。 * 输入 :-pBuffer 存放从EEPROM读取的数据的缓冲区指针。 * -WriteAddr 接收数据的EEPROM的地址。 * -NumByteToWrite 要从EEPROM读取的字节数。 * 输出 :无 * 返回 :无 * 调用 :外部调用 */ void dr_e2ReadBuffer(UINT8 *pBuffer, UINT8 ReadAddr, u16 NumByteToRead) { //*((UINT8 *)0x4001080c) |=0x80; while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); // Added by Najoua 27/08/2008 /* Send START condition */ I2C_GenerateSTART(I2C1, ENABLE); //*((UINT8 *)0x4001080c) &=~0x80; /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /* Send EEPROM address for write */ I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); /* Test on EV6 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* Clear EV6 by setting again the PE bit */ I2C_Cmd(I2C1, ENABLE); /* Send the EEPROM's internal address to write to */ I2C_SendData(I2C1, ReadAddr); /* Test on EV8 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* Send STRAT condition a second time */ I2C_GenerateSTART(I2C1, ENABLE); /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /* Send EEPROM address for read */ I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver); /* Test on EV6 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); /* While there is data to be read */ while(NumByteToRead) { if(NumByteToRead == 1) { /* Disable Acknowledgement */ I2C_AcknowledgeConfig(I2C1, DISABLE); /* Send STOP Condition */ I2C_GenerateSTOP(I2C1, ENABLE); } /* Test on EV7 and clear it */ if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) { /* Read a byte from the EEPROM */ *pBuffer = I2C_ReceiveData(I2C1); /* Point to the next location where the byte read will be saved */ pBuffer++; /* Decrement the read bytes counter */ NumByteToRead--; } } /* Enable Acknowledgement to be ready for another reception */ I2C_AcknowledgeConfig(I2C1, ENABLE); }
/** * @brief Reads a byte from a specific Camera register * @param Addr: OV2640 register address. * @retval data read from the specific register or 0xFF if timeout condition * occured. */ uint8_t OV2640_ReadReg(uint16_t Addr) { uint32_t timeout = DCMI_TIMEOUT_MAX; uint8_t Data = 0; /* Generate the Start Condition */ I2C_GenerateSTART(I2C1, ENABLE); /* Test on I2C1 EV5 and clear it */ timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { /* If the timeout delay is exeeded, exit with error code */ if ((timeout--) == 0) return 0xFF; } /* Send DCMI selcted device slave Address for write */ I2C_Send7bitAddress(I2C1, OV2640_DEVICE_READ_ADDRESS, I2C_Direction_Transmitter); /* Test on I2C1 EV6 and clear it */ timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { /* If the timeout delay is exeeded, exit with error code */ if ((timeout--) == 0) return 0xFF; } /* Send I2C1 location address LSB */ I2C_SendData(I2C1, (uint8_t)(Addr)); /* Test on I2C1 EV8 and clear it */ timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { /* If the timeout delay is exeeded, exit with error code */ if ((timeout--) == 0) return 0xFF; } /* Clear AF flag if arised */ I2C1->SR1 |= (uint16_t)0x0400; /* Generate the Start Condition */ I2C_GenerateSTART(I2C1, ENABLE); /* Test on I2C1 EV6 and clear it */ timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) { /* If the timeout delay is exeeded, exit with error code */ if ((timeout--) == 0) return 0xFF; } /* Send DCMI selcted device slave Address for write */ I2C_Send7bitAddress(I2C1, OV2640_DEVICE_READ_ADDRESS, I2C_Direction_Receiver); /* Test on I2C1 EV6 and clear it */ timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { /* If the timeout delay is exeeded, exit with error code */ if ((timeout--) == 0) return 0xFF; } /* Prepare an NACK for the next data received */ I2C_AcknowledgeConfig(I2C1, DISABLE); /* Test on I2C1 EV7 and clear it */ timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) { /* If the timeout delay is exeeded, exit with error code */ if ((timeout--) == 0) return 0xFF; } /* Prepare Stop after receiving data */ I2C_GenerateSTOP(I2C1, ENABLE); /* Receive the Data */ Data = I2C_ReceiveData(I2C1); /* return the read data */ return Data; }
void i2c_ev_handler(I2CDevice device) { I2C_TypeDef *I2Cx; I2Cx = i2cHardwareMap[device].dev; i2cState_t *state; state = &(i2cState[device]); static uint8_t subaddress_sent, final_stop; // flag to indicate if subaddess sent, flag to indicate final bus condition static int8_t index; // index is signed -1 == send the subaddress uint8_t SReg_1 = I2Cx->SR1; // read the status register here if (SReg_1 & I2C_SR1_SB) { // we just sent a start - EV5 in ref manual I2Cx->CR1 &= ~I2C_CR1_POS; // reset the POS bit so ACK/NACK applied to the current byte I2C_AcknowledgeConfig(I2Cx, ENABLE); // make sure ACK is on index = 0; // reset the index if (state->reading && (subaddress_sent || 0xFF == state->reg)) { // we have sent the subaddr subaddress_sent = 1; // make sure this is set in case of no subaddress, so following code runs correctly if (state->bytes == 2) I2Cx->CR1 |= I2C_CR1_POS; // set the POS bit so NACK applied to the final byte in the two byte read I2C_Send7bitAddress(I2Cx, state->addr, I2C_Direction_Receiver); // send the address and set hardware mode } else { // direction is Tx, or we havent sent the sub and rep start I2C_Send7bitAddress(I2Cx, state->addr, I2C_Direction_Transmitter); // send the address and set hardware mode if (state->reg != 0xFF) // 0xFF as subaddress means it will be ignored, in Tx or Rx mode index = -1; // send a subaddress } } else if (SReg_1 & I2C_SR1_ADDR) { // we just sent the address - EV6 in ref manual // Read SR1,2 to clear ADDR __DMB(); // memory fence to control hardware if (state->bytes == 1 && state->reading && subaddress_sent) { // we are receiving 1 byte - EV6_3 I2C_AcknowledgeConfig(I2Cx, DISABLE); // turn off ACK __DMB(); (void)I2Cx->SR2; // clear ADDR after ACK is turned off I2C_GenerateSTOP(I2Cx, ENABLE); // program the stop final_stop = 1; I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); // allow us to have an EV7 } else { // EV6 and EV6_1 (void)I2Cx->SR2; // clear the ADDR here __DMB(); if (state->bytes == 2 && state->reading && subaddress_sent) { // rx 2 bytes - EV6_1 I2C_AcknowledgeConfig(I2Cx, DISABLE); // turn off ACK I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to fill } else if (state->bytes == 3 && state->reading && subaddress_sent) // rx 3 bytes I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // make sure RXNE disabled so we get a BTF in two bytes time else // receiving greater than three bytes, sending subaddress, or transmitting I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); } } else if (SReg_1 & I2C_SR1_BTF) { // Byte transfer finished - EV7_2, EV7_3 or EV8_2 final_stop = 1; if (state->reading && subaddress_sent) { // EV7_2, EV7_3 if (state->bytes > 2) { // EV7_2 I2C_AcknowledgeConfig(I2Cx, DISABLE); // turn off ACK state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N-2 I2C_GenerateSTOP(I2Cx, ENABLE); // program the Stop final_stop = 1; // required to fix hardware state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N - 1 I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); // enable TXE to allow the final EV7 } else { // EV7_3 if (final_stop) I2C_GenerateSTOP(I2Cx, ENABLE); // program the Stop else I2C_GenerateSTART(I2Cx, ENABLE); // program a rep start state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N - 1 state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N index++; // to show job completed } } else { // EV8_2, which may be due to a subaddress sent or a write completion if (subaddress_sent || (state->writing)) { if (final_stop) I2C_GenerateSTOP(I2Cx, ENABLE); // program the Stop else I2C_GenerateSTART(I2Cx, ENABLE); // program a rep start index++; // to show that the job is complete } else { // We need to send a subaddress I2C_GenerateSTART(I2Cx, ENABLE); // program the repeated Start subaddress_sent = 1; // this is set back to zero upon completion of the current task } } // we must wait for the start to clear, otherwise we get constant BTF while (I2Cx->CR1 & 0x0100) {; } } else if (SReg_1 & I2C_SR1_RXNE) { // Byte received - EV7 state->read_p[index++] = (uint8_t)I2Cx->DR; if (state->bytes == (index + 3)) I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to flush so we can get an EV7_2 if (state->bytes == index) // We have completed a final EV7 index++; // to show job is complete } else if (SReg_1 & I2C_SR1_TXE) { // Byte transmitted EV8 / EV8_1 if (index != -1) { // we dont have a subaddress to send I2Cx->DR = state->write_p[index++]; if (state->bytes == index) // we have sent all the data I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to flush } else { index++; I2Cx->DR = state->reg; // send the subaddress if (state->reading || !(state->bytes)) // if receiving or sending 0 bytes, flush now I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to flush } } if (index == state->bytes + 1) { // we have completed the current job subaddress_sent = 0; // reset this here if (final_stop) // If there is a final stop and no more jobs, bus is inactive, disable interrupts to prevent BTF I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE); // Disable EVT and ERR interrupts while bus inactive state->busy = 0; } }
/** * @brief Writes more than one byte to the EEPROM with a single WRITE cycle. * @note The number of byte can't exceed the EEPROM page size. * @param pBuffer : pointer to the buffer containing the data to be written to * the EEPROM. * @param WriteAddr : EEPROM's internal address to write to. * @param NumByteToWrite : pointer to the variable holding number of bytes to * written to the EEPROM. * * @note The variable pointed by NumByteToWrite is reset to 0 when all the * data are read from the EEPROM. Application should monitor this * variable in order know when the transfer is complete. * * @note When number of data to be written is higher than 1, this function just * configure the communication and enable the DMA channel to transfer data. * Meanwhile, the user application may perform other tasks. * When number of data to be written is 1, then the DMA is not used. * * @retval None */ void sEE_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite) { /* Set the pointer to the Number of data to be written. This pointer will be used by the DMA Transfer Completer interrupt Handler in order to reset the variable to 0. User should check on this variable in order to know if the DMA transfer has been complete or not. */ sEEDataWritePointer = NumByteToWrite; /*!< While the bus is busy */ while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) { } /*!< Send START condition */ I2C_GenerateSTART(sEE_I2C, ENABLE); /*!< Test on EV5 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) { } /*!< Send EEPROM address for write */ I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); /*!< Test on EV6 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { } #ifdef sEE_M24C08 /*!< Send the EEPROM's internal address to write to : only one byte Address */ I2C_SendData(sEE_I2C, WriteAddr); #elif defined(sEE_M24C64_32) /*!< Send the EEPROM's internal address to write to : MSB of the address first */ I2C_SendData(sEE_I2C, (uint8_t)((WriteAddr & 0xFF00) >> 8)); /*!< Test on EV8 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { } /*!< Send the EEPROM's internal address to write to : LSB of the address */ I2C_SendData(sEE_I2C, (uint8_t)(WriteAddr & 0x00FF)); #endif /*!< sEE_M24C08 */ /*!< Test on EV8 and clear it */ while(! I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { } /* If number of data to be written is 1, then DMA couldn't be used */ if ((uint16_t)(*NumByteToWrite) < 2) { /*!< Send the byte to be written */ I2C_SendData(sEE_I2C, *pBuffer); /*!< Test on EV8 and clear it */ while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { } /*!< Send STOP condition */ I2C_GenerateSTOP(sEE_I2C, ENABLE); (uint8_t)(*NumByteToWrite)--; } /* DMA could be used for number of data higher than 1 */ else { /* Configure the DMA Tx Channel with the buffer address and the buffer size */ sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint8_t)(*NumByteToWrite), sEE_DIRECTION_TX); /* Enable the DMA Tx Channel */ DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, ENABLE); } }
ErrorStatus send_i2c(I2C_TypeDef * I2Cx, uint8_t* TxBuffer, uint8_t slave_address, uint8_t package_size) { static uint16_t Timeout; uint8_t TxCounter = 0; //============================================================= /* Enable Event IT needed for ADDR and STOPF events ITs */ I2C_ITConfig(I2C1, I2C_IT_EVT, DISABLE); /* Enable Error IT */ I2C_ITConfig(I2C1, I2C_IT_ERR, DISABLE); /* Enable Buffer IT (TXE and RXNE ITs) */ I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE); //============================================================= Timeout = 0xFFF; /* While the bus is busy */ while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)) { if (Timeout-- == 0) return ERROR; } /* Send I2Cx START condition */ I2C_GenerateSTART(I2Cx, ENABLE); Timeout = 0xFF; /* Test on I2Cx EV5 and clear it */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if (Timeout-- == 0) return ERROR; } /* Send slave Address for write */ I2C_Send7bitAddress(I2Cx, slave_address, I2C_Direction_Transmitter); Timeout = 0xFF; /* wait for acknowledge bit */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (Timeout-- == 0) { I2C_GenerateSTOP(I2Cx, ENABLE); while ((I2Cx->CR1&0x200) == 0x200); return ERROR; } } while(TxCounter!=package_size) { /* Send some data */ I2C_SendData(I2Cx, TxBuffer[TxCounter++]); Timeout = 0xFF; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { if (Timeout-- == 0) return ERROR; } } /* Send I2Cx STOP Condition */ I2C_GenerateSTOP(I2Cx, ENABLE); Timeout = 0xFF; while ((I2Cx->CR1&0x200) == 0x200) { if (Timeout-- == 0) I2C_GenerateSTOP(I2Cx, ENABLE); return ERROR; // really needed? } //============================================================= /* Enable Event IT needed for ADDR and STOPF events ITs */ I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE); /* Enable Error IT */ I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE); /* Enable Buffer IT (TXE and RXNE ITs) */ I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE); //============================================================= return SUCCESS; }
void I2C_EV_Handler(void) { static uint8_t subaddress_sent, final_stop; // Flag to indicate if subaddess sent, flag to indicate final bus condition static int8_t index; // Index is signed -1==send the subaddress uint8_t SReg_1 = I2Cx->SR1; // Read the status register here if (SReg_1 & I2C_SR1_SB) // We just sent a start - EV5 in ref manual { I2Cx->CR1 &= ~I2C_CR1_POS; // Reset the POS bit so ACK/NACK applied to the current byte I2C_AcknowledgeConfig(I2Cx, ENABLE); // Make sure ACK is on index = 0; // Reset the index if (reading && (subaddress_sent || 0xFF == reg)) // We have sent the subaddr or no subaddress to send { subaddress_sent = 1; // Make sure this is set in case of no subaddress, so following code runs correctly if (bytes == 2) I2Cx->CR1 |= I2C_CR1_POS; // Set the POS bit so NACK applied to the final byte in the two byte read I2C_Send7bitAddress(I2Cx, addr, I2C_Direction_Receiver); // Send the address and set hardware mode } else // Direction is Tx, or we havent sent the sub and rep start { I2C_Send7bitAddress(I2Cx, addr, I2C_Direction_Transmitter); // Send the address and set hardware mode if (reg != 0xFF) // 0xFF as subaddress means it will be ignored, in Tx or Rx mode index = -1; // Send a subaddress } } else if (SReg_1 & I2C_SR1_ADDR) // We just sent the address - EV6 in ref manual { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" volatile uint8_t a; // Read SR1, SR2 to clear ADDR #pragma GCC diagnostic pop __DMB(); // memory fence to control hardware if (bytes == 1 && reading && subaddress_sent) // We are receiving 1 byte - EV6_3 { I2C_AcknowledgeConfig(I2Cx, DISABLE); // Turn off ACK __DMB(); a = I2Cx->SR2; // Clear ADDR after ACK is turned off I2C_GenerateSTOP(I2Cx, ENABLE); // Program the stop final_stop = 1; I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); // Allow us to have an EV7 } else // EV6 and EV6_1 { a = I2Cx->SR2; // Clear the ADDR here __DMB(); if (bytes == 2 && reading && subaddress_sent) // Rx 2 bytes - EV6_1 { I2C_AcknowledgeConfig(I2Cx, DISABLE); // Turn off ACK I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // Disable TXE to allow the buffer to fill } else if (bytes == 3 && reading && subaddress_sent) // Rx 3 bytes I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // Make sure RXNE disabled so we get a BTF in two bytes time else // Receiving greater than three bytes, sending subaddress, or transmitting I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); } } else if (SReg_1 & I2C_SR1_BTF) // Byte transfer finished - EV7_2, EV7_3 or EV8_2 { final_stop = 1; if (reading && subaddress_sent) // EV7_2, EV7_3 { if (bytes > 2) // EV7_2 { I2C_AcknowledgeConfig(I2Cx, DISABLE); // Turn off ACK read_p[index++] = I2C_ReceiveData(I2Cx); // Read data N-2 I2C_GenerateSTOP(I2Cx, ENABLE); // Program the Stop final_stop = 1; // Required to fix hardware read_p[index++] = I2C_ReceiveData(I2Cx); // Read data N-1 I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); // Enable RxNE to allow the final EV7 to read data N } else // EV7_3 { if (final_stop) I2C_GenerateSTOP(I2Cx, ENABLE); // Program the Stop else I2C_GenerateSTART(I2Cx, ENABLE); // Program a rep start read_p[index++] = I2C_ReceiveData(I2Cx); // Read data N-1 read_p[index++] = I2C_ReceiveData(I2Cx); // Read data N index++; // To show job completed } } else // EV8_2, which may be due to a subaddress sent or a write completion { if (subaddress_sent || (writing)) { if (final_stop) I2C_GenerateSTOP(I2Cx, ENABLE); // Program the Stop else I2C_GenerateSTART(I2Cx, ENABLE); // Program a rep start index++; // To show that the job is complete } else // We need to send a subaddress { I2C_GenerateSTART(I2Cx, ENABLE); // Program the repeated Start subaddress_sent = 1; // This is set back to zero upon completion of the current task } } while (I2Cx->CR1 & I2C_CR1_START) { ; } // We must wait for the start to clear, otherwise we get constant BTF } else if (SReg_1 & I2C_SR1_RXNE) // Byte received - EV7 { read_p[index++] = I2C_ReceiveData(I2Cx); if (bytes == (index + 3)) I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // Disable RxNE to allow the buffer to flush so we can get an EV7_2 if (bytes == index) // We have completed a final EV7 index++; // To show job is complete } else if (SReg_1 & I2C_SR1_TXE) // Byte transmitted - EV8/EV8_1 { if (index != -1) // We dont have a subaddress to send { I2C_SendData(I2Cx, write_p[index++]); if (bytes == index) // We have sent all the data I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // Disable TXE to allow the buffer to flush } else { index++; I2C_SendData(I2Cx, reg); // Send the subaddress if (reading || !bytes) // If receiving or sending 0 bytes, flush now I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // Disable TXE to allow the buffer to flush } } if (index == bytes + 1) // We have completed the current job { subaddress_sent = 0; // Reset this here if (final_stop) // If there is a final stop and no more jobs, bus is inactive, disable interrupts to prevent BTF I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE); // Disable EVT and ERR interrupts while bus inactive busy = 0; } }
void i2cMgr_t::SendAddrTX() { //Uart.Printf("AddrTx: %X\r", CmdToRead->Address); I2C_Send7bitAddress(I2C1, ((CmdToRead->Address) << 1), I2C_Direction_Transmitter); Delay.Reset(&Timer); }