mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PIC Assembler - 8bit mit 10 LEDs ausgeben (als Prozent)


Autor: Mario G. (rodenberger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Mario G. (rodenberger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo AVR,
gut, dann versuche ich es mal so.
Danke!

Gruß Mario

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gib doch das ergebnis einfach binär aus :-)
wenn du nur Prozent willst, reichen sogar 7 Leds

Autor: Sven Stefan (stepp64) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Mario G. (rodenberger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... 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.

Autor: Sven Stefan (stepp64) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
  movf  var, w
  call  vergleich
  ...

vergleich
  sublw  .25    ;w = #lit8 - wreg

  btfsc  STATUS, Z
          retlw          istGleich

   btfsc  STATUS, C
    retlw          istGroesser
  retlw   istKleiner

Die Enumerationen kannst du im Definitionsteil erstellen:

Beispiel:

istGleich   EQU 0
istGroesser EQU 1
istKleiner  EQU 2
...

Anmerkung: Nur so aus dem Gedächtnis notiert. Bitte melden wenns nicht 
hinhaut.

Grüße,
Edson

Autor: Mario G. (rodenberger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

     MOVLW   D'1'
    ADDWF   Wert,1    
    BTFSC   STATUS,C ; bei überlauf Sprung, restliche LED dann ON
    GOTO L9

     MOVLW   D'25'
    ADDWF   Wert,1    
    BTFSC   STATUS,C
    GOTO L8    

.....
.....

     MOVLW   D'25'
    ADDWF   Wert,1    
    BTFSC   STATUS,C
    GOTO L0
    GOTO AUS

L9    BSF PORTB,0
L8    BSF PORTB,1
L7    BSF PORTB,2
L6    BSF PORTB,3
L5    BSF PORTB,4
L4    BSF PORTB,5
L3    BSF PORTB,6
L2    BSF PORTB,7
L1    BSF PORTC,6
L0    BSF PORTC,7
AUS

Gruß Mario

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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

Autor: Mario G. (rodenberger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:

led_bar:
        cjne    a, #1, _lb1
_lb1:   mov     p0.0, c                 ;  1 .. 255: p0.0 = 0 (on)
        cjne    a, #26, _lb2
_lb2:   mov     p0.1, c                 ; 26 .. 255: p0.1 = 0
        cjne    a, #51, _lb3
_lb3:   mov     p0.2, c                 ; 51 .. 255: p0.2 = 0
        cjne    a, #76, _lb4
_lb4:   mov     p0.3, c                 ; 76 .. 255: p0.3 = 0
        cjne    a, #101, _lb5
_lb5:   mov     p0.4, c                 ;101 .. 255: p0.4 = 0
        cjne    a, #126, _lb6
_lb6:   mov     p0.5, c                 ;126 .. 255: p0.5 = 0
        cjne    a, #151, _lb7
_lb7:   mov     p0.6, c                 ;151 .. 255: p0.6 = 0
        cjne    a, #176, _lb8
_lb8:   mov     p0.7, c                 ;176 .. 255: p0.7 = 0
        cjne    a, #201, _lb9
_lb9:   mov     p1.0, c                 ;201 .. 255: p1.0 = 0
        cjne    a, #226, _lb10
_lb10:  mov     p1.2, c                 ;226 .. 255: p1.1 = 0


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Patrick Weggler (pw-sys) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.