mikrocontroller.net

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


Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
}

Autor: Friz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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-Tutori...) 
für Schieberegister angegeben ist, verwende.

Trotzdem danke für deine Antwort

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ist das mit einer Mtrix überhaupt noch realisierbar?

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

Sowas aber auch..

Autor: Marvin M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;-)

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das 200ms "Stillstand" entstehen, wenn eine Taste betätigt wird.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Otto (Gast)
Datum:

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

Viele Grüsse

Otto

Autor: gast (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.