mikrocontroller.net

Forum: Compiler & IDEs Newbie in C / AVR Taste entprellen


Autor: Kai S. (kahrl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo User,

ich versuche mich seit ein paar Tagen in die Welt der AVRs 
einzuarbeiten, leider kann ich noch nicht wirklich viel in C. Habe mir 
schon einige Toturials angesehen und ein kleines Erfolgserlebnis mit dem 
ATtiny2313 gehabt.

Ich habe ein Programm geschrieben, welches einen Ausgang (PB7) schaltet 
wenn Taster_1 (PD0) gedrückt wird und ihn löscht wenn Taster_2 (PD1) 
gedrückt wird. Funktioniert soweit.

Nun hab ich das ganze erweitert um Taste_3 (PD2) diese schaltet ein, und 
bein nächsten drücken wieder aus. Nun stehe ich aber vor dem Problem der 
Tasten-Prellung. Ich habe mir die Code-Schnipsel hier von der Seite 
"gemopst" weiß leider nicht wie ich diesen nun richtig in mein Programm 
einbinde. Ich hoffe Ihr könnt mir weiter helfen...

#include <avr/io.h>

#include <util/delay.h>    
#include <avr/delay.h>


#define F_CPU 8000000UL



// Einschalten

void ein (void)              // "ein" ist eine freie Bezeichnung der Routine

  {
    PORTB = (1<<PB7);        // Schaltet PB7 auf HIGH (5V)
    return 0;
  }


// Ausschalten            

void aus (void)              // "aus" ist eine freie Bezeichnung der Routine

  {
    PORTB = (0<<PB7);        // Schaltet PB7 auf LOW (0V)
    return 0;
  }


// Funktion Entprellung


void entprellung( volatile uint8_t *port, uint8_t maske ) 
  
  {
      uint8_t   port_puffer;
      uint8_t   entprellungs_puffer;
 
      for( entprellungs_puffer=0 ; entprellungs_puffer!=0xff ; ) 
    
    {
    
      entprellungs_puffer<<=1;
        port_puffer = *port;
        _delay_us(150);
      if( (*port & maske) == (port_puffer & maske) )
        entprellungs_puffer |= 0x01;
    
    }
  }



// Hauptschleife

int main (void)              // "main" Bezeichnet die Hauptschleife

  {
    int x=0;            // "int"=Integer (Vermutlich Ganzzahl)
                    // "x" freie Variable hat Wert 0
    DDRD  = 0x7F;          // DDRD  als Eingang PD0-PD6
    PORTD = 0x7F;          // PORTD Pullups einschalten PD0-PD6
    
    DDRB  = 0xFF;          // DDRB  als Ausgang PB0-PB6

    while(1)             // Soviel wie tu.. mach was..
      
    {

      if (!(PIND & (1<<PD0)))    // Guck ob PD0 High ist, und wenn es nicht so ist*
        ein();          // geh zur "ein" Schleife

      if (!(PIND & (1<<PD1)))   // Guck ob PD1 High ist, und wenn es nicht so ist*
        aus();          // geh zur "aus" Schleife


    entprellung ( &PIND, (1<<PD2) );     // ggf. Prellen abwarten 
                       

      if (!(PIND & (1<<PD2)))    // Guck ob PD2 High ist, und wenn es nicht so ist
        if (x)  {x=0;ein();}  // --> Guck ob x=0 ist/war, wenn ja geh zur "ein" Schleife
          else        // --> oder
            {x=1;aus();}  // --> Guck ob x=1 ist/war, dann geh eben zur "aus" Schleife
                    // * Das (!) ist eine Negation, daher "wenn nicht"
    
    
    }                
      return 0;          // Fang von vorne an, bei "main"
  }



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

Bewertung
0 lesenswert
nicht lesenswert
Hol dir von hier
http://www.mikrocontroller.net/articles/Entprellung

zumindest das Debounce Makro vom Peter Danegger.

Noch besser funktionieren die Komfortroutinen weiter unten im Artikel. 
Die machen so ziemlich alles, was das Herz begehrt.

Autor: Kai S. (kahrl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl, und danke für die schnelle Antwort.

Auf der Seite hänge ich schon den halben Vormittag, ich weiß leider 
nicht wie ich das in meinen Code einbinden muss. Wie gesagt ich bin 
absoluter neuling in Sachen C. Deswegen habe ich mir erstmal für die 
"void entprellung..." von dort entschieden.


[Zitat]
zumindest das Debounce Makro vom Peter Danegger.

Noch besser funktionieren die Komfortroutinen weiter unten im Artikel.
Die machen so ziemlich alles, was das Herz begehrt.
[Zitatende]

Das mag sein, nur kann ich damit noch weniger anfangen...

Was mir helfen würde ist eine kurze Erklärung wie ich was und wo in 
meinen Code einbinden muss, damit ich es auch verstehe. Am liebsten wäre 
es mir, wenn man mir erklärt ob und was am obigen Code falsch ist und 
was man warum ändern muss.

Danke.

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

Bewertung
0 lesenswert
nicht lesenswert
Kai S. schrieb:
> Hallo Karl, und danke für die schnelle Antwort.
>
> Auf der Seite hänge ich schon den halben Vormittag, ich weiß leider
> nicht wie ich das in meinen Code einbinden muss. Wie gesagt ich bin
> absoluter neuling in Sachen C. Deswegen habe ich mir erstmal für die
> "void entprellung..." von dort entschieden.

Dort ist doch ein komplettes Beispiel!

Machs doch anders rum:
Übernimm das Beispiel so wie es ist.
Passe die Pinbelegung auf deine an, kompilier es und bring es zum 
laufen.
Und dann baust du deinen Code dort ein.

Deine 2 Funktionen und 3 Abfragen hast du doch in 0 komma nix dort 
eingebaut. Für dich ist erst mal nur das interessant, was in den 
Beispielen in der main() Funktion steht. Dort kann man sich ansehen, wie 
das jeweils verwendet wird.

> [Zitat]
> zumindest das Debounce Makro vom Peter Danegger.
>
> Noch besser funktionieren die Komfortroutinen weiter unten im Artikel.
> Die machen so ziemlich alles, was das Herz begehrt.
> [Zitatende]
>
> Das mag sein, nur kann ich damit noch weniger anfangen...

Die Routine ist so trickreich, dass es ok ist, wenn man nicht versteht 
wie sie funktioniert. Das ist eine der wenigen Ausnahmen, bei denen ich 
es als für in Ordnung befinden würde.

> Was mir helfen würde ist eine kurze Erklärung wie ich was und wo in
> meinen Code einbinden muss, damit ich es auch verstehe.

Auch dort ist ein komplettes Beispiel.

> Am liebsten wäre
> es mir, wenn man mir erklärt ob und was am obigen Code falsch ist und
> was man warum ändern muss.

Dein Hauptproblem ist, dass dein Code für die ABfrage von PD2 nicht das 
implementiert, was du haben willst.
Dein Code macht:
  * wenn die Taste gedrückt IST, dann schalte den Eingang um
Du willst aber machen:
  * wenn die Taste gedrückt WIRD, dann schalte um

Im ersten Fall detektierst du ob der Pegel des Tasteneingangs low ist, 
und so eine gedrückte Taste anzeigt. Das ist: Wenn die Taste gedrückt 
IST

Im zweiten Fall musst du aber feststellen, ob sich der Pegel des 
Tasteneingangs verändert hat, gegenüber dem Zeitpunkt an dem du zuletzt 
nachgesehen hast. Hat sich der Pegel nicht verändert, dann ist an der 
Taste auch nichts passiert. Die Taste ist immer noch gedrückt oder nicht 
gedrückt. Hat sich der Pegel aber verändert, dann ist die Taste entweder 
gedrückt oder losgelassen worden.

Die Funktion entprellung macht das aber nicht. Die stellt nur sicher 
(soll sicherstellen), dass der Pegel konstant ist. Was du dann mit dem 
Pegel weiter machst, ist dein Bier.

Autor: Kai S. (kahrl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl,

ich bekomme beim Compilieren immer folgende Meldung:


Build started 24.1.2011 at 12:44:24
avr-gcc  -mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT 
Entprellt2313.o -MF dep/Entprellt2313.o.d  -c  ../Entprellt2313.c
../Entprellt2313.c:18:2: warning: #warning kein F_CPU definiert
../Entprellt2313.c: In function 'main':
../Entprellt2313.c:119: error: 'TCCR0' undeclared (first use in this 
function)
../Entprellt2313.c:119: error: (Each undeclared identifier is reported 
only once
../Entprellt2313.c:119: error: for each function it appears in.)
make: *** [Entprellt2313.o] Error 1
Build failed with 3 errors and 1 warnings...


Woran kann das liegen?

Autor: Kai S. (kahrl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, für den ATiny muß man wohl TCCR0B schreiben, hab ich grad gelesen. 
Nun Compiliert er mit nur einer Warnung.

Build started 24.1.2011 at 12:50:03
avr-gcc  -mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT 
Entprellt2313.o -MF dep/Entprellt2313.o.d  -c  ../Entprellt2313.c
../Entprellt2313.c:18:2: warning: #warning kein F_CPU definiert
avr-gcc -mmcu=attiny2313 -Wl,-Map=Entprellt2313.map Entprellt2313.o 
-o Entprellt2313.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature 
Entprellt2313.elf Entprellt2313.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" 
--change-section-lma .eeprom=0 --no-change-warnings -O ihex 
Entprellt2313.elf Entprellt2313.eep || exit 0
avr-objdump -h -S Entprellt2313.elf > Entprellt2313.lss

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

Bewertung
0 lesenswert
nicht lesenswert
Kai S. schrieb:

> ich bekomme beim Compilieren immer folgende Meldung:

Ah. ok
An deinen Prozessor musst du die Registernamen schon anpassen.

> ../Entprellt2313.c:18:2: warning: #warning kein F_CPU definiert

Stell im AVR-Studio in den Project Options deine Taktfrequenz ein

> ../Entprellt2313.c: In function 'main':
> ../Entprellt2313.c:119: error: 'TCCR0' undeclared (first use in this
> function)

Das Konfigurationsregister für den Timer 0, in dem die Vorteilerbits 
sind, heißt beim Tiny2313 TCCR0B.
Die Belegung und die Bedeutung der Bits ist aber identisch.

Siehe Datenblatt

Autor: Kai S. (kahrl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, das ganze geht soweit.

Nun werde ich mir mal den Code "verinnerlichen" damit ich auch kapiere 
was da so passiert...


An dieser Stelle ersteinmal Vielen Dank für die Unterstützung!

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

Bewertung
0 lesenswert
nicht lesenswert
Kai S. schrieb:
> Okay, das ganze geht soweit.
>
> Nun werde ich mir mal den Code "verinnerlichen" damit ich auch kapiere
> was da so passiert...

Im einfachsten fall brauchst du nur

   get_key_press( 1<<KEY2 )

dann halt jeweils mit dem richtigen Key


   if( get_key_press( 1<<KEY2 ) )
     mach was

wird genau dann ausgeführt, wenn die Taste 1-mal gedrückt wird.
Fertig.
Einfacher gehts nicht

Autor: Kai S. (kahrl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann ich denn in so einem Code alles was nach dem letzten

"#include" bzw. schon nach dem "#endif"
und vor
"int main void"

steht in eine Datei Namens xyz.c schreiben und diese dann ganz oben 
aufrufen z.B. mit "#include <xyz.c>" oder geht das so nicht?

Wenn das ne echt dumme Frage ist, erschlag mich nicht gleich, ich 
versuche nur zu verstehen wie das Programmieren in C so von statten 
geht, was möglich ist und was nicht.

learning by doing
und wenn´s nicht geht freundlich Fragen ;-)

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

Bewertung
0 lesenswert
nicht lesenswert
Kai S. schrieb:

> steht in eine Datei Namens xyz.c schreiben

kannst du

> und diese dann ganz oben
> aufrufen z.B. mit "#include <xyz.c>" oder geht das so nicht?

aber nicht so.
*.c Files inkludiert man nicht

http://www.mikrocontroller.net/articles/FAQ#Ich_ha...

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kai S. schrieb:
> ein();          // geh zur "ein" Schleife

das ist übrigens alles mögliche, eine Funktion, Unterprogramm, Prozedur,
aber auf keinen Fall eine Schleife

Autor: Kai S. (kahrl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Kai S. schrieb:
>> ein();          // geh zur "ein" Schleife

>das ist übrigens alles mögliche, eine Funktion, Unterprogramm, Prozedur,
>aber auf keinen Fall eine Schleife


OK, Danke. Ich werd das mal in meinem Text abändern..

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.