Forum: Compiler & IDEs Entprellung funktioniert nicht


von Mathias O. (m-obi)


Lesenswert?

hallo,

meine Entprellung funktioniert nicht, Funktion key_pressed_1 
funktioniert aber die andere key_pressed_2 nicht.
Woran kann das liegen?

1
#define Taster_2 (PIND&(1<<PD3))
2
3
uint8_t key_pressed_1(const volatile uint8_t *inputreg, uint8_t inputbit)
4
{
5
  static uint8_t last_state = 0;
6
 
7
  if (last_state==(*inputreg&(1<<inputbit)))
8
  {
9
    return 0;
10
  }
11
 
12
  _delay_ms(20);
13
 
14
  last_state=(*inputreg&(1<<inputbit));
15
 
16
 
17
  return ( *inputreg & (1<<inputbit) );
18
}
19
 
20
 
21
22
 uint8_t key_pressed_2(const volatile uint8_t *input)
23
{
24
  static uint8_t last_state = 0;
25
 
26
  if ( last_state == *input ) {
27
     return 0; 
28
  }
29
 
30
  _delay_ms(20);
31
 
32
  last_state = *input;
33
 
34
  return *input;
35
}
36
37
38
39
int main(void)
40
{
41
42
DDRD = 0b11100011;
43
44
while(1)
45
{                
46
if (key_pressed_1(&PIND,PD2))
47
PORTD ^= (1<<5);
48
          
49
if (key_pressed_2(Taster_2))
50
PORTD ^= (1<<6);
51
}
52
return 0;
53
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> uint8_t key_pressed_2(const volatile uint8_t *input)
> if (key_pressed_2(Taster_2))
> #define Taster_2 (PIND&(1<<PD3))

Ist Taster_2 ein const volatile uint8_t * ? Ich denke nicht!

PS: Mich würde stark wundern, wenn der Compiler da nicht meckert.

von Mathias O. (m-obi)


Lesenswert?

was denn???

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Mathias Obetzhauser wrote:
> was denn???

Vorsicht Offtopic!

Der normale Entwicklungszyklus:

1. Unterlagen studieren
2. Rechenvorschrift ausdenken
3. Rechenvorschrift in Code pressen
4. Compiler Code auf formale Bugs checken lassen
5. Gesäuberten Code anderen vorlegen, um fettere Bugs zu finden
6. Automatische Tests ausführen
7. Interaktiv/Im System Debuggen

Warum diese Reihenfolge?

Die einzelnene Schritte sind mit steigendem Aufwand geordnet. Saubere 
Arbeit in den frühen Schritten reduziert den Aufwand in den späteren 
Schritten.

Mit der Anfrage inkl. Codefetzen steigt der OP in den Schritt 5 ein. 
Allerdings ist das kein gesäuberter Code. Der Compiler hätte in Schritt 
4 den Code angemostert. Abgesehen davon hat der OP 1. und 2. denjenigen 
vorenthalten, die für ihn "arbeiten sollen". Ein Projektleiter würde 
sagen, der OP hat "Resourcen verschwendet".

Die Idee für dieses Offtopic ist mir dadurch gekommen:

Lean coding
What's the cheapest way to get rid of bugs? Inspect code early and 
often.
By Jack Ganssle
http://www.embedded.com/design/212200181

von Mathias O. (m-obi)


Lesenswert?

mit der Antwort kann ich recht wenig anfangen....


achja und der Compiler meckert nicht

von Juergen (Gast)


Lesenswert?

0. Anforderungen definieren (was soll der Code eigentlich genau machen?)

Juergen

von Stefan B. (stefan) Benutzerseite


Lesenswert?

@ Juergen

Stimmt!

von Mathias O. (m-obi)


Lesenswert?

Das sind Entprell-Funktionen für Taster, wie gesagt die erste 
funktioniert aber die zweite nicht. Ich wollte es mit dem #define etwas 
vereinfachen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Weil durch dein falsches Makro für Taster_2 in key_pressed_2() nur ein 
uint8_t Wert ankommt. Diesen durch den Prototypen geschickt (gecastet) 
und mit dem Funktionscode als Pointer ausgewertet, ist ein Bug. Ein 
fetter Bug.

von Mathias O. (m-obi)


Lesenswert?

und wie kann man diesen Bug beseitigen, bin relativ neu in Sachen C.

von P. S. (Gast)


Lesenswert?

Stefan B. wrote:

> Mit der Anfrage inkl. Codefetzen steigt der OP in den Schritt 5 ein.
> Allerdings ist das kein gesäuberter Code.

Den Vortrag kannst du dir schenken, ist ja nicht der erste Thread des 
Posters, in dem ihm erklaert wird, wie man entwickelt...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Lernen ist Wiederholung. Nie die Hoffnung aufgeben ;-)

von Peter D. (peda)


Lesenswert?

Jaja, Entprellen ist ja so popeleinfach.

Deshalb ist es für nen Anfänger völlig unzumutbar, erstmal in Tutorials 
oder Codebeispiele reinzuschauen, wie man es richtig machen könnte.

Nur wenn man schon viele mehr schlecht als recht funktionierende 
Entprellungen selber gemacht hat, schaut man da mal rein, hat ein 
Aha-Erlebnis und nie wieder Entprellprobleme.

Aber ich kann keinem verbieten, den steinigen Weg zu gehen, nur zu.


Peter


P.S.:
Schau dochmal ins Assemblerlisting, wieviel Code Du verheizt mit Deinen 
Pointern. Und dann vergleiche mal mit professionellen Entprellroutinen, 
wie schlank und schnell die dagegen sind.

von yalu (Gast)


Lesenswert?

> achja und der Compiler meckert nicht

Bei mir schon (GCC 4.2.4 und GCC 4.3.2), nämlich in der Zeile
1
if (key_pressed_2(Taster_2))

Da meckert er zurecht folgendes:
1
warning: passing argument 1 of 'key_pressed_2' makes pointer from integer without a cast

Hast du vielleicht alle Warnungen des Compilers abgeschaltet? Das sollte
man nicht tun.

> und wie kann man diesen Bug beseitigen, bin relativ neu in Sachen C.

Am besten nur key_pressed_1 statt key_pressed_2 verwenden ;-)

Das Problem: Ein Input-Pin des Controllers ist allgemein definiert durch
einen 8-Bit-Port und eine Bitnummer innerhalb dieses Ports. Da der Input
in der Funktion mehrfach abgefragt wird, muss ihr in irgendweiner Form
eine Referenz auf das abzufragende Bit übergeben werden (du übergibst
aktuell nur den Wert des Bits). C kennt aber leider keine
Bitreferenzen, weswegen man sich anders behelfen muss, bspw.

- indem man eine Referenz auf den Port (in Form eines Zeigers) und die
  Bitnummer als zwei Argumente übergibt (so hast du es in
  key_pressed_1 getan),

- indem man die Referenz auf den Port und die Bitnummer in eine Struktur
  packt, und diese dann als eine Einheit übergibt oder

- indem man eine Zugriffsfunktion für den betreffenden Input definiert
  und diese Zugriffsfunktion als Funktionszeiger an die Entprellfunktion
  übergibt.

Da die beiden letztgenannten Alternativen nicht viel zur Lesbarkeit
beitragen, wahrscheinlich den Programmcode vergrößern, einiges an
Verständnis über Strukturen bzw. Funktionszeigern erfordern und neue
potenzielle Fehlerquellen darstellen, würde ich an deiner Stelle einfach
das key_pressed_1 weiterverwenden.

Ganz abgesehen davon taugt deine Entprellroutine nicht sehr viel, da sie
nicht viel mehr tut als mit dem delay_ms die Abfragefrequenz zu
reduzieren. Das bringt zwar schon einen gewissen Verbesserungseffekt,
erschlägt aber bei weitem nicht alle möglichen Fälle. Bspw. sind kurze
Kontaktunterbrechungen bei gedrücktem Taster, wie sie bspw. bei
Kurzhubtastern auftreten können, überhaupt nicht abgedeckt.

Nimm dir Peters Kommentar zu Herzen und schau dir die einschlägigen
Artikel dazu an :)

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.