PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Denke zu kompliziert > 7-Segment Multiplexanzeige



Andree-HB
13.01.2006, 23:36
Ich spiele gerade mit einer gemultiplexten 7-Segmentanzeige herum. Ich möchte im Endeffekt eine 4stellige Variable auf die Anzeige bekommen.

http://www.piratenabenteuer.de/pictures/7segment.jpg


(PortD setzt die Segmente, PortB.0-3 die gemeinsamen Kathoden)


...aber der Code ist gruselig

Die Einer-Stelle wird (vorerst fest) gesetzt, springt in eine Sub, die Kathode für die erste Stelle wird dort gesetzt, nach Zahlvergleich wieder Sprung in eine andere Sub, wo die entsprechenden Segmente gesetzt werden, danach wird die Kathode wieder ausgeschaltet

Zehner-Stelle wird gesetzt......usw.


Das Prinzip ist mir klar und funktioniert auch...aber laut eigener Betrachtung viel zu umständlich. Hat Jemand `nen Tipp für mich für Vereinfachung ?



$regfile = "m8def.dat"
$crystal = 8000000


Config Portd = Output
Config Portb = Output


Dim E As Byte 'einer
Dim Z As Byte 'zehner
Dim H As Byte 'hunderter
Dim T As Byte 'tausender
Dim X As Byte 'Zeit (ms), wielange Kathoden ein
X = 1


Do
E = 6 'Beispielzahl Einer
Gosub E:
Z = 5 'Beispielzahl Zehner
Gosub Z:
H = 4 'Beispielzahl Hunderter
Gosub H
T = 7 'Beispielzahl Tausender
Gosub T
Loop
End


E:
Portb.0 = 1 'Kathode Einer ein
If E = 0 Then Gosub 0
If E = 1 Then Gosub 1
If E = 2 Then Gosub 2
If E = 3 Then Gosub 3
If E = 4 Then Gosub 4
If E = 5 Then Gosub 5
If E = 6 Then Gosub 6
If E = 7 Then Gosub 7
If E = 8 Then Gosub 8
If E = 9 Then Gosub 9
Waitms X
Portb.0 = 0 'Kathode Einer aus
Return

Z:
Portb.1 = 1 'Kathode Zehner ein
If Z = 0 Then Gosub 0
If Z = 1 Then Gosub 1
If Z = 2 Then Gosub 2
If Z = 3 Then Gosub 3
If Z = 4 Then Gosub 4
If Z = 5 Then Gosub 5
If Z = 6 Then Gosub 6
If Z = 7 Then Gosub 7
If Z = 8 Then Gosub 8
If Z = 9 Then Gosub 9
Waitms X
Portb.1 = 0 'Kathode Zehner aus
Return

H:
Portb.2 = 1 'Kathode Hunderter ein
If H = 0 Then Gosub 0
If H = 1 Then Gosub 1
If H = 2 Then Gosub 2
If H = 3 Then Gosub 3
If H = 4 Then Gosub 4
If H = 5 Then Gosub 5
If H = 6 Then Gosub 6
If H = 7 Then Gosub 7
If H = 8 Then Gosub 8
If H = 9 Then Gosub 9
Waitms X
Portb.2 = 0
Return 'Kathode Hunderter aus


T:
Portb.3 = 1 'Kathode Tausender ein
If T = 0 Then Gosub 0
If T = 1 Then Gosub 1
If T = 2 Then Gosub 2
If T = 3 Then Gosub 3
If T = 4 Then Gosub 4
If T = 5 Then Gosub 5
If T = 6 Then Gosub 6
If T = 7 Then Gosub 7
If T = 8 Then Gosub 8
If T = 9 Then Gosub 9
Waitms X
Portb.3 = 0 'Kathode Tausender aus
Return





0:
Portd = &B00111111 '0
Return
1:
Portd = &B00000110 '1
Return
2:
Portd = &B01011011 '2
Return
3:
Portd = &B01001111 '3
Return
4:
Portd = &B01100110 '4
Return
5:
Portd = &B01101101 '5
Return
6:
Portd = &B01111101 '6
Return
7:
Portd = &B00000111 '7
Return
8:
Portd = &B01111111 '8
Return
9:
Portd = &B01101111 '9
Return

linux_80
13.01.2006, 23:54
Hallo,

und das ganze ohne Widerstände, wird da nix warm ?

Es lässt sich zumindest mal so zusammenfassen:



$regfile = "m8def.dat"
$crystal = 8000000


Config Portd = Output
Config Portb = Output


Dim E As Byte ' Zahl
Dim X As Byte 'Zeit (ms), wielange Kathoden ein
X = 1


Do
E = 6 'Beispielzahl Einer
Gosub E
E = 5 'Beispielzahl Zehner
Gosub Z
E = 4 'Beispielzahl Hunderter
Gosub H
E = 7 'Beispielzahl Tausender
Gosub T
Loop
End


E:
Portb.0 = 1 'Kathode Einer ein
Gosub Wertsuche
Portb.0 = 0 'Kathode Einer aus
Return

Z:
Portb.1 = 1 'Kathode Zehner ein
Gosub Wertsuche
Portb.1 = 0 'Kathode Zehner aus
Return

H:
Portb.2 = 1 'Kathode Hunderter ein
Gosub Wertsuche
Portb.2 = 0
Return 'Kathode Hunderter aus


T:
Portb.3 = 1 'Kathode Tausender ein
Gosub Wertsuche
Portb.3 = 0 'Kathode Tausender aus
Return


Wertsuche:
If E = 0 Then Gosub 0
If E = 1 Then Gosub 1
If E = 2 Then Gosub 2
If E = 3 Then Gosub 3
If E = 4 Then Gosub 4
If E = 5 Then Gosub 5
If E = 6 Then Gosub 6
If E = 7 Then Gosub 7
If E = 8 Then Gosub 8
If E = 9 Then Gosub 9
Waitms X
Return



0:
Portd = &B00111111 '0
Return
1:
Portd = &B00000110 '1
Return
2:
Portd = &B01011011 '2
Return
3:
Portd = &B01001111 '3
Return
4:
Portd = &B01100110 '4
Return
5:
Portd = &B01101101 '5
Return
6:
Portd = &B01111101 '6
Return
7:
Portd = &B00000111 '7
Return
8:
Portd = &B01111111 '8
Return
9:
Portd = &B01101111 '9
Return


evtl. eine Sub bauen, an die man den Wert und die Stelle übergibt.

Edit:
Jetzt hab ich zu schnell auf Absenden gedrückt,
ich wollte noch ja noch den Timer vorschlagen, um zB. 30mal/s die Anzeige zu aktualisieren.

izaseba
14.01.2006, 00:42
Hallo,
Leider habe ich keine Ahnung von Bascom,
aber ich packe die Wertigkeiten von den Zahlen in ein Array, bei Bascom gibt es doch Arrays, oder?
Danach kannst Du schön über den Index darauf zugreifen.

Gruß Sebastian

darwin.nuernberg
14.01.2006, 01:24
Hey Geil,
ich habe auch 'ne Handvoll ähnlicher Displays,
aber immer gescheut diese einzusetzen,
da ich befürchtete diese nich nachkaufen zu können.

Hast du die Bezeichnung, eine Bezugsquelle und ein Datenblatt von deinem Baustein?

Dann könnte ich falls beide (annähernd) kompatibel sind auch mal ein Projekt mit diesen Baustein realisieren und veröffentlichen.

Andree-HB
14.01.2006, 07:08
Info zum Display -> Die Anzeige hat die Bezeichnung 14315C (http://www.pollin.de/shop/downloads/D120289D.PDF) und kostet nur 75 Cent, Segmente sind alle parallel geschaltet, Kathoden und Punkte seperat. dadurch ist die Verdrahtung sehr minimiert (7+4 Pins)

Die Anzeige wird ohne Widerstand betrieben, da die Einschaltdauer jeder Ziffer sehr klein ist. Daher wird da auch nix warm. Mit Widerstand (getestet) wird die Anzeige viel zu dunkel. Die Kathoden werden nach Minus über einen BC547C geschaltet, der an der Basis über 1K-Widerstand von den Ausgängen angesteuert wird.

An "linux_80" :
So ähnlich habe ich mir das auch gedacht, nur weiss ich nicht, wie ich die einzelnen Werte der Stellen an die gemeinsame Sub übergeben könnte. Dass man den Wertevergleich ja nicht für jede Ziffer einzeln machen muss, geht ja definitiv einfacher.

Meine Vorstellung :
Teile Wertevariable (4 Ziffern) auf und springe für jede Ziffer nacheinander in den Vergleich und schalte gleichzeitig Segmente und entsprechende Kathode).

linux_80
14.01.2006, 11:09
Mach es so wie izaseba gemeint hat,
am Anfang ein Array anlegen von 0-9, dann muss man nur das Array mit der gewünschten Zahl auslesen, und schon hat man das gewünschte Bitmuster, also ohne die ganzen IF ...GOSUBs.

MatthiasW
14.01.2006, 11:55
Hallo ,
ich benutze eine etwas modifizierte Routine von Wolfgang Schwarz
( http://www.black-strom.de.vu ), der sowas für seine Uhr verwendet hat, schaut's euch mal an:

[Ich hab nur die relevanten Zeilen rauskopiert]



Dim Stelle_1 As Byte
Dim Stelle_2 As Byte
Dim Stelle_3 As Byte
Dim Stelle_4 As Byte

'Ausgänge:
Segment_a Alias Portb.0
Segment_b Alias Portb.1
Segment_c Alias Portb.2
Segment_d Alias Portb.3
Segment_e Alias Portb.4
Segment_f Alias Portb.5
Segment_g Alias Portc.0
Ziffer_1 Alias Portc.1
Ziffer_2 Alias Portc.2
Ziffer_3 Alias Portc.3
Ziffer_4 Alias Portc.4

Config Timer0 = Timer , Prescale = 1024
On Timer0 7segment
Const Timervorgabe = 200


Do
'Anfang Hauptschleife
Stelle_1 = 4
Stelle_2 = 3 'was angezeigt werden soll ...
Stelle_3 = 2
Stelle_4 = 1
Loop 'Ende Hauptschleife




'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
' Interrupt-Routine für Ziffer ausgabe im 7 Segmentcode
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
' Bei jedem Aufruf wir nur eine Ziffer ausgegeben, d.h nur eine Anzeige wird
' angesteuert. Die anderen bleiben dunkel. Bei jedem Aufruf wird eine Anzeige
' weitergeschaltet.
'
' Anzeigen anordnung
'
' 1111 2222 3333 4444
' 1 1 2 2 3 3 4 4
' 1111 2222 3333 4444
' 1 1 2 2 3 3 4 4
' 1111o 2222o 3333o 4444o
'
' ^-- Dezimalpunkt
' ^---- 4. Ziffer | Minute Low Wert | Variable Zl_minute
' ^---------- 3. Ziffer | Minute High Wert | Variable Zh_minute
' ^----------------- 2. Ziffer | Stunde Low Wert | Variable Zl_stunde
' ^----------------------- 1. Ziffer | Stunde High Wert | Variable Zh_stunde

7segment:
Timer0 = Timervorgabe
If Temp_ziffer = 4 Then Temp_ziffer = 0 'bestimmt die auszugebende Ziffer (1 bis 4)
Incr Temp_ziffer 'bei jedem aufruf des Lable wir eine andere Ziffer ausgegeben


Select Case Temp_ziffer 'welche Ziffer soll angesteuert werden
Case 1 : Ziffer_1 = 0 '1. Ziffer
Ziffer_2 = 1
Ziffer_3 = 1
Ziffer_4 = 1
Bcd_aus = Stelle_1
Case 2 : Ziffer_1 = 1 '2. Ziffer
Ziffer_2 = 0
Ziffer_3 = 1
Ziffer_4 = 1
Bcd_aus = Stelle_2
Case 3 : Ziffer_1 = 1 '3. Ziffer
Ziffer_2 = 1
Ziffer_3 = 0
Ziffer_4 = 1
Bcd_aus = Stelle_3
Case 4 : Ziffer_1 = 1 '4. Ziffer
Ziffer_2 = 1
Ziffer_3 = 1
Ziffer_4 = 0
Bcd_aus = Stelle_4
End Select

'Ermittelt aus der Segmentfolge-Tabelle den 7 Segmentcode für die auszugebende Zahl
Select Case Bcd_aus
Case 1 : Ausgang = Lookup(1 , Segmentfolge)
Case 2 : Ausgang = Lookup(2 , Segmentfolge)
Case 3 : Ausgang = Lookup(3 , Segmentfolge)
Case 4 : Ausgang = Lookup(4 , Segmentfolge)
Case 5 : Ausgang = Lookup(5 , Segmentfolge)
Case 6 : Ausgang = Lookup(6 , Segmentfolge)
Case 7 : Ausgang = Lookup(7 , Segmentfolge)
Case 8 : Ausgang = Lookup(8 , Segmentfolge)
Case 9 : Ausgang = Lookup(9 , Segmentfolge)
Case 0 And Temp_ziffer = 1 : Ausgang = Lookup(10 , Segmentfolge) 'Nullstellenunterdrückung bei der ersten Ziffer
Case 0 And Temp_ziffer > 1 : Ausgang = Lookup(0 , Segmentfolge) 'wenn nicht erste Ziffer Null anzeigen
End Select

'Ausgabe des 7 Segmentcodes (Invertierend [Not] bei Anz. mit gem. Anode)
Segment_a = Ausgang.0 'Segment A
Segment_b = Ausgang.1 'Segment B
Segment_c = Ausgang.2 'Segment C
Segment_d = Ausgang.3 'Segment D
Segment_e = Ausgang.4 'Segment E
Segment_f = Ausgang.5 'Segment F
Segment_g = Ausgang.6 'Segment G
Return


End 'Programm Ende



'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
' 7 Segmentcode - Tabelle
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
'
' --A--
' | |
' F B
' | |
' --G--
' | |
' E C
' | |
' --D--
Segmentfolge: 'GFEDCBA / "1" Segment AN
Data &B0111111 '0
Data &B0000110 '1
Data &B1011011 '2
Data &B1001111 '3
Data &B1100110 '4
Data &B1101101 '5
Data &B1111101 '6
Data &B0000111 '7
Data &B1111111 '8
Data &B1101111 '9
Data &B0000000 'leeres Feld (zur Nullstellenunterdrückung)

PicNick
14.01.2006, 12:03
Erster Gegenvorschlag


Wertsuche:
on E Gosub 0, 1, 2, ..................9

Zweiter


Wertsuche:
Portd = lookup(e, patt_tab)
...
patt_tab:
DATA &B00111111, &B00000110, &B01011011, ......

darwin.nuernberg
14.01.2006, 12:17
Danke für das Datenblatt, werde die Anschlüsse gelich mal vergleichen.

Willst Du nur die Segmente ohne Punkt ansteuern ein Tipp von mir:

Du kannst das ganze auf nur einem Port realisieren, wenn Du eine 7-Segment Decoder verwendest. Dann brauchst Du nur 4-Bit zur Darstellung der Zahl und hast die anderen 4-Bit für die Dezimalstellen frei.

Dann solltest Du für den Übergang der einzelnen Stellen ein gewisses Timing einhalten, um zu verhindern, dass die Segmente (kurzzeitig) noch aktiv sind, wenn die Stelle gewechselt wird. Schau mal in die Zeichnung im Anhang.

darwin.nuernberg
14.01.2006, 14:04
Leider sind unsere Displays doch nicht gleich belegt.

Falls Du später mal mit Eagle was aufbauen willst,
ich habe unsere Anzeigen mal in einer LIB aufgebaut...

nemesis-2004
14.01.2006, 18:58
Habe ich das richtig verstanden, das du jede Ziffer in einer Schleife einzeln durchgehst? (Also nicht alles auf einmal darstellst, sondern jede Ziffer hinter einander)

Kommt es da nicht zu einem sichtabaren Flimmern? :-s

darwin.nuernberg
14.01.2006, 19:23
Das ist die Technik vom Multiplexen, das geht nicht anders und ist auch so im Sinne des Erfinders.
Und Flimmern, mehr oder weniger, kommt auf die Frequenz sowie Ti/Tp an.

Fernsehr, Kino, Anzeigen von DVD oder Vidreorecorder, ja sogar die Ledrücklichter der neueren PKW's arbeiten so.

Jetz bist du Baff was?

Erkennen kann man das eigentlich nur mit einem Trick (verrat ich nich).

izaseba
14.01.2006, 22:07
ja sogar die Ledrücklichter der neueren PKW's arbeiten so.


Das kann man aber gut sehen, das erste mal, wo ich so ein Auto vor der Nase hatte, dachte ich, daß ich zum Augenarzt muß, man sollte es verbieten!

Gruß Sebastian

darwin.nuernberg
15.01.2006, 02:26
Also das hat mir jetzt keine Ruhe gelassen

Hier der Source:


' 4-Digit Multipexed Display an Port C
' PortC.4 = 1er
' PortC.5 = 10er
' PortC.6 = 100er
' PortC.7 = 1000er
' Portc.0 bis Portc.3 = BCD Code der Zahl &H00 bis &HFF
' Hierzu einen 7-Segmentdecoder (74LS48) zwischen PortC(0..3) und den Segmenten schalten
' Nicht vergessen die Treibersegmentausgänge mit 470R PullUp zu schalten.

' Der Baustein 74LS48 kann nur Zahlen (0-9) darstellen heine Hex Codes (ABCDEF)
' Falsche Werte (>9) (>&H09) (>&B00001001) führen zu Anzeigefehlern.



$regfile = "m32def.dat" ' AT Mega 32
$crystal = 16000000 ' 16 MHz
$baud = 19200 ' Serielle Schittstelle einrichten

Anzeigeport Alias Portc ' Hier einstellen an welchem Port
' das Display angeshclossen wird

Config Anzeigeport = Output ' Direction einstellen


Declare Function Anzeige(byval B_speed As Byte) As Integer



Dim X As Integer ' Variable für For Scheife
Dim Y As Integer ' Variable für For Scheife
Dim B_ar_zahl(4) As Byte

Portc = 0 ' Port C initialisieren


' Die Anzeige soll "4321" darstellen
B_ar_zahl(1) = 1 ' Hier die 1er Zahlen der Anzeige
B_ar_zahl(2) = 2 ' Hier die 10er Zahlen der Anzeige
B_ar_zahl(3) = 3 ' Hier die 100er Zahlen der Anzeige
B_ar_zahl(4) = 4 ' Hier die 1000er Zahlen der Anzeige


Do
For Y = 0 To 9
X = Anzeige(5)
Next Y

Loop

End 'end program

' ************************************************** ****************************

Function Anzeige(byval B_speed As Byte) As Integer
Dim B_x As Byte ' Schleifen Variable
Dim B_decade As Byte ' Aktivierung der Decade
Dim B_select As Byte

For B_x = 4 To 7 ' Schleife für Decaden
' Bit 4 bis 7 sind Decaden
B_decade = 2 ^ B_x ' Bitmuster für Decade berechnen
B_select = B_x - 3 ' Feld des Array's bestimmen

Anzeigeport = B_decade ' Nur Decade aktivieren
Anzeigeport = Anzeigeport Or B_ar_zahl(b_select)
' Decade + Anzeigewert aktivieren
' Hiermit wird auch das Anzeigetiming
' realisiert

Waitms B_speed ' Anzeigedauer der einzelnen Decade
Next B_x

Anzeige = 0 ' Rükgabewert 0 = ok
End Function

' ************************************************** ****************************

End 'end program

Dann noch der Schaltplan für Dein IC
und der Beweis dass es geht....

Andree-HB
15.01.2006, 09:48
So, durch den ersten Tipp von PicNick bin ich zumindest bei der Segmentansteuerung sehr kompakt fertig.

Nun hängt es noch bei der Dezimalstellenauswahl. Ich möchte eine vierstellige Variabel stellenweise aufsplitten, versuche dafür den "Mid"-Befehl - aber (mal wieder) komme ich mit den Variablenarten nicht richtig klar.


Vereinfacht (und völlig erfolglos) versuche ich gerade :



x=3465 (anzuzeigende zahl)

do
y=mid(x,3,1) (rechte Ziffer, einer/5, soll selektiert werden)
pin1=1 kathode einer ein
zeige segmente

y=mid(x,2,1) (zehner/6 soll selektiert werden)
pin2=1 kathode zehner ein
zeige segmente

y=mid(x,1,1) (hunderter/4)
pin3=1
zeige segmente

y=mid(x,0,1) (tausender/3, linke linke Ziffer)
pin4=1
zeige segmente
loop

PicNick
15.01.2006, 10:24
Vom Wald sieht' man nix, überall stehen Bäume rum !
Also, sagen wir mal: (ich weiß nicht, ob das jetzt mit deinen Pins so stimmt)


1. MID is nicht so gut, weil da ja wieder ein string rauskommt. Besser is:
dim Instring as string * 4
dim onechar(4) as byte at Instring overlay
2. Isses so ?
PORTD --> Segmente
PORTB.0 --> Einer ' ?
PORTB.1 --> zehner
PORTB.2 --> hundert
PORTB.3 --> tausend
3. Geht aber besser mit Maske als über Pin-Nummer
dim charmsk as byte

4. Arbeiten geht besser von tausend-->einer (dadurch kannst du später mal auch führende Nullen unterdrücken)
dim charidx as byte ' von 1 - 4
5. Hilfsbyte
dim E as byte ' das aktuelle Zeichen

Auf geht's:
'-----------------------------------------------------------------
Instring = "3465"
charmsk = 8 '(= pin.3)
for charidx = 1 to 4
PORTD = charmsk ' kathode aufdrehen
E = onechar(charidx) ' ~ mid(instring, chardx, 1)
E = E AND &H0F ' Reduzieren auf 0-9
on e gosub 0,1,2,....... ' kennst du schon
shift charmsk, right, 1 ' nächste Kathode
next