Forum: Mikrocontroller und Digitale Elektronik piso register per Software in c auslesen


von gast (Gast)


Lesenswert?

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
}

von Friz (Gast)


Lesenswert?

Bin selbst noch Neuling vieleicht liegt es aber daran, dass deine 
for-Schleife bis 16 zählt, ein Register dieser Art aber nur 8 Eingänge 
hat.

von gast (Gast)


Lesenswert?

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

von Otto (Gast)


Lesenswert?

> 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

von gast (Gast)


Lesenswert?

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

von Otto (Gast)


Lesenswert?

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 ?

von Matthias L. (Gast)


Lesenswert?

>Ist das mit einer Mtrix überhaupt noch realisierbar?

Nein. Da benötigt man ja 5 Ein- und 5 Ausgänge.....

Sowas aber auch..

von Marvin M. (Gast)


Lesenswert?

/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.

von gast (Gast)


Lesenswert?

/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;-)

von Otto (Gast)


Lesenswert?

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

von gast (Gast)


Lesenswert?

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

von Otto (Gast)


Lesenswert?

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.

von Otto (Gast)


Lesenswert?

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.

von gast (Gast)


Lesenswert?

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?

von Otto (Gast)


Lesenswert?

> 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.

von gast (Gast)


Lesenswert?

>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

von Otto (Gast)


Lesenswert?

OK - Du hast gewonnen - ich hatte nicht zu Ende gedacht ;-)

Nimm das Beispiel aus dem Tutorium (Beachte, ob Du mit dem Nachteil 
leben kannst)

Otto

von gast (Gast)


Lesenswert?

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?

von Otto (Gast)


Lesenswert?

das 200ms "Stillstand" entstehen, wenn eine Taste betätigt wird.

von gast (Gast)


Lesenswert?

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

von Otto (Gast)


Lesenswert?

auf jeden Fall - ich hoffe, dass ich es dann auch sehe - aber wenn 
nicht, sicher ein Anderer ;-)

Viele Grüsse

Otto

von gast (Gast)


Angehängte Dateien:

Lesenswert?

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?

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
Noch kein Account? Hier anmelden.