Archiv verlassen und diese Seite im Standarddesign anzeigen : Kann das so funktionieren? ( Lauflicht )
Namenlos
17.12.2008, 15:36
Hallo Leute :idea:
Ich bin hier dabei ein Lauflicht gerade zu Programmieren und ich habe
erstmal dazu diverse Fragen.
1.Kann das vom Code so funktionieren?
2.Wie realiesiert man Warteschleifen?
Ich hab dazu gegoogelt bis zum geht nicht mehr
und wenn ich mir die Codebeispiele durchlese
scheine ich es zu verstehen aber irgendwie bin ich nicht
fähig diese zu verändern bzw. habe ich den Eindruck das ich
doch nicht alles verstanden habe.
Zum Beispiel:
LDI ZH,HIGH(65535)
LDI ZL,LOW(65535)
Zaehl:
SBIW ZL,1
BRNE Zaehl
ZH,ZHL sind 2 Register z.B. R18/R19 , welche die Zahl 65535 ( 256*256 )
bilden.
Die Erklärung zu SBIC
"This instruction tests a single bit in an I/O register and skips the next instruction if the bit is cleared"
Heißt doch so viel das wenn das Register 'leer' ist das der nächste Befehl übersprungen wird.
BRNE versteh ich nicht ganz.
Wenn ich das nun in meinen Programmablauf einbinden möchte muss
ich das ganze nur noch Warten nennen und es noch mit ret erweitern?
Wer wäre so nett und könnte mir den Rest erklären? .... :oops:
Und alle guten Dinge sind ja Drei.
3.Wie kann man einfach das Lauflicht erweitern?
Zum Beispiel das es sich auf Tastendruck in die andere Richtung bewegt
oder oder alles Inventiert ist?
Wobei das mit den Inventieren ja noch geht da man ja ein
neues Register brauch den Inhalt darein kopiert und den Inhalt
inventiert.Aber wie sieht es mit den rest aus?:-k
Hier der Code:
Das rcall Warten ist noch leer da ich noch nicht richtig verstanden
habe wie Warteschleifen funktionieren.
Ich wollte das aber schonmal stehen haben damit ich *wenn es richtig ist*
auch das rcall an der richtigen Stelle sitzt.
Liebe Grüße
Namenlos
.include "m8def.inc"
.DEF Lauf = r16
ldi Lauf,0b11111111
out DDRB,Lauf
;Alle Pins am Port B durch Ausgabe 0b11111111 ins
;Richtungsregister DDRB als Ausgang konfigurieren
Schleife:
ldi Lauf,0b00000000
;Alle Bits Low
out PortB,Lauf
;Ausgabe in PortB
rcall Warten
ldi Lauf,0b00000001
;Erster Port High
out PortB,Lauf
;Ausgabe in PortB
rcall Warten
ldi Lauf,0b00000010
;Zweiter Port High
out PortB,Lauf
;Ausgabe in PortB
rcall Warten
ldi Lauf,0b00000100
;Dritter Port High
out PortB,Lauf
;Ausgabe in PortB
rcall Warten
ldi Lauf,0b00001000
;Vierter Port High
out PortB,Lauf
;Ausgabe in PortB
rcall Warten
ldi Lauf,0b00010000
;Fünfter Port High
out PortB,Lauf
;Ausgabe in PortB
rcall Warten
ldi Lauf,0b00100000
;Sechster Port High
out PortB,Lauf
;Ausgabe in PortB
rjmp Schleife
Warten:
Code-Tags eingefügt (PicNick)
Besserwessi
17.12.2008, 19:05
Erst mal zur Warteschleife:
ZH/ZL sind die Register 30 und 31 (weiss grade nicht in welcher reihenfolge). Das ist aber wohl das kleinste Problem. Der Befehl SBIW ist nicht bei allen AVR Controllern implementiert. Das ist ein spezieller Befehl für eine 16 Bit subtraktion: von der 16 Bit Zahl in ZH/ZL wird das in dem Beispiel jeweils 1 abgezogen.
Das BRNE ist ein normaler bedingter Sprung: Springe wenn Z-Flag nicht gesetz ist, also das Ergebnis der LEtzten Rechnung nicht 0 war.
Der Code ist umständlich könnte aber sonst fast funktionieren. Es fehlt noch die Initialliserung des Stackpointers.
Ein Erweitern des Probgramms ist sicher möglich. Man müßte da irgendwo die Tasten abfragen und dann ggf. in einen anderen Programmteil springen.
Ja, und:
SBIW (nicht SBIC) setzt das Z-Flag, wenn das Ergebnis der Subtraktion 0 ist. Dann ist "Equal" erfüllt und der Sprung findet nicht mehr statt, dh das Programm läuft einfach weiter, nachdem 65534 Mal gebranched wurde.
Wenn Du ein Unterprog aufrufen willst musst Du innerhalb dessen noch die verwendeten Register retten, sofern Du sie woanders verwenden willst. Dazu sollte man dann lieber ein Buch oä lesen, damit man weiß, was man tut.
Tasten müssen entprellt werden.
Besser wäre es natäurlich den Timer zu benutzen, aber dazu muss man IRQs auswerten.
Anstatt jedes Bitmuster zu speichern, kannst Du auch einfach ein Bit durch den Port "schieben" -> logical ship left oder right (LSL...)bzw, rotate left/right (ror...).
Gruß
Namenlos
18.12.2008, 19:30
Danke für eue Antworten!
Ich persönlich stelle mir nun einige Fragen.
1)Gibt es den Befehl SBIW auch bei einen Mega8 ?
2)Was für ein Stackpointer?
Bzw wie Initialiesiert man den?
3)Das mit den 'Bit durch den Port schieben' muss ich mir mal
genauer anschauen bis ich mal wieder richtig Zeit dafür finde.
Sind ja zum Glück bald Ferien :)
Ich hoffe die Fragen sind nicht zu blöd! :-#
Liebe Grüße
Namenlos
oberallgeier
18.12.2008, 20:03
... Gibt es den Befehl ... auch bei einen Mega8 ...Solche Fragen stellen sich Dir öfters, Anwort gibts dafür im Datenblatt:
http://www.atmel.com/dyn/products/datasheets.asp?family_id=607#760
... nimm Dir die Langfassung, die Summary nutzt nix. In der Langfassung stehen alle (Assembler-) Befehle für den entsprechenden Controller.
... 'Bit durch den Port schieben' ...Schau mal hier, da gibts etliche Tutorials; (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=413294#413294) da stehen eigentlich immer die Bitoperationen beschrieben.
Zum Stackpointer solltest Du aber selbst mal die Suchfunktion bemühen. Fast alle Fragen gabs ja schon mal - und dazu auch Antworten.
Namenlos
20.12.2008, 10:23
Huhu :)
Einmal nur ganz kurz.
Habe leider gerade keine Zeit weil ich meiner Schwester beim Umzug
helfe.
Ich wollte aufjedenfall erstmal Danke für eure Beiträge sagen :)
Oft reicht *hoffentlich O:) * ein kleiner Gedankenanstoß um
weiterzukommen.... *g* und wenn ich wieder auf Granistoße
dann werd ich mich wieder melden :)
Liebe Grüße
Namenlos
Namenlos
23.12.2008, 14:41
/Doppelpost
Danke für eure Beiträge ich hab mich mal jetzt wieder daran
gesetzt und es funktioniert sogar :)
Jetzt versuche ich das zu vereinfachen indem ich
das Bit einfach durch den Port schiebe
Und ich hab mit vorgenommen mit Displays und
AD-Wandlern was zu machen.... das kann
ja noch dauern :oops:
Liebe Grüße
Namenlos
Namenlos
10.01.2009, 23:21
Tripplepost....
Hallo Leute,
mir ist nicht ganz klar ob es angebracht ist hier weiter zu schreiben
aber vor kurzen habe ich wieder Zeit um mich mit µC zu beschäftigen und
ich habe mein Lauflicht inzwischen so verkleinert das ich nun
einen 16Bit Timer benutze und ich bei jeden Überlauf einen
Interrupt auslöse indem ich dann an den Port das Bit einfach schiebe.
Meine Frage ist nun:
Wie könnte man das ganze nun erweitern damit es bei Tasterdruck 1 ( Beispiel) schneller wird und bei einen anderen Tasterdruck wieder
Langsamer wird?
Jetzt habe ich den Timer so gewählt das er etwa alle 2 Sekunden
auslöst.
Um das oben genannte zu realiesieren könnte müsste man
den Timer verkleinern oder bei Tastendruck gewisse
Startwerte vorladen.
So das es bei einen 16 Bit Timer nicht 65536 Takte dauert bist
dieser überläuft sondern nur zum Beispiel die hälfte dieser Takte.
Und wie verknüfpt man dies noch mit Tastern damit
diese Aktion bis zum nächsten Tastendruck erhalten bleibt?
Könnte mir da jemand auf die Sprünge helfen bzw. diverse
Gedankenstupser geben? = )
Liebe Grüße
Namenlos
Der jetzige Code
.include "m8def.inc"
.def Arbeit = r16
.def Licht = r17
.org 0x0000 ; Hauptprogramm
rjmp Hauptprogramm
.org OVF1addr ;Timer 1 Interrupt Vector Addresse
rjmp Timer1
Hauptprogramm:
ldi Arbeit, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
out SPL, Arbeit
ldi Arbeit, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
out SPH, Arbeit
ldi Arbeit,0b11111111
out DDRC, Arbeit ;Alle Pins am Port C durch Ausgabe 0b11111111 ins
;Richtungsregister DDRC als Ausgang konfigurieren
ldi r16,0b000000100 ;Vorteiler 256 an Timer 1
out TCCR1B,r16 ;Setze Bit
ldi r16, 0b00000100 ;Interrupt Overflow aktivieren
out TIMSK, r16 ;Setze Bit
sei ;Interrupt Aktivieren
ldi Licht,0b00000001 ; =1
out PortC, Licht ;Erste LED an PortC an
Schleife:
rjmp Schleife
Timer1:
rol Licht ;Bits 'schieben'
out PortC, Licht ;Gebe 'Licht' an PortC aus
reti ;Springe zurück
Besserwessi
11.01.2009, 00:44
Für eine variable Frequenz haben die 16 Bit timer den CTC Mode. Da wirkt dann eines der output-compare Register-paare als obere Grenze für den Timer. Der kann dann z.B. nur bis 10000 Zählen.
Bei der Tastenabfrage wird man eine entprellen nutzen müssen, sonst wird eine Taste leicht mehrmals gezählt.
Genau.
Die Entprellung kannst Du zB dadurch erreichen, dass Du die Taste alle zB 50ms abfragst. Auf diese Zeit stellst Du Deinen Timer ein. Als Blinkfrequenz kannst Du Vielfache davon wählen, wenn Du einen Zähler in die ISR einfügst, der das Bit zB nur jedes 40ste Mal auslöst (40*50ms=2s).
Gruß
Namenlos
11.01.2009, 16:32
So wäre ich mal wieder,
Kurzer Überblick:
Ich hab jetzt alles so gemacht das ich beim Auslösen
des Timer Interuptes +1 in einen Register dazurechne
und diese mit einen anderen Register vergleiche.
Wenn dies zutrifft dann springe ich zu den Unterprogramm
wo ich das Bit einmal durch PortB schiebe und wieder
in die Hauptschleife Springe.
Das Vergleichregister soll mit einen Tastendruck den Wert +16 oder
-16 'gutgeschrieben bekommen' Somit ist das Vergleichregister
mit 17 Werten einzustellen und somit ist die Geschwindigkeit einzustellen.
Jetzt zu meinen Problem:
PD2 und PD3 sind aktiviert und die PullUps auch.
Bei Tastendruck wird entweder -16 und +16
gerechnet.Die Addition ist ein wenig umständlich gelöst O:)
Für die Subthraktion gibt es einen direkt befehl für das addieren
hab ich nichts direktes gefunden.
Oder gibt es noch was zu beachten?
Und kann mal jemand über den Code gucken?
Beim Assembilieren gab es zumal keine Fehler.... \:D/
Edit:
So jetzt habe ich den Code weiter überarbeitet und im Simulator
von AVRStudio funktioniert dieser Super, sogar die Addition
im Vergleichsregister wird aufaddiert und alles stimmt.
Nur wenn ich das in Hardware aufbaue funktioniert
das ganze Nicht.
Aufgebaut ist das ganze auf einen MyAVRBoard+Breadboard.
Die LED's laufen einfach durch aber ein Tastendruck hat keinerlei
ausmaß auf deren Geschwindigkeit.
Die Ports habe ich auch schon gewechselt,statt die Spannung vom LPT
zu nehmen habe ich auch mal einen Akku + den 7806er genommen
und da hat sich auch nichts geändert.
Jetzt bin ich mal gespannt was ihr dazu sagt.
Liebe Grüße
Namenlos
.include "m8def.inc"
.def Arbeit = r16 ;Für die Initialisieung zuständig
.def Licht = r17 ;Werte für das Lauflicht
.def Zaehler = r18 ;Zähler für jeden Interrupt
.def Vergleich = r19 ;Vergleichs Register für den Zähler [ "Referenz" ]
.def Wert = r20 ;Wert für die Addition / Subthraktion
;Für den Vergleichswert
.def Reset = r21
.org 0x0000 ; Hauptprogramm
rjmp Hauptprogramm
.org OVF0addr ;Timer 0 Interrupt Vector Addresse [8 Bit-Timer ]
rjmp Timer1
Hauptprogramm: ;Initialisierung
ldi Arbeit, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
out SPL, Arbeit
ldi Arbeit, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
out SPH, Arbeit
ldi Arbeit,0b11111111
out DDRC, Arbeit ;Alle Pins am Port C durch Ausgabe 0b11111111 ins
;Richtungsregister DDRC als Ausgang konfigurieren
ldi Arbeit,0b11111000
out DDRB, Arbeit ;PB0 und PB1 und PB2 als Eingang Aktivieren
ldi Arbeit,0b00000111 ;PB0 und PB1 und PB2 bekommen Pullup Widerstände
out DDRB, Arbeit
ldi Arbeit,0b00000001 ;Vorteiler 1024 an Timer 0
out TCCR0,Arbeit ;Setze Bits [CS02 und CS00]
ldi Arbeit,0b00000001 ;Timer Interupt Aktivieren
out TIMSK,Arbeit ;Setze Bit [T0IE0]
ldi Licht,0b00000001 ; =1
out PortC, Licht ;Erste LED an PortC an
ldi Wert,0b00010000 ;Konstante für das Subtharieren/Addieren [ 16 ]
ldi Vergleich,0b00100000 ;Startwert für das Vergleichsregister
; [ 32 ]
ldi Reset,0b00000000 ;Lösche das Reset Register
sei ;Interrupt Aktivieren
Schleife: ;Hauptschleife
rjmp Schleife
Timer1: ;Aktion beim Timerinterupt
sbic PINB,0 ;Wenn Taster gedrückt PD2 = 0
rcall Addiere
sbic PINB,1 ;Wenn Taster gedrückt PD3 = 0
rcall Subthraiere
sbic PINB,2 ;Wenn Taster gedrückt PD4 = 0
rcall Wiederherstellen
inc Zaehler ;Addiere 1 zum Zähler Register
cp Zaehler,Vergleich ;Wenn der Zähler <= ist als der Vergleich ist
;Springe zu 'Bitschieben'
brge Bitschieben ;Ansonsten:
reti ;Verlasse den Interrupt Handler
Bitschieben: ;Aktion wenn der Vergleich größer war
ldi Zaehler,0b00000000 ;Setze den Zähler Zurück
rol Licht ;Bits 'schieben'
out PortC, Licht ;Gebe 'Licht' an PortC aus
inc Reset ;Erhöhe Inhalt von 'Reset' um +1
cpi Reset,7 ;Wenn Reset= 7 Springe zu Zuruecksetzen
brge Zuruecksetzen ;wenn nicht:
reti ;Verlasse den Interrupt Handler
Zuruecksetzen:
ldi Licht,0b00000001 ;Setze 'Licht' zurück'
out PortC, Licht ;und gebe es in PortC aus
ldi Reset,0b00000000 ;Lösche das Reset-Register
reti ;Verlasse den Interrupt Handler
Addiere:
add Vergleich,Wert ;Addiere 8 zu das Vergleichregister
ret ;Gehe wieder zurück
Subthraiere:
sub Vergleich,Wert ;Subthraiere 8 von dem Vergleichregister
ret ;Gehe wieder zurück
Wiederherstellen:
ldi Vergleich,0b00100000 ;Startwert für das Vergleichsregister
ret ;Gehe wieder zurück
ldi Arbeit,0b00000111 ;PB0 und PB1 und PB2 bekommen Pullup Widerstände
out DDRB, Arbeit
Ne, so sind es Ausgänge!
DDRB = 0bxxxxx000
und
PORTB = 0bxxxxx111
Gruß
Namenlos
12.01.2009, 17:24
Danke für die Antwort.... a
ber das hat immer noch nicht geändert. :-k
Hat jemand Rat parat?Wäre riesig Dankbar dafür :-({|=
Liebe Grüße
Namenlos
sbic PINB,0 ;Wenn Taster gedrückt PD2 = 0
Ne, nicht PIN sondern PORT!
Gruß
Namenlos
13.01.2009, 10:08
Hey,
wir sind in der Schule im PC Raum...meine Güte da sind ja viel mehr
Fehler drin als ich dachte :D
Na gut...das werd ich irgendwann noch zum Laufen bekomme :)
Wie schnell soll der Timer sein damit ich die Taster vernüftig
abfragen kann ohne das diese mehrere male gezählt werden?
Vielen Dank für eure Hilfe :)
Heute werde ich das zum laufen bekommen
\:D/
Liebe Grüße
Namenlos
Namenlos
13.01.2009, 15:57
So ich melde mich mal ich hab mir nochmal alles angeschaut und da war der
Wurm wohl drin.
Beim Ersten mal Läut es durch...und danach Leuchten irgendwelche LED's.
Gerade Leuchteten alle bis auf die ersten 2.
Dann Leuchtet nur die Erste...und dann gehen alle nach und nach an bis auf die Letzte.Und dann Leuchten alle bis auf die Erste... ich bin da irgendwie
ziemlich Ratlos.
Im Simulator läuft alles richtig durch wenn ich die Pins entsprechend betätige dauert ein Durchlauf auch länger....und mehrer Durchläufe hab ich mir
auch angeschaut und alles geht.
Kriege ja noch die Krise dabei... ist wohl doch eine Nummer zu groß :-k
Liebe Grüße
Namenlos
Namenlos
13.01.2009, 16:04
Hey danke an euch nochmal :)
Es Läuft jetzt!
Jetzt muss ich nur noch den Timer,Teiler und die ganzen Werte anpassen
damit es richtig gut läuft =D>
Liebe Grüße
Namenlos
Versuche mal eine Abtastung von 50ms, damit kein Prellen auftritt.
Aber: Wenn Du den Taster länger gedrückt hältst, dann wird es mehrmals erkannt. normalerweise erkennt man bei Tastern zuerst das On, wartet, bis man das Off erkennt und schaltet dann. So kann das nicht passieren...
Viel Spass noch.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.