Hallo, mir fällt gerade kein günstiger Lösungsweg zu folgendem Problem ein. Ich möchte einfach einen 8bit-Wert (0 -255) mit 10 LEDs als Prozentanzeige ausgeben. Also mal grob 0 alles aus 1 bis 25 eine LED an 26 bis 50 zwei LEDs an .... 255 alle 10 LEDs an Mir fehlt im Moment ein kurzer Lösungsweg. Mein Gedanke ist: Den Wert in 10 Schleifen (!?) um jeweis 25 zu reduzieren, ist 0 noch nicht erreicht wird eine LED (PortPin) eingeschaltet. Sprung dann zur nächsten Schleife usw. Nachteil ist, das ich vorher ALLE LEDs löschen muss. Habt Ihr einen günstigeren Vorschlag? Der PIC hat natürlich noch mehr zu tun, deshalb soll das UP nicht so lang werden. Wenn es die Arbeit erheblich erleichtert, reduziere ich auch auf 8 LEDs, dann könnte ich es auch mit einer Datentabelle machen, aber ist das Sinnvoll 255 Datensätze einzugeben? Vielen Dank für Eure Hinweise! Gruß Mario
Das mit der Schleife ist schon der richtige Ansatz, die Reihenfolge würde ich ändern. Wert=Wert+1 Carry in LED10 bei 255 Wert=Wert+25 Carry in LED9 230 Wert=Wert+25 Carry in LED8 .. Wert=Wert+25 Carry in LED1 Wert=Wert+25 Carry in LED0 Geht aber nicht ganz auf. 10*25 < 255 daher mal 25 mal 26 damit am Ende bei 1 auch LED1 brennt. avr
gib doch das ergebnis einfach binär aus :-) wenn du nur Prozent willst, reichen sogar 7 Leds
Wenn du 255 Flashworte übrig hast, würde ich dass über eine Tabelle machen. Aus dem Flash kommen ja 14 Bits zurück. Damit benötigst du für jeden der 8-Bit Werte nur ein Flash-Wort um die 10 LEDs anzusteuern. Nebenbei bist du bei diesem Ansatz auch variabel was die Prozente angeht. Du änderst halt nur die Tabelle, wenn du eine andere Aufteilung haben willst. Gruß Sven
Es geht allerdings auch mit einer 'Vergleichsorgie'. Die 10 Vergleiche laufen so schnell ab, dass es gar nicht so einfach sein dürfte, dass mit Rechnerei zu schlagen if( Wert > 0 ) LED0 einschalten if( Wert > 25 ) LED1 einschalten if( Wert > 50 ) LED2 einschalten etc. und 10 Vergleiche wären für mich noch tragbar, um da mit der Brute-Force Holzhammermethode draufzuschlagen.
Ich grübele auch schon, was das mit den 10 Schleifen sollte und warum nicht 10 Vergleiche genommen werden. Auch, warum da Angst besteht, es könnte den PIC ausbremsen. Dazu müßte man ihn schon auf 100Hz CPU-Takt runtersetzen. Das mit der Tabelle ist völliger Overkill. Peter
Hallo, na dann diskutieren wir das mal weiter. Zu Sven: Für meine derzeitige Verwendung ist eine Tabelle unangemessen. Als Overkill (wie Peter schreibt) möchte ich es aber nicht bezeichnen, denn das dürfte die rechnerisch schnellste Lösung sein. Also da wo es nötig ist. Zu Peter: Der Begriff "Schleife" war von mir falsch gewählt. Der Gedanke war schon so wie es "AVR" geschrieben hat, nur eben anders rum. Zu Karl Heinz: Ja, das sieht auf den ersten Blick sehr logisch aus, dann schreibe aber mal if( Wert > 25 ) LED1 einschalten in Assembler (Pic 16F870) Gruß Mario
... oder die 8 Bit einfach ausgeben, und ein GAL macht daraus die 10 LED-Signale. Rechenzeit: ca. 0, und spart 2 Beinchen. Nötig wäre ein 22V10 oder 2 16V8.
In Assembler (PIC16F) sind es halt so 4-5 Zeilen pro Abfrage. Du musst ja nur die Werte subtrahieren, und dann das Carryflag testen. Damit bekommst du eine größer/gleich Funktionalität hin. Sind dann halt bei 10 Wertebereichen so ca. 50-70 Zeilen Code. Sollte aber eigentlich mit das schnellste sein, da das Lesen von Daten aus dem Flash auch Zeit kostet und relativ umständlich ist (ich meine jetzt nicht die retlw Methode, sondern das Lesen von Daten aus dem Flash-Speicher) Mit so einer Tabelle wird es halt übersichtlicher auf Kosten des Speicherplatzes. Gruß Sven
Mario G. schrieb: > Ja, das sieht auf den ersten Blick sehr logisch aus, dann schreibe aber > mal > if( Wert > 25 ) LED1 einschalten > in Assembler (Pic 16F870) Warum must Du Dir aber auch ausgerechnet den schwierigsten Assembler aussuchen? PIC ist die Härte, da muß man sich erstmal nen Haufen Macros schreiben, um die wichtigsten Befehle zusammen zu setzen. Nichtmal nen Compare-Befehl oder nen Jump-if-Carry-Befehl scheint er zu haben. Ich würde Dir raten, programmiere in C oder nimm ne Architektur mit leistungsfähigerem Befehlssatz. Peter
Peter Dannegger schrieb: > Nichtmal nen Compare-Befehl oder nen Jump-if-Carry-Befehl scheint er zu > haben. Ehrlich? Hätte ich nicht gedacht. Compare Immediate und diverse Jump-Flag Varianten hätte ich eigentlich so ziemlich jedem µC als Grundausstattung zugetraut. Ist ja nicht so, dass Vergleiche in einem Programm die grosse Ausnahme sind. > Ja, das sieht auf den ersten Blick sehr logisch aus, dann schreibe > aber mal > if( Wert > 25 ) LED1 einschalten > in Assembler (Pic 16F870) Wenn das schon schwer ist, dann wage ich mir gar nicht auszumalen, welche Klimmzüge bei Prozentrechnung notwendig sind :-) Und wie man dann aus der Prozentzahl die Anzahl der einzuschaltenden LED bestimmt repsektive die dann tatsächlich auch einschaltet. Prozent = Wert * 100 / 255 for( i = 0; i < Prozent / 10; ++i ) Turn_on_Led( i ); Ein kleiner Schritt für einen C-Programmierer, eine unüberwindliche Hürde in Assembler. Oder so ähnlich
Mario G. schrieb: > Ja, das sieht auf den ersten Blick sehr logisch aus, dann schreibe aber > mal > if( Wert > 25 ) LED1 einschalten > in Assembler (Pic 16F870) Könnte man so machen:
1 | movf var, w |
2 | call vergleich |
3 | ... |
4 | |
5 | vergleich |
6 | sublw .25 ;w = #lit8 - wreg |
7 | |
8 | btfsc STATUS, Z |
9 | retlw istGleich |
10 | |
11 | btfsc STATUS, C |
12 | retlw istGroesser |
13 | retlw istKleiner |
Die Enumerationen kannst du im Definitionsteil erstellen: Beispiel:
1 | istGleich EQU 0 |
2 | istGroesser EQU 1 |
3 | istKleiner EQU 2 |
4 | ... |
Anmerkung: Nur so aus dem Gedächtnis notiert. Bitte melden wenns nicht hinhaut. Grüße, Edson
Hallo, also gelöst ist es ja. Kann das mal einer in Assembler umwandeln. Prozent = Wert * 100 / 255 for( i = 0; i < Prozent / 10; ++i ) Turn_on_Led( i ); Wüste gerne als NICHT C-Programmierer wie es dann aussieht. So habe ich es nun: (sind etwa 50 Zeilen)
1 | MOVLW D'1' |
2 | ADDWF Wert,1 |
3 | BTFSC STATUS,C ; bei überlauf Sprung, restliche LED dann ON |
4 | GOTO L9 |
5 | |
6 | MOVLW D'25' |
7 | ADDWF Wert,1 |
8 | BTFSC STATUS,C |
9 | GOTO L8 |
10 | |
11 | .....
|
12 | .....
|
13 | |
14 | MOVLW D'25' |
15 | ADDWF Wert,1 |
16 | BTFSC STATUS,C |
17 | GOTO L0 |
18 | GOTO AUS |
19 | |
20 | L9 BSF PORTB,0 |
21 | L8 BSF PORTB,1 |
22 | L7 BSF PORTB,2 |
23 | L6 BSF PORTB,3 |
24 | L5 BSF PORTB,4 |
25 | L4 BSF PORTB,5 |
26 | L3 BSF PORTB,6 |
27 | L2 BSF PORTB,7 |
28 | L1 BSF PORTC,6 |
29 | L0 BSF PORTC,7 |
30 | AUS
|
Gruß Mario
>Hallo, also gelöst ist es ja. Ok. Um so besser. >Kann das mal einer in Assembler umwandeln. Am besten können das C-Compiler ;) > Prozent = Wert * 100 / 255 > for( i = 0; i < Prozent / 10; ++i ) > Turn_on_Led( i ); >Wüste gerne als NICHT C-Programmierer wie es dann aussieht. Ernsthaft, ich würde auf diesem PIC nicht die Prozente zur Laufzeit berechnen wollen. In deinem Fall erhältst du ja auch keinerlei Vorteil daraus, du kannst ohnehin nur 10er Schritte auflösen. >So habe ich es nun: (sind etwa 50 Zeilen) Wenns so funktioniert ist es doch in Ordnung. Grüße, Edson
Hallo Edson, das Programm selber bleibt nun so. Da ich mich mit C nun gar nicht auskenne, bin ich am überlegen ob ich damit auch schnell als Gelegenheitsprogrammierer zurecht kommen würde. Meine Projekte werden dann auch schnell mal groß, so das ich mit Speicher haushalten muss. Am Anfang hatte ich es mal mit PIC-BASIC probiert. Da klappte es nicht mal mit der Demo. Auf der anderen Seite wurden für einfache Aufgaben umgewandelt ein haufen Zeilen (Speicher) benötigt, die ich in Assembler nicht annährend gebraucht habe.
Mario G. schrieb: > So habe ich es nun: (sind etwa 50 Zeilen) 50 Befehle dürfte für nen PIC vollkommen o.k. sein. Weniger ist wohl kaum möglich. Beim 8051 mit seinen leistungsfähigeren Befehlen reichen 20 aus:
1 | led_bar: |
2 | cjne a, #1, _lb1 |
3 | _lb1: mov p0.0, c ; 1 .. 255: p0.0 = 0 (on) |
4 | cjne a, #26, _lb2 |
5 | _lb2: mov p0.1, c ; 26 .. 255: p0.1 = 0 |
6 | cjne a, #51, _lb3 |
7 | _lb3: mov p0.2, c ; 51 .. 255: p0.2 = 0 |
8 | cjne a, #76, _lb4 |
9 | _lb4: mov p0.3, c ; 76 .. 255: p0.3 = 0 |
10 | cjne a, #101, _lb5 |
11 | _lb5: mov p0.4, c ;101 .. 255: p0.4 = 0 |
12 | cjne a, #126, _lb6 |
13 | _lb6: mov p0.5, c ;126 .. 255: p0.5 = 0 |
14 | cjne a, #151, _lb7 |
15 | _lb7: mov p0.6, c ;151 .. 255: p0.6 = 0 |
16 | cjne a, #176, _lb8 |
17 | _lb8: mov p0.7, c ;176 .. 255: p0.7 = 0 |
18 | cjne a, #201, _lb9 |
19 | _lb9: mov p1.0, c ;201 .. 255: p1.0 = 0 |
20 | cjne a, #226, _lb10 |
21 | _lb10: mov p1.2, c ;226 .. 255: p1.1 = 0 |
Peter
P.S.: Zur Erklärung: "CJNE" vergleicht ein Register mit einer Zahl und springt bei ungleich an das Label (Compare and Jump if Not Equal). Der Vergleich entspricht einer Subtraktion, ohne daß das Ergebnis gespeichert wird. Das Register bleibt also unverändert. Zusätzlich wird das Carry-Bit gesetzt, wenn der Registerwert kleiner als die Zahl ist. Die Sprungfunktion wird hier nicht benötigt, daher der Sprung in die nächste Zeile. "MOV Bit, C" lädt ein Bit (das kann ein Portpin sein) mit dem Carry-Bit. Das Bit muß also vorher nicht gelöscht werden. Beim 8051 sind alle Portpins nach dem Reset high, daher schaltet man LEDs immer gegen VCC, d.h. sie leuchten bei Pin = 0. Peter
Hallo, wenn ein if-Anweisungsmarathon aber dann bitte mit else-if weiter (spart im besten Fall 90% ein.... Alternativ wäre eine Rundung mit anschließender case-Struktur möglich Gruß Patrick
Patrick Weggler schrieb: > wenn ein if-Anweisungsmarathon aber dann bitte mit else-if weiter (spart > im besten Fall 90% ein.... Na klar, ein Mensch kann ja auch LEDs schneller als 10µs ablesen. Ein Aufruf alle 100ms ist ausreichend, ergibt bei 10µs Ausführungszeit eine lächerliche CPU-Last von 10µs / 100mS = 0,01%. Ein Einfügen von nen Haufen Sprüngen hätte außer einer Explosion der Codegröße keinerlei meßbaren Effekt. Und im Mittel wird sich dadurch die Ausführungszeit sogar deutlich verlängern (Sprünge sind teurer als Operationen). Peter
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.