Hallo Klaus,

hast du diese veränderte Version auch noch?
Natürlich, die ist seit etwa 2 Monaten auf einem T24 im Einsatz und tut ihren Dienst.

Code:
;			USI_TWI_master Routinen
;**************************************************


.macro TRANSFER_8_BIT
	ldi param1,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)
	rcall USI_TWI_master_transfer
.endmacro

.macro TRANSFER_1_BIT
	ldi param1,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0xE<<USICNT0)
	rcall USI_TWI_master_transfer
.endmacro

.macro READ_ACK
	set
	rcall USI_TWI_master_read
.endmacro

.macro READ_NACK
	clt 
	rcall USI_TWI_master_read
.endmacro

.macro START_I2C
	ldi param1,(@0)
	rcall USI_TWI_master_start
.endmacro


;USI Pin Konfiguration fuer tiny 24

.equ PORT_USI = PORTA
.equ DDR_USI  = PORT_USI- 1
.equ PIN_USI  = DDR_USI - 1
.equ PORT_USI_SDA = PORTA6
.equ PORT_USI_SCL = PORTA4
.equ PIN_USI_SDA = PINA6
.equ PIN_USI_SCL = PINA4
 

.equ WRITE = 0
.equ READ = 1


; I2C Master init 
;keine Parameter, keine Rueckgabewerte
;************************************************************************
USI_TWI_master_init:
	ldi tmp1,(1<<PORT_USI_SDA)|(1<<PORT_USI_SCL);Pullups an SDA u. SCL an
	out PORT_USI,tmp1
	out DDR_USI,tmp1;SDA u. SCL als Ausgaenge
	ser tmp1 ;Lade Dataregister mit High Bytes
	out USIDR,tmp1
	;USI Interrupts inaktiv, USI im 2 Wire Modus Software Clock
	ldi tmp1,(1<<USIWM1)|(1<<USICS1)|(1<<USICLK)
	out USICR,tmp1
	ldi tmp1,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC);Lösche USI Flags
	out USISR,tmp1	;und resete den Counter
	ret
;************************************************************************


;			USI_TWI_master_start
;   Sendet Startbedingung und die Slaveadresse
;	Parameter, Slaveadresse im Register param1
;	Rueckgabe 1 beim Erfolg 0 beim Fehler ueber Register param1
;************************************************************************
USI_TWI_master_start:
	sbi PORT_USI,PIN_USI_SCL;zieht SCL High
USI_TWI_master_start_1:
	sbis PIN_USI,PIN_USI_SCL;warte bis SCL High ist
	rjmp USI_TWI_master_start_1
	rcall delay
	cbi PORT_USI,PIN_USI_SDA ; zieht SDA LOW
	rcall delay
	cbi PORT_USI,PIN_USI_SCL ;SCL wieder LOW 
	sbi PORT_USI,PIN_USI_SDA ;SDA High
	out USIDR,param1; Slaveadresse/Data in den USI Dataregister schreiben
	;mastertransfer aufrufen 
	TRANSFER_8_BIT
	cbi DDR_USI,PIN_USI_SDA	;SDA auf Eingang
	TRANSFER_1_BIT 
	ret
;***********************************************************************


;	USI_TWI_master_write
;	Sendet ein Byte am den Master
;	Parameter: Data im Register param1
;	Rueckgabe 1 beim Erfolg 0 beim Fehler ueber Register param1
;***********************************************************************
USI_TWI_master_write:
	out USIDR,param1; Data in den USI Dataregister schreiben
	;mastertransfer aufrufen für die
	TRANSFER_8_BIT ;Byte Uebergabe
	cbi DDR_USI,PIN_USI_SDA	;SDA auf Eingang
	TRANSFER_1_BIT;um ACK/Nack Abzuholen 
	ret
;***********************************************************************

;	USI_TWI_master_read
;	Liest ein Byte vom Slave aus
;	Parameter: Sende ACK/Nack im param1 1 == ACK senden; 0 == kein ACK senden(Nack)
;	Rueckgabe gelesene Daten in param1
USI_TWI_master_read:
	cbi DDR_USI,PIN_USI_SDA ;SDA auf Eingang setzen
	TRANSFER_8_BIT
	push param1
	brtc USI_TWI_master_read_send_NACK ;wenn T Flag geloescht ist erfolgt ein NACK
	;sonst muss ein ACK erfolgen
	out USIDR,null
	rjmp USI_TWI_master_read_end
USI_TWI_master_read_send_NACK:
	out USIDR,full
USI_TWI_master_read_end:
	TRANSFER_1_BIT
	pop param1
	ret
;***********************************************************************
	

;			USI_TWI_master_transfer
; sorgt für die Komunikation mit dem slave
;mit param1 wird übergeben ob ein Byte empfange/gesendet wird, oder nur 1 Bit für ACK/NACK
 
USI_TWI_master_transfer:
	out USISR,param1;der Counter wird vorgeladen
USI_TWI_master_transfer_1:
	rcall delay
	sbi USICR,USITC ;Positive Flanke an SCL erzeugen 
USI_TWI_master_transfer_2:	
	sbis PIN_USI,PIN_USI_SCL	; warten bis SCL High ist
	rjmp USI_TWI_master_transfer_2
	rcall delay
	sbi USICR,USITC;negative Flanke an SCL erzeugen
	sbis USISR,USIOIF;testen ob Counter ubergelaufen ist
	rjmp USI_TWI_master_transfer_1	;wenn nicht mit dem nächstem Bit 
	rcall delay		;wenn gelesen wird
	in param1,USIDR;Daten holen 
	out USIDR,full
	sbi DDR_USI,PIN_USI_SDA; SDA auf Ausgang stellen
	ret
;***********************************************************************


;			USI_TWI_master_stop:
;Sendet die Stop Bedingung
;***********************************************************************
USI_TWI_master_stop:
	cbi PORT_USI,PIN_USI_SDA
	sbi PORT_USI,PIN_USI_SCL
USI_TWI_master_stop_1:
	sbis PIN_USI,PIN_USI_SCL
	rjmp USI_TWI_master_stop_1
	rcall delay
	sbi PORT_USI,PIN_USI_SDA
	rcall delay
	ret
;***********************************************************************

; 			delay
;Eine kurze Pause von insgesammt 10 Takten
;***********************************************************************
delay:
	;Rcall hat 3 Takte gedauert
	nop	;1 Takt
	nop ;1 Takt
	nop ;1 Takt
	ret ; 4 Takte
;***********************************************************************
das Ganze ist als usi_master.asm gespeichert und im Hauptprogramm eingebunden.

Mögliche Verwendung sieht dann so aus:

Code:
;EEPROM Slave Adresse von HP03
.equ HP03_sEEPROM = 0xA0

.org 0x0000
	rjmp reset
.org OVF1addr
	rjmp timer1
.include "usi_master.asm"

reset:
	ldi tmp1,RAMEND
	out SPL,tmp1
                rcall USI_TWI_master_init
loop:	 
                rcall HP03_EEPROM_read
                rjmp loop


HP03_EEPROM_read:
	;es sind insgesamt 18 Bytes zu empfangen und schoen der Reihe nach bei C1
	;angefangen abzulegen
	ldi tmp1,0x12 ;Readzaehler belegen
	ldi XH,HIGH(C1)
	ldi XL,LOW(C1)
	START_I2C HP03_sEEPROM+WRITE ;Start an HP03 EEPROM senden
	ldi param1,HP03_dEEPROM ;EEPROM Adresse einstallen
	rcall USI_TWI_master_write 	
	START_I2C HP03_sEEPROM+READ ;RepStart an HP03 EEPROM senden
HP03_EEPROM_read1:
	cpi tmp1,2
	brlo HP03_EEPROM_read2
	READ_ACK
	st X+,param1
	dec tmp1
	rjmp HP03_EEPROM_read1
HP03_EEPROM_read2:
	READ_NACK
	st X,param1
	rcall USI_TWI_master_stop
	ret
Was man anpassen muß ist das hier:
Code:
;USI Pin Konfiguration fuer tiny 24

.equ PORT_USI = PORTA
.equ DDR_USI  = PORT_USI- 1
.equ PIN_USI  = DDR_USI - 1
.equ PORT_USI_SDA = PORTA6
.equ PORT_USI_SCL = PORTA4
.equ PIN_USI_SDA = PINA6
.equ PIN_USI_SCL = PINA4
Und ein paar Register benennen, welche, findest Du raus, wenn es Fehler wegen unbekannte Register hagelt

Am sonsten ist es ziemlich einfach:
rcall USI_TWI_master_init beim Reset durchführen

START_I2C HP03_sEEPROM+WRITE
Start senden an I2C Adresse HP03_sEEPROM mit WRITE Bit

rcall USI_TWI_master_write
sendet ein Byte an den Slave,davor mußt Du in param1 laden, was Du senden möchtest...

START_I2C HP03_sEEPROM+READ
start/repstart mit READ Bit

READ_ACK
empfängt ein Byte und sendet ACK an den Slave, in param1 befndet sich das, was empfangen wurde

READ_NACK
sehe READ_ACK nur mit NACK

rcall USI_TWI_master_stop
ohne Komentar(Anmerkung, ich weiß im Moment selber nicht, warum ich das nicht auch in ein Makro verpackt habe )

Am sonsten hab ich das einigermassen gut komentiert...

Ja dann schau mal

Gruß Sebastian

P.S.

Nochwas , solltest Du Dich über Fehler wegen Register null und full wundern, ehm ich lege mir am Anfang 2 untere Register null mit 0 und full mit 255 an, das erleichtet einiges beim programmieren...