Hi, Danke für die Antwort. Einziehdraht - das ist wahrscheinlich das Zeug, was ich als Einzelader kenne. Und ich dachte eher an das schwarze Kabel NYM-J 3x1,5².

Ja, das Einschalten und am I²C-Bus "anmelden". Die Lib vom microcontroller.net kenne ich nicht, allerdings habe ich vor langer Zeit angefangen mir selbst mal eine zusammenzustellen. Ging mir allerdings mehr um das Thema einheitliche Softwareschnittstelle auf TWI, USI oder 100%-Softwarelösung. Na jedenfalls sucht der Compiler raus, um welchen Controller es sich handelt und nimmt dann die passende Routine. Im Programm schreibe ich beispielsweise nur "setupTwiBusMaster()" und damit ist das dann unabhängig vom Controller erledigt.

Die Init-Routine für das USI aus dieser Lib würde ich gerne mal hier vorstellen, da ich glaube das ist der Knackpunkt. Der Trick ist den µC so an den Bus zu hängen, daß eventuell schon laufende Transfers nicht gestört werden - dann gibt es auch keine falschen "Start-" bzw. "Stop-"Zustände.

Zuerst ein Auszug aus dem Header (damit wird die Rotuine hoffentlich verständlicher). Sollte sich einigermaßen selbst erklären, hoffe ich:
Code:
#if defined (__AVR_ATtiny2313__)
	#include <avr/io.h>
	#define __TWIsupportedByUsi__
	#define TWIport 		PORTB
	#define TWIread			PINB
	#define TWIddr			DDRB
	#define TWIsclBit		7
	#define TWIsdaBit		5
#elif defined (__AVR_ATtiny26__)
	#include <avr/io.h>
	#define __TWIsupportedByUsi__
	#define TWIport 		PORTB
	#define TWIread			PINB
	#define TWIddr			DDRB
	#define TWIsclBit		2
	#define TWIsdaBit		0
Und hier die Init-Routine (nicht am Namen stören, der Init gilt definitiv für USI sowohl Master- als auch Slave-Mode!):
Code:
#if defined (__TWIsupportedByUsi__)
	char setupTwiBusMaster (void)
	{
		// setup does not disrupt any I²C transfer!
		USICR = (0b11<<USIWM0) | (0b10<<USICS0) | (0b0<<USICLK); // USI vorbereiten
		TWIddr &= ~(1<<TWIsdaBit); // SDA als Eingang = hochohmig
		TWIport |= (1<<TWIsdaBit) | (1<<TWIsclBit); // SDA und SCL pull-ups aktivieren
		TWIddr |= (1<<TWIsclBit); // SCL als Ausgang freigeben
		USISR = (1<<USIOIF) | (1<<USIDC) | (1<<USISIF) | (1<<USIPF); // USI starten
		return (0);
	}
Kernpunkt ist die Reihenfolge in der die diversen Aktionen erledigt werden; besonders die der verwendeten IO-Pins.

Ein Wort noch zur Umgebung (Compiler), der Vollständigkeit halber:
Ich benutze das WinAVR-Projekt. Der benutzte Controller wird da im Makefile definiert und die #if-Abfragen nutzen das dann aus um den richtigen Code auszuwählen (siehe Header für tiny2313 oder tiny26).

Ach ja, pro TWI-Bus je einen Pull-Up an SCL und SDA von etwa 4k7. Nicht alle µCs haben intern die Weak-Pull-Ups aktiviert, die Megas sperren das Feature im TWI-Modus sogar (schau mal ins Datenblatt).

EDIT:
Im Folgeabsatz ist mit "Controller" jeder "Teilnehmer" am Bus gemeint, also nicht nur µCs, sondern auch andere Schaltungen wie IO-Extender (z.B. PCF8574) oder EEPROMs (z.B. 2401).


Und natürlich müssen alle Controller mit Spannung versorgt sein wenn der Bus gestartet werden soll! Sonst zieht der/die unversorgte(n) Controller die Leitungen massiv gegen etwa 0,7V runter. Zuerst ist alles blockiert und dann kommt auf beiden Leitungen der Anstieg gleichzeitig - das führt dann meist zu falschen Start-Stop-Zuständen bei den bereits aktiven Controllern. Schau im Zweifel auch mal darauf.

Falls Du sie noch nicht hast, hier findest Du die Beschreibung des I²C-Bus: http://www.nxp.com/documents/user_manual/UM10204.pdf

Gruß
H.A.R.R.Y.