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ß
>Wo liegt mein Fehler?
Eine oder mehrere ODER Verknüpfungen setzen keine bereits
gesetzten Bits zurück!
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.
erfusta schrieb: > Wo liegt mein Fehler? Ich habe verschiedenste Varianten probiert, keine > davon hat je ordentlich funktioniert.
1 | PORTB &= ~ (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3); |
So wie ich das sehe, wird nur PB0 gelöscht und dann mit PB1-PB3 OR-ed.
:
Bearbeitet durch User
>
1 | if ( PINB ^ ( 1<<PINB4 ) ); |
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.
:
Bearbeitet durch User
Marc Vesely schrieb: >> Wo liegt mein Fehler? Ich habe verschiedenste Varianten probiert, keine >> davon hat je ordentlich funktioniert.
1 | PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3); |
> So wie ich das sehe, wird nur PB0 gelöscht und dann mit PB1-PB3 OR-ed.
NACHTRAG:
Und PB1-PB3 setzst du damit auch auf 1.
:
Bearbeitet durch User
Marc Vesely schrieb: > Und PB1-PB setzst du damit auch auf 1. Das nun wieder nicht. Aber ohne Klammern drumrum wird nur PB0 auf 0 gesetzt. mfg.
Thomas Eckmann schrieb: >Marc Vesely schrieb: >> Und PB1-PB setzst du damit auch auf 1. > > Das nun wieder nicht. Hmmmm. Bist du sicher damit ?
Marc Vesely schrieb: > Bist du sicher damit ? Ja. Bit0 wird gelöscht, das Geodere dahinter ist Unsinn und wird wegoptimiert. mfg.
Thomas Eckmann schrieb: > Ja. > > Bit0 wird gelöscht, das Geodere dahinter ist Unsinn und wird > wegoptimiert. LOL. Gib's zu, du hast ins .lss gekiekt ?
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.
:
Bearbeitet durch User
Thomas Eckmann schrieb: > PORTB &= ~ (1<<PB0) | (1<<PB1) | > (1<<PB2) | (1<<PB3); > PORTB &= 0xFE | 0x02 | 0x04 | 0x08 LOL nochmal. Hab gar nicht drüber nachgedacht.
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?
1 | PORTB &= ~( (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3) ); |
im Klartext:
1 | PORTB &= ~(0b00000001|0b00000010|0b00000100|0b00001000); |
2 | = PORTB &= ~(0b00001111); |
3 | = PORTB &= 0b11110000; |
> 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:
1 | if( ! (PINB & (1<<PINB4)) ) |
2 | { |
3 | ... |
4 | } |
Siehe auch: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Digitale_Signale
:
Bearbeitet durch User
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.
Nachtrag: Wenn ich den interen Pullup aktiviere, und den Taster betätige, so müsste mein Wert auf dem Eingang doch 0 sein, oder?
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:
1 | uint16_t dly = 200; |
2 | uint8_t count; |
3 | |
4 | for (count=1; count < 6; count++) { |
5 | num = rand()%6+1; |
6 | PORTB = 0x10; |
7 | |
8 | if ( num == 1 ) |
9 | {
|
10 | PORTB |= (1<<PB0); |
11 | ...
|
12 | ...
|
13 | }
|
14 | |
15 | _delay_ms(dly); |
16 | dly += 100; |
17 | }
|
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? woher soll denn der zufall kommen? der µC macht das jedes mal das gleiche. http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__stdlib_1gae23144bcbb8e3742b00eb687c36654d1.html
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.
:
Bearbeitet durch User
Und nimm den Kommentar am Anfang raus
1 | /*
|
2 | * main.c |
3 | *
|
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | ...
|
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.
:
Bearbeitet durch User
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ß
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.