• 1
  • 2

Dynamická alokácia poľa

. .

Dynamické alokovanie štruktúry prvkov s rovnakým dátovým typom nám poskytuje o level vyššiu univerzálnosť kódu.
Používame ju všade tam, kde nie je pred samotným spustením isté, koľko a aké prvky sa budú používať.
Z hľadiska univerzálnosti riešenie problému spočíva v tom, že samotný modul ako celok pracuje s dynamicky
alokovaným poľom. Je mu jedno, aké prvky v poli budú použité - nepracuje s natvrdo nastavenými prvkami. Tieto prvky si môžme ľubovoľne nastaviť len raz, a modul bude pracovať snimi nezávisle na tom, či si ich neskôr budeme chcieť znova zmeniť za iné.
Pokiaľ by sme mali množinu prvkov natvrdo nastavenú v kóde, pri zmenách zapojení (napríklad portov), by sme museli zasahovať do kódu a nastavenia pokaždom meniť.

 

Dynamickú alokáciu poľa urobíme prostredníctvom malloc, samotné alokované pole bude ako pointer dátového typu
(v našom prípade int). Ukážka dole na príklade.

Chceme napísať program, ktorý nám na nami zvolené výstupy zapojené na diody LED, privedie log. 1 a rozsvieti ich.

main.c

#define __NoTypeDef__

#include "config_diall.c"
#include "config_words.h"


struct _rozsviet_ {
int *Pins;
int size;
int i;
}Rozsviet;

void Rozsviet_Config(void)
{
   int pomocne_pole[] = {1,2,3,7,8};
        Rozsviet.size = sizeof(pomocne_pole)/sizeof(int);

   Rozsviet.Pins = malloc(Rozsviet.size);
      for (Rozsviet.i = 0; Rozsviet.i < Rozsviet.size; Rozsviet.i++)
           {
              Rozsviet.Pins[Rozsviet.i] = pomocne_pole[Rozsviet.i];
           }
}

void Rosviet_Init(void)
{
    Rozsviet_Config();

     for (Rozsviet.i=0; Rozsviet.i < Rozsviet.size; Rozsviet.i++)
          {
             Init_Port(PORTB,Rozsviet.Pins[Rozsviet.i],"digital");
             Config_OUT(TRISB,Rozsviet.Pins[Rozsviet.i]);
          }
}

void Sviet(void)
{
     for (Rozsviet.i=0; Rozsviet.i < Rozsviet.size; Rozsviet.i++)
          {
             Bit_Set(PORTB,Rozsviet.Pins[Rozsviet.i]);
          }
}

void Zhasni(void)
{
    for (Rozsviet.i=0; Rozsviet.i < Rozsviet.size; Rozsviet.i++)
        {
           Bit_Clr(PORTB,Rozsviet.Pins[Rozsviet.i]);
        }
}

int main(void)
{
    Rosviet_Init();
    while(1)
    {
       Sviet();
       Delay_s(5);
       Zhasni();
       Delay_s(5)
    }

}
 



Nadefinovali sme si štruktúru "Rozsviet". V tejto štruktúre sú deklarované: pointer dátového typu int,
veľkosť alokovaného poľa a pomocná premenná "i" pre cyklus "for".

V metóde "Rozsviet_Config" sú v dočasnom poli nadefinované čisla portov, s ktorými chceme pracovať a samotná alokácia poľa "Rozsviet.Pins" čo je, ako sme už spomenuli, pointer typu int ukazujúci do pamäte procesora.
Metóda je volaná z metódy "Rozsviet_Init".

"Rozsviet_Init" spúšťa metódu "Rozsviet_Config", následne pristupuje do alokovaného poľa a jednotlivé porty registra PORTB nastavuje ako digitálne.

"Svieť" pristupuje k prvkom (číslam portov) alokovaného poľa, prechádza nimi a nastavuje ich na hodnotu log. 1.

"Zhasni" podobne ako "Svieť" prechádza čísla portov v alokovanom poli a nastaví im hodnotu log. 0.

Vidíme, že prvky nastavujeme - vkladáme do pomocného poľa - len raz. Ostatné metódy pracujú už len s alokovaným poľom, samostatne a nezávisle.
Ľubovoľne môžme vkladať alebo odoberať čísla portov do pomocného poľa bez nutnosti nastavovania neakého ďalšieho počtu prípadne iných vecí.


*Poznámka: Je nutné si uvedomiť, že dynamické alokovanie dynamicky a nekontrolovateľne využíva hw. prostriedky MCU (ako pamäť) počas behu programu v kontroléry. Pokiaľ píšeme dlhšie zdrojové kódy, môže sa stať, že pri alokovaní dôjde k hazardom, ktoré môžu byť mäkké (pretečenie poľa prejdením maximálneho indexu), alebo tvrdé (využitie maximálnej použiteľnej kapacity pamäte MCU, MCU sa resetuje). Z dôvodu tvrdých hazardov, by sa alokácia mala používať s rozumom.

Pri chybách resetu pri alokácií je nutné zvýšiť veľkosť pamäťovej oblasti Heapu, bod 4.5 : Konfigurácia MPLAB