Erst die i2cmaster.S:
Code:
;*************************************************************************
; Title	:    I2C (Single) Master Implementation
; Author:    Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
;            based on Atmel Appl. Note AVR300
; File:      $Id: i2cmaster.S,v 1.11 2003/10/16 18:16:07 peter Exp $
; Software:  AVR-GCC 3.3
; Target:    any AVR device
;
; DESCRIPTION
; 	Basic routines for communicating with I2C slave devices. This
;	"single" master implementation is limited to one bus master on the
;	I2C bus. 
;  
;       Based on the Atmel Application Note AVR300, corrected and adapted 
;       to GNU assembler and AVR-GCC C call interface
;       Replaced the incorrect quarter period delays found in AVR300 with 
;       half period delays. 
;
; USAGE
;	These routines can be called from C, refere to file i2cmaster.h.
;       See example test_i2cmaster.c 
; 	Adapt the SCL and SDA port and pin definitions and eventually 
;	the delay routine to your target !
; 	Use 4.7k pull-up resistor on the SDA and SCL pin.
;
; NOTES
;	The I2C routines can be called either from non-interrupt or
;	interrupt routines, not both.
;
;*************************************************************************

#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303
#error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !"
#endif


#include <avr/io.h>



;***** Adapt these SCA and SCL port and pin definition to your target !!
;
#define SDA     	1		// SDA Port D, Pin 4   
#define SCL		0		// SCL Port D, Pin 5
#define SDA_PORT        PORTC           // SDA Port D
#define SCL_PORT        PORTC           // SCL Port D         

;******

;-- map the IO register back into the IO address space
#define SDA_DDR		(_SFR_IO_ADDR(SDA_PORT) - 1)
#define SCL_DDR		(_SFR_IO_ADDR(SCL_PORT) - 1)
#define SDA_OUT		_SFR_IO_ADDR(SDA_PORT)
#define SCL_OUT		_SFR_IO_ADDR(SCL_PORT)
#define SDA_IN		(_SFR_IO_ADDR(SDA_PORT) - 2)
#define SCL_IN		(_SFR_IO_ADDR(SCL_PORT) - 2)


#ifndef __tmp_reg__
#define __tmp_reg__ 0
#endif


	.section .text

;*************************************************************************
; delay half period
; For I2C in normal mode (100kHz), use T/2 > 5us
; For I2C in fast mode (400kHz),   use T/2 > 1.3us
;*************************************************************************
	.stabs	"",100,0,0,i2c_delay_T2
	.stabs	"i2cmaster.S",100,0,0,i2c_delay_T2
	.func i2c_delay_T2	; delay 5.0 microsec with 16 Mhz crystal	
i2c_delay_T2:        ; 4 cycles
	rjmp 1f      ; 2   "
1:	rjmp 2f      ; 2   "
2:	rjmp 3f      ; 2   " 10
3:	rjmp 4f      ; 2   "
4:	rjmp 5f      ; 2   "
5:	rjmp 6f      ; 2   "
6:	rjmp 7f      ; 2   "
7:	rjmp 8f      ; 2   " 20
8:	rjmp 9f      ; 2   "
9:	rjmp 10f      ; 2   "
10:	rjmp 11f      ; 2   "
11:	rjmp 12f      ; 2   "
12:	rjmp 13f      ; 2   " 30
13:	rjmp 14f      ; 2   "
14:	rjmp 15f      ; 2   "
15:	rjmp 16f      ; 2   "
16:	rjmp 17f      ; 2   "
17:	rjmp 18f      ; 2   " 40
18:	rjmp 19f      ; 2   "
19:	rjmp 20f      ; 2   "
20:	rjmp 21f      ; 2   "
21:	rjmp 22f      ; 2   "
22:	rjmp 23f      ; 2   " 50
23:	rjmp 24f      ; 2   "
24:	rjmp 25f      ; 2   "
25:	rjmp 26f      ; 2   "
26:	rjmp 27f      ; 2   "
27:	rjmp 28f      ; 2   " 60
28:	rjmp 29f      ; 2   "
29:	rjmp 30f      ; 2   "
30:	rjmp 31f      ; 2   "
31:	rjmp 32f      ; 2   "
32:	rjmp 33f      ; 2   " 70
33:	rjmp 34f      ; 2   "
34:	rjmp 35f      ; 2   "
35:	rjmp 36f      ; 2   "
36:	nop          ; 1   "
	ret          ; 3   "
	.endfunc     ; total 80 cyles = 5.0 microsec with 16 Mhz crystal 


;*************************************************************************
; Initialization of the I2C bus interface. Need to be called only once
; 
; extern void i2c_init(void)
;*************************************************************************
	.global i2c_init
	.func i2c_init
i2c_init:
	cbi SDA_DDR,SDA		;release SDA
	cbi SCL_DDR,SCL		;release SCL
	cbi SDA_OUT,SDA
	cbi SCL_OUT,SCL
	ret
	.endfunc


;*************************************************************************	
; Issues a start condition and sends address and transfer direction.
; return 0 = device accessible, 1= failed to access device
;
; extern unsigned char i2c_start(unsigned char addr);
;	addr = r24, return = r25(=0):r24
;*************************************************************************

	.global i2c_start
	.func   i2c_start
i2c_start:
	sbi 	SDA_DDR,SDA	;force SDA low
	rcall 	i2c_delay_T2	;delay T/2
	
	rcall 	i2c_write	;write address
	ret
	.endfunc		


;*************************************************************************
; Issues a repeated start condition and sends address and transfer direction.
; return 0 = device accessible, 1= failed to access device
;
; extern unsigned char i2c_rep_start(unsigned char addr);
;	addr = r24,  return = r25(=0):r24
;*************************************************************************

	.global i2c_rep_start
	.func	i2c_rep_start
i2c_rep_start:
	sbi	SCL_DDR,SCL	;force SCL low
	rcall 	i2c_delay_T2	;delay  T/2
	cbi	SDA_DDR,SDA	;release SDA
	rcall	i2c_delay_T2	;delay T/2
	cbi	SCL_DDR,SCL	;release SCL
	rcall 	i2c_delay_T2	;delay  T/2
	sbi 	SDA_DDR,SDA	;force SDA low
	rcall 	i2c_delay_T2	;delay	T/2
	
	rcall	i2c_write	;write address
	ret
	.endfunc


;*************************************************************************	
; Issues a start condition and sends address and transfer direction.
; If device is busy, use ack polling to wait until device is ready
;
; extern void i2c_start_wait(unsigned char addr);
;	addr = r24
;*************************************************************************

	.global i2c_start_wait
	.func   i2c_start_wait
i2c_start_wait:
	mov	__tmp_reg__,r24
i2c_start_wait1:
	sbi 	SDA_DDR,SDA	;force SDA low
	rcall 	i2c_delay_T2	;delay T/2
	mov	r24,__tmp_reg__
	rcall 	i2c_write	;write address
	tst	r24		;if device not busy -> done
	breq	i2c_start_wait_done
	rcall	i2c_stop	;terminate write operation
	rjmp	i2c_start_wait1	;device busy, poll ack again
i2c_start_wait_done:
	ret
	.endfunc	


;*************************************************************************
; Terminates the data transfer and releases the I2C bus
;
; extern void i2c_stop(void)
;*************************************************************************

	.global	i2c_stop
	.func	i2c_stop
i2c_stop:
	sbi	SCL_DDR,SCL	;force SCL low
	sbi	SDA_DDR,SDA	;force SDA low
	rcall	i2c_delay_T2	;delay T/2
	cbi	SCL_DDR,SCL	;release SCL
	rcall	i2c_delay_T2	;delay T/2
	cbi	SDA_DDR,SDA	;release SDA
	rcall	i2c_delay_T2	;delay T/2
	ret
	.endfunc


;*************************************************************************
; Send one byte to I2C device
; return 0 = write successful, 1 = write failed
;
; extern unsigned char i2c_write( unsigned char data );
;	data = r24,  return = r25(=0):r24
;*************************************************************************
	.global i2c_write
	.func	i2c_write
i2c_write:
	sec			;set carry flag
	rol 	r24		;shift in carry and out bit one
	rjmp	i2c_write_first
i2c_write_bit:
	lsl	r24		;if transmit register empty
i2c_write_first:
	breq	i2c_get_ack
	sbi	SCL_DDR,SCL	;force SCL low
	brcc	i2c_write_low
	nop
	cbi	SDA_DDR,SDA	;release SDA
	rjmp	i2c_write_high
i2c_write_low:
	sbi	SDA_DDR,SDA	;force SDA low
	rjmp	i2c_write_high
i2c_write_high:
	rcall 	i2c_delay_T2	;delay T/2
	cbi	SCL_DDR,SCL	;release SCL
	rcall	i2c_delay_T2	;delay T/2
	rjmp	i2c_write_bit
	
i2c_get_ack:
	sbi	SCL_DDR,SCL	;force SCL low
	cbi	SDA_DDR,SDA	;release SDA
	rcall	i2c_delay_T2	;delay T/2
	cbi	SCL_DDR,SCL	;release SCL
i2c_ack_wait:
	sbis	SCL_IN,SCL	;wait SCL high (in case wait states are inserted)
	rjmp	i2c_ack_wait
	
	clr	r24		;return 0
	sbic	SDA_IN,SDA	;if SDA high -> return 1
	ldi	r24,1
	rcall	i2c_delay_T2	;delay T/2
	clr	r25
	ret
	.endfunc



;*************************************************************************
; read one byte from the I2C device, send ack or nak to device
; (ack=1, send ack, request more data from device 
;  ack=0, send nak, read is followed by a stop condition)
;
; extern unsigned char i2c_read(unsigned char ack);
;	ack = r24, return = r25(=0):r24
; extern unsigned char i2c_readAck(void);
; extern unsigned char i2c_readNak(void);
; 	return = r25(=0):r24
;*************************************************************************
	.global i2c_readAck
	.global i2c_readNak
	.global i2c_read		
	.func	i2c_read
i2c_readNak:
	clr	r24
	rjmp	i2c_read
i2c_readAck:
	ldi	r24,0x01
i2c_read:
	ldi	r23,0x01	;data = 0x01
i2c_read_bit:
	sbi	SCL_DDR,SCL	;force SCL low
	cbi	SDA_DDR,SDA	;release SDA (from previous ACK)
	rcall	i2c_delay_T2	;delay T/2
	
	cbi	SCL_DDR,SCL	;release SCL
	rcall	i2c_delay_T2	;delay T/2
	
	clc			;clear carry flag
	sbic	SDA_IN,SDA	;if SDA is high
	sec			;  set carry flag
	
	rol	r23		;store bit
	brcc	i2c_read_bit	;while receive register not full
	
i2c_put_ack:
	sbi	SCL_DDR,SCL	;force SCL low	
	cpi	r24,1
	breq	i2c_put_ack_low	;if (ack=0)
	cbi	SDA_DDR,SDA	;      release SDA
	rjmp	i2c_put_ack_high
i2c_put_ack_low:                ;else
	sbi	SDA_DDR,SDA	;      force SDA low
i2c_put_ack_high:
	rcall	i2c_delay_T2	;delay T/2
	cbi	SCL_DDR,SCL	;release SCL
i2c_put_ack_wait:
	sbis	SCL_IN,SCL	;wait SCL high
	rjmp	i2c_put_ack_wait
	rcall	i2c_delay_T2	;delay T/2
	mov	r24,r23
	clr	r25
	ret
	.endfunc
Hier Code nur für KeyLCD und SRF02 wegen bessere Lesbarkeit:
Code:
#include "i2cmaster.h"
#include den anderen Kram ;-)

//*********** Meine I2C Methoden ***************
// PORTC0 = SCL ; PORTC1 = SDA

void sda_ein(void){
	PORTC |=  (1 << PC1);
}

void sda_aus(void){
	PORTC &= ~(1 << PC1);
}

void scl_ein(void){
	PORTC |=  (1 << PC0);
}

void scl_aus(void){
	PORTC &= ~(1 << PC0);
}

void i2cstart(){
	
	sda_ein();
	asm volatile("NOP");
	scl_ein();
	asm volatile("NOP");
	sda_aus();
	asm volatile("NOP");
	scl_aus();
	asm volatile("NOP");
	
}

void i2cstop(){

	sda_aus();
	asm volatile("NOP");
	scl_ein();
	asm volatile("NOP");
	sda_ein();
	asm volatile("NOP");
	
}

char i2c_byte_lesen(unsigned char ack){
//---------------------------------------------------------------------------------
// Liest ein Byte vom i2cbus und prueft das ACK

  	unsigned char i,wert=0;
	DDRC &= ~(1 << DDC1);			//DATA Schreibrechte an Empfaenger uebergeben
	//sda_ein();						//Aktiviert Pullup da Port als Eingang
  	for (i=0x80;i>0;i/=2)             //shift bit for masking
  	{ scl_ein();                          //bustakt
  	  
	  if (PINC & (1<<PINC1)) 
	  {	UART_transmit_string("1");
		wert=(wert | i);        //read bit  
  	  }
	  else UART_transmit_string("0");
	  
	  scl_aus();  					 
  	}
	DDRC |= (1 << DDC1);			//DATA Schreibrechte an µC uebergeben
	if(ack) sda_aus();
	else sda_ein();
	asm volatile("NOP");	
  	scl_ein();                            //clk #9 for ack
  	asm volatile("NOP");        			//Pulsbreite ca. 5 us  
	asm volatile("NOP");		
	asm volatile("NOP");
  	scl_aus();						    

  	DDRC &= ~(1 << DDC1);			//DATA Schreibrechte an Empfaenger uebergeben
	return wert;
}

char i2c_byte_schreiben(unsigned char wert){
//----------------------------------------------------------------------------------
// Schreibt ein Byte auf den Sensirion 2-Wirebus und prüft das ACK

  	unsigned char i,error=0;  
	DDRC |= (1 << DDC1);			//DATA Schreibrechte an µC uebergeben
  	for (i=0x80;i>0;i/=2)             //shift bit for masking
  	{ if (i & wert) {
		sda_ein();          //masking value with i , write to i2cbus
		UART_transmit_string("1");
		}
  	  else {
		sda_aus();                        
		UART_transmit_string("0");
		}
  	  scl_ein();                          //Takt fuer i2cBUS
  	  asm volatile("NOP");        			//Pulsbreite ca. 5 us  
	  asm volatile("NOP");		
	  asm volatile("NOP");         	
  	  scl_aus();
  	}
  	
	DDRC &= ~(1 << DDC1);			//DATA Schreibrechte an Empfaenger uebergeben
	//Hier eventuell auf ACK warten weil KeyLcd zu langsam ? waitms 100 oder so
	//sda_ein();						//Aktiviert Pullup da Port als Eingang
  	scl_ein();                            //clk #9 for ack                        
  	
	if(PINC & (1<<PINC1)) error=1;		//prueft ACK (PINC1 wird vom Empfaenger auf Low gezogen)
	else error=0;
	
	scl_aus();
	//sda_aus();						//Deaktiviert Pullup        
  	return error;                     //error=1 im Falle von keinem Acknowledge
}

int main (void)
{
unsigned char a[10];
unsigned char b[10];
unsigned char c[10];
unsigned char d,e;
unsigned int taste = 0;
unsigned int sum = 0;

value humi_val,temp_val;
unsigned int tempo;
unsigned int humi;
unsigned int cm;
float tau_punkt;
unsigned char error,checksum,hib,lob;
unsigned long i;
error=2;


DDRC = 0xFF;
hib=0;
DDRC &= ~(1 << DDC0);   // PIN als EINGANG
DDRC &= ~(1 << DDC1); // PIN als EINGANG
scl_ein(); // Interne Pullups aktivieren
sda_ein(); // Interne Pullups aktivieren




UART_init();  // UART-Init Funktion ausfhren
i2c_init();  //P. Fleury i2cmaster init




/* Hier USS Code mit Lib vom P. Fleury
i2c_start_wait(0xE0);
error=i2c_write(0x00);
error=i2c_write(0x51);
i2c_stop();

for (i=0;i<100000000;i++); //Auf Messungende warten ca 65ms

i2c_start_wait(0xE0);
error=i2c_write(0x02);
i2c_rep_start(0xE1);
hib=i2c_readAck();
lob=i2c_readNak();
i2c_stop();

cm= (hib*256)+lob;

itoa(cm,a,10);
UART_transmit_string(a);

if(error==1) UART_transmit_string("Error beim schreiben");
else UART_transmit_string("Kein Error beim schreiben");
/*


// Hier Code SRF02 mit meinen Methoden
/*
i2cstart();
i2c_byte_schreiben(0xE0); //Standard Adresse vom USS
UART_transmit_string(" ");
i2c_byte_schreiben(0x00); //Register 0
UART_transmit_string(" ");
i2c_byte_schreiben(0x51); //Messbefehl in Zentimeter
UART_transmit_string(" ");
i2cstop();

i2cstart();
i2c_byte_schreiben(0xE0); //Standard Adresse vom USS
UART_transmit_string(" ");
i2c_byte_schreiben(0x02); //Register 2
UART_transmit_string(" ");
i2cstop();

i2cstart();
i2c_byte_schreiben(0xE1); //Slaveadresse + 1 da lesen wollen
UART_transmit_string(" ");
hib=i2c_byte_lesen(ACK);
UART_transmit_string(" ");
lob=i2c_byte_lesen(noACK);
UART_transmit_string(" ");
i2cstop();
*/


//Hier Code KEYLCD mit Lib P. Fleury
//So kann ich nur ein Zeichen ausgeben und dann error=1
i2c_start_wait(0x40);
error=i2c_write(0x68);
error=i2c_write(0x61); //AB Hier error
error=i2c_write(0x6C);
error=i2c_write(0x6C);
error=i2c_write(0x6F);
i2c_stop();

if(error==1) UART_transmit_string("Error beim schreiben");
else UART_transmit_string("Kein Error beim schreiben");



/* Hier nur KEYLCD Code mit meinen Methoden
So kann ich 2 Zeichen nacheinander korrekt ausgeben, dritte dann fehler.

i2cstart();
i2c_byte_schreiben(ADD);

error=i2c_byte_schreiben(0x5A);
if(error==1) UART_transmit_string("Error1");

error=i2c_byte_schreiben(0x4A);
if(error==1) UART_transmit_string("Error2");

error=i2c_byte_schreiben(0x57);
if(error==1) UART_transmit_string("Error3");

i2cstop();
*/


}
Ist doch voll komisch oder ?!

Hey vielen Dank für eure Hilfe. Ehrlich !! Ich kann einfach keinen
Fehler finden. Immerhin funktioniert die Kommunikation ja halbwegs.
Daher ist es im Ansatz richtig.
Makefile ist OK. Kompilieren klappt auch ohne Error. Ein paar Warnungen , aber die sind egal. Ist ja nur zum experimentieren.

Viele Grüsse
Thomas