Gleichzeitiges Drücken derselben Tastenreihen

Ich entwerfe eine Tastatur in VHDL. Alles funktioniert gut, wenn nur eine einzige Taste gedrückt wird. Ich scanne jede Spalte auf einen Tastendruck in einer Zustandsmaschine und wenn keine Taste gedrückt wird, wechsle pin4pin6pin7pin2 = "0000"ich in den nächsten Zustand, um die nächste Spalte zu scannen. Also setze ich die Spalten pin3pin1pin5nacheinander auf "001", "010"und "100".

Beim Scannen pin3pin1pin5wird "001"dann pin4pin6pin7pin2einfach "0100""9" gedrückt. Ich deklariere in VHDL pin4pin6pin7pin2als Eingabe- und pin3pin1pin5als Ausgabeports. Wenn ich gleichzeitig 6 und 9 drücke pin6und . Die erste gedrückte Taste wird gelesen, die zweite wird ignoriert. Wenn ich gleichzeitig 3 und 7 drücke, gewinnt der erste, der mit wenigen ms vor Gewinnen gedrückt wurde, und die erste Taste wird gelesen, die zweite Taste wird ignoriert, und sind .pin7highpin2pin4high

Hier ist der knifflige Teil. Wenn ich gleichzeitig 4 und 6 drücke, erwarte ich pin7zu sein, highaber es wird lowund pin4pin6pin7pin2 = "0000", was ich nicht verstehe, wie und warum. Da "0000"erkannt wird, dass keine Taste gedrückt wurde, springt die Zustandsmaschine von Zustand zu Zustand. Während man 4 und 6 hält, wenn man mehrmals drückt und 4 verlässt, wird es als mehrmals gedrückte 6 erkannt, was ein großer Fehler ist . Ich würde mich freuen, wenn Sie mir beim Debuggen helfen könnten!

Dasselbe passiert mit "1" und "2", dasselbe mit "7" und "8", nur für die Tasten in derselben Reihe. Da dies ein laufendes Projekt ist, kann ich meinen VHDL-Code nicht online stellen :( Ich würde mich freuen, wenn Sie mir Tipps geben könnten, um dies zu überwinden!

Geben Sie hier die Bildbeschreibung ein

Unten, ich lade meinen Code nicht auf das Board hoch, es wird kein Code ausgeführt. Beim Anschließen Pin5an Masse schaltet ein einzelnes Drücken auf 1,2,4,5,7,8,*,0 die Pin3LED nicht ein, aber wenn ich gleichzeitig 6 und dann 4 drücke, ist die Pin3LED an und die Pin7LED ist immer noch an, aber Wenn mein Code ausgeführt wird, passiert dies nicht. Vielleicht habe ich etwas falsch angeschlossen und zum Glück Pin7ist es an, ich weiß es nicht ...

Geben Sie hier die Bildbeschreibung ein

Nachfolgend finden Sie die Schaltpläne der Tastaturplatine:

Schema

Wie stellen Sie sicher, dass das gleichzeitige Drücken von 4 und 6 nicht die Pins 3 und 5 kurzschließt?
@fru1tbat Kannst du kurz etwas mehr erläutern? Ohne meinen Code hochzuladen, wenn die Platine nichts an hat, verbinde ich Pin5 mit Masse, dann ist Pin5 LED an, dann drücke ich "6" Pin7 LED ist AN später drücke ich "4" und "6" gleichzeitig diesmal Pin3 LED ist an und Pin7 LED ist immer noch AN.
@Tut meinst du, ich sollte Pull-Up für Zeilen und Pull-Up für Spalten verwenden? Ich kann die Schaltung nicht ändern. Habe auch nicht viel von deinem Kommentar verstanden :(
Um vollständiger zu sein, werde ich eine Antwort geben. Es wäre hilfreich, wenn Sie einen Schaltplan bereitstellen könnten, der Widerstände, LEDs, Spaltentreiber und alle Inverter oder Transistoren zeigt, die sich möglicherweise in der Schaltung befinden. Sind die 4 Zeilen und 3 Spalten direkt mit einem CPLD oder FPGA verbunden?
@Tut Die Tastatur ist nicht direkt mit dem FPGA verbunden, es gibt eine andere Platine dazwischen, um verschiedene Platinen mit dem FPGA zu verbinden, und ich habe die Schaltpläne hinzugefügt.
Sind auf der FPGA-Platine die 7 Signale, die der Tastatur zugeordnet sind (3 Spaltenauswahl- und 4 Zeilensignale), direkt mit den Anschlussstiften verbunden (Anschluss 2 im obigen Schema)? Wenn dies der Fall ist, befolgen Sie die Anweisungen in meiner Antwort, indem Sie Open-Drain-Logik für die Spaltenauswahlausgänge in Ihrem FPGA verwenden.
Beachten Sie auch, dass in Ihrem Schaltplan alle LEDs rückwärts verdrahtet sind. Die Anoden gehen zu den Strombegrenzungswiderständen und die Kathoden gehen zu den Signalleitungen. Die LEDs leuchten, wenn die Signalleitungen auf Low gezogen werden.
@Tut nur 3 Spalten, 4 Zeilen sind mit dem FPGA verbunden, das habe ich in meiner UCF-Datei und natürlich dem CLK.
OK danke. Ich stehe zu meiner Antwort, verwende Open-Drain-VHDL-Logik für die Spaltenauswahlausgänge.

Antworten (3)

Die kurze Antwort:

Kehre deine Logik um. Treiben Sie die Spaltenauswahlleitungen mit Open-Drain- (oder Open-Collector-) Logik, wobei die ausgewählte Spalte nach unten gezogen wird und die nicht ausgewählten Spalten floaten. Wenn Sie sich eine Zeile ansehen, wird ein Tastendruck durch eine „0“ erkannt. Nicht gedrückte Tasten werden durch eine „1“ erkannt.

Nun die Einzelheiten:

Wie EEIgenuity betont, führt das Drücken von 2 Tasten in derselben Reihe zu einem Kurzschluss zwischen den entsprechenden Spalten. Dieses (und andere Probleme mit mehreren Tastendrücken) wird normalerweise in einer Tastaturmatrix überwunden, indem eine Diode in Reihe mit jedem Schalter hinzugefügt wird.

Da das Hinzufügen von Dioden für Sie keine Option ist, müssen Sie die Ausgänge Ihrer inaktiven Spaltenauswahlen floaten, um zu vermeiden, dass Sie versuchen, sie auf die entgegengesetzte Polarität als Ihre aktive Spaltenauswahl zu treiben. Dies geschieht mit Open-Drain-Logik. Wenn Ihre Spaltenauswahl direkt an ein CPLD oder FPGA gebunden ist, sollten Sie dies in Ihrem VHDL-Code erreichen können.

Das Foto in Ihrer Frage zeigt, dass Sie in jeder Spalte und jeder Zeile einen Pullup-Widerstand haben. Die Klimmzüge an den Säulen sind unnötig, werden aber nichts schaden. Die Pull-Ups in jeder Reihe stellen einen hohen Zustand sicher, sofern sie nicht durch den Open-Drain-Treiber an den Spaltenauswahlen (durch einen geschlossenen Schalter) nach unten gezogen werden.

Ich musste einige Annahmen über Ihre Schaltung treffen, da Sie keinen vollständigen Schaltplan oder Ihren VHDL-Code bereitgestellt haben. Du sagst

wenn keine Taste gedrückt wird, das ist die Bedingung pin4pin6pin7pin2 = "0000"

Auf dem von Ihnen bereitgestellten Foto werden jedoch Pull-up-Widerstände angezeigt. Dies impliziert, dass Sie bereits irgendwo eine logische Inversion haben, möglicherweise in Ihrem VHDL-Code oder (weniger wahrscheinlich) Invertern zwischen Ihren Zeilen und Ihrem Logikgerät (CPLD oder FPGA).

Bearbeiten:

Gemäß Ihrem Kommentar verwenden Sie in Ihren Beschreibungen eine negative Logik: "0000" zeigt an, dass alle vier Pins hoch sind usw. Dies ist der Fall, vorausgesetzt, die Spaltenauswahl- und Zeilensignale gehen direkt von Anschluss 2 in Ihrem Schaltplan zum FPGA Befolgen Sie meine obigen Anweisungen, indem Sie Open-Drain-Logik für die Spaltenauswahlausgänge in Ihrem FPGA verwenden.

Ich bin kein VHDL-Experte, aber ich habe das von Xilinx gefunden :

Leiten Sie den Open-Drain-Puffer mithilfe des folgenden Codes ab:

VHDL:

daut <= 'Z' wenn din='1' sonst '0';

Beachten Sie auch, dass in Ihrem Schaltplan alle LEDs rückwärts verdrahtet sind. Die Anoden gehen zu den Strombegrenzungswiderständen und die Kathoden gehen zu den Signalleitungen. Die LEDs leuchten, wenn die Signalleitungen auf Low gezogen werden.

Ich bin dabei, die Schaltpläne zu scannen, die den Scannertreiber installieren
Sie haben recht pin4pin6pin7pin2 = "0000"damit, dass es eigentlich keinen Tastendruck gibt 1111. In meiner Frage sollten 1s 0 sein, 0s sollten 1s sein, ich habe versucht, die Frage ein wenig zu verschlüsseln, entschuldigen Sie das, wenn es zu Missverständnissen geführt hat ...
Schaltpläne habe ich hinzugefügt.
vielen Dank für Ihre Erklärungen, nachdem ich Ihre Antwort gelesen habe, habe ich einige Ideen, aber zuerst, was meinen Sie mit "Spalten schweben", "müssen die Ausgänge schweben lassen", mit Float meinen Sie: 110, 101, 011? Das mache ich bereits, eigentlich in meinem Code, wenn eine Taste gedrückt wird, sollten alle anderen Tasten ignoriert werden. Ich verstehe nur nicht, wie die LED ausgeht und Pin7 hoch wird (1), während der Code ausgeführt wird. Wie auch immer, wenn ich es richtig verstanden habe, ist Ihre Lösung, die vorschlägt, während ich Pin5 scanne, Ausgangsports "110", die ich haben sollteout <= 'pin3' when din='1' else '0';
Schauen Sie sich den Link an, den ich bereitgestellt habe: open-drain (oder open-collector) . Die aktive Spalte wird durch Treiben von 0 V auf dieser Spaltenleitung ausgewählt. Die inaktiven Spalten sollten NICHT mit 3,3 V auf dieser Leitung angesteuert werden, sondern müssen schwebend (in einen hochohmigen Zustand versetzt) ​​werden, wodurch diese Leitungen effektiv von der Schaltung getrennt werden. Wenn Sie versuchen, sie auf 3,3 V zu fahren, führt der Kurzschluss, der durch gleichzeitiges Drücken von 2 Tasten in derselben Reihe entsteht, zu einem Konflikt zwischen einem, der versucht, niedrig zu fahren, und den anderen, die versuchen, hoch zu fahren.
Was ich vorschlage, ist so etwas wie: pin3_out <= 'Z' when pin3_internal = '1' else '0'; ... Das 'Z' gibt an, dass der Ausgang schwebend (nicht angesteuert) ist, wenn Ihre interne Logik '1' ist.
pin3_internalwird wahrscheinlich ein Ausgabeport sein, und es ist nicht möglich, Ausgabeports in VHDL zu lesen. Und was ist "Z"? Ein Bitsignal? Ich verstehe diesen whenFall nicht, der normale, den ich kenne, ist wie folgt:output <= in0 WHEN "00",
Ich habe es pin3_internal genannt, damit Sie es nicht mit Ihrem Ausgangspin verwechseln, den ich pin3_output genannt habe (pin3_internal ist KEIN Ausgangspin, sondern stammt aus Ihrer internen Logik). Wie gesagt, ich bin kein VHDL-Experte. Normalerweise codiere ich in Verilog. Mein Beispiel kam von Xilinx. „Z“ ist ein gültiger Wert (hohe Impedanz) in VHDL für std_logic . Ich denke, Sie müssen möglicherweise Ihr VHDL studieren. Ich glaube nicht, dass ich es besser erklären kann.
Ich habe etwas mehr über Open Collector recherchiert, und das ist definitiv die Antwort auf mein Problem, aber ich weiß immer noch nicht, wie ich es implementieren soll. Ich verstehe jetzt auch den Code, pin3_out <= 'Z' when pin3_internal = '1' else '0';wenn er Klammern hätte, würde ich ihn schneller verstehen :) Das heißt wann Ich überprüfe , ob pin5ich schweben sollte pin3und pin1, also denke ich, ich sollte dies in derselben Zeile tun, in der ich einstelle, pin3pin1pin5 <= "110"und pin3_internalhier pin3_out <= 'Z' when pin3_internal = '1' else '0';ist keiner der Pin2, Pin7, Pin6, Pin4? Wo soll und soll ich pin3_internalarbeiten?
Nachdem ich einige Variationen ausprobiert hatte, fand ich es heraus, vielen Dank, du bist eine Legende =) Open Collector Code, den du gegeben hast, hat funktioniert!
Jetzt schreibe ich eine Dokumentation über meine Schaltung, ich sollte auch diese Lösung erwähnen, geht Pin7 direkt auf Masse, wenn Pin3 und Pin5 gleichzeitig VDD haben? Wir lösen es, indem wir Pin3 invertieren, wodurch der Spannungsfluss gestoppt wird, habe ich das richtig verstanden ? Diese Methode wird Open-Collector genannt und für Pull-up-Widerstände verwendet? Wenn es Pulldown wäre, wäre 1 in unserem Fall hoch und wir bräuchten dout <= 'Z' when din='0' else '1';, ich weiß, dass Sie viel geschrieben haben, aber würden Sie mir bitte die Lösung ein bisschen näher erläutern?

Da Sie VHDL verwenden und eine asynchrone Eingabe haben, schreibe ich diese Antwort, um sicherzustellen, dass Sie Vorsichtsmaßnahmen getroffen haben. Ich bin mir nicht sicher, ob dies Ihr Problem ist, aber es könnte sehr gut sein.

Siehe eine Frage, die ich vor einiger Zeit gestellt habe: VHDL: Empfangsmodul schlägt zufällig fehl, wenn Bits gezählt werden

Jetzt sagst du das:

Da "0000" als keine gedrückte Taste erkannt wird, springt die Zustandsmaschine von Zustand zu Zustand. Während man 4 und 6 hält, wenn man mehrmals drückt und 4 verlässt, wird es als mehrmals gedrückte 6 erkannt, was ein großer Fehler ist.

Das ist etwas ähnlich dem, was ich konfrontiert war. Ich hatte ein Problem, bei dem meine Zustandsmaschine Zustände übersprang, was unmöglich schien.

Wenn Sie die Antworten auf die oben verlinkte Frage lesen, werden Sie sehen, dass es empfehlenswert ist, einen Synchronisierer zur Eingabeleitung hinzuzufügen, bevor sie in Ihre Zustandsmaschine eingespeist wird. Dies wird normalerweise mit zwei D-Flip-Flops in Reihe erreicht:

Geben Sie hier die Bildbeschreibung ein

Wenn Ihre Tasteneingabe nicht mit Ihrer HW synchronisiert ist, treten sehr bizarre Probleme auf, die ich bei meinem N64-Projekt erlebt habe. Das Hinzufügen dieses kleinen bisschen HW war fast wie Magie.

Überprüfen Sie daher zuerst, ob Ihre Eingaben synchronisiert werden.

Den Synchronizer auf die Antwort zu implementieren scheint nicht schwierig zu sein, aber wenn ich den Prozess lese, verstehe ich, dass er async_inmit 3 Taktzyklen verzögert ist, aber sein Wert und alles ist gleich?
Der große Unterschied besteht darin, dass Ihr Signal von asynchron zu synchron konvertiert wird. Was in HW manchmal mit asynchronen Signalen (wie Ihren Tasten) passiert, ist, dass die Bits in "Meta-Stabilität" sind, was sehr seltsame Fehler in der HW verursacht. Die Verwendung der D Flip Flops stellt sicher, dass in Ihrem Design keine Metastabilität auftritt. Ich war auch skeptisch gegenüber der Wirksamkeit, aber es hat mein Problem perfekt gelöst.
Ich habe es versucht, war einen Versuch wert, hat aber nicht geholfen :(

Das ist eine interessante Frage! Der Grund, warum Pin7 niedrig ist, wenn Sie Taste4 und Taste6 drücken, liegt an Pin3 und Pin5.

Um es weiter zu erklären, werden Pin3 und Pin5 niemals gleichzeitig hoch sein - einer von ihnen wird immer ein Pfad zur Erde sein (gemäß Ihrem Design). Wenn Sie also Taste 4 und Taste 6 drücken, erstellen Sie einen Pfad zur Masse für Pin7.

Siehe Bild:

Pin 7 sieht einen Pfad zur Erde.  Du hast einen Kurzschluss.

Ich habe meiner Frage ein Bild hinzugefügt und Pin7 sieht immer noch hoch aus, wenn beide Tasten gedrückt werden.
OP erklärte, dass er Pin 3, 1 oder 5 zu keinem Zeitpunkt gleichzeitig auf HIGH hebt. Er sequenziert die Spalten mit: "001", "010" und "100". Die Pins 3 und 5 sind zunächst nie gleichzeitig HIGH.
Das ist der Punkt, den @EEIngenuity zu erreichen versucht - es gibt einen offensichtlichen Pfad zwischen den Pins 3 und 5, der niemals denselben Wert haben wird. "Wenn Sie also die Tasten 4 und 6 drücken, erstellen Sie einen Pfad zur Masse für Pin7. "
@fru1tbat Aber wie Sie auf dem Bild sehen, das ich hochgeladen habe, ist Pin7 eingeschaltet und geht nicht auf Masse? Aber nehmen wir an, es geht zu Boden, dann wird es unmöglich sein, mein Problem zu lösen?
"Während man 4 und 6 hält, wenn man mehrmals drückt und 4 verlässt, wird es als mehrmals gedrückte 6 erkannt, was ein großer Fehler ist ." Das hört sich so an, als würden Sie zwischen gültigen Tastenerkennungen keine „Keine Tasten gedrückt“ erkennen.
@Anarkie Würden Sie in Ihrem neuen Bild zufällig wissen, ob diese jeweiligen LEDs verdrahtet sind: (a) in Reihe zwischen dem Knopf und dem Goldanschluss oder (b) parallel zwischen dem Anschluss und Masse ? Da der Goldanschluss schwebt und die LEDs immer noch leuchten, scheinen diese LEDs parallel zwischen Schalter und Masse zu sitzen. Möglicherweise leuchten sie deshalb bei dieser Eingabekombination noch.
@EEIngenuity Ich habe die Schaltpläne hinzugefügt.
@Anarkie, Wie Tut in seiner Antwort erwähnte, sind die LEDs im Schaltplan absolut rückwärts gezeichnet. Aber sie sind tatsächlich parallel an den Knoten gebunden. Die Testversion „Kein Code hochgeladen“ funktioniert ordnungsgemäß. Haben Sie auf das Kurzschlussereignis getestet, das ich in meiner ursprünglichen Antwort vorgeschlagen habe? Wenn ja, wie hast du es gemacht?
Der Test, den ich für das Kurzschlussereignis durchgeführt habe, ist das gleichzeitige Drücken von 4 und 6, wie Sie auf dem Bild sehen, sonst weiß ich nicht, was Sie meinen.
@Anarkie Im Bild ist Pin3 nicht mit GND oder VDD verbunden. Es ist ein schwebender Knoten. Dies erzeugt nicht das Kurzschlussszenario, das Sie in Ihrer ursprünglichen Studie haben. Versuchen Sie Pin 3 mit VDD und Pin5 mit GND zu verbinden und wiederholen Sie diesen Test.
@EEIngenuity Du hast vollkommen Recht!!! Ja, ja, wenn ich Pin3 mit VDD verbinde, wird Pin7 niedrig!!! Also bitte helfen Sie mir, wie ich dieses Problem überwinden und zum Laufen bringen kann :( Ich verwende VHDL und auch ein anderer Kollege, der im selben Projekt in einem anderen Team ist, hat dieses Problem nicht, also hat er es irgendwie gelöst, aber ich tue es Ich weiß nicht wie, gleiche Tastatur, gleiche Platine!