Example #1
0
/* This function transmits one byte to the slave device
 * Parameters:
 *		I2Cx --> the I2C peripheral e.g. i2c_dev
 *		data --> the data byte to be transmitted
 */
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
{
    I2C_SendData(I2Cx, data);
    // wait for i2c_dev EV8_2 --> byte has been transmitted
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
Example #2
0
/**
  * @brief  Reads a buffer of 2 bytes from the device registers.
  * @param  DeviceAddr: The address of the device, could be : IOE_1_ADDR.
  * @param  RegisterAddr: The target register adress (between 00x and 0x24)
  * @retval A pointer to the buffer containing the two returned bytes (in halfword).  
  */
uint16_t I2C_ReadDataBuffer(uint8_t DeviceAddr, uint32_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_CHANNEL, ENABLE);
  
  /* Wait until DMA Transfer Complete */
  IOE_TimeOut = 2 * TIMEOUT_MAX;
  while (!DMA_GetFlagStatus(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_CHANNEL, DISABLE);
  
  /* Disable I2C DMA request */  
  I2C_DMACmd(IOE_I2C,DISABLE);
  
  /* Clear DMA RX Transfer Complete Flag */
  DMA_ClearFlag(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 *(uint16_t *)IOE_BufferRX;  
}
Example #3
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 & 0x0001) {      //we just sent a start - EV5 in ref manual
        I2Cx->CR1 &= ~0x0800;  //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
            subaddress_sent = 1;        //make sure this is set in case of no subaddress, so following code runs correctly
            if (bytes == 2)
                I2Cx->CR1 |= 0x0800;    //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 & 0x0002) {       //we just sent the address - EV6 in ref manual
        // Read SR1,2 to clear ADDR
        __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();
            (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 (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 & 0x004) {        //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; //reuired to fix hardware
                read_p[index++] = I2C_ReceiveData(I2Cx);    //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
                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
            }
        }
        //we must wait for the start to clear, otherwise we get constant BTF
        while (I2Cx->CR1 & 0x0100) { ; }
    } else if (SReg_1 & 0x0040) {       //Byte received - EV7
        read_p[index++] = I2C_ReceiveData(I2Cx);
        if (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 (bytes == index)       //We have completed a final EV7
            index++;            //to show job is complete
    } else if (SReg_1 & 0x0080) {       //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
        //Completion Tasks go here
        //End of completion tasks
        subaddress_sent = 0;    //reset this here
        // I2Cx->CR1 &= ~0x0800;   //reset the POS bit so NACK applied to the current byte
        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;
    }
}
Example #4
0
/** \brief Envia um byte ao escravo.
 *
 * @param I2Cx  I2C a ser utilizada.
 * @param data Byte a ser enviado.
 */
void c_common_i2c_write(I2C_TypeDef* I2Cx, uint8_t data) {
        I2C_SendData(I2Cx, data);
        // wait for I2C1 EV8_2 --> byte has been transmitted
        timeoutCounter = c_common_utils_millis();
        while(while_timeout(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED), timeoutCounter));
}
/**
  * @brief  Reads a buffer of 4 bytes from IO_Expander registers.
  * @param  DeviceAddr: The address of the IOExpander, could be : IOE_1_ADDR
  *         or IOE_2_ADDR. 
  * @param  RegisterAddr: The target register adress (between 00x and 0x24)
  * @retval : The value of the read register (0xAA if Timout occured)   
  */
uint32_t I2C_ReadDataBuffer(u8 DeviceAddr, uint32_t RegisterAddr)
{
  u8 Buffer[4] , idx = 2;
  
  /* Initialize the buffer */
  Buffer[0] = 0; 
  Buffer[1] = 0; 
  Buffer[2] = 0; 
  Buffer[3] = 0;   
  
  /* Disable the I2C1 peripheral  */
  I2C_Cmd(I2C1, DISABLE);

  /* Reset all I2C2 registers */
  I2C_SoftwareResetCmd(I2C1, ENABLE);
  I2C_SoftwareResetCmd(I2C1, DISABLE);

  /* Configure the I2C peripheral */
  IOE_I2C_Config();
  
  /* Enable the I2C peripheral */
  I2C_GenerateSTART(I2C1, ENABLE);
 
  TimeOut = TIMEOUT_MAX;
  
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) 
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
   
  /* Send device address for write */
  I2C_Send7bitAddress(I2C1, DeviceAddr, I2C_Direction_Transmitter);
  
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))  
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* Clear EV6 by setting again the PE bit */
  I2C_Cmd(I2C1, ENABLE);
  
  /* Send the device's internal address to write to */
  I2C_SendData(I2C1, RegisterAddr);  
  
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) 
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* 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)) 
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* Send EEPROM address for read */
  I2C_Send7bitAddress(I2C1, DeviceAddr, I2C_Direction_Receiver);
  
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) 
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* While there is data to be read */
  while(idx)  
  {
    if(idx == 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 */
      Buffer[idx-1] = I2C_ReceiveData(I2C1);
    
      /* Decrement the read bytes counter */
      idx--;        
    }   
  }
  
  /* Enable Acknowledgement to be ready for another reception */
  I2C_AcknowledgeConfig(I2C1, ENABLE);
  
  /* return a pointer to the buffer */
  return *(uint32_t *)Buffer;
}
/**
  * @brief  Reads a register of the audio Codec through I2C.
  * @param  DeviceAddr: The address of the IOExpander, could be : IOE_1_ADDR
  *         or IOE_2_ADDR. 
  * @param  RegisterAddr: The target register adress (between 00x and 0x24)
  * @retval The value of the read register (0xAA if Timout occured)   
  */
uint8_t I2C_ReadDeviceRegister(uint8_t DeviceAddr, uint8_t RegisterAddr)
{
  uint32_t tmp = 0;
  
  /* Disable the IOE_I2C peripheral  */
  I2C_Cmd(IOE_I2C, DISABLE);
  
  /* Reset all I2C2 registers */
  I2C_SoftwareResetCmd(IOE_I2C, ENABLE);
  I2C_SoftwareResetCmd(IOE_I2C, DISABLE);
  
  /* Configure the I2C peripheral */
  IOE_I2C_Config();
  
  /* Enable the I2C peripheral */
  I2C_GenerateSTART(IOE_I2C, ENABLE);
 
  TimeOut = TIMEOUT_MAX;
  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  /* Disable Acknowledgement */
  I2C_AcknowledgeConfig(IOE_I2C, DISABLE);
  
  /* Transmit the slave address and enable writing operation */
  I2C_Send7bitAddress(IOE_I2C, DeviceAddr, I2C_Direction_Transmitter);
  
  TimeOut = TIMEOUT_MAX;
  /* Test on EV6 and clear it */
  
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* Transmit the first address for r/w operations */
  I2C_SendData(IOE_I2C, RegisterAddr);
  
  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  /* Regenerate a start condition */
  I2C_GenerateSTART(IOE_I2C, ENABLE);
  
  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* Transmit the slave address and enable writing operation */
  I2C_Send7bitAddress(IOE_I2C, DeviceAddr, I2C_Direction_Receiver);
  
  /* Test on EV6 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* Test on EV7 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* End the configuration sequence */
  I2C_GenerateSTOP(IOE_I2C, ENABLE);
  
  /* Load the register value */
  tmp = I2C_ReceiveData(IOE_I2C);
  
  /* Enable Acknowledgement */
  I2C_AcknowledgeConfig(IOE_I2C, ENABLE);
  
  /* Return the read value */
  return tmp;
}
/**
  * @brief  Writes a value in a register of the IOE through I2C.
  * @param  DeviceAddr: The address of the IOExpander, could be : IOE_1_ADDR
  *         or IOE_2_ADDR. 
  * @param  RegisterAddr: The target register adress
  * @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)
{
  uint32_t read_verif = 0;

  /* Reset all I2C2 registers */
  I2C_SoftwareResetCmd(IOE_I2C, ENABLE);
  I2C_SoftwareResetCmd(IOE_I2C, DISABLE);

  TimeOut = TIMEOUT_MAX;

  /* Enable the IOE_I2C peripheral  */
  I2C_Cmd(IOE_I2C, ENABLE);

  /* Configure the I2C peripheral */
  IOE_I2C_Config();

  /* Begin the config sequence */
  I2C_GenerateSTART(IOE_I2C, ENABLE);

  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }

  /* Transmit the slave address and enable writing operation */
  I2C_Send7bitAddress(IOE_I2C, DeviceAddr, I2C_Direction_Transmitter);
  
  /* Test on EV6 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* Transmit the first address for r/w operations */
  I2C_SendData(IOE_I2C, RegisterAddr);
  
  TimeOut = TIMEOUT_MAX;
  
  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* Prepare the register value to be sent */
  I2C_SendData(IOE_I2C, RegisterValue);
  
  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(IOE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if (TimeOut-- == 0) return IOE_TIEMOUT;
  }
  
  /* 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 = I2C_ReadDeviceRegister(DeviceAddr, RegisterAddr);
  /* Load the register and verify its value  */
  if (read_verif != RegisterValue)
  {
    /* Control data wrongly tranfered */
    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;
}