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
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)
>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 diesemPIC 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:
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