Taster entprellen beim STM32f1

OP #3438194
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
Angehängte Dateien:
#3438312
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
#3438339
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.
OP #3438358
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?
OP #3438361
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
#3438380
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);
Gast #3438394
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
#3438402
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
OP #3438422
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 :(?
#3438436
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()" ?
#3438667
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.
Angehängte Dateien:
OP #3439312
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
#3439480
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

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