8-Bit-Breadboard-Computer auf Basis einer 6502-CPU - 3-fach 7-Segment-Anzeige als dezimale Ausgabe

Bisherige Artikel dieser Serie - hier könnt ihr nochmal alle Grundlagen nachlesen, falls ihr jetzt erst einsteigt: Unser einziges Ausgabegerät für unserer Breadboard-Computer sind bisher 8 LEDs (Artikel dazu siehe Links oben).

Das ist zwar gut und schön für Lauflicht-Effekte, aber wenn wir etwa eine Zahl darauf ausgeben wollen, dann müssten dem Menschen vor dem Computer abverlange, binär zu rechnen.

Schöner wäre doch eine dreistellige 7-Segment-Anzeige, die direkt die Zahl anzeigt, in dezimal natürlich. Da ein Datenbyte Zahlen von 0 bis 255 darstellen kann, wollen wir uns mit 3 Ziffern begnügen. Für ein Byte sind diese 3 Ziffern ausreichend.

Sieben-Segment-Anzeigen

Auch wenn ich in dem Artikel Eine 7-Segment Anzeige mit dem Raspberry Pi ansteuern die 7-Segment-Anzeigen schon ausführlich besprochen hatte, noch einmal kurz zusammengefasst: In jeder 7-Segment-Anzeige sind 8 LEDs, 7 für die Balken und eine für den Dezimalpunkt. Eine 7-Segment-Anzeige hat 10 Pins, 5 oben und 5 oben, die jeweils in der Mitte sind entweder gemeinsame Kathode (Minuspol, kommt an Ground) oder gemeinsame Anode (Pluspol, kommt an +5V.

Die übrigen 8 Verbindungen gehen zu den LEDs und brauchen Vorwiderstände. Jede 7-Segment-Anzeige benötigt also 8 Vorwiderstände, ein guter Wert wird 220 Ohm sein, aber das ist abhängig von Durchlass-Spannung und max. zulässiger Stromaufnahme und wie hell man die LEDs leuchten sehen möchte. Hier ein Vorwiderstandsrechner, der euch die Rechnerei abnimmt:



Hat man eine gemeinsame Kathode, dann bewirkt ein High vor dem Widerstand zu einer LED, dass diese leuchtet (Low = LED aus). Hat man eine gemeinsame Anode ist es umgekehrt, ein High vor dem Widerstand zu einer LED bewirkt, dass diese aus ist (Low = LED an). Praktischer ist also die Version mit der gemeinsamen Kathode (meist das A-Modell) im Gegensatz zum B-Modell, dem mit der gemeinsamen Anode. Aber da wir unsere Muster selbst definieren und dann im EEPROM-Speicher ablegen müssen, ist es eigentlich egal, welche Varainte wir nehmen bzw. ob wir einzelne Balken unserer Anzeige an- (A) oder ausschalten (B). Der Speicher für das B-Modell ist immer das Komplement des A-Modell, sprich alle Bits sind invertiert (Operation: XOR 0xFF).

Ich habe mal günstig einen Zehnerpack des Modells 5611-BS (also gemeinsame Anode) erstanden, die ich hierfür verwenden will. Hier die interne Beschaltung:



Was man ausdrücklich nicht tun soll - ich jetzt aber dennoch tue, weil ich noch genug Ersatz habe - ist, nur einen Widerstand an den gemeinsamen Pol zu setzen (sei es Anode oder Kathode).

Sind dann nämlich mehr als eine LED an, dann läuft der Strom nicht nur durch eine LED und Widerstand, sondern durch etwa 2 LEDs und einen Widerstand, denn die LEDs sind ja parallel geschaltet. Die LEDs haben natürlich selbst auch einen (Innen-) Widerstand von ca. 100 Ohm.

Wir haben es also bei zwei eingeschaltenen LEDs mit Parallelschaltung von Widerständen bei den 2 LEDs (bpsw. zu je 150 Ohm) zu tun, die dann mit dem Vorwiderstand (bpsw. zu je 220 Ohm) in Reihe geschaltet sind. Dadurch ändern sich die Widerstände für die einzelne LED und damit die Strombegrenzung und ist nicht mehr die anvisisierten 220 Ohm, sondern:

Für Reihenschaltungen gilt: Rges = R1 + R2 + R3 ...

Für Parallelschaltungen gilt: 1/Rges = 1/R1 + 1/R2 + 1/R3 ... 1 LED: 220 Ω + 150 Ω, das bei 5V: I = U / R = 5V / 370 Ω = 13.51 mA / 1 = 13.51 mA 2 LED: 220 Ω + 1/ (1/150 Ω + 1/150 Ω) = 5V / (220 Ω + 75 Ω) = 5V / 295& Omega; = 16.95 mA / 2 = 8.47 mA 3 LED: 220 Ω + 1/ (1/150 Ω * 3) = 5V / (220 Ω + 50 Ω) = 5V / 270 Ω = 18.5 mA / 3 = 6.17 mA ... 8 LED: 220 Ω + 1/ (1/150 Ω * 8) = 5V / (220 Ω + 18.75 Ω) = 5V / 238.75 Ω = 20.94 mA / 8 = 2.62 mA
Ich habe spaßeshalber mal bei meiner 7-Segment-Anzeige und 220 Ohm Vorwiderstand mit dem Multimeter nachgemessen: LEDs gesamt mA 1 LED mA ges. mA / Anzahl 1 13.42 13.41 13.42 2 13.77 6.43 6.89 3 13.94 4.34 4.65 4 14.04 3.31 3.51 5 14.12 2.68 2.82 6 14.18 2.25 2.36 7 14.21 1.94 2.03 8 14.24 1.72 1.78 Stimmt zwar nicht 100%ig überein, aber die Richtung kommt schon hin: Je mehr LEDs in der Anzeige an sind, desto weniger bekommt jede einzelne ab und alle leuchten weniger stark. Und wenn alle LEDs an sind, dann leuchtet jede nur noch schwach. Das hat zur Folge, dass eine 8, bei der 7 Segmente an sind, dunkel und kaum lesbar ist und eine 1 mit nur 2 Segmente wesentlich heller ist.

Den LEDs in der 7-Segment-Anzeige sollte das nicht viel ausmachen, denn die ca. 20 mA Maximalstrom pro Segment werden nie überschritten, sondern nur geringer, je mehr Segment an sind. Es sieht halt nicht gut aus.

Aber da ich nur auf diese Weise die Anzeige auf einem einzigen Breadboard unterbringen kann - ansonsten müsste ich zwei benutzen, mache ich das ausnahmsweise mal so.

Ansteuerung der drei Anzeigen

Dass 8 Leitungen für die 7-Segment-Anzeigen ausreichen, kommt uns natürlich sehr entgegen. Denn 8 Leitungen bzw. High/Low-Zustände haben wir im Datenbyte, dass wir mit dem STA-OpCode beliebig setzen können, wir wie es schon bei unserer LED-Ausgabe (vollständiger Artikel siehe Linkliste oben) gemacht habe. Hier müssen wir dann nur jeweils das richtige Muster anzeigen, also die richtige Balken einschalten (bzw. ausschalten beim B-Modell).

Wieder brauchen wir für jedes Gerät, also jede 7-Segment-Anzeige eine eigene Geräteadresse. Natürlich sollen diese auch oberhalb der 0x7000 liegen. Das können wir schon einmal leicht sicherstellen, haben wir doch schon eine Logik für 0x7*** für unsere LED-Ausgabe.

Nun erweitern wir die Logik ein wenig um die Adressleitung A0, A1 und A2:



Ganz oben hatten wir ja schon das invertierte A12 bis A14 High-Signal vor dem letzten NAND-Gatter abgegriffen, um CK unseres 74HC374-D-Latch für unsere LED-Ausgabe zu triggern.

Nun benutzen wir die komplette alte Logik, die ja bereits aussagt: "A14 und A13 und A12" (also alles zwischen Adresse 0x7000 und 0x7FFFF und genaugenommen auch 0xF000 und 0xFFFF, da wir A15 nicht überprüfen), also inklusive des leztes NAND-Gatters, das als NOT fungiert, und ergänzen: A0 hat ja die Wertigkeit von 1, A1 von 2 und A2 von 4. Mit der Adresse 0x7003 würden wir dann A0 und A1 auf High schalten und das linke und mittlere Segment triggern, darum lassen wir diese Adresse aus und benutzen 0x7004 mit einer eigenen Adressleitung. Für das nächste IO-Gerät würden wir dann 0x7008 vergeben, um den bereits vorhandenen Geräten nicht in die Quere zu kommen. Nur unsere LED-Ausgabe bekommt mit 0x7000 immer alles ab und dient uns sozusagen als Debug-Anzeige für die D-Latches.

Auch hier können wir wieder wunderbar NAND-Gatter des Types 74HC00 einsetzen. Wir brauchen ja ein AND gefolgt von einem NOT, weil wir ein Low an der CK-Leitung der 74HC374 haben wollen, wenn die Adresse aktiv (also high ist).



So reicht uns ein weiterer 74HC00-NAND-Chip für die Realisierung der neuen 3 Adressleitungen für unsere 3 7-Segment-Anzeigen. Wir verbinden die Ausgänge der drei Gatter jeweils mit dem CK der 74HC374, die unsere 7-Segment-Anzeigen steuern werden.



Die drei 74HC374 für die 7-Segment-Anzeigen kommen auf ein neues Breadboard. Außerdem schließen wir noch den Datenbus an, indem wir ihn vom Sniffer-Board links verlängern.

Damit die Leitungen von dem rechten 74HC165 des Sniffers nicht die Mitte kreuzen müssen, drehe ich die 74HC374-ICs um, also mit der Kerbe nach rechts. Das macht die Verkabelung einfacher und kürzer.

Irgendwas stimmt nicht

Ich hatte auch schon die drei 7-Segment-Anzeigen an die Q-Ausgänge der 374er angeschlossen, doch da zeigte sich ein sehr seltsames Verhalten: Ich hatte bestimmt was falsch verdrahtet. Darum habe ich erst einmal alles mit dem Durchsgangsprüfer meines Multimeters durchgemeseen. Da konnte ich keinen Verkabelungsfehler finden.

Also habe ich beschlossen, der Sache Schritt für Schritt auf den Grund zu gehen und erst einmal zu dem Zustand, bei dem der Datenbus verkabelt ist, zurückzugehen. Mit dem Oszilloskop würde ich der Sache schrittweise auf den Grund gehen.

Debuggen der Schaltung mit dem Oszilloskop

Zuerst habe ich natürlich einmal die drei Adressleitungen getestet, ob die auch richtig takten, falls die entsprechende Adresse angesprochen wird. Dazu habe ich mir auf die Programmbänke 1 bis 3 je ein weiteres kleines Test-Programm gelegt, um die einzelnen Adresse zu testen, so dass sich ergibt: Als Beispiel das Programm für das linke Segment. Das Programm für das mittlere und rechte Segment sind genauso aufgebaut, benutzen nur eine andere Adresse. ; 3-fach Sieben-Segment-Anzeige Testprogramm ; last edit: OK, 2020-06-21 org $8000 ; Programmstartadresse (von der CPU aus gesehen) ; --- Konstanten: IO-Adressen --- LED: equ $7000 ; 8-LED-Ausgabe, hört aber auf alles von $7000 bis $7fff SEGL: equ $7001 ; linke 7-Segment-Anzeige SEGM: equ $7002 ; mittlere 7-Segment-Anzeige SEGR: equ $7004 ; rechte 7-Segment-Anzeige start: lda #$01 ; rechts anfangen sta SEGL scroll: lda #$07 ; 7x nach links left: rol SEGL dec A bne left jmp start; wieder von vorne Die Adressleitungen und die Taktung der 374er funktioniert wie gedacht: Der LED-Ausgabe-374er hat immer einen Takt an CK, die Segment-Anzeige-374er nur, wenn sie angesprochen werden. Und wenn Programm 0 läuft liegt an keinen der Segment-Anzeige-374er ein Takt an. Da dürfte sich also nirgends etwas an den Q-Ausgabe-Pins ändern, weil CK immer auf high bleibt.

Aber: Der mittlere 374er ändert seine Q-Ausgänge, obwohl er keinen CK-Takt hat. Wie ist das möglich? Ohne Takt an CK kann sich doch die Ausgabe nicht ändern!

Strahlt da irgendetwas ein? Mir fällt auf, dass nur beim mittleren Chip ein paar Datenleitungen nahe der Pins verlaufen, was bei den anderen Chip nicht der Fall ist. Also versetze ich die entsprechenden Datenleitungen weiter nach außen und teste erneut... Das war es leider nicht.

Ist etwa der mittlere Chip kaputt? Die beiden anderen Chips verhalten sich ja wie gewollt. Ich setze den linken Chip in die Mitte und nehme auch den rechten raus, so dass nur noch die Mitte besetzt ist - mit einem Chip, der 100%ig funktioniert (war ja vorher der linke und der ging). Ich teste erneut... das selbe Verhalten. Wieder ändern sich die Q-Pins, obowhl CK nicht getaktet wird. Was ist hier nur los?

Also messe ich mit dem Durchgangsprüfer meines Multimeters noch einmal die Datenanschlüsse nach... Auch alles, wie es sein soll.

Ein Kurzschluss oder Fehler im Breadboard? Sehr unwahrscheinlich bis unmöglich, aber auch das messe ich nach. Und auch hier: kein Fehler.

Mir gehen die möglichen Fehlerursachen aus... An was zum Teufel kann das nur liegen? So langsam bin ich mit meinem Latein am Ende.

Wenn ihr eine Idee habt, was es noch sein könnte, dann schreibt mir eine e-mail oder einen Kommentar unter das folgende Youtube-Video, dass meine Tests noch einmal dokumentiert. Was habe ich vergessen? Was habe ich übersehen? Wo liegt der Fehler?



Im nächsten Teil der Reihe entdecke ich einen Abfall der Flanke von 20 Nanosekunden auf Low, der die Ursache für das Takten der 374er ist.