piso register per Software in c auslesen

Gast #1195115
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
}
Gast #1196738
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
Gast #1196746
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
Gast #1196755
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.
Gast #1196768
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;-)
Gast #1196786
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
Gast #1196812
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
Gast #1196825
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.
Gast #1196831
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.
Gast #1196872
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?
Gast #1196890
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.
Gast #1196946
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
Gast #1197021
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?
Gast #1197055
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
Gast #1197745
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?
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren