Debounce-Makro von Peter Dannegger - MSP430

Gast #6227602
Lesenswert?

Ich versuche, die Routine auf meine Plattform anzupassen.
folgendes habe ich bis jetzt erreicht:
1
/************************************************************************/
2
/*                                                                      */
3
/*                      Not so powerful Debouncing Example              */
4
/*                      No Interrupt needed                             */
5
/*                                                                      */
6
/*              Author: Peter Dannegger                                 */
7
/*                                                                      */
8
/************************************************************************/
9

10
#include "msp430f5529.h"            // Einbinden der Definitionen
11
#define  LED_X     0x01     // LED (rot) an P1.0
12
#define  T_SET     0x02     // Taster an P2
13

14
#define debounce( port, pin )                                         \
15
({                                                                    \
16
  static unsigend char flag = 0;     /* new variable on every macro usage */  \
17
  unsigend char i = 0;                                                      \
18
                                                                      \
19
  if( flag ){                  /* check for key release: */           \
20
    for(;;){                   /* loop ... */                         \
21
      if( !(P2IN & 1<<T_SET) ){  /* ... until key pressed or ... */     \
22
        i = 0;                 /* 0 = bounce */                       \
23
        break;                                                        \
24
      }                                                               \
25
      _delay_us( 98 );         /* * 256 = 25ms */                     \
26
      if( --i == 0 ){          /* ... until key >25ms released */     \
27
        flag = 0;              /* clear press flag */                 \
28
        i = 0;                 /* 0 = key release debounced */        \
29
        break;                                                        \
30
      }                                                               \
31
    }                                                                 \
32
  }else{                       /* else check for key press: */        \
33
    for(;;){                   /* loop ... */                         \
34
      if( (P2IN & 1<<T_SET) ){   /* ... until key released or ... */    \
35
        i = 0;                 /* 0 = bounce */                       \
36
        break;                                                        \
37
      }                                                               \
38
      _delay_us( 98 );         /* * 256 = 25ms */                     \
39
      if( --i == 0 ){          /* ... until key >25ms pressed */      \
40
        flag = 1;              /* set press flag */                   \
41
        i = 1;                 /* 1 = key press debounced */          \
42
        break;                                                        \
43
      }                                                               \
44
    }                                                                 \
45
  }                                                                   \
46
  i;                           /* return value of Macro */            \
47
})
48

49
/*
50
   Testapplication
51
 */
52
int main(void)
53
{
54
  WDTCTL = WDTPW + WDTHOLD;   // WatchDogTimer abschalten
55
          
56
          
57
 // -- INIT_Port1
58
  P1SEL &= ~(LED_X);            // Beide sind BIN-IO       
59
  P1DIR |= LED_X;               // LED    = BIN-OUT
60
  P1OUT &= ~(LED_X);            // LED_X = AUS (weil H-aktiv)
61
      // INIT_Port_2
62
    P2SEL  &= ~(T_SET);           // Funktion ist BIN-IO
63
    P2DIR  &= ~(T_SET);           // Taster ist BIN-IN
64
    P2IES  |= T_SET;              // Int. bei neg. Flanke (H-->L)
65
    P2IE   |= (T_SET);           // Beim System.Start noch nicht frei gegeben
66
    P2IFG  &= ~(T_SET);           // Alte Fl. Ereignis löschen
67
    //
68
    P2REN |= T_SET;               // Intern.Widerstand = aktiv
69
    P2OUT |= T_SET;               // Als PullUp eingestellt
70
    
71
    
72
  for(;;){
73
    if( debounce( P2IN, T_SET ) )
74
      PORTB ^= 1<<PB2;
75
    if( debounce( PINB, PB0 ) )
76
      PORTB ^= 1<<PB3;
77

78
    _BIS_SR(GIE); 
79
  }
80
 while(1) {_NOP();}
81
}
Gast #6227611
Lesenswert?

zwei Fragen ergeben sich mir:

1. Die Funktion
1
 _delay_us( 98 );         /* * 256 = 25ms */
kommt aus diesem File #include <util/delay.h>. kann ich dieses File auch 
auf meiner Plattform laden?

2.
1
  for(;;){
2
    if( debounce( PINB, PB1 ) )
3
      PORTB ^= 1<<PB2;
4
    if( debounce( PINB, PB0 ) )
5
      PORTB ^= 1<<PB3;
6
  }
ich weiß nicht, was dass in meinem konkreten fall bedeutet
Gast #6227650
Lesenswert?

laut dem Tutorial in diesem Form gilft folgendes (siehe Anhang)

deswegen habe ich den Datentyp char als "Übersetzung" gewählt und nicht 
Integer. Inhaltlich macht das aber nicht viel Sinn...

Über Rückmeldungen würde ich mich freuen. Bin Anfänger, habe noch nie 
mit einem AVR gearbeitet, möchte aber vernünftig Entprellen
Angehängte Dateien:
#6228244
Lesenswert?

kopr schrieb:
> kommt aus diesem File #include <util/delay.h>. kann ich dieses File auch
> auf meiner Plattform laden?

Nun das Delay-Macro benutzt AVR-Assembler, dürfte also für den MSP 
Syntaxerror bedeuten. Der Trick an dem Macro ist, daß es das Macro F_CPU 
auswertet, d.h. man kann ganz bequem die Zeit in ms übergeben.
Eine stumpfe Zählschleife kann sowas nicht leisten. Die müßte man 
ausmessen oder ein Delay mittels Timer implementieren.
Vielleicht gibt es ja für Deinen MSP-Compiler auch eine funktionsgleiche 
Lib.

kopr schrieb:
> for(;;){
>     if( debounce( PINB, PB1 ) )
>       PORTB ^= 1<<PB2;
>     if( debounce( PINB, PB0 ) )
>       PORTB ^= 1<<PB3;
>   }
> ich weiß nicht, was dass in meinem konkreten fall bedeutet

PINB: Name eines 8Bit Input-Ports des AVRs
PORTB: Name eines 8Bit Output-Ports des AVRs
PB0..PB7 Bitnummern eines Ports (0..7)

Beim MSP sind die IO-Ports vermutlich 16Bit und haben andere Namen.
Wenn keine Bitnummern der Ports definiert sind, kannst Du auch einfach 
0..15 schreiben.
Gast #6228498
Lesenswert?

ahhh, der lukker ist zurück. ;->>>

kopr schrieb:
> 1<<PB2

Das ist die vergrützte Schreibweise der halbgaren AVR-Tool-Unterstützer. 
Bei richtigen Architekturen schreibt man so etwas nicht.

Für den MSP sind die #define - so wie es sich gehört - mit Masken 
belegt. Auch für BIT0...15 gibt es Masken in den header.

#define  T_SET     0x02     // Taster an P2
1
#define T_SET   BIT1

kopr schrieb:
> if( !(P2IN & 1<<T_SET) ){  /* ... until key pressed or ... */

Warum hier T_SET? Du rufst ein Makro mit Parameter auf:
1
  if( !(P2IN & pin) ){

Und warum baust du nops ein? Hat mich bei deinen anderen Threads immer 
schon gewundert.
Gast #6229435
Lesenswert?

das Problem ist: ich kann die Logik der Routine nicht verstehen, weil 
ich mich nicht mit AVR auskenne. Und wenn ich die Logik nicht verstehe, 
weiß ich nicht, wie ich den Code für Taster T_SET an Port 2.1 anzupassen 
habe. Kann mir jemand bei diesem Schritt helfen? Ich denke, dass ich den 
Code mit der Anpassung verstehen kann.
Gast #6229459
Lesenswert?

kopr schrieb:
> MaWin schrieb:
> if( !(P2IN & 1<<T_SET) ){  /* ... until key pressed or ... */
> Warum hier T_SET?
>
> was stimmt denn nicht damit? es ist der Pin 2.1 an der Taster liegt.

Dem Makro werden Port und Pin mitgegeben. Die muss man dann auch 
verwenden.
if( !(P2IN & 1<<T_SET)
1
if (!(port & pin))
Gast #6229515
Lesenswert?

kopr schrieb:
> könnt ihr nicht oder wollt ihr nicht?

kopr schrieb:
> das Problem ist: ich kann die Logik der Routine nicht verstehen...

Ja, eben.
Zuerst wirst du frech und dann kommt heraus, daß du die Logik hinter dem 
Entprellen von Tasten nicht verstehst - UND daß du dies auch mit der 
größten Selbstverständlichkeit der Welt sagst ohne dich zu schämen.

Das Entprellen von Tasten ist doch wirklich kein unendlich schwer zu 
verstehendes Problem. Und es ist in der Sache völlig unabhängig von der 
Art des verwendeten µC. Allerdings hast du es bei Peters Routinen eben 
mit einer Implementation zu tun, die sich auf die AVR konzentriert hat. 
Eben deshalb ist es besser, die Sache zu verstehen, als ohne deren 
Verständnis Peters Routinen benutzen zu wollen.

Programmtechnisch hat man mit folgenden Zuständen zu tun:
1. Taste war ungedrückt und ist jetzt gedrückt: Also erzeugt man an 
dieser Stelle ein "Tasten-Ereignis" zum Auswerten und merkt sich 
nebenbei, daß die Taste jetzt als gedrückt gilt. Das tut man, indem man 
einen Entprellzähler auf einen gewünschten Startwert setzt.

2. Taste war gedrückt und ist immer noch gedrückt. OK, nix tun, außer 
den Entprellzähler wieder auf den Startwert setzen.

3. Taste ist ungedrückt und war gedrückt: Entprellzähler herunterzählen. 
Wenn der auf Null kommt, dann gilt ab da die Taste als ungedrückt.

4. Taste war ungedrückt und ist ungedrückt. Nix tun.

Wenn man dazu noch repetieren will, dann muß man beim Zustand 1. auch 
noch nen Repetierzähler auf einen größeren Wert setzen (so für ca. 1 
Sekunde) und diesen im Zustand 2 herunterzählen. Dann kommt hinzu:

2a. Wenn Repetierzähler auf null geht, dann Tasten-Ereignis (oder 
Repetier-Ereignis, je nach deinem Geschmack) erzeugen und den 
Repetierzähler auf eine kürzere Zeit setzen (so etwa 0.15 bis 0.2 
Sekunden).

Wie groß die Entprell- und Repetierzahlen sein müssen, hängt von deinem 
Polling-Intervall ab. Für das schiere Entprellen reichen 20..30 ms aus, 
das macht bei 10 ms Polling-Intervall einen Startwert von 2..3. Die 
Werte für's Repetieren rechnest du dir selber aus.

So. jetzt solltest du das Entprellen von Tasten verstanden haben.

W.S.
Gast #6229517
Lesenswert?

kopr schrieb:
> was stimmt denn nicht damit? es ist der Pin 2.1 an der Taster liegt.

Wobei wir ja auch schon wissen, dass Dein ursprünglicher Code auch nicht 
mit pin1 (0x02) funktioniert.

Wenn Du Deinen Taster nicht auswerten kannst, wird auch Peters 
Entprellung das nicht heilen.

Sorge doch dafür, dass die LED an ist, wenn die Taste gedrückt wurde. 
Und das ohne Code, der implizit irgendwas zurückgibt.

Entstellung ist dann der nächste (wichtige) Schritt.
#6229551
Lesenswert?

kopr schrieb:
> das Problem ist: ich kann die Logik der Routine nicht verstehen, weil
> ich mich nicht mit AVR auskenne. Und wenn ich die Logik nicht verstehe,
> weiß ich nicht, wie ich den Code für Taster T_SET an Port 2.1 anzupassen
> habe. Kann mir jemand bei diesem Schritt helfen?

Klar, kein Copy&Past!

Lieber das Problem verstehen:
https://www.mikrocontroller.net/articles/Entprellung

Da is also nich viel dran, es geht ja nur darum nur den einen 
Tastendruck zu erkennen und nicht 10-100 draus zu machen. Diese Makro 
blockiert auch noch den restlichen Programmablauf! Eigentlich ein 
No-Go....
Gast #6229562
Lesenswert?

W.S. schrieb:
> So. jetzt solltest du das Entprellen von Tasten verstanden haben.

das war eine sehr gute Erklärung, danke dir!

W.S. schrieb:
> 10 ms Polling-Intervall

woher weiß ich, wie groß das Intervall ist?

kopr schrieb:
> Datentyp char als "Übersetzung" gewählt

wenn du von den Zählern sprichst (i, Flag), dann sind das int und nicht 
char. Ist das so?

Peter D. schrieb:
> kopr schrieb:
>> for(;;){
>>     if( debounce( PINB, PB1 ) )
>>       PORTB ^= 1<<PB2;
>>     if( debounce( PINB, PB0 ) )
>>       PORTB ^= 1<<PB3;
>>   }
>> ich weiß nicht, was dass in meinem konkreten fall bedeutet
>
> PINB: Name eines 8Bit Input-Ports des AVRs
> PORTB: Name eines 8Bit Output-Ports des AVRs
> PB0..PB7 Bitnummern eines Ports (0..7)

PINB würde P2IN entsprechen , PB1 0x01
PORTB entspricht P2OUT, PB2 T_SET.
PB3 entspricht 0x04
Gast #6229595
Lesenswert?

Carl D. schrieb:
> Das sind 2 Paar Stiefel. Hier geht es um "Entprellen für Anfänger". Das
> von vielen geschätzte "PeDa-Verfahren" ist was ganz anderes.

dann hab ich das verwechselt. Ehe ich die Anfängervariante nicht 
umgesetzt bekomme, hat das Verfahren wohl keinen Sinn für mich
Gast #6229604
Lesenswert?

Teo D. schrieb:
> Klar, kein Copy&Past!

naja, die Sachen wurden doch genau für diesen zweck zur Verfügung 
gestellt und bestimmt nicht, um bloß den anderen Schreibarbeit zu 
sparen. Würde ich einen AVR nutzen, hätte ich einfach kopieren können. 
Das ist doch "unfair", wenn man dann bei einem Anfänger mit einer 
anderen Plattform den Finger in die Wunde legt...
Gast #6229616
Lesenswert?

könnt ihr euch bitte in meine Lage versetzen: alles ist neu für mich, 
selbst das Bedienen der Entwicklungsumgebung bereitet mir noch 
Schwierigkeiten. Die Entprellroutine wäre für mich ersteinmal Mittel zum 
Zweck. Um eine vernünftige Grundlage zu haben. Nicht den Fehler begehen, 
den andere Anfänger machen. Da wäre es echt super, wenn ihr mir bei der 
Übertragung zu meiner plattform helfen könntet, damit ich mir andere 
Basics angucken kann.
https://de.wikipedia.org/wiki/Paretoprinzip
#6229622
Lesenswert?

kopr schrieb:
> ich kann die Logik der Routine nicht verstehen, weil
> ich mich nicht mit AVR auskenne.

Nö, die Logik ist plain C und das ist es, was Du nicht verstehst.
Mit dem AVR hat das überhaupt nichts zu tun.
Das Macro verlangt als 2. Argument die Bitnummer, z.B. 3. Das Macro 
macht dann durch Schieben daraus die entsprechende Bitmaske, also
1 << 3 = 0x08
Man könnte auch gleich die Bitmaske übergeben, dann entfällt natürlich 
das Schieben. Aber das ist reine Geschmackssache und ist weder C noch 
AVR abhängig. Es erzeugt auch identischen Code, da es zur Compilezeit 
erfolgt.
Gast #6229627
Lesenswert?

Peter D. schrieb:
> Nö, die Logik ist plain C und das ist es, was Du nicht verstehst.
> Mit dem AVR hat das überhaupt nichts zu tun.
> Das Macro verlangt als 2. Argument die Bitnummer, z.B. 3. Das Macro
> macht dann durch Schieben daraus die entsprechende Bitmaske, also
> 1 << 3 = 0x08
> Man könnte auch gleich die Bitmaske übergeben, dann entfällt natürlich
> das Schieben. Aber das ist reine Geschmackssache und ist weder C noch
> AVR abhängig. Es erzeugt auch identischen Code, da es zur Compilezeit
> erfolgt.

das ist eine Super Erklärung, ich danke dir
#6229638
Lesenswert?

kopr schrieb:
> Da wäre es echt super, wenn ihr mir bei der
> Übertragung zu meiner plattform helfen könntet, damit ich mir andere
> Basics angucken kann.

Warum? Es gibt kaum ein einfacheres Problem, als prellende Tasten!
Also lerne ein Basic nach dem anderen und nicht querbeet wild rum 
kopieren, raten, um dann doch nichts wirklich verstanden zu haben!
Fang doch mal bei dem berühmten "Blinky" Programm mit Delays an und 
stell das auf "Nicht Blockierend" um (Timer...). Der Weg zum Entpellen 
ist da nur'n Flohüpferchen. Wenn das verstanden ist und du mehr als 
~8Tasten hast, dann sieh dir Pedas Zeug an.... Man muss das Rad ja 
nich immer neu erfinden. :)
Gast #6229661
Lesenswert?

Teo D. schrieb:
> Warum? Es gibt kaum ein einfacheres Problem, als prellende Tasten!
> Also lerne ein Basic nach dem anderen und nicht querbeet wild rum
> kopieren, raten, um dann doch nichts wirklich verstanden zu haben!
> Fang doch mal bei dem berühmten "Blinky" Programm mit Delays an und
> stell das auf "Nicht Blockierend" um (Timer...). Der Weg zum Entpellen
> ist da nur'n Flohüpferchen. Wenn das verstanden ist und du mehr als
> ~8Tasten hast, dann sieh dir Pedas Zeug an.... Man muss das Rad ja
> nich immer neu erfinden. :)

da hilft nur das Sprichwort: Wenn man sich auf andere verlässt, ist man 
verlassen.
Gast #6229674
Lesenswert?

kopr schrieb:
> in meinem Fall wäre es Bit 1, also mit Linksshift 1<<1= 0x02

Da sind wir wieder am Anfang.

Zeige deinen Code ohne entprellen. Wenn der funktioniert, ist das 
entprellen ein Klacks.

Dein Problem ist, dass Du bisher  den Taster hat nicht auswerten 
konntest. Und das du wenig Erfahrung mit C hast.

Also zeige was Du hast, und lass uns das erstmal ans laufen bringen. Und 
dann entprellen.
#6229689
Lesenswert?

kopr schrieb:
> Carl D. schrieb:
>> Das sind 2 Paar Stiefel. Hier geht es um "Entprellen für Anfänger". Das
>> von vielen geschätzte "PeDa-Verfahren" ist was ganz anderes.
>
> dann hab ich das verwechselt. Ehe ich die Anfängervariante nicht
> umgesetzt bekomme, hat das Verfahren wohl keinen Sinn für mich

Die "Profi"-Variante ist aber sehr verständlich dokumentiert und und 
arbeitet genau wie die "Anfänger"-Version, nur eben 8-(/16-/32-)fach 
parallel.

Schlicht:
Alle 1..10 ms:
- Eingangswert ändert sich in Richtung "offen" -> lösche Zähler
- Einganswert ändert sich in Richtung "zu" -> incrementiere Zähler
- max. Zählerwert erreicht -> Taste als "gedrückt" ansehen

Die "Profi"-Version macht das in einem Interrupt, die andere durch 
Warten für den Fall daß sich auf der Leitung was tut.
Gast #6229715
Lesenswert?

1
/************************************************************************/
2
/*                                                                      */
3
/*                      Not so powerful Debouncing Example              */
4
/*                      No Interrupt needed                             */
5
/*                                                                      */
6
/*              Author: Peter Dannegger                                 */
7
/*                                                                      */
8
/************************************************************************/
9

10
#include "msp430f5529.h"            // Einbinden der Definitionen
11
#define  LED_X     0x01   BIT 1 // LED (rot) an P1.0
12
#define  T_SET     0x02   BIT 2  // Taster an P2
13

14
#define debounce( 2, 1 )                                         \
15
({                                                                    \
16
  static unsigend int flag = 0;     /* new variable on every macro usage */  \
17
  unsigend int i = 0;                                                      \
18
                                                                      \
19
  if( flag ){                  /* check for key release: */           \
20
    for(;;){                   /* loop ... */                         \
21
      if( !(2 & 1<<1) ){  /* ... until key pressed or ... */     \
22
        i = 0;                 /* 0 = bounce */                       \
23
        break;                                                        \
24
      }                                                               \
25
      _delay_us( 98 );         /* * 256 = 25ms */                     \
26
      if( --i == 0 ){          /* ... until key >25ms released */     \
27
        flag = 0;              /* clear press flag */                 \
28
        i = 0;                 /* 0 = key release debounced */        \
29
        break;                                                        \
30
      }                                                               \
31
    }                                                                 \
32
  }else{                       /* else check for key press: */        \
33
    for(;;){                   /* loop ... */                         \
34
      if( (2& 1<<1) ){   /* ... until key released or ... */    \
35
        i = 0;                 /* 0 = bounce */                       \
36
        break;                                                        \
37
      }                                                               \
38
      _delay_us( 98 );         /* * 256 = 25ms */                     \
39
      if( --i == 0 ){          /* ... until key >25ms pressed */      \
40
        flag = 1;              /* set press flag */                   \
41
        i = 1;                 /* 1 = key press debounced */          \
42
        break;                                                        \
43
      }                                                               \
44
    }                                                                 \
45
  }                                                                   \
46
  i;                           /* return value of Macro */            \
47
})
48

49
/*
50
   Testapplication
51
 */
52
int main(void)
53
{
54
  WDTCTL = WDTPW + WDTHOLD;   // WatchDogTimer abschalten
55
          
56
          
57
 // -- INIT_Port1
58
  P1SEL &= ~(LED_X);            // Beide sind BIN-IO       
59
  P1DIR |= LED_X;               // LED    = BIN-OUT
60
  P1OUT &= ~(LED_X);            // LED_X = AUS (weil H-aktiv)
61
      // INIT_Port_2
62
    P2SEL  &= ~(T_SET);           // Funktion ist BIN-IO
63
    P2DIR  &= ~(T_SET);           // Taster ist BIN-IN
64
    P2IES  |= T_SET;              // Int. bei neg. Flanke (H-->L)
65
    P2IE   |= (T_SET);           // Beim System.Start noch nicht frei gegeben
66
    P2IFG  &= ~(T_SET);           // Alte Fl. Ereignis löschen
67
    //
68
    P2REN |= T_SET;               // Intern.Widerstand = aktiv
69
    P2OUT |= T_SET;               // Als PullUp eingestellt
70
    
71
    
72
  for(;;){
73
    if( debounce( P2IN, BIT 2 ) )
74
      P2OUT ^= 1<<BIT 3;
75
    if( debounce( P2IN, BIT 1 ) )
76
      P2OUT ^= 1<<BIT 4;
77

78
    _BIS_SR(GIE); 
79
  }
80
 while(1) {_NOP();}
81
}
  PORTB ^= 1<<PB2; das bedeutet soviel wie toggeln von High /low
also P2out ^= 1<<2

Nur die Frage nach der Logik des Toggelns: soll eine LED blinken?
#6229729
Lesenswert?

Teo D. schrieb:
> Es gibt kaum ein einfacheres Problem, als prellende Tasten!

Darauf sind leider schon viele SW-Profis hereingefallen. Entprellen ist 
überhaupt nicht einfach, solange man die Physik dahinter und den 
Lösungsweg nicht verstanden hat.
Ich habe zu Hause und auf Arbeit haufenweise prellende Geräte, mit denen 
ich mich täglich rumärgern muß. Sogar der Aufzug hat prellende Tasten, 
obwohl man da eigentlich besonders scharfe Sicherheitsprüfungen erwarten 
würde.
Ich habe aus purer Not einen schweinisch teuren Kaffeautomaten gepimpt, 
indem ich einen ATtiny13 zwischen Drehgeber und "Profi"-MC geschaltet 
habe, der ihn entprellt. Vorher war das Einstellen der Kaffeemenge ein 
Lotteriespiel. Solche Mängel treten natürlich exakt nach Ablauf der 
Garantie ein.
Gast #6229735
Lesenswert?

kopr schrieb:
> woher weiß ich, wie groß das Intervall ist?

Weil du es dir selbst festlegst. Schließlich mußt ja DU bestimmen, wie 
häufig du in deinem Programm nach den Tasten schaust.

Ich bin davon ausgegangen, daß man so etwas bereits selbst sich überlegt 
hat, denn dein µC soll ja auch noch etwas anderes tun, als nur sich mit 
den Tasten zu beschäftigen.

Oder?

W.S.
Gast #6229737
Lesenswert?

Peter D. schrieb:
> Teo D. schrieb:
>> Es gibt kaum ein einfacheres Problem, als prellende Tasten!
>
> Darauf sind leider schon viele SW-Profis hereingefallen. Entprellen ist
> überhaupt nicht einfach, solange man die Physik dahinter und den
> Lösungsweg nicht verstanden hat.
 das ist doch ein Argument mehr, mir jetzt zu helfen
Gast #6229740
Lesenswert?

W.S. schrieb:
> Ich bin davon ausgegangen, daß man so etwas bereits selbst sich überlegt
> hat, denn dein µC soll ja auch noch etwas anderes tun, als nur sich mit
> den Tasten zu beschäftigen.

habe bisher die ISR eines Ports genommen. Alternativ natürlich einen 
Timer einstellen...
Gast #6229749
Lesenswert?

kopr schrieb:
> #define debounce( 2, 1 )                                         \
> ({                                                                    \
>   static unsigend int flag = 0;     /* new variable on every macro usage
> */  \
>   unsigend int i = 0;
> \
>                                                                       \
>   if( flag ){                  /* check for key release: */           \
>     for(;;){                   /* loop ... */                         \
>       if( !(2 & 1<<1) ){  /* ... until key pressed or ... */     \
>         i = 0;                 /* 0 = bounce */                       \
>         break;                                                        \
>       }                                                               \
>       _delay_us( 98 );         /* * 256 = 25ms */                     \
>       if( --i == 0 ){          /* ... until key >25ms released */     \
>         flag = 0;              /* clear press flag */                 \
>         i = 0;                 /* 0 = key release debounced */        \
>         break;                                                        \
>       }                                                               \
>     }                                                                 \
>   }else{                       /* else check for key press: */        \
>     for(;;){                   /* loop ... */                         \
>       if( (2& 1<<1) ){   /* ... until key released or ... */    \
>         i = 0;                 /* 0 = bounce */                       \
>         break;                                                        \
>       }                                                               \
>       _delay_us( 98 );         /* * 256 = 25ms */                     \
>       if( --i == 0 ){          /* ... until key >25ms pressed */      \
>         flag = 1;              /* set press flag */                   \
>         i = 1;                 /* 1 = key press debounced */          \
>         break;                                                        \
>       }                                                               \
>     }                                                                 \
>   }                                                                   \
>   i;                           /* return value of Macro */            \

> }

ich habe jetzt bei Port einfach den Wert 2 eingegebn, was natürlich 
quatsch ist. was soll denn Abgefragt werden? z.B. P2IFG, als ob es ein 
Interrupt gab?

und zweitens:
for(;;){
>     if( debounce( P2IN, BIT 2 ) )
>       P2OUT ^= 1<<BIT 3;
>     if( debounce( P2IN, BIT 1 ) )
>       P2OUT ^= 1<<BIT 4;
das ist die Logik dafür, daas wenn ein Drücken erkannt wurde, etwas 
passiert?
Gast #6229816
Lesenswert?

> __interrupt void P1_ISR()
> {
>   Entprell();
>
>   if(P1IFG & T_OnOff)   // Wenn Int. von T_OnOff, dann
>   {
>
> es lief darauf hinaus...

Komisch. Jedesmal nutzt du ein anderes define für deine Taste.

Und noch gestern hast Du gepostet:
kopr schrieb:
> int key1Active(void)
> {
>  if (P2IFG & T_SET)
>    return 1;
>   else
>   {_NOP();}
>
> }
Also Zufallsverhalten. Und dass Deine Auswertung nicht läuft, wenn Du 
ein Return 0 anfügst.

Und ich habe Dir erklärt, was dann vermutlich dein Fehler ist (nämlich 
Taster auf anderem Pin).

Von daher ist es wenig hilfreich, wenn Du, statt echten Code zu Posten, 
beschreibst, was er Deiner Meinung nach tun sollte.
Gast #6229818
Lesenswert?

A. S. schrieb:
> Und noch gestern hast Du gepostet:
> kopr schrieb:
>> int key1Active(void)
>> {
>>  if (P2IFG & T_SET)
>>    return 1;
>>   else
>>   {_NOP();}
>>
>> }
> Also Zufallsverhalten. Und dass Deine Auswertung nicht läuft, wenn Du
> ein Return 0 anfügst.
>


ganz anderer Zusammenhang...meine Abfrage der taster hat bis jetzt immer 
funktioniert
Gast #6229824
Lesenswert?

kopr schrieb:
> A. S. schrieb:
>> Dann zeig doch den Code. Hässlich ist kein Problem, wenn es tut, was es
>> soll.
>
> #pragma vector=PORT1_VECTOR
> __interrupt void P1_ISR()
> {
>   Entprell();
>
>   if(P1IFG & T_OnOff)   // Wenn Int. von T_OnOff, dann
>   {
>
> es lief darauf hinaus...

Back to the lukker problem. Genau hier hast du den alten Thread 
abgebrochen, weil man dir sagte, dass das Entprellen nicht das Problem 
ist. Und, der Bursche hört nicht und steht wieder vor der gleichen Tür. 
Man lukker, nimm die Hilfe endlich an!
Gast #6229909
Lesenswert?

kopr schrieb:
> ich habe doch oben viele fragen gestellt, die unbeantwortet sind. das
> macht mich unglücklich

Das hatten wir schon zweimal. Deine Fragen kann man nicht so direkt 
beantworten, wie du das gerne hättest. Wenn Softwareentwicklung so 
einfach wäre, hätten wir keinen Fachkräftemangel, denn dann könnte das 
jeder, der klare Gedanken fassen kann.

Du musst schon auf die Korrekturvorschläge und Rückfragen eingehen. 
Diese haben das Ziel, bereits offensichtliche Fehler abzustellen und die 
Ursache des Problems einzugrenzen. Dabei musst du schon mitmachen, sonst 
kommen wir auch in diesem dritten Thread nicht weiter.
Gast #6229953
Lesenswert?

kopr schrieb:
> also es haben schon mehrere User angedeutet, dass sie mir den Taster an
> P2.1 über peda entrpellen könnten. wenn sie bloß wollten

Soweit ich mitbekommen habe, ist dein Hautp-problem derzeit nicht 
(fehlende) die Entprellung. Das Programm würde auch mit erfolgreicher 
Entprellung nicht funktionieren.

Das muss man man zuerst in Ordnung bringen.

Falls du da anderer Meinung bist, entferne nochmal die PeDa Entprellung 
aus deinem Code und zeige dann den kompletten Quelltext in 
Kompilierbarer Form, also samt Makefile oder was auch immer du als 
Build-Script verwendest.
Gast #6230013
Lesenswert?

kopr schrieb:
> Stefan ⛄ F. schrieb:
>> s Programm würde auch mit erfolgreicher
>> Entprellung nicht funktionieren.
>
> von welchem Programm reden wir? habe doch garkeins gezeigt. Möchte als
> ersten Schritt die Entprellung hinbekommen und von mir aus eine LED
> toggeln lassen

Ok, dann reden wir wohl von zwei unterschiedlichen Baustellen.
Gast #6230036
Lesenswert?

> _delay_us()

> kommt aus diesem File #include <util/delay.h>.
> kann ich dieses File auch auf meiner Plattform laden?

Ich denke, das geht nicht, weil diese util/delay.h spezifisch für AVR 
Mikrocontroller ist. Du musst das durch eine Delay Funktion für deinen 
Mikrocontroller ersetzen. Wenn die C Bibliothek so etwas nicht hat, 
musst du dir selbst so eine Funktion programmieren.

>  for(;;){
>    if( debounce( PINB, PB1 ) )
>      PORTB ^= 1<<PB2;
>    if( debounce( PINB, PB0 ) )
>      PORTB ^= 1<<PB3;
> }

> ich weiß nicht, was dass in meinem konkreten fall bedeutet

PINB ist bei AVR Mikrocontroller das Register, welches man dum Abfragen 
der Eingänge von Port B liest. PB1 ist die Nummer des Bits/Pins das 
gelesen werden soll. Also bedeutet "debounce(PINB,PB1)" soviel wie: 
Entprelle den Status vom Taster an Port B Bit 1.

PORTB ist das Register, mit dem man die Ausgänge von Port B ansteuert. 
Und ^= ist eine Exklusiv-oder Verknüpfung. Also bedeutet "PORTB ^= 
1<<PB2" soviel wie: Verknüpfe das Bit 2 von Port B per Exklusiv-Oder mit 
1 - was letztendlich den Wert des Bits umkehrt. Wenn es vorher 1 war, 
dann ist es danach 0. Wenn es vorher 0 war, dann ist es danach 1. Das 
nennt man Toggeln.

Du musst das nur auf eine Plattform umschreiben. Wenn du das nicht 
kannst, dann lerne erstmal C Grundlagen. Denn das Einbinden fremder 
Quelltexte einzubinden oder gar diese Umzuschreiben ist wesentlich 
schwieriger, als erste eigene Programme zu schreiben und beruht zudem 
auf der Kenntnis der Grundlagen.

Man kann auch keinen Kuchen Backen, solange man den Ofen nicht bedienen 
kann.
Gast #6230037
Lesenswert?

kopr schrieb:
> anstatt delay würde ich einfach eine For-Schleife nehmen.

Wenn die Schleife keine sinnvollen Befehle enthält, könnte es Dir 
passieren, dass der Compiler die ganze Schleife weg optimiert (weil sie 
nichts bewirkt). Dazu solltest du dich über "volatile NOP" informieren, 
das wirst du brauchen.
Gast #6230038
Lesenswert?

kopr schrieb:
> on welchem Programm reden wir? habe doch garkeins gezeigt. Möchte als
> ersten Schritt die Entprellung hinbekommen und von mir aus eine LED
> toggeln lassen

Was ist denn mit dem Programm von gestern? Da müsstest du doch nur noch 
herausfinden, wo die Taste im Port erscheint. Das lief doch schon fast, 
auch mit entprellung.

Wieso willst Du eine zweite umsetzen, bevor die triviale läuft?

Genau dafür macht man doch einfache Beispiele, weil die einfacher sind.
Gast #6230099
Lesenswert?

Stefan ⛄ F. schrieb:
> Ich denke, das geht nicht, weil diese util/delay.h spezifisch für AVR
> Mikrocontroller ist. Du musst das durch eine Delay Funktion für deinen
> Mikrocontroller ersetzen. Wenn die C Bibliothek so etwas nicht hat,
> musst du dir selbst so eine Funktion programmiere

also es wurde mir schon ein link zu einer passenden Library geschickt. 
Mucss mich noch damit beschäftigen, wie ich diese einbinde
Gast #6230100
Lesenswert?

Stefan ⛄ F. schrieb:
> PORTB ist das Register, mit dem man die Ausgänge von Port B ansteuert.
> Und ^= ist eine Exklusiv-oder Verknüpfung. Also bedeutet "PORTB ^=
> 1<<PB2" soviel wie: Verknüpfe das Bit 2 von Port B per Exklusiv-Oder mit
> 1 - was letztendlich den Wert des Bits umkehrt. Wenn es vorher 1 war,
> dann ist es danach 0. Wenn es vorher 0 war, dann ist es danach 1. Das
> nennt man Toggeln.

genau. das habe ich auch schon herausgefunden =) siehe oben
Gast #6230102
Lesenswert?

Stefan ⛄ F. schrieb:
> Du musst das nur auf eine Plattform umschreiben. Wenn du das nicht
> kannst, dann lerne erstmal C Grundlagen. Denn das Einbinden fremder
> Quelltexte einzubinden oder gar diese Umzuschreiben ist wesentlich
> schwieriger, als erste eigene Programme zu schreiben und beruht zudem
> auf der Kenntnis der Grundlagen.

hast du meinen letzten Vorschlag gesehen? da habe ich es quasi übersetzt
Gast #6230104
Lesenswert?

A. S. schrieb:
> as ist denn mit dem Programm von gestern? Da müsstest du doch nur noch
> herausfinden, wo die Taste im Port erscheint. Das lief doch schon fast,
> auch mit entprellung.
>
> Wieso willst Du eine zweite umsetzen, bevor die triviale läuft?
>
> Genau dafür macht man doch einfache Beispiele, weil die einfacher sind.

habe im anderen thread was gepostet.
Gast #6230107
Lesenswert?

Stefan ⛄ F. schrieb:
> Ich möchte auch erst einmal sehen, dass eine LED ohne Entprellung
> getoggelt wird. Erst danach kann der nächste Schritt kommen.
>
> Wie gesagt, wenn man den Ofen nicht an bekommt, kann man keinen Kuchen
> backen.

alles klar. ich habe inzwischen was eigenes zum Entprellen gebastelt.
1
char button_down(void) {
2
    if ((P1IN & 0x02) == 0) return 1;
3
    return 0;
4
}
5

6
char haltezustand = 0;
7
char losgelassen = 1;
8
#pragma vector=TIMER1_A1_VECTOR          
9
__interrupt void TIMER1_A1_ISR(void)
10
{
11
  switch (__even_in_range(TA1IV, 14))
12
  {
13
  case  0: break; // No interrupt
14
  case  2: break; // CCR1 not used
15
  case  4: break; // CCR2 not used
16
  case  6: break; // reserved
17
  case  8: break; // reserved
18
  case 10: break; // reserved
19
  case 12: break; // reserved
20
  case 14: 
21
            if (button_down()) 
22
            {
23
              if ((haltezustand) && (losgelassen))
24
              {
25
                if (modus<3)
26
                  kop();
27
                
28
                 
29
                else 
30
                modus = 0; 
31
                  TX_String("\nSignalsukk Sinusfoermig\n");
32
                 haltezustand=0;
33
                 losgelassen=0;
34
                 
35
              }
36
              else
37
              {
38
              haltezustand=1; 
39
                 }  
40
            }
41
              else 
42
              {
43
              haltezustand=0;
44
              losgelassen=1;}
45
            
46
          
47
            TA1IV &= 0x00;
48
            TA1R = count;
49

50
            break;
51
  default: break;
52
  }
53
}
54

55
void kop (void)
56
{
57
  modus++;
58
  TX_String("\nSignal Sinusfoermig\n");
59
}
Gast #6230148
Lesenswert?

kopr schrieb:
> habe im anderen thread was gepostet.

Ja. Dass Du Deinem eigenen  Code verändert hast, ohne ihn zu verstehen 
und dass er deshalb nicht mehr läuft. Anfängerfehler, ok. Aber warum 
immer alles ganz neu, ohne erstmal ein Hallo Welt.

Wenn es nun läuft, gut. Aber du willst dich nicht erzählen, dass Du den 
Code geschrieben hast. Das ist wieder aus was anderem kopiert, ohne dass 
Du weißt, was da geschieht. Auch ok. Und die Warnungen sind immer noch 
alle aus, sonst wäre es schon vorgestern gelaufen. Auch OK. Du gehst auf 
keinen Vorschlag hier ein. Auch OK. Wenn es Dich weiterbringt, ist das 
alles OK.
Gast #6230289
Lesenswert?

A. S. schrieb:
>> guck in den Thread. da ist kein fehler!
>
> Für den Fehler hast Du nun den nächsten Thread aufgemacht. Auch OK.
>
> kopr schrieb:
>>> Warnungen ... aus
>> auch nicht aus!
> Dann ignorierst Du sie, was faktisch das gleiche ist.

es tut mir leid, ich hatte unrecht. war ein fehler
#6230309
Lesenswert?

Peter D. schrieb:
> kopr schrieb:
>> kommt aus diesem File #include <util/delay.h>. kann ich dieses File auch
>> auf meiner Plattform laden?
>
> Nun das Delay-Macro benutzt AVR-Assembler,

so ein Unfug,

ich hatte dem TO schon geraten dein C Beispiel zu nehmen im Timermode 
10ms
Beitrag "Re: Entprellen Flankenerkennung"

ein Beipiel zu Timerprogrammierung in C auch geliefert!
Beitrag "Re: Entprellen Flankenerkennung"


warum nun ASM und

kopr schrieb:
> _delay_us( 98 );

ins Spiel kommt erschliesst sich mir nicht!
Niemand braucht im Timer IRQ für die Entprellung delay!

schon gar nicht braucht es endlose Threads zum selben Thema!
Gast #6230541
Lesenswert?

Joachim B. schrieb:
> schon gar nicht braucht es endlose Threads zum selben Thema!

Nun, der TO macht lieber einen neuen Thread auf, als sich 
Compiler-Warnungen durchzulesen, eine Zeile Code zu verstehen oder gar 
Basics wie & und && nachzusehen. Und bevor er eine Zeile korrigiert oder 
postet, nimmt er lieber etwas funktionierendes aus einem ganz anderen 
Kontext.

Dafür musst Du aber PeDa nicht angehen, seine Entprellroutinen (vor 
allem die extra didaktisch einfachere) können da nix für.
Gast #6230967
Lesenswert?

kopr schrieb:
> hast du meinen letzten Vorschlag gesehen?

Wenn eine Diskussion über mehrere Threads verteilt stattfindet, kann man 
auch mal was übersehen oder durcheinander kommen.

Ich merke schon, ich kann hier nicht wirklich weiter helfen. Ich halte 
mich deswegen wieder raus, auch wenn du mich direkt darum bittest, zu 
antworten.
#6231423
Lesenswert?

Peter D. schrieb:
> Nun das Delay-Macro benutzt AVR-Assembler,

noch mal für dich!

Joachim B. schrieb:
> ich nutze deine Routinen oft und sehr gerne!
> Ich weiss nicht

wie

A. S. schrieb:
> Dafür musst Du aber PeDa nicht angehen

darauf kommt?

angehen wollte ich PeDa zu keiner Zeit und tat ich nicht,
war vielleicht mißverständich geschrieben, meine Kritik richtete sich 
gegen den TO der ziemlich viele Threads zum eigentlich gleichen Thema 
aufmacht.

Stefan ⛄ F. schrieb:
> Wenn eine Diskussion über mehrere Threads verteilt stattfindet, kann man
> auch mal was übersehen oder durcheinander kommen.

stimme zu, ist nervig und man sollte sich wirklich raushalten sobald man 
den TO Namen entdeckt
Moderator (Firma: Titel) Persönliche Seite #6232010
Lesenswert?

Stefan ⛄ F. schrieb:
> Wenn eine Diskussion über mehrere Threads verteilt stattfindet
... und der Teilnehmer in den Threads mit mehreren Namen postet, und 
dann auch noch andere Teilnehmer beleidigt, dann sieht das für mich wie 
ein Troll aus.

Joachim B. schrieb:
> man sollte sich wirklich raushalten sobald man den TO Namen entdeckt
Das hört sich für mich nach einer guten Idee an.

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