Forum: Mikrocontroller und Digitale Elektronik Daten empfangen/Eingaben während Mikrocontroller arbeitet


von Thomas H. (Gast)


Lesenswert?

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.

von Jens Gerdes (Gast)


Lesenswert?

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

von Uwe (Gast)


Lesenswert?

Hi,
Das gleich gillt für deine Taste, die muss nur einen Int. auslösen, dann 
haut es hin.
Gruß Uwe

von Günter König (Gast)


Lesenswert?

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

von Thomas H. (Gast)


Lesenswert?

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.

von Meiserl (Gast)


Lesenswert?

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.

von Günter König (Gast)


Lesenswert?

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

von Günter König (Gast)


Lesenswert?

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

von Thomas H. (Gast)


Lesenswert?

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.

von Uwe (Gast)


Lesenswert?

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

von Günter König (Gast)


Lesenswert?

Aber Hallo Uwe,

probier ich mal aus. Müsste aber laufen.

Danke und Gruß,

Günter

von Uwe (Gast)


Lesenswert?

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

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
Noch kein Account? Hier anmelden.