Hallo Klaus,
Natürlich, die ist seit etwa 2 Monaten auf einem T24 im Einsatz und tut ihren Dienst.hast du diese veränderte Version auch noch?
das Ganze ist als usi_master.asm gespeichert und im Hauptprogramm eingebunden.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 ;***********************************************************************
Mögliche Verwendung sieht dann so aus:
Was man anpassen muß ist das hier: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
Und ein paar Register benennen, welche, findest Du raus, wenn es Fehler wegen unbekannte Register hageltCode:;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![]()
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...







Zitieren

Lesezeichen