Skocz do zawartości
Chev

STM8S - problem z debouncingiem

Pomocna odpowiedź

Dzień dobry,

Mam problem z pozbyciem się debouncingu na wejściu procesora spowodowanego przez przyciski. Do nogi procesora mam oczywiście dołożony rezystor pull-up 10k oraz kondensator 100nF, równolegle z przyciskiem. Walczę z tym od kilku dni i już nie mam pomysłu dlaczego to nie działa. Problem jest taki: staram się stworzyć softwarową eliminacje debouncingu. W tym celu w przerwaniu przycisku sprawdzam stan przycisku na porcie PA3. Timer TIM2 ustawiony jest na takt 1ms, więc ustawiam sobie w pętli while czas 20ms, aby po tym jeszcze raz sprawdzić stan portu, czy oby na pewno jest niski (takim wyzwalam przycisk). I tu już klapa. Chcąc zapalić sobie diodę po drugim sprawdzeniu stanu przycisku, niestety, ale nie daje to żadnego efektu. Specjalnie jeszcze kupiłem nowy przycisk, aby wyeliminować element sprzętu, ale też nie jest to tego wina. 

Generalnie celem jest sprawdzenie stanu przyciska czy użytkownik wcisnął przycisk na krótko, czy go przytrzymał i puścił. Byłbym wdzięczny za jakieś wskazówki, bo już naprawdę nie mam pomysłu co zrobić. Wklejam kod, którym chcę to obsłużyć. Inicjalizacji przycisków, zegara itp. nie wklejam, bo to akurat działa poprawnie.

INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3)
{
    if(GPIO_ReadInputPin(GPIOA, GPIO_PIN_3) == RESET)
    { 
      countTimeKeyPress = TRUE;
      while(timeTIM2 < 10){}
          if(GPIO_ReadInputPin(GPIOA, GPIO_PIN_3) == RESET)
          {
            timeTIM2 = 1;
            while(GPIO_ReadInputPin(GPIOA, GPIO_PIN_3) == RESET){}
            
          if((timeTIM2 > 15) && (timeTIM2 < 100))
            {
              GPIO_WriteHigh(GPIOD, GPIO_PIN_3);
              countTimeKeyPress = FALSE;
              timeTIM2 = 1;
            }
          else if(timeTIM2 >= 100)
          {
              GPIO_WriteLow(GPIOD, GPIO_PIN_3);
              countTimeKeyPress = FALSE;
              timeTIM2 = 1;
          }
          else;
          }
    }
} 

INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
 {
    
   if(countTimeKeyPress == TRUE)
    {
      if(timeTIM2 > 101)
          {
            countTimeKeyPress = FALSE;
          }
          else
          {
            timeTIM2++;
            TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
          }
    }
 }

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Jeśli chcesz prawidłowo obsłużyć przyciski:

1. wykorzystuj tylko przerwanie timera

2. nie realizuj opóźnień czasowych w przerwaniu (żadnym przerwaniu!)

3. zapomnij o przerwaniu EXTI

W przerwaniu timera:

1. odczytaj stan przycisku

2. jeśli odczyt prawidłowy -> zwiększ licznik powtórzeń

3. jeśli odczyt nieprawidłowy -> wyzeruj licznik powtórzeń

4. stan licznika powtórzeń poinformuje o czasie wciśnięcia przycisku

PS.

Raczej nie chcesz pozbyć się debouncingu, tylko zrealizować go programowo 🙂

Edytowano przez rajszym

Udostępnij ten post


Link to post
Share on other sites

Najprostszy sposób:

  • Reagujesz na zmianę stanu pinu od razu
  • Nie reagujesz na zmiany stanu przez następne ileś tam milisekund.

Wszystko.

 

 

Udostępnij ten post


Link to post
Share on other sites

Dziękuję Panom za pomoc. Udało mi się to wykonać w przerwaniu timera jak napisał @rajszym.

Daje kod dla przyszłych pokoleń. Mało informacji jest ogólnie o procesorze STM8S. Myślę, że taki przykład się komuś przyda w przyszłości 🙂

 

 INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
 {
    if((GPIO_ReadInputPin(GPIOA, GPIO_PIN_3) == 0)) // sprawdzam stan przycisku
      {
        timeTIM2++; // jeśli wciśnięty, liczę czas +1ms
        TIM2_ClearITPendingBit(TIM2_IT_UPDATE); //zeruje flagę przerwania
      }
      else //jeśli zmienił się stan
        interrupt = 1; // ustawiam flagę, o zakończeniu liczenia
      
    if(interrupt == 1)
      {
        if(timeTIM2 >= 200) // jeśli >200 ms to długi przycisk, zeruje flagę, resetuje timer
          {
            GPIO_WriteHigh(GPIOD, GPIO_PIN_3);
            interrupt = 0;
            timeTIM2 = 1;
          }

        else if((timeTIM2 > 20) && (timeTIM2 < 200)) // krótki przycisk
          {
            GPIO_WriteLow(GPIOD, GPIO_PIN_3);
            interrupt = 0;
            timeTIM2 = 1;
          }
        else;
      }
 }

 

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...