Forum: Mikrocontroller und Digitale Elektronik Neuling mit AVR-Ctrl - Tasten entprellen


von Gast (Gast)


Lesenswert?

Hallo,

habe mir neulich ein AVR-Ctrl (mit ATmega32) beschafft, um als Neuling
in C ein bisschen experimentieren zu können.

Habe mir dann eine kleine Routine geschrieben, mit welcher ich das
Prellen der Tasten verhinder (sicher gibt es elegantere und kleinere
Lösungen, aber als Neuling war ich mal froh das es zumindest
funktionierte).

Als es nun ging wollte ich die Routine in eine eigene Header packen,
damit ich es leicht in andere Programme einbinden kann. Hier scheitere
ich aber.

Das AVR-Studio 4.12 wirft mir folgende Fehlermeldungen an den Kopf, die
ich einfach nicht wegbekomme:

rm -rf debounce.o keys.o  debounce.elf dep/* debounce.hex debounce.eep
Build succeeded with 0 Warnings...
avr-gcc.exe  -mmcu=atmega32 -Wall -gdwarf-2 -DF_CPU=16000000UL  -O0
-fsigned-char -MD -MP -MT debounce.o -MF dep/debounce.o.d  -c
../debounce.c
avr-gcc.exe  -mmcu=atmega32 -Wall -gdwarf-2 -DF_CPU=16000000UL  -O0
-fsigned-char -MD -MP -MT keys.o -MF dep/keys.o.d  -c  ../keys.c
../keys.c: In function `read_key':
../keys.c:25: warning: comparison between pointer and integer
../keys.c:30: error: invalid lvalue in assignment
../keys.c:31: warning: `return' with a value, in function returning
void
../keys.c:42: error: invalid lvalue in assignment
../keys.c:43: warning: `return' with a value, in function returning
void
../keys.c:47: error: invalid lvalue in assignment
../keys.c:48: warning: `return' with a value, in function returning
void
make: *** [keys.o] Error 1
Build failed with 3 errors and 4 warnings...
___________________________________________________________________

Anbei mal mein Hauptprogramm (debounce.c):

#include <avr/io.h>
#include <avr/delay.h>
#include <stdint.h>
#include <inttypes.h>
#include "keys.h"                // Beinhaltet Entprell-Routine


/*********************************************************************** 
****************
*
*  Das Hauptprogramm
*
************************************************************************ 
***************/

int main(void)
{
  PORTA = 0x00;              // Ausgabe-Zustand von Port A
  DDRA = 0x00;              // Port A als Eingang
  PORTB = 0x00;              // Ausgabe-Zustand von Port B
  DDRB = 0xFF;              // Port B als Ausgang
  int f;                  // Variable für einen kleinen Zähler
  f = 1;                  // Startwert für den Zähler festlegen

  while(1)
  {
    read_key(KEY2);            // Frage KEY2 ab

    PORTB = f;              // Gebe aktuellen Wert von f auf PORTB aus
    if (key_status == 1)        // Wenn KEY2 eine logische 1 liefert:
      f++;              // dann mache f+1

  }
}

_________________________________________________________________

Und hier noch die key.c (Entprell-Routine):

#include <stdint.h>
#include <avr/io.h>
#include <avr/delay.h>
#include "keys.h"


/*********************************************************************** 
**
*
*  Die Entprellroutine
*
************************************************************************ 
*/


void read_key(int key)
{
  while( key_status == 1 )          // Verhindern von Wiederholungen
  {
    if bit_is_clear( PINA,key )        // Warte bis Taster wieder 
losgelassen
wurde
    {
      _delay_ms(50);            // Verzögere
      key_status = 0;            // Status auf logisch 0 setzen
      return (key_status);        // Wert übergeben
    }
  }

  if( key_status == 0)            // Wenn nich gedrückt
  {
    if bit_is_set( PINA,key )        // Warte bis Taster gedrückt ist
    {
      _delay_ms(50);            // Verzögere
      if bit_is_set( PINA,key)      // Wenn immer noch gedrückt:
      {
        key_status = 1;          // Status auf logisch 1 setzen
        return (key_status);      // Wert übergeben
      }
      else                // Wenn nicht mehr gedrückt war
      {
        key_status = 0;          // Status auf logisch 0 setzen
        return (key_status);      // Wert übergeben
      }
    }
  }
}

_________________________________________________________________

Und zu letzt die zugehörige Header (key.h):

/*********************************************************************** 
*
*****  Beispiel:                          *****
*****  Um z.B. KEY2 abzufragen, schreibe: read_key(KEY2)      *****
*****  Anschließend wird der Taster eingelesen.          *****
*****  Wenn key_status anschließend 1 ist, wurde der Taster    *****
*****  gedrückt, andernfalls ist key_status 0.            *****
*****                                *****
************************************************************************ 
/

#include <inttypes.h>

/*********************************************************************** 
*
*****                                *****
*****  Definitionen der Taster des AVR-CTRL's            *****
*****                                *****
************************************************************************ 
/

#define KEY1   PA7              // Schwarzer Taster (1.)
#define KEY2   PA6              // Schwarzer Taster (2.)
#define KEY3   PA5              // Blauer Taster (3.)
#define KEY4   PA4              // Blauer Taster (4.)
#define KEY5   PA3              // Roter Taster (5.)


/*********************************************************************** 
*
*  Funktion:    extern void read_key(int key)
*  Beschreibung:  Einen Taster abfragen
************************************************************************ 
/
extern void read_key(int key);


/*********************************************************************** 
*
*  Funktion:    extern void key_status(int)
*  Beschreibung:  Eingelesenen Status abfragen
************************************************************************ 
/
extern void key_status(int);

__________________________________________________________________

Die Kommentare habe ich mal bewusst stehen lassen.
Mir ist klar das es nicht die schönste Routine der Welt ist, würde mich
aber trotzdem freuen, wenn mir jemand helfen könnte das zum Laufen zu
bekommen.

Vielen Dank!

von MasterFX (Gast)


Lesenswert?

Hallo, erstmal die Zeile:
>>keys.c:31: warning: `return' with a value, in function returning
void

GCC schreibt schon ziemlich gut was du falsch machst. Die Funktion
"void read_key(int key)" ist eine void-Funktion, daher sie gibt
keinen Wert zurück (zumindest erwartet gcc das. Du machst aber in 3
Zeilen "return (key_status)". So wie es aussieht ist key_status
nirgends deklariert, daher ist die Variable unbekannt und GCC bemängelt
dies auch. Aber du hast stattdessen eine funktion "extern void
key_status(int)". die kannst du natürlich nicht wie eine Variable
behandeln. Sondern du müsstest schreiben
1
while(key_status() == 1)
2
....

von johnny.m (Gast)


Lesenswert?

> PORTB = f;
Das könnte auch Probleme geben. f ist als int deklariert (16 Bit),
PORTB hat aber nur 8 Bit. Ich weiß jetzt nicht, ob der Compiler das
vernünftig hinbiegt, aber eine Variable, die einem 8-Bit-Register
zugewiesen wird sollte auch nur mit 8 Bit deklariert werden (also als
(unsigned) char oder uint8_t).

von johnny.m (Gast)


Lesenswert?

BTW: Die delay-Funktionen aus der delay.h sind begrenzt, was die
maximalen Wartezeiten angeht. Du arbeitest anscheinend mit 16 MHz. Dann
kann die _delay_ms()-Routine auch nur 16,384 ms maximale Verzögerung
(262,14ms/f_CPU[in MHz]). _delay_ms(50) haut jedenfalls nicht hin!

von johnny.m (Gast)


Lesenswert?

...Und vor allem (und das ist der 'Error'): Du versuchst, der FUNKTION
key_status (die unten als extern void key_status(int) deklariert ist)
einen Wert zuzuweisen. Das geht sowieso nicht!

von Gast (Gast)


Lesenswert?

Das mit PORTB = f funktioniert, danke trotzdem für den Hinweis.

@ MasterFX
Tut mir leid aber ich verstehs nicht ganz, liegt wohl daran, dass ich
noch nicht sehr viel Erfahrung hab.

Habe eben etwas herumprobiert, aber die Zeile
while(key_status() == 1)
meinst du doch dann für die Abfrage im Hauptprogramm, oder?

Wie soll ich denn die Funktion bzw. die Header umbauen, damit die
Übergabe klappt?
Währ nett wenn du mir nen Beispiel bringen könntest, oder sonst
jemand.

Danke!

von Gast (Gast)


Lesenswert?

...Und vor allem (und das ist der 'Error'): Du versuchst, der
FUNKTION
key_status (die unten als extern void key_status(int) deklariert ist)
einen Wert zuzuweisen. Das geht sowieso nicht!
_____________

Wie muss ich es denn dann machen? Mache sowas zum ersten mal.

von johnny.m (Gast)


Lesenswert?

Die Funktion erwartet einen int als Parameter. Wenn Du einen Wert von 1
oder 0 an Deine Funktion übergeben willst, dann muss es heißen
key_status(1); oder eben key_status(0);. Mehr kann ich dazu nicht
sagen, da ich die Funktion key_status nicht kenne.

Ach ja: wenn Du erstmalig mit µCs arbeitest, solltest Du versuchen,
gleich von Anfang an einen Fehler zu vermeiden, den viele Leute machen,
die bisher PCs programmiert haben. Variablen sollten immer nur so groß
sein, wie nötig. Ein µC hat nunmal nicht die Speicherressourcen eines
PC. Also wenn nur 8 Bit gebraucht werden, auch nur ne 8-Bit-Variable
nehmen (ist gegenüber einem int ein gespartes Byte).

von johnny.m (Gast)


Lesenswert?

Hast Du eigentlich ein C-Buch? Wenn nicht, bitte besorge Dir eins bevor
Du weitermachst. In Deinem Programm sind so viele elementare Fehler
drin (v.a. was den Umgang mit Funktionen angeht), dass das hier im
Forum sicher den Rahmen sprengen würde. Bitte beschäftige Dich
eigehender damit! Trotzdem viel Spaß beim basteln!

von MasterFX (Gast)


Lesenswert?

Ja, irgentwie ist das alles ein bissl seltsam bei dir. Z.B. fragst du im
Hauptprogramm den KEY2 ab (read_key(KEY2)). Ist zwar schön und gut, aber
du speicherst den Wert ja gar nicht ab. Danach machst du dann "if
(key_status == 1)", die variable key_status gibt es aber nicht.
Eher sinnvoller wäre sowas wie:
[c]
int main(void){
  char key_status;
  ...
  key_status = read_key(KEY2);
  if(key_status == 1)
     ...
}

von Gast (Gast)


Lesenswert?

Danke, das reichte als Denkansatz. Habs nun hinbekommen, wenigstens
etwas :-D

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.