  #define BYTE unsigned char
  #define WORD unsigned short

  #define I2C_PORT_SEL P3SEL
  #define EEPROM_ADDRESS 0x50


  void I2C_Init(void)				// Initialisierung des I²C-Moduls
      {
  	I2C_PORT_SEL |= 0x0A;          		// P3.1 und P3.3 --> SDA/SCL des USART0-Moduls
  	U0CTL |= I2C+SYNC;    			// USART0 auf I²C-Betrieb stellen
  	U0CTL &= ~I2CEN;       			// I²C-Modul vor der Konfiguration deaktivieren
  	I2CTCTL = I2CTRX+I2CSSEL_2;   		// Transmit Mode und SMCLK als Taktquelle
  	I2CSA = EEPROM_ADDRESS;         	// Adresse des EEPROM festlegen
  	I2CPSC = 0x00;                		// Vorteiler für I²C-Takt = SMCLK/1
  	I2CSCLH = 0x03;               		// Zeit für SCL=1 ist 10 SMCLK-Taktzyklen
  	I2CSCLL = 0x03;               		// Zeit für SCL=0 ist 10 SMCLK-Taktzyklen
						// bei SMCLK=4MHz ist SCL=200kHz
  	U0CTL |= I2CEN;        			// I²C-Modul aktivieren
      }


  void I2C_Write_Init(void)			// I²C-Initialisierung für Schreiben
      {
  	U0CTL |= MST;          			// Master Mode einstellen
  	I2CTCTL |= I2CTRX;      		// Transmit Mode (R/W-Bit ist 0)
  	I2CIFG &= ~TXRDYIFG;			// Transmit-Ready-Flag löschen
  	I2CIE = TXRDYIE;        		// Transmit-Ready-Interrupt aktivieren
      }


  void I2C_Read_Init(void)			// I²C-Initialisierung für Lesen
      {
  	I2CTCTL &= ~I2CTRX;     		// Receive Mode (R/W-Bit ist 1)
  	I2CIE = RXRDYIE;        		// Receive-Ready-Interrupt aktivieren
  	U0CTL |= MST;         			// Master Mode einstellen
      }


  void EEPROM_Write(WORD adr, BYTE data) 	// Schreiben eines Bytes in das EEPROM		
      {
  	BYTE adr_hi;
  	BYTE adr_lo;

  	while(I2CDCTL & I2CBUSY); 		// warten, solange I²C-Modul noch aktiv ist

  	adr_hi = adr >> 8;         		// High-Byte der Adresse berechnen
  	adr_lo = adr & 0xFF;       		// Low-Byte der Adresse berechnen

  	I2C_buffer[2] = adr_hi;         	// I²C-Buffer mit den zu sendenden Bytes füllen
  	I2C_buffer[1] = adr_lo;
  	I2C_buffer[0] = data;
  	pointer = 2;               		// Buffer-Pointer setzen

  	I2C_Write_Init();
  	I2CNDAT = 3;           			// Zähler der zu übertragenden Bytes
  	I2CTCTL |= I2CSTT+I2CSTP;   		// Start-Zustand senden - I²C-Kommunikation aktiv
      }						// Stop-Zustand wird automatisch gesendet, sobald
						// alle Bytes übertragen sind


  BYTE EEPROM_Read(WORD adr)			// Lesen eines Bytesatzes aus dem EEPROM
      {
  	BYTE adr_hi;
  	BYTE adr_lo;

  	while(I2CDCTL & I2CBUSY);  		// warten, solange I²C-Modul noch aktiv ist

  	adr_hi = adr >> 8;         		// High-Byte der Adresse berechnen
  	adr_lo = adr & 0xFF;       		// Low-Byte der Adresse berechnen

  	I2C_buffer[1] = adr_hi;         	// I²C-Buffer mit den zu sendenden Bytes füllen
  	I2C_buffer[0] = adr_lo;
  	pointer = 1;               		// Buffer-Pointer setzen

  	I2C_Write_Init();
  	I2CNDAT = 2;         			// Zähler der zu übertragenden Bytes
  	I2CIFG &= ~ARDYIFG;  			// Access-Ready-Flag löschen
  	I2CTCTL |= I2CSTT;   			// Start-Zustand senden - I²C-Kommunikation aktiv
						// Stop-Zustand wird automatisch gesendet, sobald
						// alle Bytes übertragen sind

  	while((~I2CIFG) & ARDYIFG);  		// Ende der Übertragung abwarten

  	I2C_Read_Init();
  	I2CNDAT = 1;         			// Zähler der zu empfangenden Datenbytes

  	I2CIFG &= ~ARDYIFG;         		// Access-Ready-Flag löschen
  	I2CTCTL |= I2CSTT+I2CSTP;   		// Start-Zustand senden - I²C-Kommunikation aktiv
						// Stop-Zustand wird automatisch gesendet, sobald
						// alle Bytes übertragen sind
  	while((~I2CIFG) & ARDYIFG);  		// Ende der Übertragung abwarten
  	return I2C_buffer[0];			// empfangenes Byte übergeben
      }


  void EEPROM_Ack_Polling(void)			// Testen auf Abschluss des Schreibzyklus
      { 
  	WORD count;
  	while(I2CDCTL & I2CBUSY); 		// warten, solange I²C-Modul noch aktiv ist
  	count = 0;
  	U0CTL &= ~I2CEN;       			// I²C-Modul vor der Rekonfiguration deaktivieren
  	I2CTCTL |= I2CRM;      			// Software kontrolliert Übertragung
  	U0CTL |= I2CEN;        			// I²C-Modul aktivieren
  	I2CIFG = NACKIFG;      			// No-Acknowledge-Flag setzen
  	while (NACKIFG & I2CIFG)
  	  {
    	    I2CIFG = 0x00;            		// Interrupt-Flags löschen
    	    U0CTL |= MST;           		// Master Mode einstellen
    	    I2CTCTL |= I2CTRX;      		// Transmit Mode (R/W-Bit ist 0)
    	    I2CTCTL |= I2CSTT;      		// Start-Zustand senden

    	    while (I2CTCTL & I2CSTT); 		// warten, bis I2CSTT-Bit wieder gelöscht ist

    	    I2CTCTL |= I2CSTP;      		// nach Adress-Übertragung Stop-Zustand senden
						// --> I²C-Kommunikation aktiv
    	    while (I2CDCTL & I2CBUSY); 		// warten, solange I²C-Modul noch aktiv ist
    	    count = count+1;
  	  }
  	U0CTL &= ~I2CEN;       			// I²C-Modul vor der Rekonfiguration deaktivieren
  	I2CTCTL &= ~I2CRM;     			// I²C-Modul kontrolliert Übertragung
  	U0CTL |= I2CEN;        			// I²C-Modul aktivieren
	return;
      }


    #pragma vector = USART0TX_VECTOR		// ISR
    __interrupt void ISR_I2C(void)
      {
  	switch (I2CIV)
  	  { 
	    case I2CIV_AL:      		// Interrupt-Vektor: Arbitrierung verloren (ALIFG)
              break;
    	    case I2CIV_NACK:    		// Interrupt-Vektor: Kein Acknowledge (NACKIFG)
              break;
     	    case I2CIV_OA:      		// Interrupt-Vektor: Eigene Adresse (OAIFG)
              break;
    	    case I2CIV_ARDY:   			// Interrupt-Vektor: Zugriff bereit (ARDYIFG)
              break;
    	    case I2CIV_RXRDY:   		// Interrupt-Vektor: Empfang bereit (RXRDYIFG)
              I2C_buffer[0] = I2CDRB;   	// empfangene Daten in den Buffer speichern
              break;
    	    case I2CIV_TXRDY:   		// Interrupt-Vektor: Übertragung bereit (TXRDYIFG)
              I2CDRB = I2C_buffer[pointer];
              pointer = pointer-1;
              if (pointer<0)
                I2CIE &= ~TXRDYIE;      	// Transmit-Ready-Interrupt deaktivieren
              break;
    	    case I2CIV_GC:      		// Interrupt-Vektor: Allgemeiner Aufruf (GCIFG)
              break;
    	    case I2CIV_STT:     		// Interrupt-Vektor: Start-Zustand empfangen (STTIFG)
              break;
          }
      }
