Arduino Macros: คู่มือฉบับสมบูรณ์ในการเชี่ยวชาญพร้อมตัวอย่าง

  • มาโครใน Arduino ช่วยให้คุณเพิ่มประสิทธิภาพโค้ดและหน่วยความจำก่อนการคอมไพล์
  • การใช้ #define ช่วยให้คุณสามารถสร้างฟังก์ชันการปรับตัว ค่าคงที่ และโครงสร้างได้
  • แมโครขั้นสูงช่วยให้คุณสามารถเชื่อมโยงตัวระบุและเข้าถึง PROGMEM
  • การใช้แมโครอย่างมีวินัยช่วยเพิ่มประสิทธิภาพโดยไม่กระทบต่อความสามารถในการอ่าน

Arduino Cores Zephyr OS เบต้า-1

แพลตฟอร์มฮาร์ดแวร์ ได้ปฏิวัติโลกของอุปกรณ์อิเล็กทรอนิกส์ด้วยความง่ายในการสร้างต้นแบบและโปรเจ็กต์ที่ใช้งานได้ อย่างไรก็ตาม สำหรับผู้ที่ต้องการพัฒนาการเขียนโปรแกรมไปอีกขั้นและเพิ่มประสิทธิภาพการใช้ทรัพยากร ให้โค้ดสะอาดและเพิ่มประสิทธิภาพ แมโคร กลายเป็นเครื่องมือสำคัญ

ในบทความนี้เราจะเจาะลึกถึงการใช้งาน มาโครใน Arduino:คืออะไร ใช้ยังไง มีข้อดีและข้อจำกัดอย่างไร และเราจะทำเช่นนี้โดยการรวบรวมข้อมูลที่ครอบคลุมและเป็นประโยชน์ที่สุดจากแหล่งข้อมูลที่ดีที่สุดที่มีบนอินเทอร์เน็ต เขียนขึ้นใหม่ด้วยวิธีที่ชัดเจนและทันสมัยเพื่อให้ใช้งานได้จริง

มาโครใน Arduino คืออะไร?

แมโครเป็นไดเรกทิฟพรีโพรเซสเซอร์ ใน C/C++ ที่อนุญาตให้คุณแทนที่ข้อความก่อนที่จะคอมไพล์โค้ด แทนที่จะดำเนินการคำสั่งเหมือนฟังก์ชันดั้งเดิม แมโครจะทำงานโดยการแทนที่บางส่วนของข้อความต้นฉบับ ซึ่งมี ผลกระทบโดยตรงต่อวิธีการสร้างรหัสไบนารีขั้นสุดท้าย.

พรีโปรเซสเซอร์ จะทำงานก่อนการคอมไพล์จริง และรับผิดชอบในการใช้การแทนที่เหล่านี้ ใน Arduino สิ่งนี้ช่วยให้ กำหนดค่าคงที่รวมไฟล์ตามเงื่อนไขหรือสร้างไฟล์ขนาดเล็ก คุณสมบัติออนไลน์ ที่ประหยัดเวลาและความจำ

ตัวอย่างพื้นฐาน: คำจำกัดความเช่น #define LED_PIN 13 ทำให้โค้ดทั้งหมดถูกแทนที่โดยอัตโนมัติ LED_PIN โดย 13 ก่อนที่จะรวบรวม

สิ่งนี้อาจดูไม่สำคัญ แต่ให้ประโยชน์ วิธีที่มีประสิทธิภาพในการเขียนโค้ดที่ยืดหยุ่นและบำรุงรักษาได้มากขึ้น.

ข้อดีของการใช้แมโคร

การนำแมโครมาใช้ในโครงการ Arduino สามารถให้ประโยชน์เฉพาะเจาะจงได้หลายประการ ดังนี้:

  • ปรับปรุงการอ่านโค้ดให้ดีขึ้น: การนำชื่อสัญลักษณ์มาใช้ซ้ำช่วยให้เข้าใจวัตถุประสงค์ของแต่ละองค์ประกอบได้ง่ายขึ้น
  • เพิ่มประสิทธิภาพ: การไม่สร้างการเรียกใช้ฟังก์ชันทำให้แมโครสามารถดำเนินการได้เร็วขึ้น
  • ลดการใช้ RAM: มีประโยชน์อย่างยิ่งบนบอร์ดที่มีทรัพยากรจำกัด เช่น Arduino UNO.
  • อนุญาตให้ปรับเปลี่ยนตามเงื่อนไข: สามารถคอมไพล์ชิ้นส่วนโค้ดต่าง ๆ ได้ ขึ้นอยู่กับประเภทของบอร์ด Arduino ที่ใช้

มาโครพื้นฐาน: การใช้ #define

คำสั่ง #กำหนด มันถูกใช้งานมากที่สุด ใช้ได้ทั้งสำหรับ กำหนดค่าคงที่ สำหรับ สร้างฟังก์ชั่นฉีดอัตโนมัติ ในช่วงเวลาก่อนการคอมไพล์

ตัวอย่างที่ 1: กำหนดพิน

#define PINLED 13

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

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

ตัวอย่างที่ 2: มาโครเป็นฟังก์ชันอินไลน์

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

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

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

อย่างที่คุณเห็น การใช้รูปแบบ ทำ { … } while(0) ช่วยให้แน่ใจว่าแมโครจะทำงานอย่างปลอดภัยแม้จะใช้ภายในโครงสร้างที่มีเงื่อนไขก็ตาม

## ตัวดำเนินการและการเรียงต่อกันของแมโคร

ตัวดำเนินการ ## เป็นเครื่องมือพรีโปรเซสเซอร์อันทรงพลัง ซึ่งช่วยให้สามารถเชื่อมโยงตัวระบุเข้าด้วยกันได้ สิ่งนี้มีประโยชน์มากเมื่อคุณต้องการสร้างชื่อตัวแปรแบบไดนามิก

ตัวอย่างการปฏิบัติ:

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

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

คำเตือนที่สำคัญ: ตัวดำเนินการนี้ไม่สามารถใช้งานร่วมกับบอร์ด Arduino ได้ทุกรุ่น ตัวอย่างเช่น มันอาจจะทำงานได้ดีกับ Uno หรือ Esplora แต่ล้มเหลวกับ Mega นอกจากนี้ คุณไม่สามารถสร้างแมโครแบบซ้อนภายในแมโครอื่นโดยใช้ ## โดยตรงได้

มาโครและการบันทึกหน่วยความจำ

ข้อได้เปรียบหลักประการหนึ่งของการใช้แมโครใน Arduino คือ การประหยัดแรม- Arduino มีความจุจำกัด ดังนั้นการโหลดสตริงข้อความโดยตรงลงใน RAM อาจกลายเป็นปัญหาสำคัญได้

เทคนิคขั้นสูงในการหลีกเลี่ยงสิ่งนี้เกี่ยวข้องกับการใช้ บังคับแบบอินไลน์ และโหลดสตริงจากหน่วยความจำโปรแกรม (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))

การใช้แมโครเหล่านี้สามารถสร้างความแตกต่างระหว่างโปรเจ็กต์ที่ทำงานได้หรือไม่ โดยเฉพาะในแอปพลิเคชันที่มีจอแสดงผลหรือเซ็นเซอร์หลายตัว

มาโครรวมกับฟังก์ชั่น

นอกจากนี้ มาโครยังอำนวยความสะดวกในการเรียกฟังก์ชันแบบไดนามิก โดยอิงตามประเภทที่ส่งผ่านเป็นพารามิเตอร์ ตัวอย่างที่ชัดเจนและชัดเจนคือ:

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

ต้องขอบคุณตัวดำเนินการ ## และแมโคร เราจึงหลีกเลี่ยงการทำซ้ำโครงสร้างและรวมตรรกะแบบไดนามิกให้เป็นศูนย์กลางได้.

มาโครพร้อมพารามิเตอร์เอาท์พุต

นอกจากนี้ยังสามารถใช้แมโครเพื่อรวมวัตถุขนาดเล็กหรือการแปลงได้:

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

แนวทางปฏิบัติที่ดีและข้อควรระวังในการใช้แมโคร

การใช้แมโครมากเกินไปหรือประมาทอาจทำให้เกิด ข้อผิดพลาดที่แก้ไขได้ยาก- ตัวอย่างเช่น การแทนที่ที่ไม่ถูกต้องหรือการกำหนดชื่อที่ขัดแย้งกับชื่อในไลบรารีภายนอก

กฎพื้นฐานบางประการเพื่อหลีกเลี่ยงปัญหา:

  • หลีกเลี่ยงการเว้นวรรคหรือแบ่งบรรทัดที่ไม่จำเป็น ภายในมหภาค
  • ไม่รวมความคิดเห็น ภายในแมโครที่ซับซ้อนซึ่งใช้หลายบรรทัด
  • ใช้ชื่อที่ไม่ซ้ำใคร หรือมีคำนำหน้า (เช่น ชื่อโครงการ) เพื่อหลีกเลี่ยงความขัดแย้ง
  • แทนที่แมโครด้วยค่าคงที่หรือฟังก์ชันจริง เมื่อใดก็ตามที่เป็นไปได้ C++ สมัยใหม่มีทางเลือกที่สะอาดและปลอดภัยยิ่งขึ้น

ในทางกลับกัน การใช้แมโครมากเกินไปอาจทำให้ความชัดเจนของโค้ดลดลง เป้าหมายควรเป็นการปรับปรุงประสิทธิภาพและการสร้างโมดูลโดยไม่กระทบต่อความสามารถในการบำรุงรักษา

คำสั่งเงื่อนไขและการคอมไพล์แบบปรับตัว

ฟังก์ชันการใช้งานที่ใช้งานได้จริงที่สุดอย่างหนึ่งในโครงการที่ปรับขนาดได้คือการใช้แมโครเพื่อ สร้างโค้ดตามเงื่อนไขสิ่งที่มีประโยชน์มากเมื่อคุณต้องการให้ภาพร่างแบบเดียวกันใช้งานบนบอร์ดที่แตกต่างกัน

ตัวอย่างทั่วไป:

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

ยังมีประโยชน์ในการควบคุมการดีบักหรือการแสดงข้อความคอมไพเลอร์ด้วย ข้อความ #pragma หรือแม้กระทั่งสร้างข้อผิดพลาดภายใต้เงื่อนไขบางประการด้วย #ข้อผิดพลาด.

มาโครคอมไพเลอร์ภายใน

พรีโปรเซสเซอร์ GCC สำหรับ AVR (ใช้ใน Arduino) ประกอบด้วยหลาย ๆ แมโครพิเศษที่ให้ข้อมูลระบบมีประโยชน์มากในระหว่างการพัฒนา:

  • __ไลน์__: หมายเลขบรรทัดปัจจุบัน.
  • __ไฟล์__: ชื่อของไฟล์ปัจจุบัน
  • __เวลา__และ__วันที่__: เวลาและวันที่รวบรวม
  • __ฟังก์ชัน__: ชื่อของฟังก์ชั่นปัจจุบัน

ช่วยให้สามารถควบคุมเวอร์ชัน สร้างโครงสร้างบันทึก และอำนวยความสะดวกในการบำรุงรักษาและการติดตามข้อผิดพลาดโดยไม่รบกวนโค้ดหลัก

มาโครเป็นวิธีที่ทรงพลังและยืดหยุ่นในการจัดโครงสร้างโครงการ Arduino มันอนุญาตให้คุณกำหนดค่าคงที่ บันทึกความทรงจำ, ปรับเปลี่ยนโค้ด ขึ้นอยู่กับสภาพแวดล้อมการดำเนินการ และสร้างบล็อกที่นำกลับมาใช้ใหม่ได้โดยไม่ต้องทำซ้ำบรรทัด แน่นอนว่าต้องมีวินัย ความชัดเจน และความรู้เพื่อหลีกเลี่ยงข้อผิดพลาดเล็กๆ น้อยๆ หรือการสูญเสียความสามารถในการอ่าน เมื่อใช้ได้อย่างถูกต้องแล้ว ถือเป็นทรัพย์สินอันล้ำค่าสำหรับนักพัฒนาระดับกลางและขั้นสูง


เป็นคนแรกที่จะแสดงความคิดเห็น

แสดงความคิดเห็นของคุณ

อีเมล์ของคุณจะไม่ถูกเผยแพร่ ช่องที่ต้องการถูกทำเครื่องหมายด้วย *

*

*

  1. ผู้รับผิดชอบข้อมูล: Miguel ÁngelGatón
  2. วัตถุประสงค์ของข้อมูล: ควบคุมสแปมการจัดการความคิดเห็น
  3. ถูกต้องตามกฎหมาย: ความยินยอมของคุณ
  4. การสื่อสารข้อมูล: ข้อมูลจะไม่ถูกสื่อสารไปยังบุคคลที่สามยกเว้นตามข้อผูกพันทางกฎหมาย
  5. การจัดเก็บข้อมูล: ฐานข้อมูลที่โฮสต์โดย Occentus Networks (EU)
  6. สิทธิ์: คุณสามารถ จำกัด กู้คืนและลบข้อมูลของคุณได้ตลอดเวลา