7 Segment Anzeige per Pic Steuern

Gast #2201459
Lesenswert?

Hallo Leute habe da ein kleines Problem ich möchte gerne eine 7 Segment 
anzeige per Pic steuern und mit dem Schalter Hoch oder Runter Schalten 
bloss wenn ich den Schalter betätige habe ich immer so ein Flackern kann 
mir jemand vieleicht sagen wie ich das weg bekomme hier ein kleiner 
Ausschnitt.


Start:movf  Sp1,w
      movwf  PORTB
      movlw  b'11011111'
      movwf  PORTD
      btfss  PORTA,0
      goto  ssh
      goto  Start

;----------------------------------------------------------------------- 
-----
ssh:  call    wait
      incf  einer,w
      movwf  einer
      call  Anzeige
      movwf  Sp1
      goto  Start
Gast #2201468
Lesenswert?

Hier der richtige Ausschnitt



Start:            movf  Sp1,w
      movwf  PORTB
      movlw  b'11011111'
      movwf  PORTD
      call  wait1
      movf  Sp2,w
      movwf  PORTB
      movlw  b'10111111'
      movwf  PORTD
      call  wait1
      movf  Sp3,w
      movwf  PORTB
      movlw  b'01111111'
      movwf  PORTD
      call  wait1
      btfss  PORTA,0
      goto  ssh
      goto  Start

;----------------------------------------------------------------------- 
---
ssh:            call  wait
      incf  einer,w
      movwf  einer
      call  Anzeige
      movwf  Sp1
      goto  Start
Gast #2201543
Lesenswert?

Ohne jetzt auf das Programm mal einzugehen:

Zum Test einer Multiplexung reicht natürlich ein Hauptprogramm mit einer 
Warteschleife. Wenn da noch irgend welche Interrupts statt finden, gibt 
es vielleicht ein Flackern oder Jittern.

Die Multiplexumschaltungen müßten korrekterweise in einem Timer-Interupt 
liegen, der eine hohe Priorität hat. Und die Frequenz muß auch so hoch 
gewählt sein, daß das Auge kein Flackern mehr beobachten kann. Minimum 
20ms für den Zeitdurchlauf eines gesamten Displays.
Gast #2201563
Lesenswert?

so jetzt hier der code wird aber erstmal eine Taste abgefragt


p=16f887
      #include <P16f887.inc>

;----------------------------------------------------------------------- 
------

einer      EQU    20h
zehner     EQU    21h
hunderter  EQU    22h
tausender  EQU    23h
Sp1        EQU    24h
Sp2        EQU    25h
Sp3        EQU   26h
Sp4        EQU    27h



;----------------------------------------------------------------------- 
---

      bsf  STATUS,RP0
      bsf  STATUS,RP1
      clrf  ANSELH
      clrf  ANSEL
      bsf  STATUS,RP0
      bcf  STATUS,RP1
      movlw  b'11111111'
      movwf  TRISA
      clrf  TRISB
      clrf  TRISC
      clrf  TRISD
      clrf  TRISE
      bcf  STATUS,RP0

;----------------------------------------------------------------------- 
------

      clrf  PORTA
      clrf  PORTB
      clrf  PORTC
      clrf  PORTD
      clrf  PORTE
      clrf  einer
      clrf  zehner
      clrf  hunderter
      clrf  tausender


;----------------------------------------------------------------------- 
------
      clrf  Sp1
Start:
      movf  Sp1,w
      movwf  PORTB
      movlw  b'10011111'
      movwf  PORTD
      call  wait1
      movf  Sp2,w
      movwf  PORTB
      movlw  b'10111111'
      movwf  PORTD
      call  wait1
      movf  Sp3,w
      movwf  PORTB
      movlw  b'01111111'
      movwf  PORTD
      btfss  PORTA,0
      goto  ssh
      goto  Start

;----------------------------------------------------------------------- 
---

ssh:            call  wait
      incf  einer,w
      movwf  einer
      call  Anzeige
      movwf  Sp1
      goto  Start


Anzeige:  addwf PCL,f

      retlw b'10111111'  ;Zahl 0
      retlw b'10000110'  ;Zahl 1
      retlw b'11011011'  ;Zahl 2
      retlw b'11001111'  ;Zahl 3
      retlw b'11100110'  ;Zahl 4
      retlw b'11101101'  ;Zahl 5
      retlw b'11111101'  ;Zahl 6
      retlw b'10000111'  ;Zahl 7
      retlw b'11111111'  ;Zahl 8
      retlw b'11101111'  ;Zahl 9

;----------------------------------------------------------------------- 
---

wait:     movlw d'175'
      movwf 31h
schl2:     movlw d'175'
      movwf 30h
schl1:     nop
      nop
      nop
      nop
      nop
      nop
      nop
      decfsz 30h,f
      goto schl1
      decfsz 31h,f
      goto schl2
      return




wait1:     movlw d'50'
      movwf 33h
schl3:     movlw d'25'
      movwf 34h
schl4:     nop
      nop
      nop
      nop
      nop
      nop
      nop
      decfsz 34h,f
      goto schl4
      decfsz 33h,f
      goto schl3
      return

      end
#2202410
Lesenswert?

Manfred John schrieb:
> Peter Dannegger schrieb:
>> Und genau deshalb macht man Multiplexen im Timerinterrupt.
>> Erst dann ist alles gut.
>
> ist so im allgemeinem dahergelaber Bullshith.

Vielen Dank für Deinen völlig unnützen Beitrag.
Warum willst Du einem Anfänger die einfache und zuverlässige Lösung 
ausreden?
Der kann doch nicht beurteilen, daß Du "Bullshith" redest.

Man kann sich theoretisch damit abquälen, die Mainloop auf gleiche 
Ausführungszeit bei jeder Verzweigung zu trimmen, damit nichts flackert.
Aber einfach und sinnvoll ist das nicht.

Nimmt man den Interrupt fürs Multiplexen, braucht die Mainloop keinerlei 
Rücksicht zu nehmen. Sie schreibt die Darstellungsmuster in den 
Display-RAM, ganz wie sie lustig ist. Und der Timerinterupt gibt ihn 
dann exakt zu gleichen Zeitintervallen aus.

Programmieren wird dadurch einfach und sicher, indem man die einzelnen 
Aufgaben voneinander trennt (Divide et impera).
Spaghetticode ist ja nicht zu Unrecht verpönt.


Peter
Gast #2202441
Lesenswert?

ich verstehe nur bahnhof? welcher Timer?

du fragst die Taste ab aber sperrst sie dann nicht. Der Controller läuft 
für die Zeit des Drückens 1000 Mal da durch, und deswegen "rattert" 
deine Anzeige. Die Taste hängt doch an Port A,0 oder?

Zu Deinem Code gehört auch, wo was angeschlossen ist ....

Willst du denn nur eine 7Seg Anzeige ansteuern oder mehrere? so wie ich 
das sehen hast du zudem deine "sp" register nirgens auf 0 gesetzt, nun 
kann es passieren das er dir ins nirvana möllert wenn dort müll drin 
steht...

T.
#2202537
Lesenswert?

Thorsten S. schrieb:
> du fragst die Taste ab aber sperrst sie dann nicht. Der Controller läuft
> für die Zeit des Drückens 1000 Mal da durch, und deswegen "rattert"
> deine Anzeige.

naja, also durch die "wait" schleifen, die 2 mal verschachtelt sind, 
dauert eine mainloop schleife doch lang genug um die taster nicht extra 
sperren zu müssen.

ich würde eher sagen, die wait schleife, die bei "ssh" aufgerufen wird, 
also 175 x 175 takte, führt dazu, dass das multiplexen nicht mehr 
schnell genug funktioniert.
mein tip: mach mal die zeit kürzer oder lösch diese wait-schleife raus, 
wozu hast du sie eingebaut? zum entprellen des tasters?
am besten wäre wohl ein taster-interrupt geeignet.
#2202584
Lesenswert?

Peter Dannegger schrieb:
> John schrieb:
>> Das Flackern tritt nur auf wenn ich die Taster betätige sonst ist alles
>> gut!
>
> Und genau deshalb macht man Multiplexen im Timerinterrupt.
> Erst dann ist alles gut.
>
>
> Peter

Ja Du hast völlig recht, Dein Beitrag hilft sicher jedem Neuling.

Peter Dannegger schrieb:
> Man kann sich theoretisch damit abquälen, die Mainloop auf gleiche
> Ausführungszeit bei jeder Verzweigung zu trimmen, damit nichts flackert.
> Aber einfach und sinnvoll ist das nicht.

LOL Du hast wirklich keine Ahnung wie man ein anständiges Timemanagement 
ohne gleich für jeden Zeitintervall einen einengen Interrupt zu 
verballern, macht!

Aber Deine Magischekugel scheint wirklich gut zu funktionieren!
Was Du alles aus zwei Sätzen von mir herauslesen kannst, Hut ab.

Nur Schade das das alles hier John nicht weiter hilft.
#2202626
Lesenswert?

@ john:

Das Multiplexen solltest Du wirklich besser über den Timer steuern, ob 
mit oder ohne Interrupt is egal.
Die Tastenabfrage würde ich in ein eigenes Unterprogramm verbannen.
so das auch dies über den Timer geregelt werden kann und keine sinnlose 
zeit in der Warteschleife verheizt wird.

Einfach den Timer auf kleinst benötigten Zeitintervall trimmen.
Durch den Interrupt oder einfaches Pollen des Timer InteruptFlags
ein Unterprogramm aufrufen in dem Du durch eigene Zählvariable(n)
die noch benötigten Zeitintervalle erzeugst. Durch setzen von Flag's 
kannst Du das dann in der Hauptschleife auswerten.

So wird das Ganze auch flexibler für Änderungen u.o. Erweiterungen.

Ach ja nicht vergessen deine Sprung-Variable für die LookUp-Tabelle auf 
Gültigkeit zu prüfen.


mfg
#2202640
Lesenswert?

@Peter

Ich möchte mich hiermit ganz ehrlich bei Dir für meine Wortwahl 
"Bullshitt"
entschuldigen. So was ist nicht nötig und war so auch nicht gewollt aber 
manchmal fällt es mir nicht auf wie unfreundlich manche "Kurzfassungen" 
beim lesenden ankommen könnten. Vor allem wenn ich angesoffen bin :/

Also Sorry noch mal's, war nich' so gemeint.


mfg
#2202664
Lesenswert?

Manfred John schrieb:
> Einfach den Timer auf kleinst benötigten Zeitintervall trimmen.
> Durch den Interrupt oder einfaches Pollen des Timer InteruptFlags
> ein Unterprogramm aufrufen in dem Du durch eigene Zählvariable(n)
> die noch benötigten Zeitintervalle erzeugst. Durch setzen von Flag's
> kannst Du das dann in der Hauptschleife auswerten.

ubs, missverständlich ausgedrückt

Wenn Interrupt benutzt, natürlich kein weiteres Subprogramm aufrufen. 
Das bisschen Zählen, testen etc. natürlich gleich in der 
Interruptroutine erledigen.
Gast #2203081
Lesenswert?

Danke für eure Antworten wie schon hier mal gesagt ich bin ein neuling 
in PicProgrammierung und kenne mich mit dem Interrupt noch nicht aus.
Gibt es vieleicht eine Seite im Internet oder ein Buch wo das Gut 
erklärt wird?
#2203701
Lesenswert?

Lehrmann Michael schrieb:
> Das findest du doch alles bei Sprut.de

Z.B.:
http://www.sprut.de/electronic/pic/programm/led.htm


Allerdings ist da noch ein Schönheitsfehler.
Kein Mensch kann Ziffern alle 250Hz ablesen. Daher ist es unnötig, im 
Interrupt immer wieder neu die Ziffern in 7-Segment-Kode umzuwandeln.
Diese Umwandlung sollte man daher besser ins Main verschieben.
Dann erfolgt die Umwandlung immer nur dann, wenn wirklich ein neuer 
Zählwert vorliegt.
Man gewinnt dadurch also CPU-Leistung, die man vielleicht an andere 
Stelle gebrauchen kann. Bzw. man kann die gleiche Anwendung mit 
langsameren Takt betreiben (Strom sparen).


Peter
Gast #2209060
Lesenswert?

Also nochmal eine Frage zu der Steuerung ich brauche oder am besten 
währe ein Timer interrupt und die Tasten frage ich dann immer ab wenn 
der Timer abgelaufen ist oder brauche ich noch einen interrupt bei den 
Tastern????
#2209106
Lesenswert?

Hi,

hab heute keinen Kopf für Große Erklärungen :/

Hier ein Timer-Interrupt-Routine von mir, is zwar keine 7Segmentdingens
aber alles drin was Du brauchst. Ich frage einen Port ab (auf 
Flankenänderung deswegen etwas aufwendiger als ne einfache 
Tastenabfrage)
und eien 1 Sekundentakt. Inkl. dem drum herum was ein Pic16Fxxx für die 
Interrupt Abwicklung braucht.
Ich hoffe es hilft Dir weiter

mfg
1
;==============================================================================
2
; INTERRUPT SERVICE ROUTINE
3
;==============================================================================
4

5
ISR       ORG     0x0004            ; interrupt vector location
6
;         Context saving for ISR
7
          MOVWF   W_TEMP            ; save off current W register contents
8
          MOVF    STATUS,W          ; move status register into W register
9
          MOVWF   STATUS_TEMP       ; save off contents of STATUS register
10
          MOVF    PCLATH,W          ; move pclath register into W register
11
          MOVWF   PCLATH_TEMP       ; save off contents of PCLATH register
12
; USER INTERRUPT SERVICE ROUTINE GOES HERE
13

14
;------------------------------------------------------------------------------
15
; Sekunden Takt / DCF77 Timer
16
;------------------------------------------------------------------------------
17
Sekunde  BCF    INTCON,T0IF    ; auf ruf alle 1/125 Sec.
18
    bcf    Sec_Flag
19
    btfsc  DCF_Port
20
    goto  DCFPortHI
21
    goto  DCFPortLO
22
DCFPortHI          
23
    btfsc  DCF_Port_Flag  
24
    goto  DCFPortEND    ; DCF_PORT war Hi
25
    bsf    DCF_Rise_Flag  ; DCF_PORT ist Hi geworden DCFBit auswerten
26
    bsf    DCF_Port_Flag  
27
    goto  DCFPortEND
28
DCFPortLO
29
    btfss  DCF_Port_Flag
30
    goto  DCFPortEND    ; DCF_PORT war bereits Lo
31
    bsf    DCF_Sink_Flag  ; DCF_PORT ist Lo geworden
32
    bcf    DCF_Port_Flag
33
DCFPortEND
34
    incf  DCF_Timer     ; Sec_Tackt erzeugen
35
    DECFSZ  Clock125
36
    goto  INT_END
37
    MOVLW  D'125'  
38
    MOVWF   Clock125
39
    bsf    Sec_Flag    
40
  
41
;         Restore context before returning from interrupt
42
INT_END
43
          MOVF    PCLATH_TEMP,W     ; retrieve copy of PCLATH register
44
          MOVWF   PCLATH            ; restore pre-isr PCLATH register contents
45
          MOVF    STATUS_TEMP,W     ; retrieve copy of STATUS register
46
          MOVWF   STATUS            ; restore pre-isr STATUS register contents
47
          SWAPF   W_TEMP,F
48
          SWAPF   W_TEMP,W          ; restore pre-isr W register contents
49
          RETFIE                    ; return from interrupt
50
;==============================================================================
Gast #2209212
Lesenswert?

Also kein Interrupt bei den Tastern nur der Timerinterrupt?
Tschuldigung muss fragen das der Schaltplan und Layout fertig ist und 
die eingänge der Taster sich auf PORTA befinden wo kein interrupt 
möglich ist.
#2209308
Lesenswert?

John schrieb:
> Also kein Interrupt bei den Tastern nur der Timerinterrupt?
> Tschuldigung muss fragen das der Schaltplan und Layout fertig ist und
> die eingänge der Taster sich auf PORTA befinden wo kein interrupt
> möglich ist

Jo, Du kannst natürlich den Taster abfragen wann und wo Du willst :)
Sollte ja nicht auf die µSec genau wichtig sein wann der Schalter 
gedrückt wurde.
in meinem Beispiel ist das hauptsächlich mit im Interrupt weil das ganze 
eigentlich eine Zeitmessung ist.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren