Hallo liebe Forenmitglieder,
ich habe da einmal eine simple aber trotzdem fuer mich nicht klare
Frage:
Wenn mein Controller gerade arbeitet, z. B. Daten berechnet oder
Schleifen durchlaeuft, und ich Signale ueber einen Eingabeport oder
einen UART sende dann bemerkt er die Signale doch nicht?
also konkret: Wenn mein Controller beschaeftigt ist und ich in der Zeit
z. B. einen Taster druecke der an einen Port angeschlossen ist, merkt er
sich das Signal und bearbeitet es wenn er fertig ist oder muss ich das
so machen, dass er dauernd immer meine Port abfragen muss waehrend er
rechnet?
Das ist doch recht aufwendig, wenn ich in mein Programm dauernd
Abfrageschleifen einbauen muss wenn er eigentlich rechnet!? Gibt es da
Alternativen?
Z. B. gibt es einen Port, den man so konfigurieren kann, dass wenn da
ein Signal anliegt und er gerade rechnet trotzdem zu einer andern Stelle
springt und anschliessend wieder zurueck?
Dazu gliech noch eine analoge Frage. Wenn ich Signale zu UART sende muss
mein Controller gerade diese abfragen, damit er die Signale empfaengt -
sonst laufen sie doch ins leere?
Viele Fragen zum gleichen Thema, die vielleicht sonnenklar sind, aber
mir leider nicht klar sind. Trotzdem danke fuer jede Antwort,
Thomas H.
Hallo Thomas,
Du musst deinen UART so programmieren, dass er einen Interrupt auslöst,
wenn er ein Zeichen empfangen hat. In der Interrupt-Routine liest Du
dieses Zeichen aus dem UART und schreibst es in einen Ringpuffer. Den
Ringpuffer kann Dein Controller dann auslesen, wenn er Zeit dazu hat.
mfg
Jens
Moin Jens,
das ist interessant. Ich habe ein ähnliches Problem, es sollen an den
UART insgesamt 4 Bytes gesendet werden. Der UART löst einen Interrupt
aus und soll nun das erste Byte speichern dann das zweite usw. und nach
Empfang der 4 Bytes die Empfangsroutine verlassen.
Ich habe damit gestern angefangen und der Stand ist nun folgender:
Nach auslösen des Interrupts Sprung nach:
in temp2,udr
st x+,temp2
reti
Der X-Pointer zeigt auf lowbyte $60 und highbyte $00, liegt also beim
4414 im RAM-Bereich.
Logischerweise klappt das natürlich nicht. Es ist so, das sich das
letzte empfangene Byte in $60 befindet. Die anderen Speicherstellen sind
leer ($FF).
Mit nur einem Byte klappt es prima.......
in guter Hoffnung,
Günter
Hallo,
ich habe mich heute etwas in der Bibliothek umgesehen und bin zu dem
selben Ergebnis gekommen wie ihr. Tortzdem danke fuer euere Bemuehungen.
Jetzt muss ich die gelesene Theorie nur noch in die Praxis umsetzten.
Ciao,
Thomas H.
Hallo
Um mehrere Aufgaben quasi parallel laufen zu lassen könnte man auch ein
Multitaskinsystem verwenden.
Habe vor ca. 10 Jahren mal auf einem 51er solch ein System ausprobiert.
Hat gut funktioniert.
Aber wenn es sich nur um UART und Tasten handelt bist mit der alleinigen
Interruptlösung besser dran.
Hallo Thomas,
ich habe heute doch noch die Routine fertig bekommen. Es war so richtig
wie ich begonnen habe. Das Problem lag im auslesen.
Wenn du dir im Tutorial mal das Kapitel über den UART anschaust, findest
du dort ein interruptgesteuerte Empfangsroutine für den 2313. Hier
kannst du folgende Änderungen vornehmen:
nach
.def temp = r16
füge ein:
.def kontrolo = r17; Kontrollvariable für empfangene Bytes
Die Routine rx_com muss geändert werden in
rx_com:
in temp,udr
st x+,temp ;erstes Byte in $60 speichern, Pointer um 1
erhöhen
inc kontrolo ;Bytezähler um 1 hochzählen
cpi kontrolo,$80 ;Größe des Pufferspeichers z.B. $80 = 128Byte
breq res_count ;Ende Puffer erreicht,wenn ja, Pointer auf Anfang
setzen
reti ;Ende der Routine, nächstes Byte empfangen
res_count:
clr kontrolo ;Bytezähler auf 0 setzen
ldi r26,$60 ;Pointer auf RAM-Anfang
ldi r27,$00
reti ;Ende der Routine, die nächsten 128byte
empfangen
Jetzt noch in der "Start" Routine vor sei ;Interrupts
einschalten"
clr kontrolo ; Bytezähler auf 0
ldi r26,$60 ; Adresse Lowbyte RAM
ldi r27,$00 ; Adresse Highbyte RAM
Der X-Pointer ist jetzt initialisiert und zeigt auf die unterste RAM
Adresse.
Es stehen jetzt folgende Informationen zur Verfügung:
1. die empfangenen Bytes stehen im RAM
2. die Anzahl der empfangenen Bytes
Werden mehr als 128 Bytes empfangen, beginnt der Zyklus wieder bei der
untersten RAM-Adresse.
Ich benutze einen 4414 /8515 und der erhält für diese Zwecke noch ein
externes RAM (64KByte).
Probiers mal aus.
Gruß,
Günter
Hallo auch,
die von mir vorgeschlagene Routine ist vermutlich nicht fehlerfrei und
soll ja auch nur als Grundlage dienen. Verbesserungen sind daher immer
gut und interessieren mich natürlich da mit Sicherheit irgendwo noch ein
Gedankenfehler liegt.
Es grüßt ein weiterprobierender
Günter
Hallo,
danke fuer die Mithilfe. Jetzt kann ich einmal in Ruhe die Codes ansehen
und versuchen. Ihr habt euch da ja richtig Muehe gegeben.
Viele Gruesse,
Thomas H.
Hi Günter,
Du kannst noch eine Zeile einsparen wenn du kontrolo auf $80 setzt und
dann (dec)rementierst dabei wird Z-Flag gesetzt und die Zeile
breq res_count ;Ende Puffer erreicht,wenn ja, Pointer auf Anfang setzen
haut auch hin.
Gruß Uwe
Hi,
und es geht noch kürzer
ISR's und Sub's können ja im Prog. auch oben stehen (nach den
INT-Sprüngen)
.def temp = r16
füge ein:
.def kontrolo = r17; Kontrollvariable für empfangene Bytes
Die Routine rx_com muss geändert werden in
rx_com:
in temp,udr
st x+,temp ;erstes Byte in $60 speichern, Pointer um 1 erhöhen
dec kontrolo ;Bytezähler um 1 runterzählen
brne ende
rcall res_count ;Ende Puffer erreicht, Pointer auf Anfang setzen
ende:reti ;Ende der Routine, nächstes Byte empfangen
res_count:
ldi kontrolo,$80 ;Bytezähler auf$80 setzen
ldi r26,$60 ;Pointer auf RAM-Anfang
ldi r27,$00
ret ;Ende der Routine, die nächsten 128byte empfangen
Jetzt noch in der "Start" Routine vor sei ;Interrupts einschalten"
;clr kontrolo ; Bytezähler auf 0
;ldi r26,$60 ; Adresse Lowbyte RAM
;ldi r27,$00 ; Adresse Highbyte RAM
ersetzt durch
rcall res_count
Der X-Pointer ist jetzt initialisiert und zeigt auf die unterste RAM
Adresse.
Gruß Uwe