Moin, brauch mal euren Rat, wie man am sinnvollsten mit sehr großer Anzahla n Ein- und Ausgängen umgeht. Um mal mit schönen Zahlen z urechnen runde ich mal auf auf 64 Taster und doppelt sovielen Treiber-Ausgängen, die jeweils einen Impuls rauswerfen sollen, wenn der zugehörige Taster den Zustand toggelt sowie noch einmal 128 LED-Ausgänge um den Zustand dauerhaft anzuzeigen. Sonderlich zeitkritisch ist das ganze nicht, bis zu 'ner Drittel Sekunde störts nicht wirklich. Wer jetzt Tastaturmatrix schreit - Nö, es sollen mehrere gleichzeitige Tastendrücke möglich sein. AFAIK geht das mit einer Matrix dann nicht mehr so ohne weiteres? Dachte jetzt an PISO-Schieberegister, die man dann einliest. Ausgabe dann über SIPO-Schieberegister. Soweit die Grundidee - aber wie setzt man das nun um? Zwischen Erfassen des Eingangstastendrucks und ausgabe sollen noch diverse Verriegegelungbedingungen abgeprüft werden, man mus also ggf. jeden Ein/Ausgang mehrfach verarbeiten. Ist es nun sinniger, jeweils das Eingangsabbild am Stück zu lesen und auc hz speichern? So als riesen bitfeld oder dergleichen? (gibt's da ein Größenlimit?). Entprellung durch Abgleich mit den letuten beiden Einlesevorgängen, auf das sich nix mehr ändert? Oder geht man da besser "Kanalorientiert" ran und speichert für jeden Taster + zugehörige Ausgänge die diversen anfallenden Daten in einer dem eigenen Variabeln/Bitfeld pro "Kanal"? Also Meinetwegen letzte 3 Eingangszustände, 2 bits für aktuellen Ausgangszustand, 2 bit für angeforderten Ausgangszustand, 2 Ausgangs-LED, 2 Treiber-Ports, 3 bit minimalst-Timer zur Treiberpulslängenbegrenzung, ggf. noch zwei Flags für blockiert durch verriegelung und blinkmodus. Welche Variante ist Vorteilhafter? Es jeweils in einer Variablen abzuhandeln oder am Stück? Kann man die manipulierte Variable in einer Schleife einfach höchzählen? Also nich 'nen Wert ++ oder += sondern die Funktion auf die nächste der 64 variablen loslassen, um nich alle 64 mal nen aufruf tippen zu müssen. Lassen sich Pointer da einfach mit ++ passend im Speicherberiech weiterschalten? schöne Grüße, Trabi
Zumindest bei so einer großen Anzahl Taster, wäre es ja schon fast praktischer eine Tastatur(PS/2) zu verwenden und das Protokoll dazu zu benutzen. Damit weißt du über die Scancodes von der Tastatur direkt was gedrückt wurde. Auch gleichzeitige Tasten sind dabei möglich. Ob A jetzt ein A irgendwo hinschreibt, oder du sonst was damit anstellst, entscheidest du ja beim programmieren.
Teletrabi wrote: > Wer jetzt Tastaturmatrix schreit - Nö, es sollen mehrere gleichzeitige > Tastendrücke möglich sein. AFAIK geht das mit einer Matrix dann nicht > mehr so ohne weiteres? Na klar.
Hmm, wie macht man das bei 'ner Matrixanordnung und mehreren zugleich gedrückten Tasten? Tastatur - scheidet aus, die Taster sollen in bestimmter Form auf einem Schaltpult angeordnet werden. Geht also nicht nur um möglichst viele Tasten sondern schnelle Zuordnung zur gewünschten Funktion. Gruß, Trabi
64 Tasten, das sind 8 mal 74HC165 + Pullups 8*4,7k, fertsch. Für je 8 Ausgänge dann 74HC595 oder mit mehr Power TPIC6B595. Peter
>64 Tasten, das sind 8 mal 74HC165 + Pullups 8*4,7k, fertsch.
Warum nicht 1x74HC595, 1x74HC165 und 8xPullUp...?
Eine Matrix kann doch mehrere Tasten zugleich erkennen..
Matrix. Scannen musste die sowieso. Und wenn mehrere Tasten auftreten kann man das auch sauber erkennen. Ev. zum Rechenleistung sparen nen kbhit() (oder per ISR) realisieren, wo ein freier ausgang des select chips (z.B. 3->8) gleichzeitig (Dioden-ODER) alle selects auf HIGH legt. Danach dann per ScanMatrix() die Matrix auslesen. Der User wird die Taste schon lange genug festhalten (vom uC aus gesehen...) :-) VG, /th.
Matthias Lipinsky wrote: > Warum nicht 1x74HC595, 1x74HC165 und 8xPullUp...? > > Eine Matrix kann doch mehrere Tasten zugleich erkennen.. Dann hast Du aber noch die 64 Dioden vergessen. Das sind dann 67 Bauteile anstelle nur 16 Bauteile bei meinem Vorschlag. Aber auch, wenn Du nur 2 Tasten gleichzeitig erkennen willst, brauchst Du noch 8 Dioden, sonst kämpfen die 74HC595-Ausgänge gegeneinander. Peter
lippy schrieb
>Eine Matrix kann doch mehrere Tasten zugleich erkennen.
Aber ohne Dioden nicht beliebig.
Skua wrote:
> Matrix mit Dioden entkoppeln.
Dioden sind unnötig, wenn man die Zeilentreiber-Pins, die nacheinander
low werden, nicht allesamt gleichzeitig auf Output programmiert, sondern
wenn man immer nur den Pin auf Ausgang programmiert, den man gerade
low-setzen möchte; die anderen bleiben Inputs, aber mit int. Pullup. So
gibt es keine gegenseitigen Kurzschlüsse beim gleichzeitigen Drücken
mehrerer Tasten, und man kann dennoch gleichzeitiges Drücken einwandfrei
auswerten.
Natürlich: die Software ist etwas aufwendiger.
Günter R. wrote:
> Dioden sind unnötig
Quatsch.
Nimm ne 2*2 Matrix und dann drücke 3 Tasten.
Ohne Dioden kannst Du nicht erkennen, welches die nicht gedrückte Taste
ist.
Peter
>Matrix. >Scannen musste die sowieso. Bloß keine Matrix :-) Das Abklappern der Matrix benötigt unnötig viel Zeit. Mit Schieberegistern und dem SPI (USI) Interface eines AVR werden Ausgaben und Eingaben schnell erledigt. Vorteilhaft ist zudem, daß die I/O-Leitungen dezentral verlegt werden können; die Schieberegister werden entsprechend angeordnet. Ausgaben erfolgen nur, wenn sich der Zustand einer LED geändert hat. Entprellen muß Du permanent (10-30ms Intervalle). Jede Änderung eines Tasters würde ich als Wert mit Tastennummer und Zustand in ein FIFO schreiben, welches dann im Hauptprogramm ausgelesen wird und entsprechende Reaktionen auslöst. Um ein EMV-leises System zu bekommen, kann man den Tastern noch XOR-Gatter spendieren, die - kaskadiert - jede Zustandsänderung an den µC melden und erst dann eine Abfrage der Schieberegister veranlassen (z.B. CMOS 4531).
Seit wann braucht man bei einer Tastenmatrix denn Dioden? Ich bin mir ziemlich sicher, dass meine Tastatur nach ziemlich genau dem gleichen Prinzip funktioniert :P Einfach (wie schon gesagt) jede Zeile nacheinander abscannen und die Eingänge einlesen. EDIT: Ich glaube nicht, dass die Schieberegister Variante zeitlich irgendeinen Vorteil gegenüber der Scan Variante hat. Eher andersherum würde ich jetzt behaupten.
> Bloß keine Matrix :-) Das Abklappern der Matrix benötigt unnötig viel Zeit.
Dummfug!
Daher die kbhit - schaltung.
Habe das selber mal auf nem M16C gemacht, wo ich massig Rechenleistung
für was anderes brauchte.
VG,
/th.
> Seit wann braucht man bei einer Tastenmatrix denn Dioden?
Was kommt denn heraus, wenn Scanline A aktiv ist?
1 | o +5V |
2 | | |
3 | .-. |
4 | | | |
5 | | | |
6 | '-' |
7 | | |
8 | o----o---------o-------------. |
9 | | | |
10 | o +5V o o |
11 | | | | |
12 | .-. S1 | S3 | |
13 | | | o o |
14 | | | | | |
15 | '-' '--. '--. |
16 | | | | |
17 | o----o---------o--)----------. | |
18 | | | | | |
19 | \ o | o | |
20 | \ | | | |
21 | S2\ | S4 | | |
22 | o | o | |
23 | | | | | |
24 | '--o '--o |
25 | | | |
26 | | | |
27 | | | |
28 | o o |
29 | | | |
30 | |/ |/ |
31 | -| A -| B |
32 | |> |> |
33 | | | |
34 | | | |
35 | --- --- |
Kannst du erkennen, ob S2 betätigt ist?
Mit Dioden geht das:
1 | o +5V |
2 | | |
3 | .-. |
4 | | | |
5 | | | |
6 | '-' |
7 | | |
8 | o----o---------o---------------. |
9 | | | |
10 | o +5V o o |
11 | | | | |
12 | .-. S1 | S3 | |
13 | | | o o |
14 | | | | | |
15 | '-' '->|-. '->|-. |
16 | | | | |
17 | o----o---------o----)----------. | |
18 | | | | | |
19 | \ o | o | |
20 | \ | | | |
21 | S2\ | S4 | | |
22 | o | o | |
23 | | | | | |
24 | '->|-o '->|-o |
25 | | | |
26 | | | |
27 | | | |
28 | o o |
29 | | | |
30 | |/ |/ |
31 | -| A -| B |
32 | |> |> |
33 | | | |
34 | | | |
35 | --- --- |
Die Diode an S3 sperrt den Pfad über S4 --> es wird korrekt erkannt, dass S2 nicht betätigt ist.
Peter Dannegger wrote: > Günter R. wrote: > >> Dioden sind unnötig > > Quatsch. > > Nimm ne 2*2 Matrix und dann drücke 3 Tasten. > Ohne Dioden kannst Du nicht erkennen, welches die nicht gedrückte Taste > ist. > > > Peter Da hast Du recht. Ich muß etwas zurückrudern: bei meiner Methode können bis zu 2 gleichzeitig gedrückte Tasten erkannt werden; mehr gleichzeitige Tastendrucke führen zu Fehlerkennung.
Lothar Miller wrote: >> Seit wann braucht man bei einer Tastenmatrix denn Dioden? > Was kommt denn heraus, wenn Scanline A aktiv ist? Hm, ich könnte schwören ich hab das mal irgendwo ohne Dioden gesehen, finde es aber gerade nicht wieder. Na gut, gebe ich mich erst mal geschlagen. Wenn das schon so viele hier behaupten, ziehe ich lieber den Kürzeren ;)
> Hm, ich könnte schwören ich hab das mal irgendwo ohne Dioden gesehen, > finde es aber gerade nicht wieder. Ich verwende so eine Matrix auch ohne Dioden. Allerdings lasse ich nur 1 Tastendruck zu. Werden mehrere Tasten gleichzeitig betätigt (mehrere Return-Lines sind low) dann wird dieser Zustand solange ignoriert, bis nur noch 1 Taste aktiv ist.
Lothar Miller wrote: > Ich verwende so eine Matrix auch ohne Dioden. Allerdings lasse ich nur 1 > Tastendruck zu. Werden mehrere Tasten gleichzeitig betätigt (mehrere > Return-Lines sind low) dann wird dieser Zustand solange ignoriert, bis > nur noch 1 Taste aktiv ist. Genau so mache ich es auch, vorzugsweise mit fertigen Folientastaturen von Hoffmann & Krippner (für Labor-Modelle). Dort gibt es keine Dioden.
Mahlzeit, hab noch einen Vorschlag. Man könnte das Problem mit EINEM IC (MAX6954-55)erschlagen. Ist nicht ganz billig, aber das Ding steuert bis zu 128 LEDs und 32 Taster an. Mit nem kleinen Trick gehen auch 64 Taster. Die Ansteuerung geht entweder über SPI(MAX6954) oder I2C (MAX6955). (Gibt es bei DigiKey) Gruss Uwe
>Habe das selber mal auf nem M16C gemacht, wo ich massig Rechenleistung >für was anderes brauchte. Hut ab, Du scheinst ja ein Profi zu sein. Hast Du in Deiner Matrix auch Schalter abgefragt? Und wie ist Dein Lösungsvorschlag für die vielen, vielen LEDs und die vielen, vielen Treiberausgänge? Gibt es dafür auch eine Matrix?
Wie auch immer: ich nehm dafür ein CPLD und mach da einen SPI-Slave rein. Schwuppdiwupp, fertig sind 64 Aus- und Eingänge mit einem billigen XC95144 von Xilinx (für 6,60 Euro bei Angelika). Oder wenns nicht unbedingt 5V resistent sein muß: X2C-Familie oder MachXO-FPGAs (aber das ist dann schon eine andere Liga).
Lothar Miller wrote: > Wie auch immer: ich nehm dafür ein CPLD und mach da einen SPI-Slave > rein. Schwuppdiwupp, fertig sind 64 Aus- und Eingänge mit einem billigen > XC95144 von Xilinx (für 6,60 Euro bei Angelika). Was, so teuer? Je 8* 74HC165 und 74HC595 gibts bei Angelika für nur 3,12€. Peter
>>Was, so teuer? >Je 8* 74HC165 und 74HC595 gibts bei Angelika für nur 3,12€. Und da ist die Programmierung als SPI-Slave schon dabei ;-)
>und mach da einen SPI-Slave rein.
Und was kostet der bei Angelika?
Lothar Miller wrote:
>> XC95144 von Xilinx (für 6,60 Euro bei Angelika).
Ich sehe grad im Datenblatt, der frißt ja im low power mode stolze
160mA.
Damit gewinnst Du aber keinen Umweltpreis.
Peter
Wieso verwendest Du nich einfach I2C-Bus I/O Expander, z.B. der weiter oben bereits erwähnte PCF8575 (16 IOs pro Chip) Ich bin mir sicher, das ist in diesem Fall die beste und einfachste Lösung...
> Damit gewinnst Du aber keinen Umweltpreis. Das war nie meine Absicht ;-) Natürlich ist dieses CPLD ein uralter Zombie, andere könnnen das besser. Mir gings um die Richtung: 1 IC mit wenig Layoutfläche und vielen Pins. > Und was kostet der bei Angelika? Den gibts da nicht, da mußt du wonaders suchen :-/
>oben bereits erwähnte PCF8575 (16 IOs pro Chip)
Davon sind max. acht Stück an einem IIC-Bus adressierbar. Ich fürchte
nur, das reicht nicht aus.
Gasst wrote: >>oben bereits erwähnte PCF8575 (16 IOs pro Chip) > > Davon sind max. acht Stück an einem IIC-Bus adressierbar. Ich fürchte > nur, das reicht nicht aus. Und außerdem kommt man preislich doppelt so hoch aus, als würde man einfache Schieberegister verwenden. Die Schieberegister kann man übrigens kaskadieren, das ist im Prinzip noch besser als 8 einzelne Chips an nem I2C Bus anzubinden.
Peter Dannegger wrote: >>> XC95144 von Xilinx (für 6,60 Euro bei Angelika). > Ich sehe grad im Datenblatt, der frißt ja im low power mode stolze 160mA. Der XC95144XL begnügt sich schon mal mit 45mA bei 1MHz ... ... und könnte notfalls bis über 150MHz Taktfrequenz ;-)
Moin, schönen Dank schonaml für eure Vorschläge. Mal gucken, ob ich mir die Arbeit mit dem Dioden löten machen will. ich tendiere eher zu den Schieberegistern, als SMD aufgelötet, andere Seite aös GND und sich schonmal nen haufen bohrungen sparen mittels Flachbandkabel-Platinensteckverbinder und dann je zwei Adern zum Schalter geführt. Ist glaub ich insgesamt der wenigste Hardware-Aufwand. Noch interessanter ist für mich eher die Softwareseite. Bislang favorisiere ich da, jeweils ein Eingangs- und Ausgangsabbild zu erstellen und mit entsprechenden Verarbeitugnsfunktionen die Verbindung dazwichen herzustellen. Hat den Vorteil, ich kann ohne den weiteren Ablauf zu stören einfach eine fragliche Verarbeitung auskommentieren und muss nich nach jedem gelesenen Eingangsbit schon wissen, was ich damit mach bzw. im Probiermodus jedesmal in den Eingangslese und Ausgangschreibfunktionen rumeditieren. Nur - wie parkt man die 64 bzw 2x128 bit am sinnigsten? Als eine Bitfeld-Structure? Geht das mit solch großer Anzahl? Oder als ein Array? Oder nützt mir Union hier was? Zum Bitfeld-Ansatz - ich befürchte mal, der unten angehängte Code wird so nicht laufen, weil einmal die Referenzierung innerhlab der Structure ".1", ".2" usw. ein Art Name ist, während Bitplatz eine Int-Zahl darstellt und damit vermutlich nicht geeignet um per structure.bitzahl drauf zuzugreifen? Gibts eine Möglichkeit in einer Schleife im Bitfeld entlangzulaufen oder muss man da bis zu 128 den Befehl mit dem passenden Bitplatz innerhalb der Structure aufrufen? Lässt sich so ein Bitfeldinhalt vielleicht mittels Shift / Rotate-Befehl verschieben? Soweit ich das überschaue sind Pointer ja unzulässig? Oder nur nicht offiziell unterstützt aber doch möglich? Liegt denn der Speicherbereich überhaut nebeneinander oder landet man dann irgednwo, abe rnur nich im zweiten Structure-Byte, wenn man den Zeiger erhöhen würde? Anderer Ansatz - Array. Hier ist ja ein entlanglaufen halbwegs problemlos möglich. Gibts denn ein Bit-Array? Oder belegt er wie ich vermute gleich ein Byte pro gewünschtem Bit? (okay, notfalls kann man ein Byte ja noch als Bitfeld missbrauchen, wird nur recht unübersichtlich) Wie krieg ich nun am besten bis zu 128 bit leicht ansprechbar für vergleiche und leicht per schleife abarbeitbar umgesetzt? schönen Dank im vorraus, Trabi #define inputanzahl = 16 #define inp_clk = PB7 #define inp_date = PB6 #define inp_load = PB5 struct { unsigned char 1:1; // je ein bit unsigned char 2:1; // [...] unsigned char 15:1; unsigned char 16:1; } inp; // Function prototypes [...] int read_inp () { //Port initialisieren: // [....] // PISO-Register laden: // [...] // Daten in Eingangs-Bitfeld übernehmen: for (int bitplatz = 0; bitplatz <inputanzahl; ) { set_PORTB_bit (1<<inp_clk); set_PORTB_bit (0<<inp_clk); inp.bitplatz = (PINB & (1<<inp_data)); bitplatz++; } return 1; }
Hallo, also wenns preiswert sein soll könnte die Matrix mit Dioden die Lösung sein, andererseits ist das hier ein Microcomputer-Forum, das schreit doch irgendwie nach einer eleganten Lösung wie - M8 als Slave mit jeweils 8 Leds und 8 Tastern - I2C-Bus zur Verbundung zum Master - Master z.B. M32 je nach Applikation auch kleiner Gruß, Michael P.S.: bitte das Entprellen nicht vergessen !!!
Teletrabi wrote: > Noch interessanter ist für mich eher die Softwareseite. Bislang > favorisiere ich da, jeweils ein Eingangs- und Ausgangsabbild zu > erstellen und mit entsprechenden Verarbeitugnsfunktionen die Verbindung > dazwichen herzustellen. Ja, so mache ich das auch. Das SPI schaufelt Bytes in und aus dem SRAM. Damit das gut lesbar ist, vergebe ich den Bits Namen. Dazu benutze ich das Macro RBIT (siehe Anhang):
1 | #include "sbit.h" |
2 | |
3 | /****************************** Inputs *********************************/
|
4 | |
5 | #define PLC_REM RBIT( input_ram[0], 0)
|
6 | #define PLC_CONNECT RBIT( input_ram[0], 1)
|
7 | #define HFC_HFON RBIT( input_ram[0], 2)
|
8 | #define PLC_DBM RBIT( input_ram[0], 3)
|
9 | #define STC_REQ RBIT( input_ram[0], 4)
|
10 | #define HFC_PWR RBIT( input_ram[0], 6)
|
11 | #define PLC_PWR RBIT( input_ram[0], 7)
|
12 | |
13 | #define MCU_ACK RBIT( input_ram[1], 4) // MCU ready
|
14 | #define TARGET RBIT( input_ram[1], 3)
|
15 | |
16 | /****************************** Outputs *********************************/
|
17 | |
18 | #define MCU_REQ RBIT( output_ram[0], 7) // MCU request
|
19 | #define MCU_X0V RBIT( output_ram[0], 6)
|
20 | #define STC_ACK RBIT( output_ram[0], 4)
|
21 | #define STC_X0V RBIT( output_ram[0], 5)
|
22 | #define HFC_ST0 RBIT( output_ram[0], 0)
|
23 | #define HFC_ST1 RBIT( output_ram[0], 1)
|
24 | #define HFC_REM RBIT( output_ram[0], 2)
|
25 | |
26 | #define REL_HFC RBIT( output_ram[1], 0) // HFC on (PLC or HFC)
|
27 | #define REL_STC RBIT( output_ram[1], 2) // STC on
|
28 | #define REL_SHC RBIT( output_ram[1], 3) // SHC on
|
29 | #define REL_SHCO RBIT( output_ram[1], 1) // SHC off
|
30 | #define REL_SIMS RBIT( output_ram[1], 4) // Display voltage off
|
31 | |
32 | |
33 | /********************** State machines **********************************/
|
34 | |
35 | |
36 | void stc_actions( void ) |
37 | {
|
38 | LED_STC = 0; |
39 | MCU_REQ = 0; |
40 | STC_ACK = 0; |
41 | STC_X0V = 0; |
42 | MCU_X0V = 0; |
43 | |
44 | if( STC_REQ || MCU_ACK || ! TARGET ){ |
45 | LED_STC = 1; |
46 | LED_SHC = 0; // SHC off |
47 | }
|
48 | |
49 | if( STC_REQ ){ // STC -> MCU |
50 | MCU_REQ = 1; |
51 | if( MCU_ACK && REL_STC ){ |
52 | STC_ACK = 1; // ACK = MCU ready |
53 | }
|
54 | }
|
55 | if( TARGET ){ // if Target = +24V |
56 | STC_X0V = 1; |
57 | MCU_X0V = 1; |
58 | }
|
59 | }
|
Peter
Beitrag #5878632 wurde vom Autor gelöscht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.