- LiTime Speicher und Akkus         
Ergebnis 1 bis 7 von 7

Thema: TWI mit ATtiny25/26

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    01.02.2008
    Beiträge
    12

    TWI mit ATtiny25/26

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Guten Tag an alle Assembler-Programmierer
    ich möchte den (eingeschränkten) TWI (i2C) Bus am tiny 25/26 nutzen und werde nicht ganz schlau aus dem Datenblatt. Man muss sich wohl einige Befehle selber stricken.
    hat jemand Erfahrung damit? ich habe nichts gefunden bisher.
    Vielen Dank im Voraus
    Herzlich Klaus

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Hallo Klaus,

    Hier Master ziemlich zum Schluß.
    Hier Slave

    Vielleicht hilft es Dir weiter.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    01.02.2008
    Beiträge
    12
    Hallo Sebastian, das ist interessant und ich werde es ausprobieren und das Ergebnis melden.

    Du schreibst in og. thread:
    Ich habe mittlerweile die Routine etwas abgeändert, es werden keine Register verändert und ein paar Makros ersetzen die lästige rcalls.

    Ich habe sie schon mehrere Tage im Einsatz und keine Probleme festgestellt
    hast du diese veränderte Version auch noch?
    herzlich Klaus

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    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...
    Software is like s e x: its better when its free.
    Linus Torvald

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    01.02.2008
    Beiträge
    12
    Hallo Sebastian, extra noch ne Nachtschicht für mich, Vielen Dank!
    Es brennt nicht so weil ich viel arbeite und nur zwischendurch zeit habe, außerdem ist die Festplatte meine laptops abgeschmiert und ich muss einiges an Wiederherstellung machen, ich melde mich wieder wenn was neues gibt.
    Dieses Thema hier wird ja relativ viel gelesen, da hast du eine wichtige Vorarbeit geleitest.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Hallo Sebastian, extra noch ne Nachtschicht für mich, Vielen Dank!
    Ach was, manchmal kann ich nicht einschlafen, liegt wahrscheinlich am Alter

    Dieses Thema hier wird ja relativ viel gelesen, da hast du eine wichtige Vorarbeit geleitest.
    Naja, ich habe die Erfahrung gemacht, daß die Leute USI nicht sehr mögen, man muß halt etwas selber Programmieren, und das ist zu umständlich...

    Mir hat es trotzdem Spaß gemacht, diese Routinen zu entwickeln und mit 100 und paar Bytes ist sie sicherlich nicht zu groß.

    Ich würde mich auf jedem Fall freuen, wenn sie bei Dir auch funktionieren würde.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    01.02.2008
    Beiträge
    12
    Hallo Sebastian, vielleicht liest du das hier eines tages.
    Ich wollte dir gern rückmelden, dass da mit dem USI_TWI jetzt funktioniert mit einen I2C-LCD. Hatte im Frühjahr keinen Erfolg und den Sommer über keine Zeit. Habs jetzt noch einmal versucht mit einer MInimalkonfiguration und jetzt geht es. Werde es mit weitren I2C Bausteinen versuchen.

    Noch mal vielen Dank für deine Unterstützung

    Frohes Fest
    herzlich
    Klaus-Dieter

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus