STM32 in C - Optimiziranje GPIO operacij

Moderator: tilz0R

STM32 in C - Optimiziranje GPIO operacij

OdgovorNapisal/-a Jule » 21 Mar 2017, 19:57

Zanima me, kako bi se dalo optimirati naslednji problem.

Poenostavljen prikaz problema:

Imam STM32 mikrokontroler in recimo 20 tipk vezanih vsaka na svoj GPIO.
Imam tudi 20 ledic vezanih vsako na svoj GPIO.
Rad bi naredil, da vsaka tipka prižiga svojo ledico in ob tem pritisku poženem še nekaj druge kode.
Imam:
Trenutno kar z HAL driverji, ker je zadeva ne rabi biti hitra, ampak nimam nič proti registrom. S HAL driverji je bolj pregledno za prikaz problema.
Koda: Izberi vse
#define TIPKA1         GPIO_PIN_0
#define TIPKA1_PORT    GPIOA
#define TIPKA2         GPIO_PIN_1
#define TIPKA2_PORT    GPIOE
#define TIPKA3         GPIO_PIN_2
#define TIPKA3_PORT    GPIOF

#define LED1           GPIO_PIN_8
#define LED1_PORT      GPIOA
#define LED2           GPIO_PIN_9
#define LED2_PORT      GPIOA
.
.
.


#define LED1_OFF     HAL_GPIO_WritePin(LED1_PORT, LED1, 0);
#define LED1_ON      HAL_GPIO_WritePin(LED1_PORT, LED1, 1);
#define LED2_OFF     HAL_GPIO_WritePin(LED2_PORT, LED2, 0);
#define LED2_ON      HAL_GPIO_WritePin(LED2_PORT, LED2, 1);
.
.
.



Kar hočem poudariti je, da je teh tipk in ledic veliko. Rad bi se izognil pisanju 20 takih if stavkov:

Koda: Izberi vse
if(0 == HAL_GPIO_ReadPin(TIPKA1_PORT,TIPKA1))
{
LED1_ON
funkcija1();
}else
{
LED1_OFF
}

if(0 == HAL_GPIO_ReadPin(TIPKA2_PORT,TIPKA2))
{
LED2_ON
funkcija2();
}else
{
LED2_OFF
}


Nekako bi rad zmapiral te porte in fukcije, da bi to lahko nekako obdelal v FOR zankah.
Sem dokaj prepričan, da se da to narediti s strukturami "struct" in kazalci, vendar mi trenutno ne nese. :_helpsos

Ker če bi bilo teh tipk in ledic še več (recimo 50) bi bila zadeva zelo nepregleden špageti code. Rad bi nekako naredil zadevo fleksibilno, da je enostavno dodajati ali zmanjševati število uporabljenih stikal.

Za branje tipk DMA ne pride v poštev, ker so inputi in outputi pomešani po portih. Sploh pa ni nobene potrebe po hitrosti.

Ima kdo kakšno idejo?
Jule
 
Prispevkov: 643
Pridružen: 18 Jan 2015, 12:00
Kraj: Ajdovščina
Zahvalil se je: 129 krat
Prejel zahvalo: 131 krat
Uporabnika povabil: gumby
Število neizkoriščenih povabil: 16

Re: STM32 in C - Optimiziranje GPIO operacij

OdgovorNapisal/-a zanka » 21 Mar 2017, 20:27

Če bi rad s struct, ga ustvariš. Sicer nisem (še) poznavalec STM32 in zato ne poznam tipov registrov in pišem v kvazi-pseudo kodi.
Koda: Izberi vse
struct tipka_odziv {
void tipka_pin;
volatile void tipka_port;
void led_pin;
volatile void led_port;
void (*funkcija)(void);
};

struct tipka_odziv MAP[] = {
  {PIN1, PORTA, PIN1, PORTB, funkcija1},
  {},
  {NULL, NULL, NULL, NULL, NULL}
}

Potem pa imaš zanko
Koda: Izberi vse
 struct tipka_odziv *cur;
  for ( cur = MAP; cur->funkcija; cur++ ) {
    if ( PRESSED(cur->tipka_port, cur->tipka_pin) ) {
        LED_ON(cur->led_port, cur->led_pin)
        cur->funkcija();
    }
  }

Zadnja vrstica MAP je polna NULL, da se for zanka tam konča.
Uporabniški avatar
zanka
 
Prispevkov: 1235
Pridružen: 17 Mar 2016, 00:16
Kraj: Krško
Zahvalil se je: 74 krat
Prejel zahvalo: 114 krat
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 21

Re: STM32 in C - Optimiziranje GPIO operacij

OdgovorNapisal/-a tilz0R » 21 Mar 2017, 22:13

ideja spodnje kode je "class" v C-ju.

Koda: Izberi vse
//Struktura za ledico, lahko dodaš tudi callback funkcijo, če hočeš imeti kje.
typedef struct LED_t {
    GPIO_TypeDef* Port;
    uint16_t Pin;
    GPIO_TypeDef* BtnPort;
    uint16_t BtnPin;
    void (*func)(void);  //Menim, da imaš funkcijo ki vrne void in ne sprejme argumentov
} LED_t;

//Funkcija
void funkcija(void) {
    //Delaj kar je potrebno
}

//Deklariraj array vseh tvojih ledic
LED_t myLeds[] = {
  //LED                   BTN              CALLBACK
    {GPIOA, GPIO_PIN_1, GPIOB, GPIO_PIN_3, funkcija},
    {GPIOB, GPIO_PIN_2, GPIOB, GPIO_PIN_3, funkcija},
    {GPIOC, GPIO_PIN_3, GPIOB, GPIO_PIN_3, funkcija},
}

//Za F4, F7, F0 bo ta koda delala (najhitreje), lahko pa uporabiš HAL
#define LED_ON(i)       myLeds[i].Port->BSRR =  myLeds[i].Pin
#define LED_OFF(i)      myLeds[i].Port->BSRR =  myLeds[i].Pin << 16
#define BTN_PRESSED(i) (myLeds[i].BtnPort->IDR & myLeds[i].Pin)
#define CALL_FUNC(i)   myLeds[i].func()

//Uporaba:
LED_ON(0); //Prižgi led 0
LED_ON(1); //Prižgi led 1
LED_OFF(2); //Vgasni led 2

če imaš več array-ev tvojih ledic, lahko macroje popraviš v:
#define LED_ON(p)       (p)->Port->BSRR =  (p)->Pin
#define LED_OFF(p)      (p)->Port->BSRR =  (p)->Pin << 16
#define LED_TOGGLE(p)    (p)->Port->ODR = (p)->Pin

//In potem uporaba
LED_ON(&myleds[1]); //Prižgi led 1 v myleds array-u
LED_ON(&myledsNeki[1]); //Prižgi led 1 v myledsNeki array-u


Potem pa tvoja for zanka:

Koda: Izberi vse
for (i = 0; i < sizeof(myLeds) / sizeof(myLeds[0]); i++) {
    if (BTN_PRESSED(i)) {
        //Odloči se, kaj boš z led sedaj, mogoče toggle?
        LED_ON(i);
        CALL_FUNC(i);  //Callback tukaj
    } else {
        LED_OFF(i);
    }
}
"Words come easy, when they're true!"
Robbie Williams, Gary Barlow
Moj nickname je tilz[NULA]R.
Uporabniški avatar
tilz0R
 
Prispevkov: 1106
Pridružen: 17 Jan 2015, 23:12
Kraj: Črnomelj
Zahvalil se je: 159 krat
Prejel zahvalo: 272 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: STM32 in C - Optimiziranje GPIO operacij

OdgovorNapisal/-a Jule » 22 Mar 2017, 17:46

To je točno to kar sem potreboval!

Že dela!

Hvala obema!
Jule
 
Prispevkov: 643
Pridružen: 18 Jan 2015, 12:00
Kraj: Ajdovščina
Zahvalil se je: 129 krat
Prejel zahvalo: 131 krat
Uporabnika povabil: gumby
Število neizkoriščenih povabil: 16

Re: STM32 in C - Optimiziranje GPIO operacij

OdgovorNapisal/-a zanka » 22 Mar 2017, 18:18

Zanke obstajajo z razlogom. :D
Uporabniški avatar
zanka
 
Prispevkov: 1235
Pridružen: 17 Mar 2016, 00:16
Kraj: Krško
Zahvalil se je: 74 krat
Prejel zahvalo: 114 krat
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 21


Vrni se na C in sorodni jeziki

Kdo je na strani

Po forumu brska: 0 registriranih uporabnikov in 1 gost