Arduino makrokomandos: išsamus jų įvaldymo vadovas su pavyzdžiais

  • „Arduino“ makrokomandos leidžia optimizuoti kodą ir atmintį prieš kompiliuojant.
  • Naudodami #define galite kurti prisitaikančias funkcijas, konstantas ir struktūras.
  • Išplėstinės makrokomandos leidžia sujungti identifikatorius ir pasiekti PROGMEM.
  • Drausmingas makrokomandų naudojimas pagerina efektyvumą neprarandant skaitomumo.

Arduino Cores Zephyr OS beta-1

Arduino padarė revoliuciją elektronikos pasaulyje dėl to, kad galima lengvai sukurti funkcinius prototipus ir projektus. Tačiau tiems, kurie nori programuoti dar vieną žingsnį ir optimizuoti išteklius, išlaikyti kodą švarų ir padidinti efektyvumą, makrokomandos tapti pagrindine priemone.

Šiame straipsnyje mes gilinsimės į jo naudojimą makrokomandos Arduino: kas jie yra, kaip jie naudojami, jų pranašumai ir apribojimai. Ir mes tai padarysime rinkdami išsamiausią ir naudingiausią informaciją iš geriausių internete esančių šaltinių, perrašytą aiškiai ir šiuolaikiškai, kad būtų tikrai praktiška.

Kas yra Arduino makrokomandos?

Makrokomandos yra išankstinio procesoriaus direktyvos C/C++, kurie leidžia pakeisti tekstą prieš sudarant kodą. Užuot vykdydama instrukcijas kaip tradicinė funkcija, makrokomanda veikia pakeičiant dalis šaltinio teksto, kuris turi tiesioginis poveikis galutinio dvejetainio kodo generavimui.

Pirminis procesorius Jis paleidžiamas prieš faktinį kompiliavimą ir yra atsakingas už šių pakeitimų taikymą. „Arduino“ tai leidžia nuo apibrėžti konstantas, sąlyginai įtraukite failus arba net sukurkite mažus internetinės funkcijos kurie taupo laiką ir atmintį.

Pagrindinis pavyzdys: apibrėžimas kaip #define LED_PIN 13 automatiškai pakeičiamas visas kodas LED_PIN iki 13 prieš sudarant.

Tai gali atrodyti nereikšminga, tačiau ji siūlo a galingas būdas rašyti lankstesnį ir prižiūrimesnį kodą.

Makrokomandų naudojimo pranašumai

Makrokomandų diegimas Arduino projektuose gali pasiūlyti keletą konkrečių pranašumų:

  • Pagerinkite kodo skaitomumą: Pakartotinai naudojant simbolinius pavadinimus, lengviau suprasti kiekvieno elemento paskirtį.
  • Optimizuokite našumą: Negeneruodamos funkcijų iškvietimų, makrokomandos gali greičiau atlikti operacijas.
  • Sumažinkite RAM naudojimą: ypač naudinga ribotų išteklių turinčiose plokštėse, tokiose kaip Arduino UNO.
  • Leidžia sąlygines adaptacijas: Priklausomai nuo naudojamos Arduino plokštės tipo, galima kompiliuoti skirtingus kodo fragmentus.

Pagrindinės makrokomandos: naudokite #define

Direktyvą #apibrėžti Jis yra dažniausiai naudojamas. Jis naudojamas tiek apibrėžti pastovias reikšmes tarsi sukurti įšvirkščiamas automatines funkcijas išankstinio kompiliavimo metu.

1 pavyzdys: apibrėžkite kaištį

#define PINLED 13

void setup() {
  pinMode(PINLED, OUTPUT);
}

void loop() {
  digitalWrite(PINLED, HIGH);
  delay(500);
  digitalWrite(PINLED, LOW);
  delay(500);
}

2 pavyzdys: makrokomandos kaip įterptoji funkcija

int itemCounter = 0;
#define COUNT_ITEM() do { itemCounter++; } while(0)

void setup() {
  Serial.begin(9600);
  COUNT_ITEM();
  COUNT_ITEM();
}

void loop() {
  Serial.println(itemCounter);
}

Kaip matote, modelio naudojimas daryti { … }, kol (0) užtikrina, kad makrokomanda veiktų saugiai, net jei naudojama sąlyginėse struktūrose.

## operatorius ir makrokomandos sujungimas

## operatorius yra galingas pirminio procesoriaus įrankis. kuri leidžia sujungti identifikatorius. Tai labai naudinga, kai norite dinamiškai generuoti kintamųjų pavadinimus.

Praktinis pavyzdys:

#define GENERAR_VARIABLE(no) \
  int var##no = no;

void setup() {
  GENERAR_VARIABLE(3); // crea int var3 = 3
}

Svarbus įspėjimas: Šis operatorius nėra vienodai suderinamas su visais Arduino plokščių modeliais. Pavyzdžiui, jis gali gerai veikti „Uno“ ar „Esplora“, bet nepavykti „Mega“. Be to, negalite įdėti makrokomandų kūrimo į kitas makrokomandas, naudodami ## tiesiogiai.

Makrokomandos ir atminties taupymas

Vienas iš pagrindinių Arduino makrokomandų naudojimo pranašumų yra taupyti RAM atmintį. Arduino talpa yra ribota, todėl teksto eilučių įkėlimas tiesiai į RAM gali tapti didele problema.

Pažangi technika, siekiant to išvengti, apima naudojimą FORCE_INLINE ir įkelti eilutes iš programos atminties (PROGMEM):

#include <HardwareSerial.h>
#define MYSERIAL Serial
#define FORCE_INLINE __attribute__((always_inline)) inline

FORCE_INLINE void printFromFlash(const char *str) {
  char ch = pgm_read_byte(str);
  while (ch) {
    MYSERIAL.write(ch);
    ch = pgm_read_byte(++str);
  }
}

#define SERIAL_LOG(x) (MYSERIAL.print(x))
#define SERIAL_LOGLN(x) (MYSERIAL.println(x))

Naudodami šias makrokomandas galite skirtis, ar projektas veikia, ar ne, ypač programose su ekranais arba keliais jutikliais.

Makrokomandos derinamos su funkcijomis

Makrokomandos taip pat gali palengvinti funkcijų iškvietimą dinamiškai, atsižvelgiant į tipą, pateiktą kaip parametras. Aiškus ir gana vaizdingas pavyzdys:

#define FUNC_LENTA(tipo) \
  { funcion_##tipo##_lenta(); }

#define FUNC_RAPIDA(tipo) \
  { funcion_##tipo##_rapida(); }

void funcion_caminar_lenta() {
  Serial.println("Andando despacio");
}

void funcion_caminar_rapida() {
  Serial.println("Andando rápido");
}

void setup() {
  Serial.begin(9600);
  FUNC_LENTA(caminar);
}

void loop() {
  FUNC_RAPIDA(caminar);
}

Operatoriaus ## ir makrokomandų dėka galime išvengti struktūrų pasikartojimo ir centralizuoti dinaminę logiką..

Makrokomandos su išvesties parametrais

Taip pat galima naudoti makrokomandas mažiems objektams arba konversijoms įterpti:

#define BOOL_OUT() (bool){false}
#define NUM_OUT(a,b) (float){a+b}
#define STR_OUT(msg) (String){msg}

void loop() {
  Serial.println(BOOL_OUT());
  Serial.println(NUM_OUT(1.2, 3.4));
  Serial.println(STR_OUT("Mensaje"));
}

Gera praktika ir atsargumo priemonės naudojant makrokomandas

Pernelyg arba neatsargiai naudojant makrokomandas gali atsirasti sunkiai derinamos klaidos. Pavyzdžiui, atliekant neteisingus pakeitimus arba apibrėžiant pavadinimus, kurie susiduria su išorinių bibliotekų pavadinimais.

Keletas pagrindinių taisyklių, kurios padės išvengti problemų:

  • Venkite nereikalingų tarpų ar eilučių pertraukų makrokomandoje.
  • Neįtraukti komentarų sudėtingose ​​makrokomandose, kuriose naudojamos kelios eilutės.
  • Naudokite unikalius pavadinimus arba su priešdėliais (pvz., projekto pavadinimu), kad išvengtumėte konfliktų.
  • Pakeiskite makrokomandas tikrosiomis konstantomis arba funkcijomis kai tik įmanoma. Šiuolaikinė C++ suteikia švaresnių ir saugesnių alternatyvų.

Kita vertus, per didelis makrokomandų naudojimas gali sumažinti kodo aiškumą. Tikslas turėtų būti pagerinti efektyvumą ir moduliškumą nepažeidžiant priežiūros.

Sąlyginės direktyvos ir adaptyvi kompiliacija

Viena iš praktiškiausių keičiamo dydžio projektų funkcijų yra makrokomandų naudojimas sąlygiškai generuoti kodą, kažkas labai naudingo, kai norite, kad tas pats eskizas veiktų skirtingose ​​​​lentose.

Tipiškas pavyzdys:

#ifdef ARDUINO_MEGA
  #define LEDPIN 53
#else
  #define LEDPIN 13
#endif

Tai taip pat naudinga norint valdyti derinimą arba rodyti kompiliatoriaus pranešimus #pragma žinutė arba net generuoti klaidų tam tikromis sąlygomis su #klaida.

Vidinės kompiliatoriaus makrokomandos

GCC pirminis AVR procesorius (naudojamas Arduino) apima keletą specialios makrokomandos, teikiančios sistemos informaciją, labai naudinga kuriant:

  • __LINE__: dabartinės linijos numeris.
  • __FILE__: dabartinio failo pavadinimas.
  • __TIME__ ir __DATE__: sudarymo laikas ir data.
  • __funkc__: esamos funkcijos pavadinimas.

Jie leidžia valdyti versijas, žurnalų struktūras ir palengvinti techninę priežiūrą bei klaidų atsekimą nepažeidžiant pagrindinio kodo.

Makrokomandos siūlo galingą ir lankstų būdą struktūrizuoti Arduino projektus. Jie leidžia apibrėžti konstantas, taupyti atmintį, pritaikyti kodą priklausomai nuo vykdymo aplinkos ir kurkite daugkartinio naudojimo blokus nedubliuodami eilučių. Žinoma, jie reikalauja disciplinos, aiškumo ir žinių, kad būtų išvengta subtilių klaidų ar skaitomumo praradimo. Tinkamai pritaikius, jie yra neįkainojamas turtas vidutiniams ir pažengusiems kūrėjams.