Problem z obsługą przycisku

Język C dla mikrokontrolerów ARM
ODPOWIEDZ
jarecki
Użytkownik
Posty: 17
Rejestracja: 25 paź 2017, 11:20

Problem z obsługą przycisku

Post autor: jarecki » 19 wrz 2019, 13:38

Cześć,

mam małą zagwozdkę z programem. Założenie było takie, żeby napisać program (niezależny od użytego mikrokontrolera AVR, STM, PIC) do obsługi dowolnej ilosci przycisków.

Idea programu jest taka, że w struktórze inicjalizacyjnej przycisku, podpinamy swoje funkcje, które będą wywoływane po wciśnięciu i puszczeniu przycisku.

Dodatkowo podpinamy funkcję, która bada stan pinu (uniezależnienie od mikrokontrolera).

Poniżej przedstawiam kod:
  1. #include "stm32l0xx.h"
  2.  
  3. #include <string.h>
  4.  
  5.  
  6. #include "printf.h"
  7. #include "gpio.h"
  8.  
  9.  
  10.  
  11. typedef void PressFreeCb(void);
  12. typedef uint8_t inputDataCb(void);
  13.  
  14.  
  15. typedef struct
  16. {
  17.     uint8_t state;
  18.     inputDataCb *inputDataCb;
  19.     PressFreeCb *PressCb;
  20.     PressFreeCb *FreeCb;
  21. }MyKeyBody;
  22.  
  23. static void Pressed(void)
  24. {
  25.     UART_printf("Pressed!\r\n");
  26. }
  27.  
  28. static void Free(void)
  29. {
  30.     UART_printf("Free!\r\n");
  31. }
  32.  
  33. static uint8_t checkInputPin(void)
  34. {
  35.     if(HAL_GPIO_ReadPin(GPIOA, BLUE_BUTTON_Pin) == GPIO_PIN_SET)
  36.     {
  37.         return 0;
  38.     }
  39.     else
  40.     {
  41.         return 1;
  42.     }
  43. }
  44.  
  45. MyKeyBody KeyUpBody =
  46. {
  47.     .state = 0,
  48.     .inputDataCb = checkInputPin,
  49.     .PressCb = Pressed,
  50.     .FreeCb = Free
  51. };
  52.  
  53. MyKeyBody KeyDownBody =
  54. {
  55.     .state = 0,
  56.     .FreeCb = NULL,
  57.     .inputDataCb = NULL,
  58.     .PressCb = NULL
  59. };
  60.  
  61. MyKeyBody *MyKeyBodyTab[2] = {
  62.     &KeyUpBody,
  63.     &KeyDownBody,
  64. };
  65.  
  66. static MyKeyBody **CurrentKeyBody = NULL;
  67.  
  68. int keyInit(MyKeyBody *MyKeyBodyTab[])
  69. {
  70.     CurrentKeyBody = MyKeyBodyTab;
  71.  
  72.     if(!CurrentKeyBody)
  73.     {
  74.         return -1;
  75.     }
  76.  
  77.     return 0;
  78. }
  79.  
  80. void keyMain(void)
  81. {
  82.     for(uint8_t i = 0; i < 2; i++)
  83.     {
  84.  
  85.     switch(CurrentKeyBody[i]->state)
  86.         {
  87.         case 0:
  88.  
  89.             if(CurrentKeyBody[i]->inputDataCb)                  /* Sprawdzenie czy wskaźnik na funkcję odczytującą pin jest ustawion */
  90.             {
  91.                 if((CurrentKeyBody[i]->inputDataCb()) == 0)     /* Jeżeli tak to wywołanie funkcji odczytującej stan pinu */
  92.                 {
  93.                     if(CurrentKeyBody[i]->PressCb)              /* Jeżeli pin wciśnięty to sprawdzenie czy wskaźnik na funkcję obsługi przycisku jest ustawiony */
  94.                     {
  95.                         CurrentKeyBody[i]->PressCb();           /* Jak funkcją "podpięta" to wywołanie */
  96.                     }
  97.  
  98.                     CurrentKeyBody[i]->state = 1;               /* Zmiana stanu maszynki stanów */
  99.                 }
  100.             }
  101.  
  102.             break;
  103.         case 1:
  104.             if(CurrentKeyBody[i]->inputDataCb)                  /* Sprawdzenie czy wskaźnik na funkcję odczytującą pin jest ustawion */
  105.             {
  106.                 if((CurrentKeyBody[i]->inputDataCb()) == 1)     /* Jeżeli tak to wywołanie funkcji odczytującej stan pinu */
  107.                 {
  108.                     if(CurrentKeyBody[i]->FreeCb)               /* Jeżeli pin puszczony to sprawdzenie czy wskaźnik na funkcję obsługi przycisku jest ustawiony */
  109.                     {
  110.                         CurrentKeyBody[i]->FreeCb();            /* Jak funkcją "podpięta" to wywołanie */
  111.                     }
  112.  
  113.                     CurrentKeyBody[i]->state = 0;               /* Zmiana stanu maszynki stanów */
  114.                 }
  115.             }
  116.             break;
  117.         }
  118. }
  119. }
  120.  
  121. void OPER_appMain(void)
  122. {
  123.     keyInit(MyKeyBodyTab);
  124.  
  125.     while(1)
  126.     {
  127.         keyMain();
  128.     }
  129. }
  130.  

Dla przykładu wrzuciłem dwie struktóry, dla dwóch przycisków ale tylko pierwszy jest obsługiwany (drugi ma wskaźniki poustawiane na NULL).

Program działa ale tylko w połowie :)

Tzn. po wciśnięciu przycisku dostaję na terminalu komunikat "pressed" ale nistety po zwolnieniu przycisku nie wywołuje się funkcja printująca napis "free".

Obydwa case-y są identyczne, sprawdzany jest tylko stan 1 lub 0 przycisku i wywoływany jest inny callback.

Nie wiem, może problem jest w tym że jako callback wywołuje funkcję, która wywołuje kolejną funkcję (sprawdzenie przycisku) ?

Oczywiście prostym debbugiem z LED-em sprawdziłem obsługę przycisku w pętli glównej i tam wszystko śmiga. Może coś z tymi wskaźnikami pokopałem?

Będę wdzięczny za wskazówki bo mi skończyły się pomysły....

Dodano po 47 minutach 20 sekundach:
Problem rozwiązany :)

Mikrokontroler miał włączone przerwanie od przycisku i sobie w nim wisiał :)

temat do zamknięcia :)

ODPOWIEDZ