Forum: Mikrocontroller und Digitale Elektronik Taster entprellen beim STM32f1


von Fabian L. (fabls)


Angehängte Dateien:

Lesenswert?

Guten Tag liebe Forum Mitglieder,

ich bin ein blutiger Anfänger in der Programmierung und suche seit 2 
Tagen ein Tutorial oder einen fertigen Code um Tasten bei einem STM32F1 
in einer ISR zu entprellen.

Ich weis es gibt jede Menge Code im Forum, doch keiner von denen ich 
gefunden habe konnte ich Ansatzweise an dem STM einsetzen (ist mit 
großer Wahrscheinlichkeit ein klax, doch leider fällt es mir sehr 
schwer).

Mir würde sehr den Code von Peter Dannegger gefallen es einzusetzen, 
doch leider verstehe ich diesen Code zu 80% nicht und daher kann ich es 
nicht für meinem STM32F1 "umschreiben".


Ich hoffe sehr, dass mir jemand helfen kann.


Ich bedanke mich jetzt schon ganz herzlich im Voraus.

Mit freundlichen Grüßen
Fabian

von Uwe B. (derexponent)


Lesenswert?

Hi Fabian,

wenn du den Code nicht verstehst...warum willst du ihn dann benutzen ?

hier ein Schnippsel das vlt. einfacher zu verstehen ist
(und auch funktionieren müsste...blind coded :-)
1
uint8_t button_status=Bit_RESET;
2
3
4
//--------------------------------------
5
void gpio_init(void) {
6
  GPIO_InitTypeDef GPIO_InitStructure;
7
8
  RCC_AHBPeriphClockCmd(GPIOA, ENABLE);
9
10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
11
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
12
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
13
  GPIO_Init(GPIOA, &GPIO_InitStructure);
14
}
15
16
17
//--------------------------------------
18
void main(void) {
19
20
  SysTick_Config(SystemCoreClock / 1000); // => 1ms Systick
21
  gpio_init();
22
23
  while(1) {
24
  
25
    if(button_status==Bit_RESET) {
26
      // mach was
27
    }
28
    else {
29
      // mach was anderes
30
    }
31
  }
32
}
33
34
35
//--------------------------------------
36
void SysTick_Handler(void)
37
{
38
  static uint32_t ms_cnt=0;
39
40
  ms_cnt++;
41
  if(ms_cnt>50) {
42
    // 50ms debounce
43
    ms_cnt=0;
44
    button_status=GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
45
  }
46
}

Gruss Uwe

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

"PINB"
ist der Port, an dem Du die Tasten anlegst

"KEY0"
ist die Bitnummer einer Taste

"SIGNAL (SIG_OVERFLOW0)"
Ist ein Timerinterrupt von etwa 10ms

Du mußt also nur einen Timerinterrupt und die Pins entsprechend 
initialisieren, dann funktioniert der ganze Rest.

: Bearbeitet durch User
von Fabian L. (fabls)


Lesenswert?

Vielen Dank für deine Antwort Uwe!

>
> wenn du den Code nicht verstehst...warum willst du ihn dann benutzen ?
>
Ja du hast da vollkommen Recht, ich fand den halt nur gut, weil er sehr 
Ressourcen schonend ist und viele Funktionen beinhaltet was mich 
interessiert. Leider konnte ich es nicht umsetzen.



>   SysTick_Config(SystemCoreClock / 1000); // => 1ms Systick

Meine CPU läuft mit 24Mhz , muss ich an der SysTick etwas beachten bzw. 
einen Wert ändern um auf die 1ms zu kommen?

von Fabian L. (fabls)


Lesenswert?

Peter Dannegger schrieb:
> "PINB"
> ist der Port, an dem Du die Tasten anlegst
>
> "KEY0"
> ist die Bitnummer einer Taste
>
> "SIGNAL (SIG_OVERFLOW0)"
> Ist ein Timerinterrupt von etwa 10ms
>
> Du mußt also nur einen Timerinterrupt und die Pins entsprechend
> initialisieren, dann funktioniert der ganze Rest.


Danke Peter!

Ich wage mich erst mal mit dem Code von Uwe und wenn das dann geschafft 
ist versuche ich deinen Code umzusetzen.

Grüße
Fabian

von ich (Gast)


Lesenswert?

Uwe B. schrieb:
> hier ein Schnippsel das vlt. einfacher zu verstehen ist
> (und auch funktionieren müsste...blind coded :-)
Handelt es sich dabei wirklich um eine Entprellung? Ich glaube nicht...

von Uwe B. (derexponent)


Lesenswert?

>Handelt es sich dabei wirklich um eine Entprellung?
>Ich glaube nicht...

dann definiere mal "Entprellung"


>weil er sehr
>Ressourcen schonend ist

ich glaube beim STM32F1 musst du dir zu begin
keine Gedanken um "Ressourcen" machen :-)

>Meine CPU läuft mit 24Mhz


prüf mal im Debugger den Inhalt der Variabeln "SystemCoreClock"
die muss bei dir "24000000" liefern...dann ist alles ok

in der Clock-Config war noch ein Fehler,
richtig muss es lauten :
1
RCC_AHBPeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

von public (Gast)


Lesenswert?

Servus Fabian,

Regel 1: für einen Taster benutzt man keinen Interrupt!
Regel 2: Ist die Elektronik in Ordnung? Kannst du das Prellen am 
Oszilloskop sehen? Wie viel Zeit dauert das längste gemessene Prellen?

Sind diese Fragen geklärt, dann Regel 3:

Taster werden gepollt, also beispielsweise folgendes:

if (Taster_an_GPIO == HIGH) then counter++;

if ((Taster_an_GPIO == HIGH) && (counter == 10)) then 
gewünschte_Routine_ausführen();

Wie hoch der "counter" laufen muss hängt von den gemessenen Paramtern 
ab, siehe Oszi!

Noch besser gehts mit nem Timer. Also Timer starten und warten bis der 
Tasterzustand sich nicht mehr ändert und dann auf Timerablauf warten.

Grüßle

von Uwe B. (derexponent)


Lesenswert?

shit, beim F1 liegt der GPIOA an "APB2"

also noch eine Korrektur :
1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

und du musst den Port und das Bit natürlich anpassen

sorry...hab mich zu sehr an den F4 gewöhnt


>Regel 1: für einen Taster benutzt man keinen Interrupt!

gut...das notier ich mir

: Bearbeitet durch User
von Fabian L. (fabls)


Lesenswert?

Uwe B. schrieb:
> shit, beim F1 liegt der GPIOA an "APB2"
>
> also noch eine Korrektur :
> RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
>
> und du musst den Port und das Bit natürlich anpassen
>
> sorry...hab mich zu sehr an den F4 gewöhnt
>
>>Regel 1: für einen Taster benutzt man keinen Interrupt!
>
> gut...das notier ich mir


Danke diese Einstellungen habe ich schon im Vorfeld gehabt, von daher 
kam es auch nicht zu einem Fehler.

Also bei mir ist es nämlich so:

Sobald ich den Taster drücke habe ich am Eingang des Pins einen 3,3V 
Pegel.

int main (void)
{
  SysTick_Config(SystemCoreClock / 1000); // => 1ms Systick

while(1)
  {
    loop();
    if(button_status==Bit_SET) {

      GPIO_SetBits(GPIOB,  LED1_TEMPERATUR);
      GPIO_ResetBits(GPIOB,  LED2_TEMPERATUR);
                          }
                           else {

      GPIO_SetBits(GPIOB,  LED2_TEMPERATUR);
      GPIO_ResetBits(GPIOB,  LED1_TEMPERATUR);
                          }

  }
}

------------------------------------------------------------------
 (stm32f10x_it.c)


extern uint8_t button_status;

void SysTick_Handler(void)
{
   static uint32_t ms_cnt=0;

          ms_cnt++;
          if(ms_cnt>50) {
                    // 50ms debounce
           ms_cnt=0;
          button_status=GPIO_ReadInputDataBit(GPIOC, 
PIN_VIBRATIONSMOTOR_TASTER);
  }


}
---------------------------------------------

Mein Problem ist jetzt, dass die LED2 immer an. Das heisst sobald der 
Taster gedrückt ist schaltet die LED1 nicht ein.

Habe ich da was falsch gemacht :(?

von Uwe B. (derexponent)


Lesenswert?

>Habe ich da was falsch gemacht

Ja ...sonst würde es ja funktionieren :-)

spass beiseite,

der Fehler liegt event. an meinem Beispiel (war nur so hingeschrieben)

teste erstmal ob der Systick und die Globale Variable "button_status" 
funktioniert

1
void SysTick_Handler(void)
2
{
3
  static uint32_t ms_cnt=0;
4
5
  ms_cnt++;
6
  if(ms_cnt>50) {
7
    // 50ms debounce
8
    ms_cnt=0;
9
    button_status=1-button_status; // toggelt den wert
10
  }
11
}


die LEDs müssen jetzt mit 20Hz blinken...das müsste ein Flackern sein


und wo ist deine "GPIO init" und was macht die "loop()" ?

: Bearbeitet durch User
von M. K. (kichi)


Angehängte Dateien:

Lesenswert?

Ich habe den Code von Peter vor einiger Zeit mal aufgeteilt und auf 
STM32L1 "portiert".

Die Funktion "CollectKeys" soll die zu entprellenden Signale "sammeln" 
und muss dementsprechend angepasst werden. Evtl. nötige Invertierungen 
können hier oder beim Aufruf in der "Service"-Funktion vorgenommen 
werden.

"Service" muss regelmäßig (main-loop, Timer-ISR, usw.) aufgerufen werden 
und kümmert sich um die Entprellung an sich.

In der debounce.h können ein paar Einstellungen vorgenommen werden.
Um das Ganze auf anderen Controllern zu nutzen muss nur der Teil 
zwischen Zeile 33 und 43 (*.h) erweitert werden.

von Fabian L. (fabls)


Lesenswert?

Michael K. schrieb:

>
> In der debounce.h können ein paar Einstellungen vorgenommen werden.
> Um das Ganze auf anderen Controllern zu nutzen muss nur der Teil
> zwischen Zeile 33 und 43 (*.h) erweitert werden.

Vielen Dank Michael!

Auf Zeile 39-40 befindet sich dieses include

#include <avr/io.h>
#include <avr/interrupt.h>    // for cli() and sei()

Es ist an sich für einen AVR und ich habe einen STM32F100 kann man es 
trotzdem benutzen?
Wenn ja, kann man es wo erhalten??

Liebe Grüße
Fabian

von Stefan W. (dl6dx)


Lesenswert?

Fabian L. schrieb:
> ich habe einen STM32F100

Dann musst du dort einen passenden Abschnitt für diesen Controller 
einfügen. Das würde in etwa so aussehen:
1
#elif defined (STM32F1xx)
2
#include <stm32Flxx.h>
3
#define ENABLE_INTERRUPTS     __enable_irq
4
#define DISABLE_INTERRUPTS    __disable_irq
5
#else

(Das ist ein Beispiel, die genauen Symbole, Headerdateien und Makros 
bitte nachsehen!)

Grüße

Stefan

von Fabian L. (fabls)


Lesenswert?

Ich wollte mich nochmal bei Uwe bedanke und allen anderen die mir 
geholfen habe!

Es hat jetzt alles geklappt!

Liebe Grüße
Fabian

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.