0
0
Power-electronicsDebug / FixBeginner · 4 min read

How to Handle I2C ACK and NACK in Embedded C Correctly

In embedded C, handle ACK and NACK by checking the I2C status register after each byte transfer. If an ACK is received, continue communication; if a NACK occurs, stop or retry the transfer to avoid errors.
🔍

Why This Happens

When communicating over I2C, the master expects an ACK (acknowledge) from the slave after sending each byte. If the slave does not respond with ACK, it sends a NACK (not acknowledge). This usually means the slave did not receive the data or is not ready. If the code does not check for these signals, the master may continue sending data incorrectly, causing communication failure.

c
void i2c_write_byte(uint8_t data) {
    I2C_DATA_REG = data;  // Send data
    while (!(I2C_STATUS_REG & TX_COMPLETE));  // Wait for transmission
    // Missing ACK check here
}

// Usage
// i2c_write_byte(0x50); // No ACK check, may fail silently
Output
Communication may hang or data is not received correctly because ACK/NACK is ignored.
🔧

The Fix

After sending a byte, check the I2C status register for the ACK bit. If NACK is detected, stop the transfer or retry. This ensures the master knows if the slave accepted the data and can handle errors gracefully.

c
bool i2c_write_byte(uint8_t data) {
    I2C_DATA_REG = data;  // Send data
    while (!(I2C_STATUS_REG & TX_COMPLETE));  // Wait for transmission

    if (I2C_STATUS_REG & NACK_RECEIVED) {  // Check for NACK
        i2c_stop();  // Stop communication
        return false;  // Indicate failure
    }
    return true;  // ACK received, continue
}

// Usage
if (!i2c_write_byte(0x50)) {
    // Handle error: retry or abort
}
Output
Data sent successfully if ACK received; stops and returns false if NACK detected.
🛡️

Prevention

Always check the I2C status register after each byte transfer to detect ACK or NACK. Use timeouts to avoid infinite waits. Implement retries or error handling when NACK occurs. Use clear function names and comments to make the code easy to maintain.

Enable I2C interrupts if supported to handle ACK/NACK asynchronously for better efficiency.

⚠️

Related Errors

Common related errors include:

  • Bus hang: Not releasing the bus after NACK causes the I2C bus to freeze.
  • Wrong slave address: Causes immediate NACK on address phase.
  • Missing stop condition: Leads to incomplete transactions and bus errors.

Fixes involve checking status bits, sending stop conditions properly, and verifying slave addresses.

Key Takeaways

Always check I2C status register for ACK/NACK after each byte transfer.
Stop or retry communication immediately if NACK is detected to avoid errors.
Use timeouts and error handling to prevent bus hangs.
Implement clear, maintainable code with comments for I2C communication.
Verify slave addresses and send proper stop conditions to avoid related errors.