Hi,
ich habe einen ATTiny 861, der als TWI slave arbeiten soll.
Ich habe aus dem sehr bescheidenen APNotes von Atmel zum thema USI als TWI slave (AVR:312) und dem Datenblatt des Tinys einen Code erstellt.
Jedoch wird mir aus keinem der beiden pdfs klar, was ich machen muss, damit die USI ein ACK sendet.
Codes zur ansteuerung finde ich meistens nur in C und für andere controller (C is nicht so meine stärke).
Hier mal mein Code:
Hauptcode:
und die Init:Code:.include "Tn861def.inc" .include "Bezeichnung.asm" rjmp Init .org 0x0007 rjmp USI_START ; USI Start Handler .org 0x0008 rjmp USI_OVF ; USI Overflow Handler .include "init.asm" main: out porta,USI_Status rjmp main rjmp main USI_START: push temp1 ;temp1 sichern ldi USI_Status, 0x00 ;Status auf 0 setzen (adresse empfangen) wait: sbic pinb,2 ;warten bis scl low ist,da sonst der counter erhöht wird rjmp wait SBI USICR,6 ;USI Overflow interrupt aktivieren rcall timer_8bit ;counter reseten, flags löschen pop temp1 ;temp1 zurückholen reti USI_OVF: push temp1 push temp2 ;Status auslesen cpi USI_Status,0 breq Status0 ;adresse cpi USI_Status,1 breq Status1 ;Slave soll senden cpi USI_Status,2 breq Status2 ; cpi USI_Status,3 breq Status3 ; cpi USI_Status,4 breq Status4 ;Slave soll empfangen cpi USI_Status,5 breq Status5 ; rjmp reset_USI Status0: ;Adresse empfangen in temp2,USIDR ;kann auch USIBR/USIDR sein, sollte egal sein mov temp1,temp2 ;Empfangene Adresse sichern (wegen R/W) andi temp1,0xfe ;Adresse Maskieren cpi temp1, ((Slave_adr*2));Eigene Adresse? breq Status01 ;Wenn JA, Springe zu Status01 rjmp reset_USI ;Wenn nein, USI reseten (interrupt deaktivieren) Status01: ;Eigene Adresse erkannt rcall sende_ACK ;ACK senden Andi temp2,0x01 ;R/W auslesen und entsprechend Status wählen SBRC temp2,0 ;Wenn 1 = Read LDI USI_Status,1 ;Wenn 0 = Write SBRS temp2,0 LDI USI_Status,4 rjmp ende Status1: ;Master will Byte empfangen (Slave soll senden) out USIDR,data ;Daten in Datenregister laden ,kann auch durch laden von daten aus einer Tabelle ersetzt werden sbi PORTB,0 ;Port transparent machen LDI USI_Status,2 rjmp ende Status2: ;Slave hat gesendet, empfangen von ACK vorbereiten cbi DDRB,0 ;Empfangen von ACK vorbereiten cbi PORTB,0 ; LDI USI_Status,3 ;Status ändern rcall Timer_1Bit ;Timer auf das erhalten von 1 Bit einstellen rjmp ende Status3: ;ACK oder NACK erhalten? in temp1,USIDR ;Empfangene daten einlesen Andi temp1,0x01 ;ACK/NACK maskieren sbi DDRB,0 ;SDA auf low ziehen SBRS temp1,0 ;Wenn ACK, siehe Status1 rjmp Status1 rjmp reset_USI ;Wenn NACK, reset Status4: ;Slave soll Empfangen rcall Zuruckstellen_ACK LDI USI_Status,5 ;Status ändern rjmp ende Status5: ;Byte empfangen, ACK senden in data,USIDR ;Daten einlesen rcall sende_ACK rcall Timer_1Bit ldi USI_Status,4 rjmp ende sende_ACK: cbi PORTB,0 ;prepare to send "0" on SDA sbi DDRB,0 ;setup the SDA line as output rcall Timer_1Bit ;timer für ACK zurückstellen ret Zuruckstellen_ACK: cbi DDRB,0 ;SDA wieder als eingang ret TImer_8Bit: ldi temp1,0xe0 ;flags löschen, counter resetten könnte auch 0xf8 sein out USISR,temp1 ret Timer_1Bit: ldi temp1,0xee out USISR,temp1 ;timer für ACK zurückstellen und flags löschen ret reset_USI: cbi USICR,(USIOIE) ;interrupt deaktivieren ldi USI_STATUS,6 ;TESTZWECK rjmp ende Ende: sbi USISR,(USIOIF) ;Interrupt flag löschen pop temp2 ;Stack zurückholen pop temp1 ; reti
Als master verwende ich einen Mega8, mit hardware TWI. Dieser bekommt nach dem senden der Adresse kein ACK zurück, die Adresse stimmt aber, hab sie schon mehrfach gedreht, hat nie geklappt.Code:init: init: ;Stack ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse out SPL, temp1 ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse out SPH, temp1 ;I/O einstellen ldi temp1, 0xFF ; Port A = Ausgang out DDRA, temp1 Ldi temp1, 0x00 ;PortB = Eingang out DDRB, temp1 ldi temp1, 0x00 ;Pullups bei TWI pins deaktivieren out PORTB,temp1 ;TWI Slave mit interrupt cbi DDRB,0 ;SDA als Input ldi temp1,0x00 ;Pinbelegung von TWI bei 0x01 PA, bei 0x00 PB out USIPP,temp1 ; ;TWI modus aktivieren (ohne Clockstreching), Ldi temp1,(1<<USISIE)+(0<<USIOIE)+(1<<USIWM0)+(1<<USIWM1)+(1<<USICS1)+(0<<USICS0)+(0<<USICLK) out USICR,temp1 ; ldi temp1,0xf0 ;flags löschen, counter resetten out USISR,temp1 ser temp1 ;TESTZWECK mov data,temp1 ; LDI USI_Status,0xFF ;TESTZWECK sei ;interrupts aktivieren rjmp main
Das Problem dass ich habe ist, dass ich nicht weis, wie ich mit der Slave ein ACK Signal erzeugen kann, oder falls USI das automatisch macht, warum keins beim Master ankommt.
Könnte vlt. jemand drüberschaun, ich such schon den ganzen tag nach fehlern und find keine mehr, auser die sache mit dem ACK.
mfg robin







Zitieren

Lesezeichen