From the project “You bought for your son a microcontroller - program it yourself”
The code can indicate which addresses are used by the I2C bus. I wrote it in one evening. For it I use embedded realization I2C driver for AVR.
Fully source here https://github.com/kindsoldier/arduino-tiny-shell
... void twi_start(void) { TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); } void twi_stop(void) { TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); while ((TWCR & (1 << TWSTO))); } void twi_write(uint8_t data) { TWDR = data; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); } uint16_t twi_scan(void) { uint8_t addr = 1; uint8_t str[4]; outnl(); while (addr < 127) { if((addr == 0x38) || (addr == 0x7c)) { addr++; continue; } twi_start(); twi_write(addr << 1); if(TW_STATUS == TW_MT_SLA_ACK ) { outs("0x"); int2str(addr, str, 3, 16); outl(str); } twi_stop(); addr++; } i2c_init(); return addr; } uint16_t twi_scan_lcd(void) { uint8_t addr = 1; uint8_t str[4]; lcd_command(LCD_CLEAR); lcd_gotolr(0,0); lcd_print("# "); while (addr < 127) { if((addr == 0x38) || (addr == 0x7c)) { addr++; continue; } twi_start(); twi_write(addr << 1); if(TW_STATUS == TW_MT_SLA_ACK ) { int2str(addr, str, 3, 16); lcd_print(str); lcd_putchar(' '); } twi_stop(); addr++; } i2c_init(); return addr; } cdef_t cdef[] = { ... {.name = "ts", .func = &twi_scan, .argc = 0} }; uint8_t *prompt = "READY>"; int main() { fifo_iohook(); uart_init(); timer_init(); i2c_init(); lcd_init(); wdt_init(); sei(); _delay_ms(1000); outl("\r\nTINY SHELL V01"); outs(prompt); lcd_print(prompt); uint8_t str[STR_LEN]; memset(str, 0, STR_LEN); _delay_ms(1000); while (1) { twi_scan_lcd(); uint8_t *s; s = str; while (fifo_gett(in, str, STR_LEN, '\r') > 0) { shell(str, cdef, sizeof(cdef) / sizeof(cdef[0])); outs("\r\n"); outs(prompt); } _delay_ms(200); } }