Habe den optimierten Code gefunden und poste ihn an dieser Stelle nochmal. Nochmal ein Danke an izaseba für die Arbeit!

Der Code stand hier:
https://www.roboternetz.de/phpBB2/pr...=39337&start=0
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: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this 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: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this 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
[/code]