Forum: Mikrocontroller und Digitale Elektronik 16F84A 7Segment Anzeige umschreiben in assembler (Anfänger)


von Myho (Gast)


Lesenswert?

Guten Tag,
Ich habe erst vor 3 Wochen mit PIC-Programmierung angefangen. Ich habe 
schon ein fertiges programm im internet gefunden und wollte das 
umschreiben.

Hier mein umgeschriebenes Programm:

;*****************
;* Programmstart *
;*****************

      ORG   00H         ; Das Programm wird ab Speicherstelle 0 in den 
Speicher geschrieben
      GOTO   init   ; Springe zur Grundinitialisierung der Ports A und B


;*******************
;* Initialisierung *
;*******************

init   BSF   STATUS,RP0      ; wechsle zu Registerbank 1 (spezielle 
Register)
      MOVLW   B'00011111'
      MOVWF   TRISA       ; RA0 .. RA4 Eingänge
      MOVLW   B'00000000'
      MOVWF   TRISB      ; RB0-RB7 Ausgänge
      BCF   STATUS,RP0      ; wechsle zu Registerbank 0 (normaler 
Speicherbereich)
      MOVLW   b'00000111'   ; Komparatoren abschalten, nur Digitalports
      MOVWF   CMCON
      CLRF   PORTA      ; Port A löschen
      CLRF   PORTB      ; Port B löschen


;*****************
;* Hauptprogramm *
;*****************

main   MOVF   PORTA,W      ; Lade Zustand von Port A in Arbeitsregister 
W
      CALL   table      ; Springe zur Tabelle
      MOVWF   PORTB      ; Schreibe Arbeitsregister nach Port B
      GOTO   main      ; Wiederhole...

; Dekodier-Tabelle
;******************

table   ADDWF   PCL,F         ; Addiere Arbeitsregister zum 
Programmzähler

      RETLW   B'00111111'      ; 7-Segment-Code für die Ziffer '0'
      RETLW   B'00000110'      ; 7-Segment-Code für die Ziffer '1'
      RETLW   B'01011011'      ; 7-Segment-Code für die Ziffer '2'
      RETLW   B'01001111'      ; 7-Segment-Code für die Ziffer '3'
      RETLW   B'01100110'      ; 7-Segment-Code für die Ziffer '4'
      RETLW   B'01101101'      ; 7-Segment-Code für die Ziffer '5'
      RETLW   B'01111101'      ; 7-Segment-Code für die Ziffer '6'
      RETLW   B'00000111'      ; 7-Segment-Code für die Ziffer '7'
      RETLW   B'01111111'      ; 7-Segment-Code für die Ziffer '8'
      RETLW   B'01101111'      ; 7-Segment-Code für die Ziffer '9'
      RETLW   B'01110111'      ; 7-Segment-Code für die Ziffer 'E'
      RETLW   B'01111100'      ; 7-Segment-Code für die Ziffer 'E'
      RETLW   B'00111001'      ; 7-Segment-Code für die Ziffer 'E'
      RETLW   B'01011110'      ; 7-Segment-Code für die Ziffer 'E'
      RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'
      RETLW   B'01110001'      ; 7-Segment-Code für die Ziffer 'E'

END
______________________________________________________________________ 
___________

Meine Fragen:
1. Bei den "RETLW" Befehlen waren die Buchstagen nach den Ziffern von a 
bis f definiert. Ich möchte da aber nur das E für error haben. geht das 
so oder muss man das noch wo anders definieren?

2. Ich möchte an Pin 0 von Port A ein "Übernahmetaster" mit einbauen und 
die 4 ansteuerungstaster für den BCD-Code sollen von Pin 1-4 sein (Port 
A). wo wird das definiert?

3. Der Übernahmetaster soll folgendermaßen funktionieren: Er ist an Pin 
0 von Port A angeschlossen. Man soll die 4 Taster beliebig umstellen 
können ohne das man es auf der 7 Segmentanzeige sieht. Drückt man den 
taster soll es eine art aktuallisierung sein und er zeigt den momentanen 
wert der tasterkombination so lange an, bis der taster erneut gedrückt 
wird.

hoffe ich habe mich verständlich ausgedrückt. würde mich über hilfe 
freuen
gruß

von tastendrücker (Gast)


Lesenswert?

Mir scheint, da fehlen noch reichlich Grundlagen. Für PIC-Anfänger immer 
wieder gern vorgeschlagen: www.sprut.de

Ein erster Tip:

>      RETLW   B'00111111'      ; 7-Segment-Code für die Ziffer '0'
>      RETLW   B'00000110'      ; 7-Segment-Code für die Ziffer '1'
>      RETLW   B'01011011'      ; 7-Segment-Code für die Ziffer '2'
>      RETLW   B'01001111'      ; 7-Segment-Code für die Ziffer '3'
>      RETLW   B'01100110'      ; 7-Segment-Code für die Ziffer '4'
>      RETLW   B'01101101'      ; 7-Segment-Code für die Ziffer '5'
>      RETLW   B'01111101'      ; 7-Segment-Code für die Ziffer '6'
>      RETLW   B'00000111'      ; 7-Segment-Code für die Ziffer '7'
>      RETLW   B'01111111'      ; 7-Segment-Code für die Ziffer '8'
>      RETLW   B'01101111'      ; 7-Segment-Code für die Ziffer '9'
>      RETLW   B'01110111'      ; 7-Segment-Code für die Ziffer 'E'
>      RETLW   B'01111100'      ; 7-Segment-Code für die Ziffer 'E'
>      RETLW   B'00111001'      ; 7-Segment-Code für die Ziffer 'E'
>      RETLW   B'01011110'      ; 7-Segment-Code für die Ziffer 'E'
>      RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'
>      RETLW   B'01110001'      ; 7-Segment-Code für die Ziffer 'E'


Hinter einem ';' steht nur Kommentar, das ignoriert der Assembler. Wenn 
du   da etwas Änderst, hat das keine Auswirkungen.

Also: Wenn du die Ausgabe von 'A' nach 'E' ändern willst, dann musst du 
die  Ansteuerung der Segmente anpassen. Im Original-Code war für 'E' 
folgende Zeile:

>  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'

Das heisst '01111001' ergibt ein 'E' auf deiner Anzeige (jede 1 ist ein 
leuchtendes Segment). Und nun überlege mal, was du ändern musst, damit 
'0'-'9' und dann nur noch 'E' ausgegeben wird.

von Myho (Gast)


Lesenswert?

hmm...
ich habe hier mit meinen Unterlagen und Befehlslisten echt ne halbe 
stunde überlegt aber da ist nichts sinnvolles bei rausgekommen.

Meine beste überlegung war mit einem BTFSS befehl die bits abfragen und 
wenn es a,b,c,d oder f wäre, würde er die ausgabe überspringen und dann 
ein direkten goto befehl zu dem "E"  setzen

von tastendrücker (Gast)


Lesenswert?

Also: Was das Programm jetzt macht ist, dass es in Abhängigkeit von 
PORTA einen der Werte

   0 1 2 3 4 5 6 7 8 9 A B C D E F

ausgibt und dass endloos. Am PORTA können ja die Werte 0-15 anliegen. 
Ausgegeben wird dann an der Anzeige (an PORTB)

Eingabe PORTA   0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Ausgabe PORTB   0 1 2 3 4 5 6 7 8 9 A  B  C  D  E  F

Willst du stattdessen

Eingabe PORTA   0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Ausgabe PORTB   0 1 2 3 4 5 6 7 8 9 E  E  E  E  E  E

musst du nur deine Tabelle ändern in

  RETLW   B'00111111'      ; 7-Segment-Code für die Ziffer '0'
  RETLW   B'00000110'      ; 7-Segment-Code für die Ziffer '1'
  RETLW   B'01011011'      ; 7-Segment-Code für die Ziffer '2'
  RETLW   B'01001111'      ; 7-Segment-Code für die Ziffer '3'
  RETLW   B'01100110'      ; 7-Segment-Code für die Ziffer '4'
  RETLW   B'01101101'      ; 7-Segment-Code für die Ziffer '5'
  RETLW   B'01111101'      ; 7-Segment-Code für die Ziffer '6'
  RETLW   B'00000111'      ; 7-Segment-Code für die Ziffer '7'
  RETLW   B'01111111'      ; 7-Segment-Code für die Ziffer '8'
  RETLW   B'01101111'      ; 7-Segment-Code für die Ziffer '9'
  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'
  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'
  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'
  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'
  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'
  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'

Dann wird für alle Eingabewerte grösser 9 ein 'E' ausgegeben

von nixversteh (Gast)


Lesenswert?

@Myho

sowas vielleicht?
1
;*****************
2
;* Hauptprogramm *
3
;*****************
4
5
main   MOVF   PORTA,W      ; Lade Zustand von Port A in Arbeitsregister W
6
       BSF    STATUS,C     ; setze Carry-Bit
7
       SUBLW  0x09         ; wenn der Wert in W größer ist als 0x09,
8
                           ; wird das Carry-Bit GELÖSCHT (mußte ich auch erst mal drauf kommen)
9
       MOVLW  0x0E         ; W mit 0x0E laden (Carry-Bit wird dadurch nicht beeinflußt)
10
       BTFSC  STATUS,C     ; Carry-Bit auswerten
11
       MOVF   PORTA,W      ; Carry-Bit war noch gesetzt, Wert an PORTA gültig
12
13
       CALL   table        ; Springe zur Tabelle
14
       MOVWF  PORTB        ; Schreibe Arbeitsregister nach Port B
15
       GOTO   main         ; Wiederhole...
16
17
; Dekodier-Tabelle
18
;******************
19
20
table   ADDWF   PCL,F      ; Addiere Arbeitsregister zum Programmzähler
21
  RETLW   B'00111111'      ; 7-Segment-Code für die Ziffer '0'
22
  RETLW   B'00000110'      ; 7-Segment-Code für die Ziffer '1'
23
  RETLW   B'01011011'      ; 7-Segment-Code für die Ziffer '2'
24
  RETLW   B'01001111'      ; 7-Segment-Code für die Ziffer '3'
25
  RETLW   B'01100110'      ; 7-Segment-Code für die Ziffer '4'
26
  RETLW   B'01101101'      ; 7-Segment-Code für die Ziffer '5'
27
  RETLW   B'01111101'      ; 7-Segment-Code für die Ziffer '6'
28
  RETLW   B'00000111'      ; 7-Segment-Code für die Ziffer '7'
29
  RETLW   B'01111111'      ; 7-Segment-Code für die Ziffer '8'
30
  RETLW   B'01101111'      ; 7-Segment-Code für die Ziffer '9'
31
  RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'

von tastendrücker (Gast)


Lesenswert?

Und zum "Übernahmetaster" an RA0:

Du wartest in einer Endloos-Schleife bis der RA0 0 oder 1 ist (je nach 
dem, wie der Taster angeschlossen ist) und gibst dann den Wert von 
RA1..4 aus.

Der Anfang deines Programms sollte so aussehen:

;*****************
;* Programmstart *
;*****************

TEMP EQU 0x0C      ; Speicher für Temp-Variable

     ORG   00H     ; Reset-Vector
     GOTO  init    ; Springe zur Grundinitialisierung der Ports A und B

     ORG   04H     ; Interrupt-Vector
     GOTO  init    ; auch zu init (weil kein Interrupt aktiv)


Dein Hauptprogramm sollte dann so etwa aussehen:

;*****************
;* Hauptprogramm *
;*****************

Deine MAIN-Routine sollte dann ungefär so aussehen (nicht getestet):


main

waret_auf_taste
      BTFSC  PORTA,0           ; Taste gedrückt?
      GOTO   warte_auf_taste   ; nein, warten

      MOVF   PORTA,W           ; Lade Zustand von Port A in 
Arbeitsregister
      MOVWF  TEMP              ; Speichern
      RRF    TEMP,W            ; Nach rechts schieben und nach W
      ANDLW  b'00000111'       ; gewünschte Bits maskieren

      CALL   table             ; Springe zur Tabelle (Wert ist in W)
      MOVWF  PORTB             ; Schreibe Arbeitsregister nach Port B
      GOTO   main              ; Wiederhole...


Aber vielleicht solltest du noch kleiner anfangen und ersteinmal eine 
LED in Abhängigkeit von einem Taster zum Leuchten bringen

von Myho (Gast)


Lesenswert?

hey
das ist gut
das könnte funktionieren
coole sache dankeschön

hab trotzdem noch eine "definitions frage"
und zwar: muss nicht irgendwo definiert werden an welchem Pin z.B. der 
Übernahmetaster sein muss?
Was ist wenn man angenommen ein "a" oder ein "c" mit dem passenden BCD 
Code ansteuert? das ist ja gar nicht aufgeführt... dann soll ja das "E" 
kommen. wie wird das denn nun gemacht?

von whitenoise (Gast)


Lesenswert?

als erstes solltest du dafür sorgen das du nicht über deine tabelle 
hinweg springst,

das kannst du machen indem du nach dem einlesen des port a ein:

andlw  h'0F'

machst damit lässt du nur die unteren 4 bits des port a passieren, 
ansonsten musst du daráuf achten das die andren 4567 auch auf low sind, 
jenachdem wie du sie konfiguriert hast, wenn ich recht schätze hast du 
den 16f628 im einsatz!?


in der routine von tastendrücker ist das ganze so aisgeführt das der 
taster per pull up an 5v gehaten wird, wird er geschlossen zieht er den 
jeweilige pin auf 0, das merkt der pic und geht aus seiner 
warteschleife. kannst zb 10k als pull up nehmen.

jetzt sind auch in der routine noch fehler enthalten:

      MOVWF  TEMP              ; Speichern
      RRF    TEMP,W            ; Nach rechts schieben und nach W
      ANDLW  b'00000111'       ; gewünschte Bits maskieren

      CALL   table             ; Springe zur Tabelle (Wert ist in W)
      MOVWF  PORTB             ; Schreibe Arbeitsregister nach Port B
      GOTO   main              ; Wiederhole...



su solltest einfach den porta,7 nehmen, stelle in der 
entwicklungsumgebung entsprechend ein, das restet nicht aktiv sein soll, 
programming bits... hast du einen externen quarz oder nutzt du den 
internen oszi? ansonsten könntest du auch die anderen port a bits nutzen 
(5,6)...

bei der routine oben sind fehler enthalten, wenn su also den pic ohne 
sonderliche veränderunegen nutzt, kannst du auch prorta,4 als eingang 
nutzen für den taster, der code oben geht davon aus das du die 
anschlüsse port a 1-4 als bcd nutzt schließt aber nicht aus das du die 
pins ra5-7 auch aktiviert hast... was bei deinem modell pic möglich wäre 
denn er hat comperatoren und ist damit kein f84 ...

also, mein vorschlag:

nutze porta,4 als eíngang für den taster, und die bits ra0-3 für den bsd 
code.

und vergiss nicht die bits auszumaskieren mit:

    movf    porta,w
    andlw   h'0f'
    call    table


viel spass.

whitenoise

ps.: btfsc steht für Bit Test F(register) Scip if Clear, der nächste 
befehl wird übersprungen wenn das  spezielle bit in diesem fall clear 
ist, wenn du deinen taster nach plus angeschlossen hast, brauchst du nur 
den befehl ändern in btfss (if Set) ändern.

übrigens, das was du suchst kann zb auch die til311 ganz ohne 
controller, einfach taster an der freigabeeingan anlegen und das bcd 
zeichen für e anlegen...

von tastendrücker (Gast)


Lesenswert?

@whitenose

Beim 16f84a hat der PORTA nur 5 Pins (RA0..RA4) und meine Maskierung

      MOVWF  TEMP              ; Speichern
      RRF    TEMP,W            ; Nach rechts schieben und nach W
      ANDLW  b'00000111'       ; gewünschte Bits maskieren

      CALL   table             ; Springe zur Tabelle (Wert ist in W)
      MOVWF  PORTB             ; Schreibe Arbeitsregister nach Port B
      GOTO   main              ; Wiederhole...

setzt voraus, dass der Taster an RA4 sitzt (wie vom TO gepostet) und 
verhindert auch, dass die Tabelle "übersprungen" wird.

von Myho (Gast)


Lesenswert?

Ich habe jetzt soweit das Programm fertig wo ich denke das funktioniert 
so (dank eurer Hilfe)

Hier das Programm:

; *********************************************
; *  7segment2.asm - BCD zu 7-Segment Decoder *
; *********************************************
;
;   Zeichen    Segmente
;      0      a,b,c,d,e,f
;      1          b,c
;      2       a,b,d,e,g
;      3       a,b,c,d,g
;      4        b,c,f,g
;      5       a,c,d,f,g
;      6      a,c,d,e,f,g
;      7         a,b,c
;      8     a,b,c,d,e,f,g
;      9      a,b,c,d,f,g
;      E       a,d,e,f,g
;
;
;
; EINGÄNGE:
;
; PortA,0 -> Übernahmetaster
; PortA,1 -> BCD-1 - Schließer
; PortA,2 -> BCD-2 - Schließer
; PortA,3 -> BCD-4 - Schließer
; PortA,4 -> BCD-8 - Schließer
;
;
; AUSGÄNGE:
;
; PortB,0 -> Segment a
; PortB,1 -> Segment b
; PortB,2 -> Segment c
; PortB,3 -> Segment d
; PortB,4 -> Segment e
; PortB,5 -> Segment f
; PortB,6 -> Segment g


;*********************************************************************** 
****
;* Bestimmung des Prozessortyps für den Assembler und das 
Programmiergerät *
;*********************************************************************** 
****

    LIST P=16F84A

;******************************************
;* Includedatei für den 16F84A einbinden  *
;******************************************

    #include <P16f84a.INC>

;*****************
;* Programmstart *
;*****************

TEMP EQU 0x0C        ; Speicher für Temp-Variable

     ORG   00H     ; Reset-Vector
     GOTO  init    ; Springe zur Grundinitialisierung der Ports A und B

     ORG   04H     ; Interrupt-Vector
     GOTO  init    ; auch zu init (weil kein Interrupt aktiv)



;*******************
;* Initialisierung *
;*******************

init  BSF  STATUS,RP0      ; wechsle zu Registerbank 1 (spezielle 
Register)
    MOVLW   B'00011111'
    MOVWF   TRISA        ; RA0 .. RA4 Eingänge
    MOVLW   B'00000000'
    MOVWF   TRISB      ; RB0-RB7 Ausgänge
    BCF  STATUS,RP0      ; wechsle zu Registerbank 0 (normaler 
Speicherbereich)
    MOVLW  b'00000111'    ; Komparatoren abschalten, nur Digitalports
    MOVWF  CMCON
    CLRF  PORTA      ; Port A löschen
    CLRF  PORTB      ; Port B löschen


;*****************
;* Hauptprogramm *
;*****************

main

waret_auf_taste
      BTFSC  PORTA,0           ; Taste gedrückt?
      GOTO   warte_auf_taste   ; nein, warten

      MOVF   PORTA,W           ; Lade Zustand von Port A in
Arbeitsregister
      MOVWF  TEMP              ; Speichern
      RRF    TEMP,W            ; Nach rechts schieben und nach W
      ANDLW  b'00000111'       ; gewünschte Bits maskieren

      CALL   table             ; Springe zur Tabelle (Wert ist in W)
      MOVWF  PORTB             ; Schreibe Arbeitsre

;********************
;* Dekodier-Tabelle *
;********************

table   ADDWF   PCL,F      ; Addiere Arbeitsregister zum Programmzähler

  RETLW   B'00111111'      ; 7-Segment-Code für die Ziffer '0'
   RETLW   B'00000110'      ; 7-Segment-Code für die Ziffer '1'
   RETLW   B'01011011'      ; 7-Segment-Code für die Ziffer '2'
   RETLW   B'01001111'      ; 7-Segment-Code für die Ziffer '3'
    RETLW   B'01100110'      ; 7-Segment-Code für die Ziffer '4'
    RETLW   B'01101101'      ; 7-Segment-Code für die Ziffer '5'
    RETLW   B'01111101'      ; 7-Segment-Code für die Ziffer '6'
    RETLW   B'00000111'      ; 7-Segment-Code für die Ziffer '7'
    RETLW   B'01111111'      ; 7-Segment-Code für die Ziffer '8'
    RETLW   B'01101111'      ; 7-Segment-Code für die Ziffer '9'
    RETLW   B'01111001'      ; 7-Segment-Code für die Ziffer 'E'

END

__________________________________________________________________

wenn ich nun "build all" mache, kommt folgende Fehlermeldung mit der ich 
nicht klar komme:

*Error[113]   C:\PIC\7SEGMENT2.ASM 77 : Symbol not previously defined 
(CMCON)
Error[113]   C:\PIC\7SEGMENT2.ASM 90 : Symbol not previously defined 
(warte_auf_taste)*


(hab mal das wichtige rauskopiert)

von whitenoise (Gast)


Lesenswert?

wer lesen kann ist klar im vorteil
(waret... und warte.. ist wohl kaum das gleiche)

und ich kanns nur nochmal sagen -  dein controller ist ein f84a und kein 
f628a - der hat keine komparatoren - weniger code copieren - mehr 
nachdenken und vor allem gründlich lesen!

whitnenoise

von Myho (Gast)


Lesenswert?

Ja du hast recht.
Und wie schaff ich es nun diesen "CMCON" Befehl um zu schreiben das es 
für den f84a funktioniert? Den kenn ich gar nicht und bei google hab ich 
auch nicht viel gefunden.

von tastendrücker (Gast)


Lesenswert?

1)
>   MOVLW  b'00000111'    ; Komparatoren abschalten, nur Digitalports
>   MOVWF  CMCON

der 16f84 hat keine Komparatoren, also kann ma die auch nicht 
abschalten...weg mit den Zeilen

2)
>warte_auf_taste (NICHT waret_auf_taste)
>      BTFSC  PORTA,0           ; Taste gedrückt?
>      GOTO   warte_auf_taste   ; nein, warten

3) (mein Fehler)
      MOVWF  TEMP              ; Speichern
      RRF    TEMP,W            ; Nach rechts schieben und nach W
      ANDLW  b'00001111'       ; gewünschte Bits maskieren

Und dann wird dein Prog immer noch nicht funktionieren. Z.B. kannst du 
über die Eingänge 16 Werte eingeben (0..15) deine Tabelle hat jetzt aber 
nur noch 11 Einträge. Was passiert wenn du 13 eingibst?

Versuche erst einmal den Controller, den du verwendest kennenzulernen 
und dan n das Programm zu verstehen.  Bitte die Tipps, die dir hier 
gegeben werden, nicht als abschreibfertige Lösungen ansehen.

von Myho (Gast)


Lesenswert?

danke dir
ich werde erstmal ein tag darüber nachdenken. vielleicht fällt mir ja 
eine lösung ein

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
Noch kein Account? Hier anmelden.