User Tools

Site Tools


I2C scanner on Atmel micro-controller

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/sadsoldier/arduino-tiny-shell

twiscan-cut.c
...
 
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);
    }
}