Hallo,
ich habe diesen Schaltplan nachgebaut:
http://www.avr-asm-tutorial.net/avr_de/wuerfel/wuerfel3.gif
Jedoch mit einem Unterschied, ich habe den GND der LEDs nicht auf den
AVR gelegt, sondern die positive Seite auf den AVR, ein Test-Programm
zeigt auch, dass alle LEDs leuchten (... wenn ich alle outputs auf on
setze).
Ich bin neu in der AVR Programmierung, mein Ziel sollte es sein, dass
der AVR wenn ich den Taster auf PB4 betätige eine random Zahl zwischen 1
und 6 generiert, diese dann mittels der LEDs ausgibt.
Meinen Code habe ich angehängt. Wenn ich diesen Code so verwende, dann
blinkt die mittlere LED herum, in unregelmäßigen Abständen, alle anderen
LEDs leuchten durchgehend.
Wo liegt mein Fehler? Ich habe verschiedenste Varianten probiert, keine
davon hat je ordentlich funktioniert.
Danke!
Gruß
holger schrieb:>>Wo liegt mein Fehler?>> Eine oder mehrere ODER Verknüpfungen setzen keine bereits> gesetzten Bits zurück!
Auf den ersten Blick sollte "PORT =" statt "PORT |=" reichen.
mfg.
Du fragst den Taster mit XOR ab.
Taster gedrückt: 1 XOR 1 = 0
Taster nicht gedrückt= 0 XOR 1 = 1
Verwende also ein & statt ^.
eventuell solltest du in Erwägung ziehen, den Taster zu entprellen. Du
hast zwar ein delay von 100 ms drin, da kann aber bei etwas längerem
Tastendruck auch mehrmals auslösen.
Marc Vesely schrieb:> Gib's zu, du hast ins .lss gekiekt ?
Nein, warum?
Da steht:
PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3);
PORTB &= 0xFE | 0x02 | 0x04 | 0x08
0xFE | 0x02 | 0x04 | 0x08 = 0xFE
Und dann ist nur noch ein Bit zu löschen.
genau genommen wird es nicht wegoptimert, sondern das ist eine
Konstante, die errechnet und eingesetzt wird. Da der Compiler schlau
ist, nimmt er für das eine Bit auch den passenden Befehl, anstatt
Read-Modify-Write. Das ist allerdings eine Optimierung.
Geht also schön schnell, funktioniert aber nicht wie vom TO erwartet.
mfg.
Hallo,
danke erstmal für die Antworten.
Marc Vesely schrieb:> So wie ich das sehe, wird nur PB0 gelöscht und dann mit PB1-PB3 OR-ed.
Du hast recht, ja. Wie bekomme ich es in einer Zeile zusammen, alle zu
löschen?
>PORTB &= ~ (1<<PB0) ~ (1<<PB1) ~ (1<<PB2) ~(1<<PB3);
funktioniert ja nicht. Oder muss ich da für jeden Port eine eigene Zeile
machen?
M. S. schrieb:> Du fragst den Taster mit XOR ab.>> Taster gedrückt: 1 XOR 1 = 0> Taster nicht gedrückt= 0 XOR 1 = 1>> Verwende also ein & statt ^.
Danke, werde ich versuchen. Was ich nicht ganz verstehe, der Taster ist
in dem Schaltplan auf GND, somit sollte er den Eingang des AVRs auf 0
setzen, lieg ich damit richtig?
M. S. schrieb:> eventuell solltest du in Erwägung ziehen, den Taster zu entprellen. Du> hast zwar ein delay von 100 ms drin, da kann aber bei etwas längerem> Tastendruck auch mehrmals auslösen.
Stimmt, danke, werde ich machen.
Danke!
Gruß
erfusta schrieb:> Du hast recht, ja. Wie bekomme ich es in einer Zeile zusammen, alle zu> löschen?>>PORTB &= ~ (1<<PB0) ~ (1<<PB1) ~ (1<<PB2) ~(1<<PB3);> funktioniert ja nicht. Oder muss ich da für jeden Port eine eigene Zeile> machen?
Ich habe es nun so geschafft:
> PORTB &= ~ (1<<PB0) & ~ (1<<PB1) & ~ (1<<PB2) & ~ (1<<PB3);
Damit hätte ich schon mal den Lampen-Test vor der eigenen
Würfel-Anwendung funktionierend bekommen. :)
erfusta schrieb
> Wie bekomme ich es in einer Zeile zusammen, alle zu> löschen?>>PORTB &= ~ (1<<PB0) ~ (1<<PB1) ~ (1<<PB2) ~(1<<PB3);> funktioniert ja nicht. Oder muss ich da für jeden Port eine eigene Zeile> machen?
> Was ich nicht ganz verstehe, der Taster ist> in dem Schaltplan auf GND, somit sollte er den Eingang des AVRs auf 0> setzen, lieg ich damit richtig?
Sorry, habe ich nicht bemerkt. Dann funktioniert dein XOR, Standardmäßig
würde man es dann so machen:
M. S. schrieb:> im Klartext:
Danke, deine Version ist kürzer, als die die ich im Post davor durch
probieren herausgefunden habe. Ich habe diese nun übernommen.
M. S. schrieb:> Sorry, habe ich nicht bemerkt. Dann funktioniert dein XOR, Standardmäßig> würde man es dann so machen:
Hab ich probiert. Ich hab die Anwendung umgeschrieben, ich will einfach
mal testweise bei einem Tastendruck alle LEDs zum leuchten bringen.
Siehe Anhang. Funktioniert allerdings kein bisschen, und ich hab auch
keine Ahnung wieso. Sämtliches herumspielen mit Operatoren hat nichts
gebracht.
Hast du noch eine Idee?
Danke!
Gruß
erfusta schrieb:> Du hast recht, ja. Wie bekomme ich es in einer Zeile zusammen, alle zu> löschen?erfusta schrieb:> Ich habe es nun so geschafft:>> PORTB &= ~ (1<<PB0) & ~ (1<<PB1) & ~ (1<<PB2) & ~ (1<<PB3);Thomas Eckmann schrieb:> Auf den ersten Blick sollte "PORT =" statt "PORT |=" reichen.
Auf den zweiten Blick auch.
Lass die bitfummelei, du setzst PortB eh auf Null.
Hast du genau wie im Schaltplan nur den Taster zwischen den Pin und GND?
Dann solltest du einen Pull-Up Widerstand (z.B. 10 kOhm) zwischen VDD
und ebendiesen Pin hängen, oder direkt den Pin mit VDD verbinden und den
internen Pull-Up aktivieren. Das hat den Hintergrund, dass der Pin sonst
bei geöffnetem Schalter "in der Luft" hängt, durch den PullUp wird er
auf ein definiertes Potential (VDD, also "1") gezogen.
M. S. schrieb:> Hast du genau wie im Schaltplan nur den Taster zwischen den Pin> und GND?> Dann solltest du einen Pull-Up Widerstand (z.B. 10 kOhm) zwischen VDD> und ebendiesen Pin hängen, oder direkt den Pin mit VDD verbinden und den> internen Pull-Up aktivieren. Das hat den Hintergrund, dass der Pin sonst> bei geöffnetem Schalter "in der Luft" hängt, durch den PullUp wird er> auf ein definiertes Potential (VDD, also "1") gezogen.
Ja, das habe ich. Hm. Also mit taster auf GND habe ich aktuell keine
Chance?
Dann werde ich das morgen auf VDD umlöten.
Yep, ich habs.
> PORTB |= (1<<PB4); /* internen Pull-Up an PC7 aktivieren */
Danach funktioniert der Code aus dem letzten Anhang. Mal schauen, ob ich
das Ding nun fertig bekomme. Danke! :)
Doch, natürlich hast du eine Chance mit Taster auf GND. Ist eben die
Frage, ob Active High, oder Active Low. Nur in beiden Fällen muss der
Taster im geöffneten Zustand über einen Widerstand auf das jeweils
andere Potential verbunden sein, da er sonst ja nirgends angeschlossen
wäre und der Pin einfach "irgendwas" liest.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Eing.C3.A4nge_.28Wie_kommen_Signale_in_den_.C2.B5C.29
-> Taster und Schalter
erfusta schrieb:> Danach funktioniert der Code aus dem letzten Anhang. Mal schauen, ob ich> das Ding nun fertig bekomme. Danke! :)
Vorschlag:
Mach mal eine function z.B. RollDice.
Da machst du dann deine rand(), Abfrage usw.
Und lass mal die Wurfel langsam ausrollen, etwa so:
Marc Vesely schrieb:> Vorschlag:> Mach mal eine function z.B. RollDice.> Da machst du dann deine rand(), Abfrage usw.> Und lass mal die Wurfel langsam ausrollen, etwa so:
Danke, werde ich probieren.
Ich habe es gestern im Übrigen noch geschafft das Ganze zum laufen zu
bekommen.
Interessantwerweise Würfelt der Würfel immer die gleichen Zahlen, sprich
die random Funktion ist bei mir nicht wirklich random ...
Nach dem Einschalten: 2-6-4-1, jedes mal gleich.
Jemand eine Idee wieso? Wird das evtl im RAM gespeichert?
Gruß
erfusta schrieb:> Jemand eine Idee wieso?
Die Startbedingung ist immer gleich. Da du nicht Uhrzeit und Datum
dazurechnen kannst, um immer eine andere Startbedingung zu haben, musst
du dem Zufall anders auf die Sprünge helfen.
Eine einfache Möglichkeit wäre, die Random-Funktion nach dem
Programmstart einfach in einer Schleife laufen zu lassen, die mit
Tastendruck beendet wird. Die Zeit vom Einschalten bis zum Tastendruck
ist immer unterschiedlich. Dann bekommst du auch immer unterschiedliche
Zahlen.
mfg.
außerdem ist das auch nicht ganz richtig:
> rand()%6+1;
denn rand liefert kein vielfaches von 6, damit werden einige Zahlen
bevorzugt und andere benachteiligt.
@Thomas Eckmann:
>>Marc Vesely schrieb:>> Gib's zu, du hast ins .lss gekiekt ?>>Nein, warum?_________________________________________________________>Da steht:> PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3);
leuchtet mir ein, was es tut
>PORTB &= 0xFE | 0x02 | 0x04 | 0x08>>0xFE | 0x02 | 0x04 | 0x08 = 0xFE
Thomas, könntest Du bitte nochmal gena uerklären, was die beiden
Anweisungen tun? und warum ist bei der unteren das "=" auf der rechten
Position?
>Und dann ist nur noch ein Bit zu löschen.>genau genommen wird es nicht wegoptimert, sondern das ist eine>Konstante, die errechnet und eingesetzt wird. Da der Compiler schlau>ist, nimmt er für das eine Bit auch den passenden Befehl, anstatt>Read-Modify-Write. Das ist allerdings eine Optimierung.>>Geht also schön schnell, funktioniert aber nicht wie vom TO erwartet.>>mfg.
tommyProg schrieb:> @Thomas Eckmann:>>>>Marc Vesely schrieb:>>> Gib's zu, du hast ins .lss gekiekt ?>>>>Nein, warum?> ___________________________________________________________>>Da steht:>> PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3);>> leuchtet mir ein, was es tut>>>PORTB &= 0xFE | 0x02 | 0x04 | 0x08>>>>0xFE | 0x02 | 0x04 | 0x08 = 0xFE>> Thomas, könntest Du bitte nochmal gena uerklären, was die beiden> Anweisungen tun?
Welche beiden?
> und warum ist bei der unteren das "=" auf der rechten> Position?
Das ist keine C Anweisung.
Das ist einfach nur der Rechengang.
1
1 ist einfach nur binär 00000001
2
1 << diese binäre 1 wird nach links geschoben. Um wieviel?
3
1 << PB0 Aha! Um PB0 Stellen. PB0, das ist einfach nur ein anderes
4
Wort für 0. Also schieb mal 00000001 um 0 Stellen nach links
5
Das Ergebnis ist binär 00000001. Das'binär' deute ich in
6
weiterer Folge mit dem Präfix 0b an. Also 0b00000001
7
8
~( 1<<PB0) die 0b00000001 werden also invertiert.
9
Neues Zwischenergebnis ist also 0b11111110
10
11
Und da mir binäre Schreibweise auf Dauer zu blöd ist,
12
schreib ich dieselbe Zahl Hexadezimal auf. Jede 8 Bit
13
Binärzahl lässt sich ach als 2 stellige Hex-Zahl darstellen
14
ohne dass man gross rechnen muss. Einfach die 8 Bit in der
15
Mitte in2 4-Bit Einheiten teilen und getreu
16
17
0000 0 1000 8
18
0001 1 1001 9
19
0010 2 1010 A
20
0011 3 1011 B
21
0100 4 1100 C
22
0101 5 1101 D
23
0110 6 1110 E
24
0111 7 1111 F
25
26
neu anschreiben.
27
Aus 0b11111110 wird also 1111 1110 und das wird Hexadezimal
28
als 0xFE geschrieben.
dasselbe für die anderen Teilausdrücke.
Aus (1<<PB1) wird 0x02
Aus (1<<PB2) wird 0x04
Aus (1<<PB3) wird 0x08
und dann oderst du die Einzelteile zusammen
1
Hex Binär
2
3
0xFE 0b11111110
4
| 0x02 0b00000010
5
-------------------------
6
ergibt 0b11111110
7
| 0x04 0b00000100
8
-------------------------
9
ergibt 0b11111110
10
| 0x08 0b00001000
11
-------------------------
12
ergibt 0b11111110
0b11111110, das ist aber nichts anders als Hexadezimal 0xFE
Das Ergebnis von
1
~(1<<PB0)|(1<<PB1)|>(1<<PB2)|(1<<PB3);
isr also ausgerechnet die Zahl 0xFE.
Und mit der wird dann das PORT Register verundet.
sowas ist lächerlich.
Du kannst kaum programmieren, tust aber so, als ob du bei den Grossen
mitspielst. Das ist genauso lächerlich, wie die Skifahrer, die sich kaum
auf den Bretteln halten können aber die tollste und teuerste Ausrüstung
haben und auf der Hütte angeben, wie schnell sie nicht die Streif runter
gefahren wären.
tommyProg schrieb:> Thomas, könntest Du bitte nochmal gena uerklären, was die beiden> Anweisungen tun? und warum ist bei der unteren das "=" auf der rechten> Position?
Wenn man noch am überlegen ist, wie man es schreiben soll, hat
Karl-Heinz, sofern er online ist, schon die perfekte Erklärung fertig:
Karl Heinz schrieb:> Das ist keine C Anweisung.> Das ist einfach nur der Rechengang.
mfg.
Hallo,
Karl Heinz schrieb:> sowas ist lächerlich.> Du kannst kaum programmieren, tust aber so, als ob du bei den Grossen> mitspielst. Das ist genauso lächerlich, wie die Skifahrer, die sich kaum> auf den Bretteln halten können aber die tollste und teuerste Ausrüstung> haben und auf der Hütte angeben, wie schnell sie nicht die Streif runter> gefahren wären.
Zunächst einmal, vielen Dank für deine guten Erklärungen bzlg den Bits,
ich werde mich weiter damit beschäftigen.
Danke auch an alle anderen, mein Würfel funktioniert nun erstmal, ich
werde nun eure Kommentare Stück für Stück einarbeiten, und mich
versuchen zu verbessern.
Zu deinem letzten Kommentar: Ich bin doch sehr erstaunt darüber.
Ich habe im Startpost sowie im weiteren Verlauf deutlich klar gemacht,
dass ich Anfangs absolut keine Ahnung hatte was ich tat, und das ich ein
absoluter Anfänger bin.
Als Anfänger nutzt man auch IDEs, mit vordefinierten Templates. Nicht
jeder konnte mit vim und avr-gcc auf der Konsole bei seinem ersten
Projekt herumjonglieren.
Meine IDE, in dem fall Geany, fügt diesen Text automatisiert ein, ich
habe ihn nicht weiter beachtet, und mich nicht darum kümmern.
Ich werde aber in Zukunft darauf achten, dass meine IDEs nichts, was
meinem "Skill-Level" nicht entsprechen könnte, einfügt, ok? :)
Nein, mal im Ernst: Wie gesagt, deine Erklärungen haben mir viel
geholfen, wirklich Danke dafür. Das letzte war aber meiner Meinung nach
sinnloses herumgebashe, da ich oft erwähnt habe, dass ich Anfänger bin
...
Gruß