So, hier erstmal meine TWILib.
Es gibt 6 Routinen:
2 Initialisierroutinen für Master und Slave, Mastertransmitter, Masterreceiver, Slavetransmitter und Slavetransmitter. Funktion sollte klar sein.
Insbesondere die Slaveroutinen fehlen meist bei den Beispielen, die man im Netz findet (zB bei WinAVR), weil die Kommunkation da meist mit EEPROMs abläuft.
Die Routinen scheinen bei mir zu funktionieren, ich habe aber nicht alle mögliche Fehlereinflüsse (Slave funkt rein, oder hört nicht zu, oder ähnliches getestet. Leider habe ich den Multimastermodus noch nicht implementiert.
Ich bin natürlich für Kritik, Verbesserungen oder Begeisterung (vorzugsweise letzteres) offen.



Code:
/* ************************************* 
   TWI Lib Version 5 oder so
   bhm 2006
  ************************************** */

// bislang keinmultimaster support
// keine Garanie für irgendwas
// Bemerkungen, Fehlerreports usw willkommen


#ifndef _TWILIB_
#define _TWILIB_ 1

#include <avr/io.h>                                      //Zugriff auf IO's des Controllers
#include <stdint.h>
#include <compat/twi.h>

void init_Master (void) {
	TWSR &= ~(_BV(TWPS0) | _BV(TWPS1)); 	//0b11111100: Prescaler auf 1 setzen, Bit 1 und 0 auf 0 
	TWBR = 0x0A;   							//Bitrate auf 10 setzen, gibt 220kHz Bustakt bei 8MHz 	
}

void init_Slave (uint8_t SlvAdd) {
	TWAR = SlvAdd;		 						// eigene Address, hier ohne general call
	TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);	//slave receive, TWEA > ACK,	
}


void waitTWINT (void) {
	uint32_t m=0,mmax=F_CPU; //zZt einfach eine große Zahl
	
	while (bit_is_clear(TWCR, TWINT)) {
		if (m++ > mmax) return;         // bricht waitTWINT ab, TW_Status enthält dann TW_NO_INFO
	}
}

// *********** MasterTransmitter *************
// Daten in *Data, lenmax #Daten senden, MT #gesendete Daten 
uint8_t MT (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
	uint8_t len=1;
	
	TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);	//sende start
	waitTWINT();
	if ((TW_STATUS != TW_START) &&	(TW_STATUS != TW_REP_START)){	// chk Start | repeated start
		goto ENDE;
	}

	TWDR = SlvAdd + TW_WRITE;					//Addresse des Slaves angeben, SLA+W 
	TWCR = _BV(TWINT) | _BV(TWEN);					// sende sla_w
	waitTWINT();
	if (TW_STATUS != TW_MT_SLA_ACK) {				// chk sla_ack
		goto STOP;
	}
	
	do {
		TWDR = *Data++; 					// Datum laden
		TWCR = _BV(TWINT) | _BV(TWEN);				// sende Datum
		waitTWINT();
		if (TW_STATUS != TW_MT_DATA_ACK) {			// chk data_ack
			goto STOP;
		}
	} while (len++<lenmax); 
	
STOP:	
	TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO);	// sende stop, kein warten auf TWINT	

ENDE:
	return len-1;
}	

// *********** MasterReceiver *************
// empfangene Daten nach *Data, Speicher muss bereitgestellt sein, 
// lenmax #Daten empfangen, MR #empfangene Daten 
uint8_t MR (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
	uint8_t len=1;
	
	TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);	//sende start
	waitTWINT();
	if ((TW_STATUS != TW_START) &&	(TW_STATUS != TW_REP_START)){	// chk Start | repeated start
		goto ENDE;
	}

	TWDR = SlvAdd + TW_READ;						//Addresse des Slaves angeben, SLA+r 
	TWCR = _BV(TWINT) | _BV(TWEN);					// sende sla_r
	waitTWINT();
	if (TW_STATUS != TW_MR_SLA_ACK) {				// chk sla_ack
		goto STOP;
	}
	
	while (1) { 			// endlos, verlassen via break in if TW_Status
		if (len<lenmax) {
			TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);		//receive, ACK,
		} else {
			TWCR =             _BV(TWEN) | _BV(TWINT);		//receive, NACK,
		}	
		waitTWINT();
		if (TW_STATUS != TW_MR_DATA_ACK) break;			// LOOP VERLASSEN
		*Data++ = TWDR; len++;							// Daten verarbeitet
	}

	if (TW_STATUS == TW_MR_DATA_NACK) {
		*Data++ = TWDR; len++;							// Daten verarbeitet	
		goto STOP;
	}	
	
STOP:	
	TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO);	// sende stop, kein warten auf TWINT	
ENDE:
	return len-1;
}


// *********** SlaveReceiver *************
// empfangene Daten nach *Data, Speicher muss bereitgestellt sein, 
// lenmax #Daten empfangen, SR #empfangene Daten 
uint8_t SR (uint8_t *Data, uint8_t lenmax) {
	uint8_t len=1;						// lenmax >= 1, min ein Byte empfangen!
	
// auf SLA warten 
	while (bit_is_clear(TWCR, TWINT)); 				// beliebig lange warten oder pollen

// jetzt geht's los	
	if (TW_STATUS != TW_SR_SLA_ACK) {				// chk SLA+W
		goto STOP;
	}
	
	while (1) { 			// endlos, verlassen via break in if TW_Status
		if (len<lenmax) {
			TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);		//slave receive, TWEA > ACK,
		} else {
			TWCR =             _BV(TWEN) | _BV(TWINT);		//slave receive, TWEA > NACK,
		}	
		waitTWINT();
		if (TW_STATUS != TW_SR_DATA_ACK) break;			// LOOP VERLASSEN
		*Data++ = TWDR; len++;							// Daten verarbeitet
	}
	
	if (TW_STATUS == TW_SR_DATA_NACK) {					// Datum mit NACK beantwortet
		*Data = TWDR; len++;							// im Prinzip noch ein Datum verfügbar
	}

STOP:	// (TW_STATUS == TW_SR_STOP)  einzig anderer möglicher Status, von ARBs abgesehen
	TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);	//slave receive, TWEA > ACK,	
	return len-1;
}

// *********** SlaveTransmitter *************
// Daten in *Data, lenmax #Daten senden, ST #gesendete Daten 
uint8_t ST (uint8_t *Data, uint8_t lenmax) {
	uint8_t len=0;						// lenmax >= 1, min ein Byte senden!
	
// auf SLA warten 
	while (bit_is_clear(TWCR, TWINT)); 				// beliebig lange warten oder pollen

// jetzt geht's los	
	if (TW_STATUS != TW_ST_SLA_ACK) {				// chk SLA+R
		goto STOP;
	}
	
	do {
		TWDR = *Data++; len++;
		if (len<lenmax) {
			TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);
		} else {
			TWCR = _BV(TWEN) | _BV(TWINT);	
		}	
		waitTWINT();
	} while (TW_STATUS == TW_ST_DATA_ACK);

STOP:	
	TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);	//slave receive, TWEA > ACK,	
	return len;
}

#endif
Bei den versprochenen Links habe ich immernoch nicht die Zeit gefunden ...

ciao ... bernd