Frage zu Entprellungsprogramm

Gast #2502709
Lesenswert?

Hallo,
bin gerade dabei ein Programm für eine einfache Tasterentprellung zu 
schreiben. Leider bekomme ich beim Compilieren bisher immer noch einen 
Übersetzungsfehler. Hier ist mein bisheriges Programm:
1
#include <avr/io.h>
2
#include <util/delay.h>  
3
#include "lcd-routines.h"
4

5
char buffer[20];
6

7

8
void delay_ms(uint16_t ms)
9
{
10
  while(ms>0)
11
  {
12
  _delay_ms(1);
13
  ms--;
14
  }
15
}
16

17

18
bool entprellung(uint8_t port)
19
{
20
  
21
  
22
  if(!(PIND & (1<<port)))    //wenn Taster gedrückt, also PD0 auf low
23
  {  
24
    delay_ms(10);    //10ms warten, danach abfragen ob Pin PD0 immer noch auf low ist
25
    
26
    if(!(PIND & (1<<port)))
27
    {  lcd_setcursor(0,1);
28
        lcd_string("buffer");          
29
      return 1;
30
      
31
    }
32
    return 0;
33
  }
34
}
35

36

37

38
int main(void)
39
{
40

41
  DDRD = 0x00;  //alle Ports als Eingang
42
  DDRB = 0xFF;  //alle Ports als Ausgang
43
  PORTB = 0xFF;  //alle LEDs aus
44

45
  lcd_init();
46
  lcd_setcursor(0,1);
47
  lcd_string("Hallo");
48

49

50

51

52
  while(1)
53
  {
54
    if(entprellung(PD0))
55
    {
56
      PORTB &= ~(1<<PB7);  //LED7 an, wenn taster an  PD0 gedrückt
57
    }
58
    
59
    
60
      
61
  }
62

63

64

65
}

Der Fehler muss auf jeden Fall an meiner Funktion entprellung liegen. 
Ich möchte, dass diese bei gedrücktem Taster ein True und bei nicht 
gedrückem ein False zurückgibt und somit bestimmt ob die LED7 an PD0 
eingeschaltet wird.

Wer kann mir sagen, was ich codetechnisch ändern muss, damit das 
Programm fehlerfrei übersetzt wird?

Gruß
Gast #2502720
Lesenswert?

hier ist die Fehlermeldung:

../Tasterentprellung.c:18: error: expected '=', ',', ';', 'asm' or 
'__attribute__' before 'entprellung'


Leider wird mir die Stelle im Programm beim anklicken der Fehlermeldung 
grad nicht angezeigt. Weiß auch nicht warum das des AVR Studio da nicht 
macht. Normal geht des nämlich schon.
#2502747
Lesenswert?

Frank schrieb:
> Der Fehler muss auf jeden Fall an meiner Funktion entprellung liegen.
Nein. Deine Fehlermeldung sagt dir doch, wo der Fehler liegt:

> ../Tasterentprellung.c:18: error: expected '=', ',', ';', 'asm' or
> '__attribute__' before 'entprellung'
>>before 'entprellung'
Da fehlt VORHER was.

#include <avr/io.h>
#include <util/delay.h>
#include "lcd-routines.h"

die io.h und die delay.h gehören zur libc, die lcd-routines.h und die 
vermutliche lcd-routines.c sind von dir.
Wahrscheinlich fehlt irgendwo ein Semikolon.
Entscheide selber, wo du anfängst zu suchen.

mfg.
Gast #2502753
Lesenswert?

Thomas Eckmann schrieb:
> die io.h und die delay.h gehören zur libc, die lcd-routines.h und die
> vermutliche lcd-routines.c sind von dir.
> Wahrscheinlich fehlt irgendwo ein Semikolon.
> Entscheide selber, wo du anfängst zu suchen

Also einen Fehler in den LCD-Unterprogrammen kann ich ausschließen. Die 
wurden in der Vergangenheit schon ausgiebig getestet und verwendet. 
Falls also wirklich ein Semikolon fehlen sollte, kann es nur im 
dargestellten Code sein.

Gruß
Gast #2502769
Lesenswert?

>> Frank:
> Was gibt es dann für ne alternative Möglichkeit das Ganze in C zu
> programmieren?

Einen in C bekannten Datentyp nehmen.

Also statt
bool entprellung(uint8_t port)

z.B.
#include <stdint.h> // für uint8_t
...
uint8_t entprellung(uint8_t port)

>>  Peter II:
> deine funktion delay_ms ist auch sehr ungünstig. jeder schlaue compiler
> wird sie einfach ignorieren.

IMHO stimmt das nicht. delay_ms hat als Seiteneffekt einen Aufruf 
Funktion _delay_ms, die ihrerseite volatile gekennzeichnete Anweisungen 
enthält. Der Aufruf von delay_ms darf nicht "wegoptimiert" werden.
Gast #2502771
Lesenswert?

Peter II schrieb:
> deine funktion delay_ms ist auch sehr ungünstig. jeder schlaue compiler
> wird sie einfach ignorieren.

Ich habs gerade mit meinem LCD getestet. Die Funktion delay_ms() wird 
ausgeführt.


Jetzt hab ich das Programm leicht abgeändert und jetzt funktioniert es 
wie gewünscht:
1
#include <avr/io.h>
2
#include <util/delay.h>  
3
#include "lcd-routines.h"
4

5
char buffer[20];
6

7

8
void delay_ms(uint16_t ms)
9
{
10
  while(ms>0)
11
  {lcd_setcursor(0,1);
12
    lcd_string("Zeitverzoegerung");
13
  _delay_ms(1);
14
  ms--;
15
  }
16
}
17

18

19
inline uint8_t entprellung(uint8_t port)
20
{
21
  
22
  
23
  if(!(PIND & (1<<port)))    //wenn Taster gedrückt, also PD0 auf low
24
  {  
25
    delay_ms(10);    //10ms warten, danach abfragen ob Pin PD0 immer noch auf low ist
26
    
27
    if(!(PIND & (1<<port)))
28
    {            
29
      return 1;
30
      
31
    }
32
    return 0;
33
  }
34
}
35

36

37

38
int main(void)
39
{
40

41
  DDRD = 0x00;  //alle Ports als Eingang
42
  DDRB = 0xFF;  //alle Ports als Ausgang
43
  PORTB = 0xFF;  //alle Pins auf high => alle LEDs aus
44

45
  lcd_init();
46
  lcd_setcursor(0,1);
47
  lcd_string("Hallo");
48

49

50

51

52
  while(1)
53
  {
54
    if(entprellung(PD0))
55
    {
56
      PORTB &= ~(1<<PB7);  //LED7 an, wenn taster an PD0 gedrückt
57
    }
58
    
59
    
60
      
61
  }
62

63

64

65
}

das "inline uint8_t" vor der Funktion entprellung hab ich aus einem 
Beispielprogramm von dieser Seite "geklaut":

http://www.mikrocontroller.net/articles/Entprellung

Jetzt lässt sich das Programm fehlerfrei übersetzen und funktioniert 
auch so wie ich will.

Jetzt ist nur mein Problem, dass ich die Bedeutung von dem "inline 
uint8_t" in Verbindung mit der Funktion entprellung nicht verstehe bzw 
kenne. Es muss sich wohl auf den Rückgabewert der Funktion beziehen

Kann mir vielleicht jemand die Bedeutung in diesem Zusammenhang 
erklären?

Gruß
Gast #2502781
Lesenswert?

Krapao schrieb:
> z.B.
> #include <stdint.h> // für uint8_t
> ...
> uint8_t entprellung(uint8_t port)

Hab ich jetzt im Nachhinein auch ausprobiert. Lässt sich zwar fehlerfrei 
compilieren. Das Programm funktioniert aber dann nicht mehr wie 
gewünscht, da die LED dann dauerhaft leuchtet, auch dann schon wenn ich 
den Taster noch gar nicht gedrückt habe.

Gruß
#2502792
Lesenswert?

Frank schrieb:
> Das Programm funktioniert aber dann nicht mehr wie gewünscht,

Deine Funktion ist unvollständig.
Sie handelt nur den Fall ab, wenn die Taste gedrückt wurde. Was macht 
sie, wenn die Taste nicht gedrückt wurde?

bool entprellung(uint8_t port)
{
  if(!(PIND & (1<<port)))  {
    delay_ms(10);

    if(!(PIND & (1<<port)))
    {  lcd_setcursor(0,1);
        lcd_string("buffer");
      return 1;

    }
    return 0;
  }
return 0;  //Damit sollte es gehen.
}
Gast #2503051
Lesenswert?

Thomas Eckmann schrieb:
> Deine Funktion ist unvollständig.
> Sie handelt nur den Fall ab, wenn die Taste gedrückt wurde. Was macht
> sie, wenn die Taste nicht gedrückt wurde?
>
> bool entprellung(uint8_t port)
> {
>   if(!(PIND & (1<<port)))  {
>     delay_ms(10);
>
>     if(!(PIND & (1<<port)))
>     {  lcd_setcursor(0,1);
>         lcd_string("buffer");
>       return 1;
>
>     }
>     return 0;
>   }
> return 0;  //Damit sollte es gehen.
> }

Stimmt. Jetzt hab ich das Programm mal folgendermaßen abgeändert und 
jetzt funktioniert alles wie gewünscht:
1
#include <avr/io.h>
2
#include <util/delay.h>  
3
#include "lcd-routines.h"
4
#include <stdbool.h>
5

6
char buffer[20];
7

8

9
void delay_ms(uint16_t ms)
10
{
11
  while(ms>0)
12
  {lcd_setcursor(0,1);
13
    lcd_string("Zeitverzoegerung");
14
  _delay_ms(1);
15
  ms--;
16
  }
17
}
18

19

20
bool entprellung(uint8_t port)
21
{
22
  
23
  
24
  if(!(PIND & (1<<port)))    //wenn Taster gedrückt, also PD0 auf low
25
  {  
26
    delay_ms(10);    //10ms warten, danach abfragen ob Pin PD0 immer noch auf low ist
27
    
28
    if(!(PIND & (1<<port)))
29
    {            
30
      return 1;
31
      
32
    }
33
    return 0;
34
  }
35
  return 0;
36
}
37

38

39

40
int main(void)
41
{
42

43
  DDRD = 0x00;  //alle Ports als Eingang
44
  DDRB = 0xFF;  //alle Ports als Ausgang
45
  PORTB = 0xFF;  //alle Pins auf high => alle LEDs aus
46

47
  lcd_init();
48
  lcd_setcursor(0,1);
49
  lcd_string("Hallo");
50

51

52

53

54
  while(1)
55
  {
56
    if(entprellung(PD0))
57
    {
58
      PORTB &= ~(1<<PB7);  //LED7 an, wenn taster an PD0 gedrückt
59
    }
60
    
61
    
62
      
63
  }
64

65

66

67
}

Interessanterweise funktioniert das Programm nicht richtig, wenn ich das 
zweite return 0 in der Funktion entprellung weglasse. Dann leuchtet 
nämlich die LED auch dann schon, wenn ich noch gar nicht den Taster 
gedrückt habe.
Ich kann mir dieses Phänomen nur so erklären, dass die Funktion 
entprellung dann auch bei nicht gedrücktem Taster ein True-Ergebnis 
zurückmeldet. Kann diese Einschätzung jemand bestätigen?

Gruß
Moderator #2503085
Lesenswert?

Frank schrieb:
> Interessanterweise funktioniert das Programm nicht richtig, wenn ich das
> zweite return 0 in der Funktion entprellung weglasse.

Weil dann der Rückgabewert bei nicht gedrückter Taste undefiniert ist.
Schaltest du mit -Wall die Ausgabe von Compiler-Warnungen ein, wird dir
dies mit der Meldung
1
warning: control reaches end of non-void function

mitgeteilt.

Übrigens hätte bei deinem ursprünglichen Problem ein etwas aktuellerer
GCC (4.6+) folgende Fehlermeldung ausgegeben, wodurch sich deine erste
Frage wahrscheinlich erübrigt hätte:
1
../Tasterentprellung.c:18:1: error: unknown type name 'bool'

Noch etwas: Wenn eine Funktion vom Typ bool ist, sollte sie konsequen-
terweise nicht 0 oder 1, sondern false oder true zurückgeben. Diese
Konstanten sind ebenfalls in stdbool.h definiert.
#2503165
Lesenswert?

Das Programm ist leider kompletter Muell.

1) eine Delay funktion ist der Beginn allem Uebels.
   Denn sie wartet nicht nur, sondern macht das
   Programm auch total unuebersichtlich. Das ist
   die sogenannte Procedurale Programmierung.
   Irgendwann weiss man nicht mehr genau wo das
   Programm denn steht. Und dann wird es schwierig.
2) Man sollte sich angewoehnen in main genau an
   einer Stelle zu warten, und den Rest mit einer
   Zustandsmaschine zu machen. Das oben beschriebene
   Problem ist hier viel einfacher, denn man weiss
   wo im code Das Programm wartet, man weiss nur
   den State nicht, un den kann man dann einfach
   mitteilen.
3) arbeite mit einem Timer, der einen Tick vorgibt.
   zB 10ms, oder aehnlich. Der Timer setzt ein Flag,
   und auf das reagiert man dann im Main.

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