Forum: Mikrocontroller und Digitale Elektronik Frage zu Entprellungsprogramm


von Frank (Gast)


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ß

von Herr Biber (Gast)


Lesenswert?

Ich versteh dein Probelm nicht, normalerweise teilt dir ein Compiler 
doch mit in welcher Zeile der Fehler liegt...

von Frank (Gast)


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.

von Krapao (Gast)


Lesenswert?

> Leider bekomme ich beim Compilieren bisher immer noch einen
> Übersetzungsfehler.

Welchen? Dein Quellcode bietet mehrere Möglichkeiten.

von STK500-Besitzer (Gast)


Lesenswert?

Frank schrieb:
> Leider bekomme ich beim Compilieren bisher immer noch einen
> Übersetzungsfehler

Und was meldet der Compiler genau?

von Booool (Gast)


Lesenswert?

C - kein bool Datentyp ( standardmäßig )
C++ - hat bool

Das sollte alles erklären.

von Thomas E. (thomase)


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.

von Frank (Gast)


Lesenswert?

Booool schrieb:
> C - kein bool Datentyp ( standardmäßig )
> C++ - hat bool

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

von Thomas E. (thomase)


Lesenswert?

Frank schrieb:
> Booool schrieb:
>> C - kein bool Datentyp ( standardmäßig )
>> C++ - hat bool
>
> Was gibt es dann für ne alternative Möglichkeit das Ganze in C zu
> programmieren?

Keine Ahnung, was der will. Wahrscheinlich hat er letzte Nacht zuviel 
getrunken.

mfg.

von Frank (Gast)


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ß

von Peter II (Gast)


Lesenswert?

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

von Thomas E. (thomase)


Lesenswert?

Frank schrieb:
> Also einen Fehler in den LCD-Unterprogrammen kann ich ausschließen.
Das sagen alle. Aber dann würde es auch laufen.

Frank schrieb:
> Falls also wirklich ein Semikolon fehlen sollte, kann es nur im
> dargestellten Code sein.
Da ist kein Fehler drin.

Peter II schrieb:
> jeder schlaue compiler wird sie einfach ignorieren
Warum sollte er das tun?

mfg.

von Krapao (Gast)


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.

von Frank (Gast)


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ß

von Frank (Gast)


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ß

von Thomas E. (thomase)


Lesenswert?

Krapao schrieb:
> bool entprellung(uint8_t port)
Hast recht. Das ist der Fehler.
Nehme alles zurück.
Booool (Gast) ist nicht betrunken.

#include <stdbool.h> und dann geht's.

mfg.

von Thomas E. (thomase)


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.
}

von Frank (Gast)


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ß

von Yalu X. (yalu) (Moderator)


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.

von Purzel H. (hacky)


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.

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.