#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#define SDA_PIN PD2
#define SCL_PIN PD3
// --- I²C macros (open-drain style) ---
#define SDA_LOW() { DDRD |= (1<<SDA_PIN); PORTD &= ~(1<<SDA_PIN); } // drive 0
#define SDA_RELEASE(){ DDRD &= ~(1<<SDA_PIN); } // release line
#define SCL_LOW() { DDRD |= (1<<SCL_PIN); PORTD &= ~(1<<SCL_PIN); } // drive 0
#define SCL_HIGH() { DDRD |= (1<<SCL_PIN); PORTD |= (1<<SCL_PIN); } // drive 1
#define SDA_READ() (PIND & (1<<SDA_PIN)) // read SDA state
#define I2C_DELAY() _delay_us(5) // ~100 kHz I²C
// --- I²C functions ---
void i2c_init(void) {
SDA_RELEASE();
SCL_HIGH();
}
void i2c_start(void) {
SDA_RELEASE(); SCL_HIGH(); I2C_DELAY();
SDA_LOW(); I2C_DELAY();
SCL_LOW(); I2C_DELAY();
}
void i2c_stop(void) {
SDA_LOW(); I2C_DELAY();
SCL_HIGH(); I2C_DELAY();
SDA_RELEASE(); I2C_DELAY();
}
// Write byte and return ACK/NACK
uint8_t i2c_write(uint8_t data) {
for (uint8_t i=0; i<8; i++) {
if (data & 0x80) SDA_RELEASE(); else SDA_LOW();
I2C_DELAY();
SCL_HIGH(); I2C_DELAY();
SCL_LOW(); I2C_DELAY();
data <<= 1;
}
// ACK cycle
SDA_RELEASE(); // release SDA for slave
I2C_DELAY();
SCL_HIGH(); // pulse SCL for ACK
I2C_DELAY();
uint8_t ack = (SDA_READ()==0); // read SDA while high
SCL_LOW();
return ack; // 1=ACK, 0=NACK
}
int main(void) {
i2c_init();
while (1) {
i2c_start();
uint8_t ack = i2c_write(0xC0); // MAX2112 slave address (write)
i2c_stop();
// Here ack variable tells if MAX2112 pulled SDA low
// Connect logic analyzer to SDA/SCL to see the ACK bit
_delay_ms(500);
}
}
I am programming my ATMEGA32A 16 MHz external clock to write address C0 in MAX2112, but I am not getting any acknowledge bit or command from MAX2112, meaning at the 9th pulse of SCL Clock Signal I should get 0 on SDA but there is no Low or 0 there is High, what should be the solution?