This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to handle NACK in I2C (TWI) communication.

Hi,

I am using nrf52832AA, SDK15.0, SD s131.

In some cases, an NRF_DRV_TWI_EVT_ADDRESS_NACK event occurs during I2C communication with the IQS263 sensor.

It would be nice if I could not get a NACK, but I do not know the exact cause yet.

How do I respond when I receive a NACK?

void IQS263_reg_read(uint8_t reg, uint8_t* rx, uint8_t len){
    ret_code_t err_code;
    
    uint8_t myTX[1] = {reg};
    m_xfer_done = false;

    err_code = nrf_drv_twi_tx(&CDC_twi_master, CDC_ADDRESS, myTX, 1, true);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    err_code = nrf_drv_twi_rx(&CDC_twi_master, CDC_ADDRESS, rx, len);
    APP_ERROR_CHECK(err_code);
    nrf_delay_ms(1); // If not, it receives a NACK.
}

The above code works fine. (I do not know if it does not work without 1ms delay)
However, when receiving a NACK, while (m_xfer_done == false) does not exit.

What should I do when I receive a NACK?
Do I have to send it back to do while?

The event handler is as follows.

void CDC_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            m_xfer_done = true;
            break;
            
        case NRF_DRV_TWI_EVT_ADDRESS_NACK:
            break;
            
        case NRF_DRV_TWI_EVT_DATA_NACK:
            break;
          
        default:
            break;
    }
}

Thank you in advance.

Have a nice day.

Parents
  • Receiving a NACK indicates that something is wrong, and according to this document it may be due one of the following conditions:

    • "The receiver is unable to receive or transmit because it is performing some real-time function and is not ready to start communication with the master."
    • "During the transfer, the receiver gets data or commands that it does not understand."
    • "During the transfer, the receiver cannot receive any more data bytes."

    You should check with your sensor, if any of the following conditions may happen.

    Best regards,

    Simon

Reply
  • Receiving a NACK indicates that something is wrong, and according to this document it may be due one of the following conditions:

    • "The receiver is unable to receive or transmit because it is performing some real-time function and is not ready to start communication with the master."
    • "During the transfer, the receiver gets data or commands that it does not understand."
    • "During the transfer, the receiver cannot receive any more data bytes."

    You should check with your sensor, if any of the following conditions may happen.

    Best regards,

    Simon

Children
  • Hi,

    I haven't found the exact cause of getting a NACK yet.
    Thus, the code was modified as follows to enable it to function even when it received NACK.

    void IQS263_reg_read(uint8_t reg, uint8_t* rx, uint8_t len){
        ret_code_t err_code;
    
        uint8_t myTX[1] = {reg};
        m_xfer_done = false;
        do{
          while(nrf_gpio_pin_read(RDY) == 1);
          err_code = nrf_drv_twi_tx(&CDC_twi_master, CDC_ADDRESS, myTX, 1, true);
          APP_ERROR_CHECK(err_code);
          nrf_delay_us(500);
        }while (m_xfer_done == false);
        //while (m_xfer_done == false);
    
        err_code = nrf_drv_twi_rx(&CDC_twi_master, CDC_ADDRESS, rx, len);
        APP_ERROR_CHECK(err_code);
        nrf_delay_ms(1);
    }

    We used "do,while" instead of "while" to send the data again when we received "nack".
    Is there any problem with this?
    Or is there another way?

    (It would be best not to receive the NACK, but we haven't found the exact cause. T^T)

    Best regards,

    PU

  • I think this is the right approach, and it seems like the reason for the NACK signal is due to the sensor being busy at the moment. However, I found a nice blog post here that explains how to handle I2C NACK signals.

    Best regards,

    Simon

Related