Guten Tag,
Ich versuch im Moment folgendes Projekt zu realisieren:
Ich möchte ,dass SOLANGE Schalter 1 gedrückt wird 8 LED nacheinander
angehen.Und SOLANGE ich Schalter 2 drücke sie wieder ausgehen.
Nur weiss ich leider nicht genau wie ich das mit dem SOLANGE
hinbekommen soll.
Könnt ihr mir ein Beispiel Code geben ??
Reiner Messner schrieb:> SOLANGE Schalter 1 gedrückt wird 8 LED nacheinander angehen.
Während dieser Zeit muss eine Variable hochgezählt werden. z.B alle
Sekunde um 1 erhöhen
> Und SOLANGE ich Schalter 2 drücke sie wieder ausgehen.
Während dieser Zeit muss eine Variable runter-gezählt werden. z.B alle
Sekunde um 1 verringern.
Dann im Hauptprogramm:
Wenn Variable = 1 dann Portxx = 0000 0001;
Wenn Variable = 2 dann Portxx = 0000 0010;
usw.
Axel
Hallo
Was hast du denn bereits? Zeig mal her!
Was soll passieren, wenn beide gleichzeitig gedrückt sind?
Welcher Taster gewinnt, der als erstes oder als zweites gedrückt wird?
Gruß
Joachim
Zur Zeit Programmiere ich den ATmega 644 mit AVR Studio
in C.
Wichtig ist auch noch das die anderen LEDs nicht ausgehen.
Lässt sich dass mit folgendem Befehl machen :
PORTA = (~(PORTA << 1));
Hi
Es ist im Prinzip einfach... und da du uns nicht die Programmiersprache
vorgibst, werde ich dir mal einen kleinen Gedankenanstoß liefern :
8 LED = 8 Bit = 1 Byte = Variable LED_Byte
2 Taster = 2 Bit = Bit 0 und Bit 1 von einem Byte und das nenn ich
IO_CTRL.
Timer liefert Interrupt vo 1ms und den teile ich auf die Sekunde
herunter...
1
Timer_ISR:
2
Push .... ; alle Register, die verwendet werden
3
LDS Reg_1, ms0 ; ms*10^0
4
INC Reg_1
5
CPI Reg_1,10
6
BREQ Set_ms1 ; Überlauf
7
STS ms0, Reg_1 ; ablegen
8
RJMP Timer_End
9
Set_ms1:
10
CLR Reg_1 ; Register auf 0 setzen
11
STS ms0, Reg_1 ; ablegen
12
LDS Reg_1,ms1 ; ms*10^1
13
INC REG_1
14
CPI Reg_1,10
15
BREQ Set_ms2 ; Überlauf
16
STS ms1, Reg_1 ; ablegen
17
RJMP Timer_End
18
Set_ms2: ;
19
CLR Reg_1 ; Register auf 0 setzen
20
STS ms1, Reg_1 ; ablegen
21
LDS Reg_1,ms2 ; ms*10^2
22
INC REG_1
23
CPI Reg_1,10
24
BREQ Set_Sek ; Überlauf
25
STS ms2, Reg_1 ; ablegen
26
RJMP Timer_End
27
Set_Sek:
28
CLR Reg_1 ; Register auf 0 setzen
29
STS ms2, Reg_2 ; ablegen
30
RCALL Chk_Taster ; Aufruf jede Sekunde....
31
Timer_End:
32
POP ... ; alle gepushten Register
33
RETI
In einer Subroutine werten wir nun die Taster aus. Die Signalinformation
stellen wir in einer Variablen zur Verfügung.
1
Chk_Taster :
2
Push .... ; Register, die verwendet werden, weil aufruf aus ISR
3
; hier fragst du die Taster ab
4
; setzt Bit hoch oder runter
5
6
Chk_Taster_End:
7
POP
8
RET
Die Routine Chk_Taster wird nun jede Sekunde aufgerufen. Zuerst
kontrollierst du die Taster. Ist keiner betätigt, verläßt du die Routine
durch einen Sprung zu "Chk_Taster_End:"
Nun gibt es die Bitrotation. Um ein Bit nach links zu schieben heißt der
Befehl ROL. Danach setzt du Bit 0 in der Variablen LED_Byte.
1
LDS Reg_1, LED_Byte
2
ROL Reg_1
3
ORI Reg1, 0b00000001
4
STS LED_Byte, Reg_1
Ist der entsprechende Taster gedrückt, wird in der nächsten Sekude
wieder der Registerinhalt einmal nach links geschoben und Bit 0 gesetzt.
Da sieht dann so aus, als würdest du dein Byte füllen.
Leeren geht ähnlich, nur das du mit ROR nach rechts schiebst und
anschließend das Bit 7 löscht.
1
LDS Reg_1, LED_Byte
2
ROR Reg_1
3
ANDI Reg1, 0b01111111
4
STS LED_Byte, Reg_1
In deinem Hauptprogramm weist du nun die Bits aus LED_Byt den Ausgängen
zu
Nun hab ich aber fast vollständig deine Hausaufgabe gemacht, den Rest,
das in deine Sprache zu packen, mußt du selbst machen.
lasst dieses grauseliege delay_ms_(1000) weg, vergesst dass es so was
gibt und benutzte es nie nie wieder.
Danke
Dann mache im Timerinterrupt0 eine weitere Schleife, sodass es es einen
Programmteil gibt, der nur ein mal pro Sekunde durchlaufen wird.
SIGNAL(SIG_OVERFLOW0) // signal handler for tcnt0 overflow
interrupt
{
hlg++;
if (hlg >=100) { // Wert so wählen, dass 1 Sekunde
rauskommt
// dieser Teil wird nur 1 mal pro Sekunde durchlaufen
if (taster 1 gedrückt) variable++;
if (taster 2 gedrückt) variable--;
hlg=0;
}
TCNT0 = 246; // Wert so wählen, dass 10 ms rauskommt
Axel
Reiner Messner schrieb:> Und wie muss ich dann die DRR Register setzten ??
Spätestens jetzt ist es an der Zeit sich mit den Grundlagen zu
beschäftigen und das Lauflicht wegzulegen und erst mal einzelne LED
anzusteuern
AVR-GCC-TutorialAVR-Tutorial
Auch wenn das 2.te das Assembler Tutorial ist, findet sich doch jede
Menge aus dem Umfeld (zb was hat es mit dem DDR Register auf sich), dass
sich lohnt zu lesen.
auch wenn es gleich einen Aufschrei gibt:
vergess auch dass es Assembler gibt und fang gleich in C an.
Zeitkritische Anwendungen die irgend wie Assembler rechtfertigen hat ein
Anfänger vorerst nicht.
Axel
Düsendieb schrieb:> auch wenn es gleich einen Aufschrei gibt:>> vergess auch dass es Assembler gibt und fang gleich in C an.
Tut er doch.
Was er als Anfänger allerdings nicht tun sollte:
Sich mit seinem Wissen auf Timer stürzen.
Auch wenn du im Grunde recht hast und man keine _delays in dieser
Größenordnung macht: Für den Moment ist es ok.
Später wird er dann lernen, wie man es besser machen kann (mit einem
Timer).
Aber jetzt geht es darum
wie funktioniert das DDR Register
was sind Schiebeoperationen
wie setzt man einzelne Bits
wie löscht man einzelne Bits
wie werden Tasten abgfragt (zunächst ohne, in bälde dann
mit Entprellung)
genereller Programmaufbau
weg vom sequentiellen Denken in Schleifen, hin zu Ereignissen
Das ist schon reichlich Tobak, der ihn eine Weile bschäftigen wird. Da
jetzt auch noch Timer mit reinzupacken, wäre zu viel auf einmal.
Düsendieb schrieb:> auch wenn es gleich einen Aufschrei gibt:>> vergess auch dass es Assembler gibt und fang gleich in C an.>> Zeitkritische Anwendungen die irgend wie Assembler rechtfertigen hat ein> Anfänger vorerst nicht.>> Axel
hier ist schon der aufschrei!!!
Assembler sollte sich jeder der einen µC programmiert schon mal
angeschaut haben nur dann wird einem klar wie das ding wirklich arbeitet
und welche dinge der µC wirklich kann.
Es geht hier nicht um optimierung es geht um Grundlagen.
z.b. Warum muss man hier etwas atomar ausführen wenn es noch interupts
gibt
int i;
i++;
Na ja.
man kann auch mit dem Assembler Zeugs anfangen, wenn irgend was in C
alsolut nicht klappen will.
Ist bei mir aber noch nicht vorgekommen, dass ich mir den kompilierten
Code anschauen musste.
Da schreibe ich lieber zwei Zeilen mehr in C und habe einen einfacheren
Code. Speicherplatz und Taktfrequenz kosten heute nix mehr.
Düsendieb schrieb:> lasst dieses grauseliege delay_ms_(1000) weg, vergesst dass es so was>> gibt und benutzte es nie nie wieder.
Dem widerspreche ich. In halbwegs komplexen Anwendungen haben delays in
der Tat nichts verloren, da man i.d.R. sich an einem globalen
Systemtimer orientiert.
Aber: Will man eine so simple Aufgabe wie die des OP implementieren, so
ist das delay genau das Mittel zum Zweck um mit möglichst wenig Aufwand
zum Ziel zukommen. Zumal es hier auch nicht um ein genaues Timing geht.
Wenn wir beide das Problem implementieren müsste, wäre ich nach 3
Minuten fertig, du nach 10 Minuten. Dann haben wir zwei Controller vor
uns liegen, die sich äußerlich völlig identisch verhalten. Wie
rechtfertigst Du dann aber deinen Mehraufwand bei der Programmierung?!
Ein wichtiger Aspekt bei der Entwicklung ist es geeignete Methoden zu
finden, die das Problem am einfachsten und schnellsten lösen. Und in
diesem Fall muss man nicht mit Kanonen auf Spatzen schießen, wenn sie
auch mit einfacheren Mitteln am Ende tod sind. ;-)
Düsendieb schrieb:> Da schreibe ich lieber zwei Zeilen mehr in C und habe einen einfacheren> Code. Speicherplatz und Taktfrequenz kosten heute nix mehr.
darum kommen auch immer diese Frage ob für ein lauflicht ein 8Mhz µC
ausreicht.
Es gab schon genug Anfragen warum etwas zu langsam ist und wenn man sich
den code anschaut wurde mal ein paar quardratische gleichungen im
Interupt gelöst. Sind ja nur ein paar zeilen code kann ja nicht so lange
dauen. Wenn man es einmal ein ASM gemacht hat weiss man das soetwas
lange dauert.
@Fabian
Klar geht das mit einer Verzögerung, aber dann ist die Programmstruktur
im A...
Wenn der TE dann noch etwas an seinem Programm ändern will ist das zu
nicht zu gebrauchen.
@ Peter
natürlich simuliert man ein Progrann und schaut mal wie lange was
braucht. Kommt man dann auch in C auf seltsame Werte kann man dann immer
noch mit den Nachdenken über den entstandenen Assenbler Code anfangen.
Düsendieb schrieb:> @Fabian> Klar geht das mit einer Verzögerung, aber dann ist die Programmstruktur> im A...>> Wenn der TE dann noch etwas an seinem Programm ändern will ist das zu> nicht zu gebrauchen.
Ich wiederhole mich gerne nochmal.
Dein Einwand mit den Timern ist berechtigt.
Aber lass ihn erst mal die Grundlagen lernen!
Wenn du einen Lernenden am Anfang mit zuviel auf einmal überschüttest,
tust du ihm nichts gutes damit.
Fabian schrieb:> Wenn wir beide das Problem implementieren müsste, wäre ich nach 3> Minuten fertig, du nach 10 Minuten. Dann haben wir zwei Controller vor> uns liegen, die sich äußerlich völlig identisch verhalten. Wie> rechtfertigst Du dann aber deinen Mehraufwand bei der Programmierung?!
Dadurch, dass sie sich eben nicht komplett identisch verhalten, wenn man
genauer hinschaut :-)
Die Timerlösung reagiert sofort auf einen Tastenwechsel, bei der Delay
Lösung muss unter Umständen maximal 1 Sekunde vergehen, ehe der µC bei
einem Tastenwechsel auf das neue Kommando reagiert.
Von daher hat Dusendies schon recht. Ich gehe allerdings mit dir
konform, wenn du sagst: Timer sind erst nächste Woche drann. Für den
Moment reicht es, wenn die Leds korrekt aufleuchten und über die kleine
Unzulänglichkeit sehen wir erst mal großzügig hinweg.
Reiner Messner schrieb:> Hätte nicht erwatet das sich soviele melden..
so sind wir halt, nett und bescheiden.
Du könntest dafür von Deinen Erfolgen bei diesem Projekt berichten.
Axel