Guten Nachmitag,
im Zuge eines Projektes (Taschenrechner selbst erstellen) muss ich eine
Tastatur erstellen. Da ich keine komplizierte Taster-Matrix verwenden
möchte (bin noch Neuling im Gebiet der µC Programmierung), habe ich mich
für eine Porterweiterung per piso Register (74HC165) entschieden. Als
Kontroller verwende ich für Testzwecke einen ATMEGA48-20PU, später soll
eine ATMEGA168-20PU zum Einsatz kommen (was für den Quellcode keine
Unterschied machen sollte?).
Nun zum Problem, da die beiden Pins PB4 und PB3 (MISO und MOSI) bereits
in Verwendung sind, ist es mir nicht mehr möglich die Schieberegister
seriell mithilfe des µC auszulesen. Also habe ich mich für die
Softwarevariente mithilfe dreier I/O Pins am Controller entschieden. Als
Programmiersprache verwende ich C. Das Problem bei der Ausgabe am
Display wird Angezeit, dass jedes Eingangspin des Inputregisters high
ist, obwohl dies in der Schaltung nicht der Fall ist.
Hier der Verwendete C-code:
#include <avr/io.h>
#include <util/delay.h>
#include "lcd-routines.c"
#define PC4 4
#define PC3 3
#define PC5 5
#define CLK PC4
#define PL PC3
#define DATA PC5
volatile char cSchiebreg[16];
int main(void)
{
lcd_init();
set_cursor(0, 1);
DDRC &=~ ( (1 << DATA) ); //data als Eingang fürs serielle einlesen
DDRC = ( (1 << CLK) | (1 << PL)); //CLK und PL als Ausgang
PORTC |= (1 << PL); //PL wird high
while (1)
{
_delay_ms(500);
dataFromReg();
}
return 0;
}
void dataFromReg(void)
{
uint8_t i = 0;
PORTC |= (1 << CLK); //clk auf high wegen des Aufbaus
PORTC &=~ (1 << PL); //pl auf Wert der Register einfrieren
PORTC |= (1 << PL); //pl high für den nächsten Aufruf
for (i = 0; i < 16; i++)
{
PORTC |= (1 << CLK); //clk high erstes Bit kann gelesen werden
if ( PINC & ( 1 << DATA ) )
cSchiebreg[i] = '1'; //wenn serieller Ausgang des Inputregisters
high ist 1 ins array schreiben
else
cSchiebreg[i] = '0'; /wenn serieller Ausgang des Inputregisters
low ist 0 ins array schreiben
PORTC &=~ (1 << CLK); //clk low um die Werte des Registers weiter
zu schieben
}
for (i = 0; i < 16; i++)
lcd_data(cSchiebreg[i]);
//für testzwecke Ausgabe auf dem Display
}
Danke für die Antwort.
Leider kann das aber auch nicht das Problem sein, da ich zwei
kaskadierte Register, wie es im AVG Tutorial
(http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister)
für Schieberegister angegeben ist, verwende.
Trotzdem danke für deine Antwort
> Da ich keine komplizierte Taster-Matrix verwenden möchte
Da ist nichts kompliziertes dran - es ist viel einfacher als Dein "piso"
und benötigt im einfachsten Fall keine zusätzliche Hardware.
Otto
Das mag vieleicht sein. Mein µC hat jedoch nur noch 3 i/o-Pins zur
Verfügung und ich benötige mindestens 24 Tasten. Ist das mit einer Mtrix
überhaupt noch realisierbar?
Danke für die Antwort gast
nein - das ist ein gutes Argument - aber wahrscheinlich nicht richtig.
Du kannst die Displayausgänge für die Tastatur mitbenutzen.
oder: weshalb steigst Du nicht auf einen Typen mit mehr I/O um ?
/CE des 74..165 ist auf low?
Ich würde die Kommunikation mit einem Oszilloskop anschauen, um
Hardwarefehler auszuschließen bzw. lange delays in die Software
einbauen, und mir alles mit LEDs anschauen. So richtig offensichtlich
scheint mir kein Fehler im Source zu sein.
/CE des 74..165 ist auf low?
ja ce wurde auf Masse gezogen.
delays habe ich bereits eingebaut und die Flankenwechsel mit dem
Multimeter nachkontrolliert?
weshalb steigst Du nicht auf einen Typen mit mehr I/O um ?
Der Umstieg ist leider nich mehr möglich, da die Bestellung eines neuen
µC zu lange dauern würde und der Abgabetermin der 31.03 ist;-)
Wie bereits geschrieben, können die Leitungen des Display mit verwendet
werden - bei 8 Anschlüssen für das Display und 3 freien Eingängen kämst
Du hin.....
Das auch nur als Backup, fall das mit dem piso nicht läuft....
Otto
Also muss die Matrix als Notlösung herhalten, obwohl mir die piso
-Register lieber wären.
Wie werden also die Taster zu einer Matrix zusammengeschlossen?
Wie funktioniert das Auslesen und Entprellen der einzellen Taseter?
Danke inzwischen
Wenn Du 8 Datenleitungen zum Display zur Verfügung hast, schaltest Du
jede Datenleitung auf die eine Seite von 3 Tastern - die andere Seite
jedes Tasters auf je einen Eingang.
Es gibt also 8 Taster auf Eingang 1, 8 auf Eingang 2 und 8 auf Eingang3.
(Kurz gesagt: 8 Spalten und 3 Reihen.)
Die Abfrage läuft so, dass Du das Display ausschaltest, eine
Display-Datenleitung auf "1" schaltest und anschliessend "nachsiehst",
wo die "1" zurückkommt.
Das ganze in einer Schleife.
Zur Beachtung:
==============
Wenn Du mehrere Tasten auf einmal drückst, funktioniert die Abfrage
nicht mehr - zue Entkopplung werden dann 24 Dioden benötigt.
Ach ja - das Entprellen:
Eine neue gleiche Taste (erneuter "1"-Pegel) wird nur akzeptiert, wenn
Du an der Spalte und Reihe eine "0" ausgelesen hast.
D. h. Taste gelesen -> merken -> wenn "neue Taste = alte Taste"
ignorieren.
Die Taste frage ich dann also in einem Timerinterrupt ab?
Ich setze in der Interruptroutine den ersten der 8 Ausgänge auf 1, Frage
der Reihe nach die 3 Eingänge ab und weiß welcher der 3 Taster gedrückt
wurde? Setze den ersten Ausgang wider auf 0 und gehe weiter zum zweiten
(das ganze bis zum Ausgang 8).
Das müsste so hinhauen?
Müssen dabei die Pullabwiderstände an den 3 Eingängen aktiviert werden
und die drei Eingänge entprellt werden?
Und wie Funktioniet die Endkoppelung mit den Dioden?
> Die Taste frage ich dann also in einem Timerinterrupt ab?
ja - oder Du pollst schnell genug
> Ich setze in der Interruptroutine den ersten der 8 Ausgänge auf 1, Frage> der Reihe nach die 3 Eingänge ab und weiß welcher der 3 Taster gedrückt> wurde? Setze den ersten Ausgang wider auf 0 und gehe weiter zum zweiten> (das ganze bis zum Ausgang 8). Das müsste so hinhauen?
ja - die 3 Eingänge kannst Du auch quasi-parallel - also direkt
hintereinander abfragen.
> Müssen dabei die Pullabwiderstände an den 3 Eingängen aktiviert werden
nein - an den 3 Eingängen empfiehlt sich ein 10k Pull-Down oder Du
invertierst die Logik - schiebst also eine "0" durch und fragst auf
diese ab - dann werden für dir 3 Eingänge die pull-up aktiviert.
> und die drei Eingänge entprellt werden?
hier habe ich oben noch einen Post nachgeschoben.
> Und wie Funktioniet die Endkoppelung mit den Dioden?
Bei Abfrage auf "1":
Datenleitung ->|- Taster 1.1 Eingang 1
1 ->|- Taster 1.2 Eingang 2
->|- Taster 1.3 Eingang 3
Datenleitung ->|- Taster 2.1 Eingang 1
2 ->|- Taster 2.2 Eingang 2
->|- Taster 2.3 Eingang 3
usw.
>Ach ja - das Entprellen:
Sorry für meine Dummheit, aber das mit der Entprellung ist mir nicht
ganz klar?
Also eine Taste prellt und ändert mehrmals die Flanke high - low - high
(neue Taste?). Frage ich am Eingangspin die Taste nun ab wenn sie nicht
durchgeschlaten ist (also low -Pegel), ist es so als ob die Taste nicht
gedrückt worden wäre. Frag ich die Taste ab wenn sie high ist erhalte
ich am Eingangspin eine 1 und ich weiß, dass die Taste gedrückt wurde.
Kann ich das ganze Problem nich umgehen wenn ich die Tasten wie im
Tutorial (http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial)
angegeben mit, der inline uint8_t debounce(volatile uint8_t *port,
uint8_t pin) Funktion an den Eingängen abfrage?
Das mit der Endkopplung sollte kein Problem mehr sein
Danke
Ich verstehe die Funktion zwar nicht völlig (was nicht das Problem ist).
Bei Testzwecken (Taster direkt am i/o pin abfragen) hat sie aber gut
funktioniert und das Prellen der Tasten behoben.
Was für ein Nachteil ergibt sich duch das verwenden der genannten
Funktion?
Ok das hatte ich mir schon gedacht aber damit kann ich leben. Da ich nur
einen Timerinterrupt verwende dürfte dies zu keinen Problem führen.
Ich werden mich bei der nächsten Gelegenheit an die Arbeit machen.
Danke für die Umstimmung, es scheint wirklich nicht sehr kompliziert zu
sein. Ich hoffe ich kann bei möglichen Fertigungsproblemen;-) nochmals
drauflosfragen
Danke
Sorry für die erneute Fragerei. Ich bin gerade dabei einen Schlatplan
für die Matrix zu entwerfen. Also die Dioden müssen vor jeden Taster
geschaltet werden? Oder ist es besser wenn ich sie wie im Schaltplan
(Anhang) nach den Tastern einsetze?
Und ist es in Ordnung wenn ich einen der beiden Diodentypen (1n4148 oder
1n4004) verwende?