Hallo bin beim Einarbeiten. Folgendes kl. Programm wundert mich. Es soll mit Taster (PB2) eine Led (PB1) ausgeschaltet werden, solange der Taster gedrückt ist. Wird der Taster gerückt wird die LED aber heller obwohl der PortB1 doch gelöscht wird. Wo mache ich etwas falsch? .include "tn13def.inc" Start: sbi DDRB,0b00000001 ;PortB1 soll Ausgang sein, Rest ist als Eingang konfig. sbi PortB,1 ;PortB1 wird gesetzt sbi PortB,2 ;Pullup einschalten, hier ist der Taster dran sbic PinB,2 ;überspringe nächsten Befehl, wenn Taster gedückt ist. cbi PortB,1 ;PortB,1 ausschalten rjmp Start Es handelt sich um keine Schulaufgabe und ist nur von privaten Interesse. Mit freundlichen Grüßen Fred.
Fred schrieb: > Folgendes kl. Programm wundert mich. Dann laß es dochmal im Simulator laufen. Allgemein hat ein Programm ein Init, was nur einmal durchlaufen wird und danach folgt die Mainloop.
Fred schrieb: > sbi DDRB,0b00000001 ;PortB1 soll Ausgang sein, Rest ist als Eingang > konfig. Tu dir selbst einen Gefallen. sbi will die Nummer des Bits haben, das es setzen soll. Es gibt keinen Grund da Binärzahlen anzugeben. Wenn du das Bit 1 im DDRB gesetzt haben willst, dann schreib ganz einfach
1 | sbi DDRB, 1 |
An dieser Stelle ist eine Deziamlschreibweise das einfachste. Willst du das Bit 5 auf 1 haben, dann eben
1 | sbi DDRB, 5 |
Da muss man nicht mit Binärzahlen künsteln. Deine Freundin wird auch so beeindruckt sein, ohne dass du maximale Komplexität mit Binärzahlen an allen möglichen unangebrachten Stellen vortäuscht. Deine grundsätzliche Programm-Idee ist zwar recht naheliegenden, aber sie äussert sich genau so wie du das siehst. Wenn du die LED ausschalten willst, dann musst du sie auch wirklich ausschalten. Eine LED zuvor dauernd einzuschalten und gleich wieder auszuschalten weil ein Taster gedrückt ist, ist eben nicht dasselbe. Der Portpin wechselt, so wie du das programmiert hast dadurch ja ständig zwischen 0 und 1. Das geht so schnell, dass du das Blinken nicht als Blinken siehst, sonder als halbhell leuchtende LED. Lässt du das ausschalten dann weg, dann brennt die LED natüclich mit voller Kraft. Was du programmiert hast, ist
1 | +---------> |
2 | | LED einschalten |
3 | | wenn Taste gedrückt |
4 | | dann LED ausschalten |
5 | | | |
6 | +----------+ |
und das schaltet die LED eben nicht komplett aus, weil sie ja am Beginn der Schleife erst mal eingeschaltet wird. Was du zum Beispiel programmieren müsstest, ist
1 | +---------> |
2 | | wenn Taste nicht gedrückt |
3 | | dann LED einschalten |
4 | | wenn Taste gedrückt |
5 | | dann LED ausschalten |
6 | | | |
7 | +----------+ |
Das sorgt dafür, dass die LED entweder ein oder aus geschaltet wird, je nach Tasterstellung. Aber nicht in einem Durchlauf durch die Schleife beides. Das ist ein entweder oder. Weil ja die Taste auch entweder gedrückt oder nicht gedrückt sein kann. Aber immer nur eines von beiden und nicht erst mal einschalten und dann bei Bedarf ausschalten. Auf die Art ist die LED nie komplett aus.
:
Bearbeitet durch User
Hallo , recht herzlichen Dank für die sehr ausführliche und bisher in keinem anderen TUT gelesenen Erläuterungen. mein 2.Versuch: sbi DDRB,1 ; Led Sbi PORTB,2 ; Taster- Pullup Start: sbic PinB,2 ; springe wenn Taster gedrückt zu "cbi...." rjmp aus cbi PortB,1 ; Led ist an rjmp Start aus: ; wenn Taster nicht gedrückt, Led aus sbi PortB,1 rjmp Schleife Ich habe es am lebenden Objekt getestet, es geht tatsächlich die Led aus! Es geht aber nicht ohne Unterprogramm. Ich halte die Lösung nicht für sonderich elegant. Wäre es vl. besser Register mit entsprechendem Muster zu laden und diese dann aufzurufen? Vl. Grüße und nochmals vl. Dank Fred.
sorry, (Alzheimer)das letzte Sprungziel muss auch "Schleife" heißen.
Fred schrieb: > Es geht aber nicht ohne Unterprogramm. Na ja. Ein Unterprogramm ist schon noch was anderes. Nur weil du da ein paar Sprünge drinn hast, hast du noch lange kein Unterprogramm. > Ich halte die Lösung nicht für sonderich elegant. > Wäre es vl. besser Register mit entsprechendem Muster zu laden und diese > dann aufzurufen? Besser wäre es, seinen Befehlssatz zu kennen. So wie es ein SBIC als Befehl gibt, gibt es auch ein SBIS als Befehl. SBIC 'Skip if Bit is Clear' SBIS 'Skip if Bit is Set' und damit sind die beiden Operationen 'Wenn Taste gedrückt' bzw. 'Wenn Taste nicht gedrückt' ja trivial umzusetzen. Und da die eigentliche Oepration, die eine LED zu schalten, lediglich 1 Befehl lang ist, braucht man auch nicht mit einem RJMP durch die Gegend springen, sondern es reicht die jeweilige Schaltoperation einfach durch den Skip überspringen zu lassen. Das einemal 'wenn gedrückt', das andere mal 'wenn nicht gedrückt'
1 | Loop: |
2 | sbic PINB, 2 |
3 | sbi PORTB, 1 |
4 | sbis PINB, 2 |
5 | cbi PORTB, 1 |
6 | |
7 | rjmp Loop |
Sobald mehrere Operationen abhängig vom Zustand des Pins am PINB abhängig sind, muss man dann allerdings mit einem RJMP aus der normalen linearen Abarbeitung ausbrechen und den zugehörigen Code anspringen, so wie du das gemacht hast. Hier allerdings geht es noch ohne.
:
Bearbeitet durch User
Fred schrieb: > Es geht aber nicht ohne Unterprogramm. Ein Unterprogramm hast du auch nicht! Das sind nur wilde Sprünge. Schreibe dir mal Schritt für Schritt auf, was du machen willst. Dann siehst du, dass es da es auch einfacher geht. (in dieser Beschreibung kommt sicher nicht 'springe zu aus' vor ;-) )
Fred schrieb: > Ich halte die Lösung nicht für sonderich elegant. Die Lösung ist schon elegant, da sie funktional richtig ist und keine Nebeneffekte hat. Karl Heinz schrieb: > Loop: > sbic PINB, 2 > sbi PORTB, 1 > sbis PINB, 2 > cbi PORTB, 1 > > rjmp Loop Sparlösungen haben oft Einschränkungen. Z.B. darf die Aktion nur einen Befehl lang sein. Und wenn ein Eingang 2-mal abgefragt wird, dann muß man prüfen, ob eine Änderung dazwischen keine unerwünschten Resultate liefert. Bei Assembler muß man sich damit abfinden, daß man einen beträchtlichen Overhead hat. Will man das nicht, muß man eine Hochsprache verwenden (C ist sehr weit verbreitet).
Peter Dannegger schrieb: > Sparlösungen haben oft Einschränkungen. > Z.B. darf die Aktion nur einen Befehl lang sein. ... *)
1 | Loop: |
2 | sbic PINB, 2 |
3 | rcall up_an |
4 | sbis PINB, 2 |
5 | rcall up_aus |
6 | rjmp Loop |
7 | |
8 | up_an: |
9 | sbi PORTB, 1 |
10 | ; viiieeel Code |
11 | ret |
12 | up_aus: |
13 | cbi PORTB, 1 |
14 | ; noch mehr Code |
15 | ret |
*) macht doch nichts ;-)
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.