mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik mit Tastern auswählen (ATMEGA8)


Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

hab ein Problem damit mehreren Auswahltastern zu sagen was sie machen
sollen. Will zum Beispiel an Port B eines ATMEGA 8 einen Taster drücken
und dann soll z.B. ein Lauflicht an PIN D starten. Wollt das ganze mit
einer switch case Anweisung machen. Hab auch schon meine erste Idee
fertig und im AVR Studio funktioniert das auch alles in der Simulation
Wunderbar, aber das wars auch. In der Praxis ist alles für die Katz und
es passiert nix.

Hier mal ein Auszug:

------------------

test=PINC;
switch (test)
{
case 0x02: goto knight; break;
case 0x04: goto knight2; break;
case 0x08: goto knight3; break;
default: goto anfang;

-------------------

vielleicht hat ja wer noch eine andere Idee wie man das machen kann.
Und vielleicht auch eine Möglichkeit die in der Praxis klappt.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht noch das Problem der prellenden Tasten?
Und "goto" ist ganz böse...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du in C mit goto arbeitest, brauchst Du Dich wegen gar nix zu
wundern...

Abgesehen davon: Wie sind die Taster an Port B angeschlossen? Ich
vermute mal Low-Side...

Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was soll ich denn anstelle von goto benutzen?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einen Funktionsaufruf??? Es gibt unter normalen Umständen keine einzige
Anwendung für goto, die nicht auch anders gelöst werden könnte
(vielleicht von ganz wenigen sehr exotischen Beispielen abgesehen).
goto ist höchst unsauber, da es irgendwo hinspringt und man hinterher
nicht mehr weiß, wo man vorher war. Du solltest wirklich mal
C-Grundlagen pauken...

Abgesehen davon hatte ich oben schon mal gefragt, wie die Taster denn
überhaupt angeschlossen sind... Davon hängt nämlich ab, wie die Abfrage
zu machen ist!

Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
will es ja lernen, so ist es ja nicht. ist nur schwer sowas auf eigene
Faust zu machen.

die Taster sind wie folgt angebunden:

http://www.mikrocontroller.net/articles/Bild:Active_Low.gif

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, genau so hab ichs mir gedacht. Da steht was von 'Active Low'...
wenn Du aber abfragst, ob Dein Pin '1' ist, macht das wenig Sinn, es
sei denn, Du willst wissen, ob Dein Taster NICHT gedrückt ist. Die
Abfrage muss also invertiert werden.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...Ach ja, wenn Du an Port B einen Taster drückst und PINC einliest,
bringt Dir das ganze auch recht wenig... Müsste also mindestens test =
PINB heißen

Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sowas hab ich mir auch schonmal gedacht. Hab somit auch schon mal die
Abfrage invertiert, leider auch kein Ergebnis. Genau das selbe Problem.
In der Simulation geht alles und danach in der Praxis auf dem Board nix.


Auch wenn ich alles auf Active High aufbaue, es kommt nix raus.

Vielleicht ist das Problem ja das goto. oder ein prellender Taster.
Muss man sehen wie ich ihn entprellen kann.

Autor: Thomas O. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei mir in ASM schaut das so aus

main:
sbis pina, 7
rcall main1
sbis pina ,6
rcall main2
sbis pina, 5
rcall main3
sbis pina,4
rcall main4
rjmp main

Habe die Pullups eingeschalten und ziehe mit einem Drehschalter den
entsprechenden Pin gegen Masse. Man kann auch die Pullups deaktivieren
und mit dem Drehschalter auf 5V hochziehen, dann muss man das SBIS in
SBIC ändern, vielleicht kannste das ja in C einbinden

Autor: Manos (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also statt 0x02 (oder 0b00000010) ein 0xFD (oder 0b11111101)...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
goto ist eigentlich immer ein Problem. Meide es wie die Pest. Wie oben
schon gesagt: Es gibt eigentlich immer eine sauberere Lösung, und die
ist in jedem Falle vorzuziehen. Du kannst Deine Funktionen ja auch
direkt in die switch-Anweisung reinschreiben. Solange das nicht zu viel
Code ist, bleibt das auch noch einigermaßen übersichtlich.

Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das mit PORT B ist oben ein Tippfehler. Soll PORT C heißen.

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"goto" wird nicht gerne genommen, weil es den optischen Programmfluß
unterbricht (schlechter lesbar).

Ansonsten ist es nicht "böse", wenn Dein Programm logisch stimmt.


Das Problem bei ner Taste ist, daß man sie erst ausmaskieren muß, d.h.
alle anderen Bits sind egal:
#define KEY0 1 // Portpin 1
#define KEY1 5 // Portpin 5

unsigned char input = ~PINB;

if( input & 1<<KEY0 ){
    // mache was
}
if( input & 1<<KEY1 ){
    // mache was
}
// usw.

Dann kann es immer noch sein, daß Dein Taster prellt
(Mehrfacherkennung) oder Du gerade losgelassen hast (keine Erkennung),
wenn die Abfrage erfolgt.

Daher bietet sich dafür der Timerinterrupt an (1..8 Tasten, siehe
Codesammlung).


Peter

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:
Ich halte goto deshalb für 'böse', weil es einen großen Vorteil der
Programmiersprache C (Stichwort strukturierte Programmierung) völlig
aushebelt. Ich programmiere schließlich u.a. deshalb in C, damit ich
übersichtlicheren Code erhalte, den man auch bei größeren Projekten
noch entziffern kann. Die Verwendung von goto macht genau diesen
Vorteil zunichte... Deshalb ist (und bleibt voraussichtlich auch) goto
das wahrscheinlich einzige C-Schlüsselwort, das ich noch nie in einem
Programm verwendet habe.

Ansonsten hast Du natürlich recht. Die Methode mit der Abfrage ohne
Maskierung haut dann daneben, wenn mehrere Tasten gleichzeitig gedrückt
werden oder wenn an irgendeinem anderen Pin des Ports irgendwas anderes
passiert.

Gruß

Johnny

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um mal das Gezetere über den 'goto' (das ich im Übrigen teile)
in einen praktischen Vorschlag umzuwandeln.

Du kannst das so machen:

   while( 1 ) {           /* das ist eine Endlosschleife     */
    test = PINC;          /* Pins einlesen                   */
    switch( test ) {      /* die Pins sind active Low        */
                          /* d.h. wenn der Taster an Pin 2   */
                          /* gedrueckt wird, dann geht Bit 2 */
                          /* auf 0                           */
      case 0b11111101:    /* Pin2                            */
        knight();         /* rufe die Funktion knight auf.   */
        break;

      case 0b11111011:    /* Pin 4                           */
        knight2();
        break;

      case 0b11110111:    /* Pin 8                           */
        knight3();
        berak;

      default:
        ;                 /* keine Aktion notwendig         */
    }
  }

Jetzt liegt es an dir die Funktionen knight(), knight2() und
knight3() zu schreiben.

Ach ja: Besorg Dir unbedingt ein Buch über C-Programmierung.
Ich weiss, es gibt Unmengen an Online-tutorials im Web. Kauf
Dir trotzdem ein Buch. Es hat schon seinen Grund, warum die
meisten Tutorials nicht über 20 Seiten hinauskommen, ein Buch
aber mindestens 150 Seiten hat :-)
Im Übrigen: als Nachschklagewerke zum 'neben der Tastatur liegen'
sind Bücher unschlagbar. Mal ganz davon abgesehen, dass man sich
in einem Buch auch Notizen machen kann.

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl Heinz,

ein sehr schönes Beispiel, wie man es genau nicht machen darf !

Damit beziehst Du alle Pins ein, auch die, die gar keine Tasten sind,
sondern vielleicht fröhlich in der Gegend rumfloaten.

Ein Funktionieren wäre dann purer Zufall.

Der einzig zuverlässige Weg, einzelne Eingänge zu erkennen, ist das
UNDieren des jeweiligen Bits.


Peter

Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hey, eure ideen sind super und ich werd sie morgen mal ausprobieren,
wenn die Zeit ist.

Ein gutes Buch, für den kleinen Anfänger, wäre super, wenn man wüsste
welches sich lohnen würde. Also irgendwelche Ideen? Preis ist nur eine
zweitrangige Sache bei der Sache.

@Peter danegger
was meinst du genau mit undieren? Meinst du das schreiben (so
vielleicht: (PIN B 1 & PIN B2) weis gerade nicht genau wie es richtig
ist. oder wie meinst du es?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter

mea culpa
Du hast natuerlich recht. Wo hatte ich nur meine Gedanken?

@Hubert

Also Hubert. Es gibt da mehrere Möglichkeiten.
Eine simple ist zb: Bevor du die Auswertung machst, musst du
zunaechst mal alle anderen Bits, an denen kein Taster hängt
in einen definierten Zustand bringen. Jetzt mach ich mir das
einfach und setzte die einfach 1, dann brauch ich im Rest
vom Pgm nichts zu ändern.

    test = PINC;
    test = test | 0b11110001;
    switch( test ) {
      ...

ist eine Möglichkeit. Ne andere wäre, wie Peter Dannegger völlig
richtig anmerkt, mit einem UND die relevante Bitposition 'heraus-
ziehen' und damit weiterzuarbeiten. Dann müsste man den switch-case
durch eine if-elseif Leiter ersetzen.

Es führen halt viele Wege nach Rom.

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"was meinst du genau mit undieren?"

Das, was mein erster Beitrag macht.


Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hubert

Das würde dann so aussehen:

  while( 1 ) {
   test = PINC;

   if( ( test & 0x02 ) == 0 )       /* Pin 2 */
     knight();

   else if( ( test & 0x04 ) == 0 )  /* Pin 4 */
     knight2();

   else if( ( test & 0x08 ) == 0 )  /* Pin 8 */
     knight3();
  }

> Ein gutes Buch, für den kleinen Anfänger, wäre super,
> wenn man wüsste welches sich lohnen würde.

Mit dem 'Klassiker' kann man nie was falsch machen:
Kernighan & Ritchie, Programmieren in C

http://www.amazon.de/exec/obidos/ASIN/3446154973/3...

Autor: Jörn-h. G. (joern_g)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du den WINAVR nimmst, geht die abfrage auch einfacher - nämlich mit
dem Makro: bit_is_clear():

Und else-if Ketten sind (angeblich) besser auf Controllern, daher mein
Vorschlag:

if( bit_is_clear(PINB, 0) )
 function0();
else if ( bit_is_clear(PINB, 1) )
 function1();
else if ( bit_is_clear(PINB, 2) )
 function2();

cu joern

Autor: Marco S. (masterof)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
abo

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist "bit_is_clear" nicht auch bei der letzten grossen
"Reinigungsaktion" des WinAVR mit entsorgt worden (so wie "inp" und
"out")?
Die Schreibweise mit "(1<<x)" ist auch C-konformer und damit
übertragbar; nicht jeder Compiler liefert "bit_is_clear" mit (hat
Jörg ja schon durch das Erwähnen von WinAVR eingeschränkt).

@Marcor: Master of abo?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vergesst die Entprellung nicht...

...

Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so, hab heut schon ein wenig herumexperimentiert, leider ohne ein
wirkliches praktisches Ergebnis nur in der Simulation funktioniert es
toll.
Nun bin nun dabei alle "goto" Anweisungen zu killen, welches viele
Änderungen bei meinem Lauflicht erfordern, aber wenn "goto" böse ist
dann ist es böse und ich werde es killen. Vielleicht ist es ja das
Problem.

Kann mich auch wage dran erinnern das mir mein Lehrer sowas von
"goto" auch mal erzählt hat. Das es "unsauber sei" usw.

Autor: Huber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es geht, ich glaubs ja nicht. Aber meinen Fehler hab ich nicht gefunden.
Hab nun erstmal es ganz einfach gemacht und gesagt wenn ich Taste drücke
geht Licht an und bleibt erstmal an, wenn ich eine andere Taste drücke
geht die andere Lampe an. Nun hab ich es erweitert und es geht auch.

Ich danke euch für die vielen Beispiele und im Endeffekt hat mir der
Vorschlag von Karl Heinz Buchegger weitergeholfen. Aber allen anderen
auch ein großes Lob, denn nun wird sich ein Buch gekauft in nächster
Zukunft und fleißig gelernt. Und dann finde ich auch Lösungen gegen
"goto"

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm...

So unterschiedlich ist das... In ASM gibt's eigentlich fast nur
"Goto" (rjmp, jmp) und "Goto wenn" (brxx) zur Realisierung von
Schleifen und Verzweigungen... Da kann doch "goto" garnicht so
"böse" sein... ;-)

Duck & wech...

...

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes: goto schon... aber seine ASM-Familie mögen wir alle, auch wenn
mancheiner mit der Familie nicht gut zurecht kommt (es handelt sich
wohl um Sprachbarrieren [wie zwischen Mann und Frau...])

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schtümpth... - Das Runde muss in das Eckige... - Oder so...

...

Autor: Thomas O. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
brxx würde ich eher damit in Basic programmieren "if a = x then gosub"
dann landet man nach diesem Unterprogramm wieder am Anfang. Ich verstehe
deswegen Peter voll und ganz wenn man nach einem Dutzend gotos nicht
mehr richtig weiß wo man eigentlich ist.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> brxx würde ich eher damit in Basic programmieren "if a = x then
> gosub"
> dann landet man nach diesem Unterprogramm wieder am Anfang.

Nix GOSUB, 'brcs label1' verzweigt nach 'label1:' ohne sich wie bei
GOSUB (RCALL, CALL) die gegenwärtige Adresse zu merken, es ist also ein
'IF Carryflag=thrue then goto label1'.

Mir ist klar, dass die Hochsprachen mächtige Befehle für die
übersichtliche Gestaltung von Schleifen und Verzweigungen zur Verfügung
stellen und das man diese auch konsequent nutzen sollte wenn man die
Vorteile der Hochsprache ausschöpfen will. Daher sollte man schon auf
GOTO verzichten.

In ASM ist die Denkweise aber nunmal etwas anders, etwas näher an der
Hardware, und da gibt es keine Schleifenbefehle, da muss man eben mit
RJMP oder JMP (GOTO) zurück springen, bei Schleifen mit
Abbruchbedingungen auch mit BRxx.

Dass mein Beitrag als Scherz zu verstehen war, kann man übrigens am
'Duck & wech' erkennen.

...

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.