Hallo,
ich möchte mit einer Folinetastatur (3x4) (1-0,*,#) einen Code eingeben.
Dazu möchte ich zunächst die angegebene Zahl erkennen und ausgeben
lassen.
if ( PINC & (1<<PINC3) ) usart_transmit_string("1 ");
13
if ( PINC & (1<<PINC4) ) usart_transmit_string("4 ");
14
if ( PINC & (1<<PINC5) ) usart_transmit_string("7 ");
15
if ( PIND & (1<<PIND4) ) usart_transmit_string("* ");
16
PORTC &= ~(1 << DDC0); // column 1 low
17
PORTC |= (1 << DDC1); // column 2 high
18
if ( PINC & (1<<PINC3) ) usart_transmit_string("2 ");
19
if ( PINC & (1<<PINC4) ) usart_transmit_string("5 ");
20
if ( PINC & (1<<PINC5) ) usart_transmit_string("8 ");
21
if ( PIND & (1<<PIND4) ) usart_transmit_string("0 ");
22
PORTC &= ~(1 << DDC1); // column 2 low
23
PORTC |= (1 << DDC2); // column 3 high
24
if ( PINC & (1<<PINC3) ) usart_transmit_string("3 ");
25
if ( PINC & (1<<PINC4) ) usart_transmit_string("6 ");
26
if ( PINC & (1<<PINC5) ) usart_transmit_string("9 ");
27
if ( PIND & (1<<PIND4) ) usart_transmit_string("# ");
28
}
Doch leider kommt permanent eine Ausgabe, obwohl ich gar nichts drücke.
hauptsächlich kommt die #-Taste. Aber auch 1, 2, 3, 0, * kommen sehr
häufig vor (alle anderen Zahlen tauchen auch ab und zu auf).
Ich habe die Tastatur durchgemessen, ob vielleicht eine taste dauerhaft
gedrückt ist, konnte aber niergendwo eine durchkontaktierung messen.
Kann das auch an der Software liegen?
Franz
Das sieht mir sehr nach offenen Eingängen aus. Sorgst du dafür, daß die
Eingänge einen definierten Pegel sehen? Zum Beispiel mit Pullup's?
Wenn nicht, floaten die Eingänge und du bekommst ein Zufallsmuster.
Peter II schrieb:> wo ist das column 3 low?
PORTC &= ~((1 << DDC0) | (1 << DDC1) | (1 << DDC2)); // all low
hier werden wieder alle auf low gesetzt. Aber wenn ich es hinter dem
Block machen würde, wäre es bestimmt übersichtlicher.
Tobias schrieb:> Sorgst du dafür, daß die> Eingänge einen definierten Pegel sehen? Zum Beispiel mit Pullup's?
Ich habe die Ausgänge/Eingänge der Tastatur direkt am Mikrocontroller
gesetzt (Atmega328p). Dieser hat mein ich intern pullups.
Anders müsste ich die Signale von den Reihen (DC3, DC4, DC5, DD4) auf
einen Transistor legen, welcher dann durchschaltet und die
Versorgungsspannung durchlässt oder?
> DDRC &= ~(1 << DDD4); // input
Da wolltest du sicher DDRD schreiben.
Dein Programm erfordert Pull-Down Widerstände an allen Eingängen. Sind
die vorhanden?
> Dieser hat mein ich intern pullups.
Nur, wenn du sie auch aktivierst. Hast du aber nicht. Abgesehen davon
würde die Pull-Ups alle Eingänge permanent auf High ziehen. Dann sind
alle deine if-Bedingungen immer wahr.
Habe jetzt den Code noch einmal ein bisschen umprogrammiert.
Ich habe die internen pullups eingeschaltet (das hatte ich vorher nicht
gemacht) und ich warte, bis der ausgeschaltete pin für die Reihe
wirklich auf low ist.
Jetzt ist es aber so, dass ich alle Zahlen nach der Abfrage rausbekomme.
Also output:
1 4 7 * 2 5 8 0 3 6 9 # 1 4 7...
Mit dem Pullup kann ich ja einfach abfragen, ob der pin low ist.
if ( !(PINC & (1<<PINC3)) ) usart_transmit_string("1 ");
Jetzt ist, dass wenn ich z.B. die 1 drücke, mir die 5 und 6 ausgegeben
wird. Das wird wahrscheinlich daran liegen, dass ich spalten und zeilen
falsch verbunden habe. Wenn ich aber z.B. die erste und letzte Leitung
der Tastatur auf Durchkontaktierung messe und jede Taste drücke, bekomme
ich nie eine Durchkontatkierung. Wie kann ich denn jetzt ermitteln,
welche Leitungen für die Spalten und welche für die Zeilen sind?
Die Begründung habe ich Dir schon geschrieben. Wenn du die Pull-Up
Widerstände aktivierst, ziehen sie alle Eingänge permanent auf High,
dann sind alle deine if Bedingungen immer wahr.
Dein Ruhepegel (nichts gedrückt) ist jetzt High. Also musst du das alles
so umprogrammieren, dass einzelne Spalten (Ausgang) auf Low gesetzt
werden und dann testen, welche Reihe (Eingang) durch den gedrückten
Taster auf Low gezogen wird.
> ich warte, bis der ausgeschaltete pin für die Reihe wirklich auf low ist.
Das ist unnötig.
if ( !(PINC & (1<<PINC4)) ) usart_transmit_string("1 ");
19
if ( !(PINC & (1<<PINC5)) ) usart_transmit_string("2 ");
20
if ( !(PIND & (1<<PIND4)) ) usart_transmit_string("3 ");
21
PORTC |= (1 << DDC0);
22
PORTC &= ~(1 << DDC1);
23
if ( !(PINC & (1<<PINC4)) ) usart_transmit_string("4 ");
24
if ( !(PINC & (1<<PINC5)) ) usart_transmit_string("5 ");
25
if ( !(PIND & (1<<PIND4)) ) usart_transmit_string("6 ");
26
PORTC |= (1 << DDC1);
27
PORTC &= ~(1 << DDC2);
28
if ( !(PINC & (1<<PINC4)) ) usart_transmit_string("7 ");
29
if ( !(PINC & (1<<PINC5)) ) usart_transmit_string("8 ");
30
if ( !(PIND & (1<<PIND4)) ) usart_transmit_string("9 ");
31
PORTC |= (1 << DDC2);
32
PORTC &= ~(1 << DDC3);
33
if ( !(PINC & (1<<PINC4)) ) usart_transmit_string("* ");
34
if ( !(PINC & (1<<PINC5)) ) usart_transmit_string("0 ");
35
if ( !(PIND & (1<<PIND4)) ) usart_transmit_string("# ");
36
PORTC |= (1 << DDC3);
37
}
Drücke ich jetzt z.B. auf die 2, wird mir die 2 herausgegeben (solange
wie ich diese gedrückt halte). Allerdings passiert in der ersten Spalte
nichts (1,4,7,*). Diese Tasten werden nicht erkannt. Zunächst habe ich
gedacht, dass irgendetwas mit dem Pin PC4 nicht stimmt, da die ganze
Spalte betroffen ist.
lasse ich allerdings nur einen Block in der while-schleife
1
PORTC &= ~(1 << DDC0); // row 1 low
2
if ( !(PINC & (1<<PINC4)) ) usart_transmit_string("1 ");
3
if ( !(PINC & (1<<PINC5)) ) usart_transmit_string("2 ");
4
if ( !(PIND & (1<<PIND4)) ) usart_transmit_string("3 ");
Wird mir in diesem Fall die 1 rausgegeben. Gleiches ist auch mit den
anderen Blocks.
Wieso wird mir die erste Spalte nicht ausgegeben, wenn ich die ganze
Tastatur abfrage, aber schon, wenn ich nur eine reihe abfrage?
Christian H. schrieb:> Auch wenn das vom Wert her egal ist, solltest Du statt DDC0 bitte PC0> verwenden.
Bei allen? Was ist der unterschied? Also theoretisch?
> Bei allen? Was ist der unterschied? Also theoretisch?
PC0 und DDC0 sind beides Makros mit dem Wert 2. PC steht für "Port C"
und DDC steht für "Data Direction C".
Wenn ich auf einem Port etwas ausgebe, wirkt der Begriff "Data
Direction" an dieser Stelle irritierend auf den Leser des Quelltextes.
>>> ich warte, bis der ausgeschaltete pin für die Reihe>>> wirklich auf low ist.>> Das ist unnötig.> Dem ist nicht so.
Warum denkst du, dass es nötig ist?
Warum hast du das dann trotzdem aus deinem Quelltext entfernt?
> Wieso wird mir die erste Spalte nicht ausgegeben, wenn ich die> ganze Tastatur abfrage, aber schon, wenn ich nur eine reihe abfrage?
Das liegt an der Synchronisation der Eingänge. Wenn du ein PIN Register
abfragst, bekommst du nicht die jetzt gerade anliegenden Pegel, sondern
was einen Takt zuvor angelegen hat.
Der Knackpunkt ist also nicht, dass der Ausgang verzögert auf Low geht,
sondern dass das PIN Register den tatsächlichen Signalen immer einen
Takt hinterher läuft. Irgendwo im Datenblatt ist das auch erklärt,.
Nachdem du einen Pin auf Low legst, musst du mindestens einen Takt
warten. Am Einfachsten stellst du das sicher, indem du einen NOP Befehl
einfügst.
Also vier mal so: