//------------------------------------------------------------------------ static unsigned int i2c_write_byte ( unsigned int b ) { unsigned int ra; for(ra=0x80;ra;ra>>=1) { i2c_delay(); if(ra&b) sda_high(); else sda_low(); i2c_delay(); scl_high(); i2c_delay(); scl_low(); i2c_delay(); sda_low(); i2c_delay(); } i2c_delay(); sda_input(); i2c_delay(); scl_high(); i2c_delay(); ra=sda_read(); i2c_delay(); scl_low(); i2c_delay(); sda_output(); i2c_delay(); return(ra); }
static uint8_t getByte(const I2C_ABSTRACT_BUS* bus, boolean isLastByte){ const I2C_SOFTWARE_BUS* i2c = (const I2C_SOFTWARE_BUS*)bus; int8_t i; uint8_t b = 0; sda_high(i2c); for(i=7; i>=0; i--){ b <<= 1; scl_high(i2c); halfDelay(); if(pin_is_high(i2c->sda)){ b |= 1; } scl_low(i2c); halfDelay(); } // Put the ACK if(isLastByte){ sda_high(i2c); }else{ sda_low(i2c); } scl_high(i2c); halfDelay(i2c); scl_low(i2c); sda_high(i2c); return b; // return received byte }
// Send the start and address // return TRUE if acknowledged static boolean start(const I2C_ABSTRACT_BUS* bus, uint8_t addr, boolean writeMode){ boolean rtn = FALSE; const I2C_SOFTWARE_BUS* i2c = (const I2C_SOFTWARE_BUS*)bus; if(i2c){ sda_high(i2c); halfDelay(); scl_high(i2c); halfDelay(); sda_low(i2c); halfDelay(); scl_low(i2c); halfDelay(); // Send the device addr and direction // uint8_t addr = device->addr & 0xfe; if(writeMode==FALSE){ addr |= 1; }else{ addr &= 0xfe; } rtn = putByte(bus, addr); } return rtn; }
BOOL hw_i2c_master_rx(uint8_t *buf, uint8_t buf_len, BOOL ack) { BOOL error = FALSE; BOOL send_ack; #if USE_HARDWARE_I2C uint8_t twsr; cpu_disable_int(); while ((buf_len > 0) && !error) { send_ack = (buf_len > 1) || ack; if (send_ack) { TWCR = TWICR_TWEN | TWICR_TWINT | TWICR_TWEA; } else { TWCR = TWICR_TWEN | TWICR_TWINT; } while ((TWCR & TWICR_TWINT) == 0); *buf++ = TWDR; twsr = TWSR & TW_STATUS_MASK; if (send_ack) { error = twsr != TW_MR_DATA_ACK; } else { error = twsr != TW_MR_DATA_NACK; } buf_len--; } #else uint8_t data; cpu_disable_int(); while ((buf_len > 0) && !error) { uint8_t i; send_ack = (buf_len > 1) || ack; data = 0; for (i = 0; i < 8; i++) { data = (data << 1) | hw_i2c_read_bit(); } *buf++ = data; delay_T2(); if (send_ack) { sda_low(); } else { sda_hi(); } delay_T2(); scl_hi(); delay_T2(); scl_low(); sda_hi(); buf_len--; } #endif cpu_enable_int(); return !error; }
// Send the stop static void stop(const I2C_ABSTRACT_BUS* bus){ const I2C_SOFTWARE_BUS* i2c = (const I2C_SOFTWARE_BUS*)bus; sda_low(i2c); halfDelay(); scl_high(i2c); halfDelay(); sda_high(i2c); halfDelay(); }
//------------------------------------------------------------------------ static void i2c_start ( void ) { i2c_delay(); i2c_delay(); sda_low(); i2c_delay(); i2c_delay(); scl_low(); i2c_delay(); }
BOOL hw_i2c_master_start(uint8_t address, hw_i2c_rdwr_t hw_i2c_rd_wr) { #if USE_HARDWARE_I2C BOOL error = FALSE; uint8_t twsr; cpu_disable_int(); TWCR = TWICR_TWEN | TWICR_TWINT | TWICR_TWSTA; while ((TWCR & TWICR_TWINT) == 0); twsr = TWSR & TW_STATUS_MASK; if ((twsr != TW_START) && (twsr != TW_REP_START)) { error = TRUE; } else { TWDR = (address & 0xfe) | hw_i2c_rd_wr; TWCR = TWICR_TWEN | TWICR_TWINT; while ((TWCR & TWICR_TWINT) == 0); twsr = TWSR & TW_STATUS_MASK; if (hw_i2c_rd_wr == hw_i2c_rd) { error = twsr != TW_MR_SLA_ACK; } else { error = twsr != TW_MT_SLA_ACK; } } cpu_enable_int(); return !error; #else cpu_disable_int(); delay_T2(); if (hold_bus) { sda_hi(); delay_T2(); scl_hi(); delay_T2(); } sda_low(); delay_T2(); scl_low(); hold_bus = TRUE; hw_i2c_write_byte((address & 0xfe) | hw_i2c_rd_wr); return hw_i2c_read_bit() == 0; // will call cpu_enable_int() #endif }
// Put a byte across the wire // Return true if the slave acknowledges static boolean putByte(const I2C_ABSTRACT_BUS* bus, uint8_t b){ const I2C_SOFTWARE_BUS* i2c = (const I2C_SOFTWARE_BUS*)bus; int8_t i; for(i=7; i>=0; i--){ if( b & 0x80 ){ sda_high(i2c); }else{ sda_low(i2c); } scl_high(i2c); b <<= 1; scl_low(i2c); } return getAck(i2c); // return ACK value }
void hw_i2c_write_byte(uint8_t data) { uint8_t i; cpu_disable_int(); for (i = 0; i < 8; i++) { delay_T2(); if (data & 0x80) { sda_hi(); } else { sda_low(); } scl_hi(); delay_T2(); scl_low(); data <<= 1; } cpu_enable_int(); }
void hw_i2c_master_stop(void) { #if USE_HARDWARE_I2C TWCR = TWICR_TWEN | TWICR_TWINT | TWICR_TWSTO; #else cpu_disable_int(); delay_T2(); scl_low(); sda_low(); delay_T2(); scl_hi(); delay_T2(); sda_hi(); hold_bus = FALSE; cpu_enable_int(); _delay_ms(1); // FIXME, why is this needed when sending [0xA6 0 0][0xA7 r] to eeprom with logging off? #endif }
int main(void) { int test; unsigned char byte; // PCF_ADRESS = 0; // Adresse des PCF'S printf("*** i²c-LCD Test (c) Ingo Gerlach 10/2000 *** \n"); COM = 0; // Vorbelegung Ser - Port, 0 Automatisch suchen set_port_delay(15); // Portdelay 0-255 test = init_iic(COM); // Init ii2c printf("Suche i2c-Interface..."); if (test) { printf(" gefunden an Port 0x%03xh! \n",test); } else { printf("Interface nicht gefunden.\n"); exit (0); } /* set_strobe(1); // Für den Seriellen Port nur dummy io_disable(0); */ sda_high(); scl_high(); printf("read_sda %d \n",read_sda()); printf("read_scl %d \n",read_scl()); iic_start(); byte =getchar(); iic_stop(); sda_low(); scl_low(); printf("read_sda %d \n",read_sda()); printf("read_scl %d \n",read_scl()); lcd_backlight(0); byte = getchar(); printf("deinit %d\n",deinit_iic()); return 0; }
// Send the start and address // return TRUE if acknowledged static boolean start(const I2C_DEVICE* device, boolean writeMode){ boolean rtn = FALSE; const I2C_SOFTWARE_BUS* i2c = (const I2C_SOFTWARE_BUS*)(device->bus); if(i2c){ sda_high(i2c); halfDelay(); scl_high(i2c); halfDelay(); sda_low(i2c); halfDelay(); scl_low(i2c); halfDelay(); // Send the device addr and direction uint8_t addr = device->addr & 0xfe; if(writeMode==FALSE){ addr |= 1; } rtn = putByte(device->bus, addr); } return rtn; }