Exemplo n.º 1
0
uint32_t I2C_WrBuf(uint8_t DevAddr, uint8_t *buf, uint32_t cnt) {

    //Generate a Start condition
    I2C_Start();

    //Send I2C device Address
    I2C_Addr(DevAddr, I2C_Direction_Transmitter);
    //Unstretch the clock by just reading SR2 (Physically the clock is continued to be strectehed because we have not written anything to the DR yet.)
    (void) I2Cx->SR2;

    //Start Writing Data
    while (cnt--) {
        I2C_Write(*buf++);
    }

    //Wait for the data on the shift register to be transmitted completely
    WaitSR1FlagsSet(I2C_SR1_BTF);
    //Here TXE=BTF=1. Therefore the clock stretches again.

    //Order a stop condition at the end of the current tranmission (or if the clock is being streched, generate stop immediatelly)
    I2Cx->CR1 |= I2C_CR1_STOP;
    //Stop condition resets the TXE and BTF automatically.

    //Wait to be sure that line is iddle
    WaitLineIdle();

    return 0;
}
Exemplo n.º 2
0
/*-----------------------------------------------------------------------------
 *      I2C_RdData:
 *
 * Parameters: addr - 7-bit device address
 *             secByte - byte to send after address, before switching to read mode
 *             buf     - data buffer
 *             cnt     - number of bytes to read
 *
 * Return:     0 on success, nonzero on error
 *----------------------------------------------------------------------------*/
uint32_t I2C_RdData (uint8_t addr, uint8_t secByte, uint8_t *buf, uint32_t cnt) {
  uint8_t  *dp  = buf;
  uint32_t  num = cnt;
  uint32_t  err = 0;
  uint32_t  st  = 0;
  uint32_t  br  = 0;

  do {
    switch (st++) {
      case 0: err  = I2C_Start ();            break;
      case 1: err |= I2C_Addr  (addr, A_WR);  break;
      case 2: err |= I2C_Write (secByte);     break;
      case 3: err |= I2C_Start ();            break;
      case 4: err |= I2C_Addr  (addr, A_RD);  break;
      case 5:
        while (!err && num--) {
          err |= I2C_Read ((num != 0), dp++);
        }
        break;
      case 6: err |= I2C_Stop  ();            break;
    }

    if (err) {
      br++;
      /* Attempt recovery for 10 times, break otherwise */
      if (br < 10) {
        if (I2C_Recovery (err) == 0) {
          /* Recovery succedded, retry */
          dp  = buf;
          num = cnt;
          err = 0;
          st  = 0;
        }
      }
      else break;
    }
  } while (err == 0 && st < 7);
  return (err);
}
Exemplo n.º 3
0
uint32_t I2C_RdData(uint8_t DevAddr, uint8_t RegAddr, uint8_t *buf, uint32_t cnt) {
    //Reads "cnt" number of data starting from RegAddr

    //Send the Register Addres
    I2C_Start();
    I2C_Addr(DevAddr, I2C_Direction_Transmitter);
    (void) I2Cx->SR2;
    I2Cx->DR = RegAddr;
    WaitSR1FlagsSet(I2C_SR1_BTF);

    //Start Reading
    I2C_RdBuf(DevAddr, buf, cnt);

    return 0;
}
Exemplo n.º 4
0
uint32_t I2C_WrData(uint8_t DevAddr, uint8_t RegAddr, uint8_t data) {
    //Write a single byte data to the given register address

    //Generate a Start condition
    I2C_Start();

    //Send I2C device Address and clear ADDR
    I2C_Addr(DevAddr, I2C_Direction_Transmitter);
    (void) I2Cx->SR2;

    //Send Data
    I2Cx->DR = data;
    WaitSR1FlagsSet(I2C_SR1_BTF);  //wait till the data is actually written.

    //Generate Stop
    I2Cx->CR1 |= I2C_CR1_STOP;

    //Wait to be sure that line is iddle
    WaitLineIdle();

    return 0;
}
Exemplo n.º 5
0
uint32_t I2C_RdBufEasy (uint8_t DevAddr, uint8_t *buf, uint32_t cnt) {
    //The easy read.
    //We assume that we will reset ACK and order a stop condition while the last byte is being received by the shift register.
    //If this can't be done on time (during last byte reception), the slave will continue to send at least 1 more byte than cnt.
    //In most cases, such a condition does not hurt at all. Therefore people uses this method exclusively.

    //Note that it is impossible to guarantee the timig requirement only for single byte reception.
    //For N>=2, the timing is almost always satisfied. (if there is no interrupt, it will definetely be satisfied)

    //Generate Start
    I2C_Start();

    //Send I2C Device Address and clear ADDR
    I2C_Addr(DevAddr, I2C_Direction_Receiver);
    (void)I2Cx->SR2;

    while ((cnt--)>1) {
        I2C_Read(buf++);
    }

    //At this point we assume last byte is being received by the shift register. (reception has not been completed yet)
    //Reset ack
    I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);

    //Order a stop condition
    I2Cx->CR1 |= I2C_CR1_STOP;

    //Now read the final byte
    I2C_Read(buf);

    //Make Sure Stop bit is cleared and Line is now Iddle
    WaitLineIdle();

    //Enable the Acknowledgement
    I2Cx->CR1 |= ((uint16_t)I2C_CR1_ACK);

    return 0;
}
Exemplo n.º 6
0
uint32_t I2C_RdBuf (uint8_t DevAddr, uint8_t *buf, uint32_t cnt) {
    //Generate Start
    I2C_Start();

    //Send I2C Device Address
    I2C_Addr(DevAddr, I2C_Direction_Receiver);

    if (cnt==1) {//We are going to read only 1 byte
        //Before Clearing Addr bit by reading SR2, we have to cancel ack.
        I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);

        //Now Read the SR2 to clear ADDR
        (void)I2Cx->SR2;

        //Order a STOP condition
        //Note: Spec_p583 says this should be done just after clearing ADDR
        //If it is done before ADDR is set, a STOP is generated immediately as the clock is being streched
        I2Cx->CR1 |= I2C_CR1_STOP;
        //Be carefull that till the stop condition is actually transmitted the clock will stay active even if a NACK is generated after the next received byte.

        //Read the next byte
        I2C_Read(buf);

        //Make Sure Stop bit is cleared and Line is now Iddle
        WaitLineIdle();

        //Enable the Acknowledgement again
        I2Cx->CR1 |= ((uint16_t)I2C_CR1_ACK);
    }

    else if (cnt==2) {  //We are going to read 2 bytes (See: Spec_p584)
        //Before Clearing Addr, reset ACK, set POS
        I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
        I2Cx->CR1 |= I2C_CR1_POS;

        //Read the SR2 to clear ADDR
        (void)I2Cx->SR2;

        //Wait for the next 2 bytes to be received (1st in the DR, 2nd in the shift register)
        WaitSR1FlagsSet(I2C_SR1_BTF);
        //As we don't read anything from the DR, the clock is now being strecthed.

        //Order a stop condition (as the clock is being strecthed, the stop condition is generated immediately)
        I2Cx->CR1 |= I2C_CR1_STOP;

        //Read the next two bytes
        I2C_Read(buf++);
        I2C_Read(buf);

        //Make Sure Stop bit is cleared and Line is now Iddle
        WaitLineIdle();

        //Enable the ack and reset Pos
        I2Cx->CR1 |= ((uint16_t)I2C_CR1_ACK);
        I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_POS);
    }
    else { //We have more than 2 bytes. See spec_p585
        //Read the SR2 to clear ADDR
        (void)I2Cx->SR2;

        while((cnt--)>3) {//Read till the last 3 bytes
            I2C_Read(buf++);
        }

        //3 more bytes to read. Wait till the next to is actually received
        WaitSR1FlagsSet(I2C_SR1_BTF);
        //Here the clock is strecthed. One more to read.

        //Reset Ack
        I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);

        //Read N-2
        I2C_Read(buf++);
        //Once we read this, N is going to be read to the shift register and NACK is generated

        //Wait for the BTF
        WaitSR1FlagsSet(I2C_SR1_BTF); //N-1 is in DR, N is in shift register
        //Here the clock is stretched

        //Generate a stop condition
        I2Cx->CR1 |= I2C_CR1_STOP;

        //Read the last two bytes (N-1 and N)
        //Read the next two bytes
        I2C_Read(buf++);
        I2C_Read(buf);

        //Make Sure Stop bit is cleared and Line is now Iddle
        WaitLineIdle();

        //Enable the ack
        I2Cx->CR1 |= ((uint16_t)I2C_CR1_ACK);
    }

    return 0;
}