Exemplo n.º 1
0
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);     
  }
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 5
0
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;
  
}
Exemplo n.º 10
0
/**
  * @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;

}
Exemplo n.º 11
0
/**
  * @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;
}
Exemplo n.º 12
0
/**
  * @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];
}
Exemplo n.º 13
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) */

}
Exemplo n.º 14
0
/*******************************************************************************
* 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;
  }
}
Exemplo n.º 15
0
/**
  * @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));
}
Exemplo n.º 17
0
/**
  * @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)
  {
  }
}
Exemplo n.º 18
0
/**
 * @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);
}
Exemplo n.º 20
0
/**
  * @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);
}
Exemplo n.º 21
0
/**
  * @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;
}
Exemplo n.º 22
0
/**
  * @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);
}
Exemplo n.º 23
0
/**
  * @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();
    }
  }
}
Exemplo n.º 24
0
/*
 * 函数名: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);
}
Exemplo n.º 25
0
/**
  * @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;
}
Exemplo n.º 26
0
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;
    }
}
Exemplo n.º 27
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);
  }
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
0
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;
    }
}
Exemplo n.º 30
0
void i2cMgr_t::SendAddrTX() {
    //Uart.Printf("AddrTx: %X\r", CmdToRead->Address);
    I2C_Send7bitAddress(I2C1, ((CmdToRead->Address) << 1), I2C_Direction_Transmitter);
    Delay.Reset(&Timer);
}