Hallo zusammen Ich habe einzelne Beispiele bei dem ich über den UART senden oder empfangen kann. Aber das Programm geht nicht. Ich will das auf den AVR schicken und dann den Wert verändert zurückbekommen. Einmal lief die Sache. Aber ich weiss nicht mehr warum. include "8515def.inc" .equ CLOCK = 6000000 .equ BAUD = 9600 .equ UBRRVAL = CLOCK/(BAUD*16)-1 .def temp = r16 rjmp Reset ;Reset vector reti ;Ext Int 0 reti ;Ext Int 1 reti ;Timer 1 Capt reti ;Timer 1 CompA reti ;Timer 1 CompB reti ;Timer 1 OVF reti ;Timer 0 OVF reti ;Serial Transfer Complete rjmp int_rxc;UART Rx Complete reti ;UART Data register empty rjmp int_txc;UART Tx Complete reti ;Analog Comparator Reset: ldi temp,LOW(RAMEND) ;LOW-Byte der obersten RAM-Adresse out SPL, temp ldi temp,HIGH(RAMEND) ;HIGH-Byte der obersten RAM-Adresse out SPH, temp ldi temp,UBRRVAL ;Baudrate einstellen out UBRR,temp sbi UCR, RXEN ;Interrupt für Empfangen vom PC sbi UCR, RXCIE ;Interrupt für Empfangen vom PC sbi UCR, TXEN ;Interrupt für Senden zum PC sbi UCR, TXCIE ;Interrupt für Senden zum PC ldi temp , 0b11000000 ;RXC=Aktiv, TXC=Aktiv out USR, temp ldi temp,0xFF out DDRB, temp ;Datenrichtung von Port B einstellen, 1 = Ausgang sei Main: sei Lupping: rjmp Lupping ;********************* Empfangen von PC ********************* int_rxc: in temp,SREG ;CPU-Status sichern push temp ;temp auf dem Stack sichern in temp, UDR ;später Wert ausgeben out PORTB, temp ;rcall int_txc pop temp ;temp aus dem Stack wieder herstellen reti ;Interrupt beenden ;********************* Empfangen von PC ********************* ;********************* Senden an PC ************************* int_txc: inc temp sbis UCR,UDRE ;Warten bis UDR für das nächste rjmp int_txc ;Byte bereit ist out UDR, temp reti ;********************* Senden an PC ************************* MfG Peter
Möglicherweise weil 'rcall int_txc' auskommentiert ist?
nach dem int_rxc: in tmp1, sreg push tmp1 ... pop tmp1 fehlt das out sreg, tmp1 hmm temp heist das hier, ich nenne es immer tmp1
Hallo
Es geht immer noch nicht. Wo liegt der Fehler?
Blöde Frage warum muss man das CPU-Register sichern?
.include "8515def.inc"
.equ CLOCK = 6000000
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
.def temp = r16
rjmp Reset ;Reset vector
reti ;Ext Int 0
reti ;Ext Int 1
reti ;Timer 1 Capt
reti ;Timer 1 CompA
reti ;Timer 1 CompB
reti ;Timer 1 OVF
reti ;Timer 0 OVF
reti ;Serial Transfer Complete
rjmp int_rxc;UART Rx Complete
reti ;UART Data register empty
rjmp int_txc;UART Tx Complete
reti ;Analog Comparator
Reset:
ldi temp,LOW(RAMEND) ;LOW-Byte der obersten RAM-Adresse
out SPL, temp
ldi temp,HIGH(RAMEND) ;HIGH-Byte der obersten RAM-Adresse
out SPH, temp
ldi temp,UBRRVAL ;Baudrate einstellen
out UBRR,temp
sbi UCR, RXEN ;Interrupt für Empfangen vom PC
sbi UCR, RXCIE ;Interrupt für Empfangen vom PC
sbi UCR, TXEN ;Interrupt für Senden zum PC
sbi UCR, TXCIE ;Interrupt für Senden zum PC
ldi temp , 0b11000000 ;RXC=Aktiv, TXC=Aktiv
out USR, temp
ldi temp,0xFF
out DDRB, temp ;Datenrichtung von Port B einstellen, 1
=
Ausgang
sei
Main:
sei
Lupping:
rjmp Lupping
;********************* Empfangen von PC *********************
int_rxc:
in temp,SREG ;CPU-Status sichern
push temp ;temp auf dem Stack sichern
in temp, UDR ;später Wert ausgeben
out PORTB, temp
pop temp
out sreg, temp ;CPU-Status aus dem Stack wieder herstellen
rcall int_txc
reti ;Interrupt beenden
;********************* Empfangen von PC *********************
;********************* Senden an PC *************************
int_txc:
inc temp
sbis UCR,UDRE ;Warten bis UDR für das nächste
rjmp int_txc ;Byte bereit ist
out UDR, temp
reti
;********************* Senden an PC *************
beim aufruf einen interrupts - dafür sind sie da- wird der normal ablauf
unterbrochen und der interrupt eingschoben.
wenn du aber im normalen programm grad in einer berechnung bist und
brauchst zB das carry flag oder sowas (die sind ja alle im SREG
versammelt) musst du das sichern, bevor es in der interrupt routine
verändert wird.
hab mir das ganze nochmal genauer angeguckt (heut is nicht so spät :)
das kann doch nicht gehen ;)
ich würd da so machen:
main:
hier den Stack initiallisieren
rcall uart_init
loop:
rjmp loop
und hier die unterfunktionen
UART_Init:
;Baudrate einstellen
ldi tmp1, UART_fosc / (UART_Baud * 16)-1
out UBRR, tmp1 ;Baudrate in Register übertragen
sbi UCR, TXEN ;TX (Senden) aktivieren
sbi UCR, RXEN ;RX (Empfang) aktivieren
sbi UCR, RXCIE ;bei Empfang Interrupt auslösen
ret
UART_SendByte:
;Warten, bis UDR für das nächste Byte bereit ist:
sbis USR,UDRE
rjmp UART_SendByte
out UDR, prm1 ;das Byte aus prm1 Senden
ret
;interrupt zum emfangen über uart
UART_Int_rxc:
;SREG nicht gesichert, da nicht verändert
push prm1 ;tmp1 retten
in prm1, UDR
rcall UART_SendByte ;hier das byte senden
pop prm1 ;tmp1 wieder herstellen
reti
Das rcall int_txc muss schon an der Stelle bleiben an der es auch vorher war, also bevor temp gepopt wird
ach ja: hab das sei vergessen nach dem Uart_init. und im komentar steht noch tmp1, dabei push ich prm1, aber das ja nich so wild. der interrupt tx ready ist dazu da, wenn du große datenmengen im ram ablegt und schnell senden möchtes wird nach der fertigen übertragung eines bytes der interrupt ausgelöst und du kannst sofort das nächste senden. so kannst du die uart maximal auslasten. tut hier aber ja nicht not... sach, wenn´s klappt
Hallo
Danke für die Hilfe. Hier habe ich mein Beispiel so abgeändert dass
es geht.
MfG
Peter
.include "8515def.inc"
.equ CLOCK = 6000000
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
.def temp = r16
rjmp Reset ;Reset vector
reti ;Ext Int 0
reti ;Ext Int 1
reti ;Timer 1 Capt
reti ;Timer 1 CompA
reti ;Timer 1 CompB
reti ;Timer 1 OVF
reti ;Timer 0 OVF
reti ;Serial Transfer Complete
rjmp int_rxc;UART Rx Complete
reti ;UART Data register empty
rjmp int_txc;UART Tx Complete
reti ;Analog Comparator
Reset:
ldi temp,LOW(RAMEND) ;LOW-Byte der obersten RAM-Adresse
out SPL, temp
ldi temp,HIGH(RAMEND) ;HIGH-Byte der obersten RAM-Adresse
out SPH, temp
ldi temp,UBRRVAL ;Baudrate einstellen
out UBRR,temp
sbi UCR, RXEN ;RX (Empfang) aktivieren
sbi UCR, RXCIE ;bei Empfang Interrupt auslösen
sbi UCR, TXEN ;TX (Senden) aktivieren
ldi temp , 0b11000000 ;RXC=Aktiv, TXC=Aktiv
out USR, temp
ldi temp,0xFF
out DDRB, temp ;Datenrichtung von Port B einstellen, 1
=
Ausgang
sei
Main:
sei
loop:
rjmp loop
;********************* Empfangen von PC *********************
int_rxc:
in temp,SREG ;CPU-Status sichern
push temp ;temp auf dem Stack sichern
in temp, UDR ;später Wert ausgeben
out PORTB, temp
rcall int_txc
pop temp
out sreg, temp ;CPU-Status aus dem Stack wieder herstellen
reti ;Interrupt beenden
;********************* Empfangen von PC *********************
;********************* Senden an PC *************************
int_txc:
sbis USR,UDRE
rjmp int_txc
inc temp
out UDR, temp ;das Byte aus prm1 Senden
ret
;********************* Senden an PC *************************
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.