Forum: Mikrocontroller und Digitale Elektronik while_keypressed mit avr assembler...(at tiny 2313) ??


von Tilman W. (tilman)


Lesenswert?

Schönen guten Abend... Für den Experten womöglich ein eher einfaches
Problem, für mich im Moment eine harte Nuss: Wie kann ich mit Assembler
eine Funktion hinbekommen, die eine LED solange leuchten lässt, wie eine
entsprechende Taste gedrückt ist...und zwar über UART ? Im Moment habe
ich folgenden Code:

.include        "tn2313def.inc"

    USART_Init:
  ;Set baud rate
  ldi  r16,4000000/(9600*16)-1 ;set baud rate
  out UBRRL,r16
  ;Enable receiver & transmitter
  ldi r16,(1<<RXEN)|(1<<TXEN)
  out UCSRB, r16
  ;Set frame format: 8 data, 2 stop bits
  ldi r16, (1<<USBS)|(3<<UCSZ0)
  out UCSRC, r16

serin:  sbis ucsra,7
        rjmp serin

  in r16,udr
  out DDRB,r16
  rjmp serin

Bei Tastendruck (am Laptop-mit Hyperterminal)werden die entsprechenden
LEDs aktiviert...ok, was aber muss ich tun, damit bei loslassen der
Taste wieder alle ausgehen...ich kriegs nicht hin...
Danke & Gruss, Tilman

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Also ich würde es so lösen, du wislt ja solange eine Taste gedrückt wird
das etwas passiert.

Dan machs so: Merk dir in einer Variablen welche Taste gedrück ist,
sagen wir mal r18
in r16 ist deine "neue gedrückte Taste"

dann einfach:

cp r18, r16 ;Prüfen ob beide Gleich sind
bneq Ledaus ;Wenn ungelich wurde die Taste losgelassen oder eine andere
gedrückt
(Hier Code um die benötigte LED anzuschalten)
jmp serin
Ledaus:
(Code um benötigte LED anzuschalten)
jmp serin

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

vor dem lezten jmp serin, natürlich noch ein
mov r18, r16 ;Die neue Taste in r18 für erneuten durchlauf

von Mario Richter (Gast)


Lesenswert?

Hallo,

ich glaube, er will die LED bereits dann ausschalten, wenn man eine
Taste auch nur loslässt. Oder ?

Das ist nicht ganz so einfach, weil das Terminal ja nicht mitteilt,
wann eine Taste losgelassen wird, sondern nur, wenn eine gedrückt wird.
Einzige Möglichkeit, die ich sehe, ist über die Wiederholrate: wenn man
länger auf einer Taste bleibt, wird das Zeichen ja nach kurzer Zeit
mehrfach ausgegeben. Man könnte also eine Abfrage machen, die nach
einiger Zeit ohne erneutes Eintreffen des Zeichens über die USART die
LED wieder ausschaltet. Nachteil: deutliche Verzögerung.

Einfacher wäre es, eine Taste zum Einschalten und eine andere zum
Ausschalten der LED zu benutzen.

(Oder natürlich du nimmst nicht das Terminal, sondern schreibst dir ein
Windows-Programm, dass beim Drücken und Loslassen der Taste
entsprechende Nachrichten lossendet ...)

Grüße, Mario

von thkais (Gast)


Lesenswert?

Oder man macht eine "Toggle"-Funktion. Einmal drücken = an, nochmal
drücken = aus usw.
Oder eine alte PC-Tastatur direkt an den µC anschließen, die teilt über
die Codes nämlich mit, wann die Taste gedrückt und wann sie wieder
losgelassen wird.

von Tilman W. (tilman)


Lesenswert?

Hallo Leute !
Vielen Dank für Eure Antworten. Nun ja, Laeubis Lösung habe ich
ausprobiert. Die Folge war zwar prinzipiell richtig - die LEDs gehen
bei Tastendruck an - und dann wieder aus, wenn ich die Taste loslasse,
jedoch flackern sie wie verrückt...
Marios...ja, die Idee ist Gold, ein eigenes Programm (anstelle von
Hyperterminal) zu schreiben...in C# etwa gibts ja fertige Befehle wie
while_KeyPressed...und sobald man dann loslässt wird ein Befehl
geschickt, der alle LEDs wieder ausschaltet. Trotzdem...das kann doch
nicht sein, dass wir das nicht auch so hinkriegen...
Ich habe jetzt mal folgendes gemacht: Den internen Oszi auf 8 MHz
hochgestellt...mit folgendem Code funktionierts zwar, aber auch nur mit
einer Delay-Funktion, so dass zwischen Ein- und Ausschalten so ca. eine
halbe Sekunde Zeit ist. Ich will aber, dass das Zack-zack geht... Taste
gedrück: LED an...Taste halten...LED bleibt an...Taste loslassen...LED
aus...


.include        "tn2313def.inc"

    USART_Init:
  ;Set baud rate
  ldi  r16,8000000/(9600*16)-1 ;set baud rate
  out UBRRL,r16
  ;Enable receiver & transmitter
  ldi r16,(1<<RXEN)|(1<<TXEN)
  out UCSRB, r16
  ;Set frame format: 8 data, 2 stop bits
  ldi r16, (1<<USBS)|(3<<UCSZ0)
  out UCSRC, r16
    sbi ucsrb,rxcie

default:  ldi r16,0b10101010
      out DDRB,r16
      sbis ucsra,7    ;Wenn Daten im RX Buffer, dann weiter zu serin2
      rjmp default
                   ;if UART Receive Complete bit is clear
serin2:  in r16,udr
    out DDRB,r16
    cbi ucsra,7
    rcall dly
    sbis ucsra,7
    rjmp default
    rjmp serin2


dly:
dec r17
brne dly
dec r18
brne dly
ret



Irgendwie muss das gehen !
Das Bit7 von UCSRA wird halt nur gesetzt, wenn auch ein ganzes Zeichen
im RCX Register angekommen ist und dann wird es erst wieder gesetzt,
wenn ein neues Zeichen ankommt...irgendwie ist mir das selbst noch
nicht genau klar...

von Rolf Magnus (Gast)


Lesenswert?

> Ich will aber, dass das Zack-zack geht... Taste
> gedrück: LED an...Taste halten...LED bleibt an...Taste
> loslassen...LED aus...

....

> Irgendwie muss das gehen !

Klar geht das irgendwie, aber halt nicht mit einem normalen
Terminalprogramm, da das dir eben nicht mitteilt, wann eine Taste
losgelassen wurde.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

klar geht das Zackzack... mach einfach nen Timerint und wenn innerhalb
von 100ms keien gleicher Buchstabe angekomemn ist.. -> LED aus

von Rolf Magnus (Gast)


Lesenswert?

Naja, die erste Wiederholung wird normalerweise um mehr als 100ms
verzögert, und die Verzögerungszeiten können konfiguriert werden. Wenn
da einer 150ms eingestellt hat, geht's nicht mehr.
Außerdem ist es natürlich Definitionssache, ob das als "Zackzack"
bezeichnet werden kann. Zum Testen von Reaktionszeiten wäre es wohl
inakzeptabel.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

klar dan nimmt ma halt 200ms oder sowas in der Art, aber das sidn Zeiten
die man nicht durch Schnelles drücken machen kann, sonder nur wenn man
gedrückt läßt,
 und bei nem Reaktiosntest nimmt man für gewöhnlich ein Toggelmodus,
Taster 1 Startet, es kommt das Signal, am drückt Taster 2 udn hat die
Reaktiosnzeit.

von Hannes L. (hannes)


Lesenswert?

Die über das Betriebssystem ausgewertete Computertastatur ist für diesen
Zweck ungeeignet. Denn zwischen dem ersten Zeichen und der ersten
Wiederholung ist eine Pause, erst danach folgen die Zeichen direkt
hintereinander.

...

von Tilman W. (tilman)


Lesenswert?

Ich schreibe gerade ein eigenes Terminalprogramm in C#. Müsste heute
abend oder so fertig sein. Ich verwette 100 Ampere-Stunden, dass es
dann geht !
Grüße, Tilman

von Hannes L. (hannes)


Lesenswert?

Aber sicher ist das machbar, nur nicht mit einem
Standard-Terminal-Programm. In QBASIC habe ich das vor Jahren schon
gemacht. Ist z.B. Bestandteil des Simulationsmodus der Steuerung für
die ATV-Relaisstation DB0WTB.

In C/C++ kann ich es aber nicht, dazu ist mir C zu fremd...
Viel Erfolg...

Bit- & Bytebruch...
...HanneS...

von Tilman W. (tilman)


Lesenswert?

Das Problem mit Hyperterminal ist, wie Du es ja genau gesagt hast, dass
das Betriebssystem eine gedrückte Taste nicht immer als gedrückt
identifiziert, sondern zwischen dem ersten Drücken und einem
permanenten Signal zuerst noch eine Pause von ca. 250ms setzt.
Vielleicht kann man dieses ja irgendwo ändern.
In C gibts es die Methoden, bzw. Funktionen "KeyPress", "KeyDown"
und "KeyUp". Somit kann jeder Status immer eindeutig erkannt und
entsprechend verarbeitet werden. Damit funktioniert es jetzt !
Danke für alle Tips und: Gruuß !
Tilman

von Hannes L. (hannes)


Lesenswert?

Völlig korrekt. Aber diese Pause ist norwendig, ohne sie könnte man
keine Texte vernünftig eintippen, denn die Tasten würden dann prellen
und jedes Zeichen mehrfach eingeben...

...

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.