Arduino-makroer: En komplett guide for å mestre dem med eksempler

  • Makroer i Arduino lar deg optimalisere kode og minne før kompilering.
  • Ved å bruke #define kan du lage adaptive funksjoner, konstanter og strukturer.
  • Avanserte makroer lar deg slå sammen identifikatorer og få tilgang til PROGMEM.
  • Disiplinert bruk av makroer forbedrer effektiviteten uten å ofre lesbarheten.

Arduino Cores Zephyr OS beta-1

Arduino har revolusjonert elektronikkens verden takket være den enkle funksjonelle prototyper og prosjekter kan lages med. Men for de som ønsker å ta programmeringen et skritt videre og optimalisere ressursene, holde koden ren og få effektivitet, makroer bli et nøkkelverktøy.

I denne artikkelen skal vi dykke dypt ned i bruken av makroer i Arduino: hva de er, hvordan de brukes, deres fordeler og begrensninger. Og vi vil gjøre dette ved å samle den mest omfattende og nyttige informasjonen fra de beste ressursene tilgjengelig på nettet, omskrevet på en klar og moderne måte for å være virkelig praktisk.

Hva er makroer i Arduino?

Makroer er forbehandlerdirektiver i C/C++ som lar deg erstatte tekst før koden kompileres. I stedet for å utføre instruksjoner som en tradisjonell funksjon, fungerer en makro ved å erstatte deler av kildeteksten, som har en direkte innvirkning på hvordan den endelige binære koden genereres.

Forbehandleren Den kjører før selve kompileringen, og er ansvarlig for å bruke disse erstatningene. I Arduino tillater dette fra definere konstanter, betinget inkludere filer eller til og med lage små nettfunksjoner som sparer tid og minne.

Grunnleggende eksempel: en definisjon som #define LED_PIN 13 fører til at all kode automatisk erstattes LED_PIN av 13 før kompilering.

Dette kan virke trivielt, men det tilbyr en kraftig måte å skrive mer fleksibel og vedlikeholdbar kode på.

Fordeler med å bruke makroer

Implementering av makroer i Arduino-prosjekter kan tilby en rekke spesifikke fordeler:

  • Forbedre kodelesbarheten: Ved å gjenbruke symbolske navn er det lettere å forstå formålet med hvert element.
  • Optimaliser ytelsen: Ved å ikke generere funksjonskall kan makroer utføre operasjoner raskere.
  • Reduser RAM-bruk: spesielt nyttig på ressursbegrensede tavler, for eksempel Arduino UNO.
  • Tillater betingede tilpasninger: Det er mulig å kompilere forskjellige kodefragmenter avhengig av typen Arduino-brett som brukes.

Grunnleggende makroer: Bruk #define

Direktivet #definere Det er den mest brukte. Den brukes både til definere konstante verdier som for lage injiserte automatiske funksjoner på forhåndskompileringstidspunktet.

Eksempel 1: Definer en pinne

#define PINLED 13

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

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

Eksempel 2: Makro som innebygd funksjon

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

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

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

Som du kan se, bruken av mønsteret gjør { … } mens(0) sikrer at makroen oppfører seg trygt selv om den brukes innenfor betingede strukturer.

## operator og makrosammenkobling

##-operatoren er et kraftig forprosessorverktøy. som tillater sammenkobling av identifikatorer. Dette er veldig nyttig når du ønsker å generere variabelnavn dynamisk.

Praktisk eksempel:

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

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

Viktig advarsel: Denne operatøren er ikke like kompatibel med alle Arduino-kortmodeller. For eksempel kan det fungere bra på en Uno eller Esplora, men mislykkes på en Mega. Du kan heller ikke neste makrooppretting inne i andre makroer ved å bruke ## direkte.

Makroer og minnesparing

En av de viktigste fordelene med å bruke makroer i Arduino er sparer RAM. Arduino har begrenset kapasitet, så å laste tekststrenger direkte inn i RAM kan bli et betydelig problem.

En avansert teknikk for å unngå dette innebærer å bruke FORCE_INLINE og last inn strenger fra programminnet (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))

Bruk av disse makroene kan utgjøre forskjellen mellom et prosjekt som fungerer eller ikke, spesielt i applikasjoner med skjermer eller flere sensorer.

Makroer kombinert med funksjoner

Makroer kan også gjøre det lettere å kalle funksjoner dynamisk, basert på en type som sendes som en parameter. Et tydelig og ganske grafisk eksempel er:

#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);
}

Takket være ##-operatoren og makroer kan vi unngå repeterende strukturer og sentralisere dynamisk logikk..

Makroer med utdataparametere

Det er også mulig å bruke makroer for å kapsle inn små objekter eller konverteringer:

#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"));
}

God praksis og forholdsregler med makroer

Bruk av makroer overdrevent eller uforsiktig kan føre til vanskelig å feilsøke feil. For eksempel ved å gjøre feil erstatninger eller definere navn som kolliderer med navn i eksterne biblioteker.

Noen grunnleggende regler for å unngå problemer:

  • Unngå unødvendige mellomrom eller linjeskift i makroen.
  • Ikke ta med kommentarer i komplekse makroer som bruker flere linjer.
  • Bruk unike navn eller med prefikser (som prosjektnavnet) for å unngå konflikter.
  • Erstatt makroer med reelle konstanter eller funksjoner når det er mulig. Moderne C++ gir renere, tryggere alternativer.

På den annen side kan overbruk av makroer redusere kodeklarheten. Målet bør være å forbedre effektiviteten og modulariteten uten at det går på bekostning av vedlikehold.

Betingede direktiver og adaptiv kompilering

En av de mest praktiske funksjonene i skalerbare prosjekter er bruken av makroer til betinget generere kode, noe veldig nyttig når du vil at den samme skissen skal fungere på forskjellige brett.

Typisk eksempel:

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

Det er også nyttig for å kontrollere feilsøking eller vise kompilatormeldinger med #pragmamelding eller til og med generere feil under visse forhold med #feil.

Interne kompilatormakroer

GCC-forprosessoren for AVR (brukt i Arduino) inkluderer flere spesielle makroer som gir systeminformasjon, veldig nyttig under utvikling:

  • __LINJE__: gjeldende linjenummer.
  • __FIL__: navnet på gjeldende fil.
  • __TIME__ og __DATE__: kompileringstidspunkt og dato.
  • __func__: navnet på gjeldende funksjon.

De tillater versjonskontroll, loggstrukturer og forenkler vedlikehold og feilsporing uten å invadere hovedkoden.

Makroer tilbyr en kraftig og fleksibel måte å strukturere Arduino-prosjekter på. De lar deg definere konstanter, lagre minne, tilpasse koden avhengig av utførelsesmiljøet og lag gjenbrukbare blokker uten å duplisere linjer. Selvfølgelig krever de disiplin, klarhet og kunnskap for å unngå subtile feil eller tap av lesbarhet. Når de brukes riktig, er de en uvurderlig ressurs for middels og avanserte utviklere.


Bli den første til å kommentere

Legg igjen kommentaren

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *

*

*

  1. Ansvarlig for dataene: Miguel Ángel Gatón
  2. Formålet med dataene: Kontroller SPAM, kommentaradministrasjon.
  3. Legitimering: Ditt samtykke
  4. Kommunikasjon av dataene: Dataene vil ikke bli kommunisert til tredjeparter bortsett fra ved juridisk forpliktelse.
  5. Datalagring: Database vert for Occentus Networks (EU)
  6. Rettigheter: Når som helst kan du begrense, gjenopprette og slette informasjonen din.