В чем отличие при объявлении pin'а?

funakoshi
Offline
Зарегистрирован: 13.03.2015

Всем привет.

Господа, разъясните новичку следующий вопрос:

Могу pin 5 объявить через #define:

#define LED_PIN 5
void setup() {
 pinMode(LED_PIN, HIGH);
}
void loop() {
бла-бла-бла
}

а могу через константу:

const int ledPin = 13;
void setup() { 
pinMode(ledPin, HIGH);
}
void loop() { 
бла-бла-бла
}

в чем  принципиальное различие? И как правильно?

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Вопрос философский, IMHO.

Код, генерируемый компилятором для данного примера кода одинаковый для обоих вариантов. Номер пина подставляется как константа в обоих случаях.

По-большому счету для C++ define использовать нежелательно, хотя и никто особо не запрещает.

Впрочем может кто-нибудь объяснит это более точно с точки зрения стандартов.

Лично я использую оба варианта.

 

vserg
Offline
Зарегистрирован: 07.05.2015

Если по простому :)

#define LED_PIN 5

Везде где встречается в тексте LED_PIN, компилятор будет вставлять 5.

const int ledPin = 13;

Компилятор выделит память и запишет туда 13. Потом можно будет читать из этой ячейки.

funakoshi
Offline
Зарегистрирован: 13.03.2015

vserg пишет:

 Потом можно будет читать из этой ячейки.

А в каком случае это может пригодиться? Тоже по простому :)

vserg
Offline
Зарегистрирован: 07.05.2015

Для экономии памяти. 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Если по простому, то это в дальнейшем позволяет быстро заменить номер пина без поиска всех мест где он используется.
Экономии памяти здесь нет.

funakoshi
Offline
Зарегистрирован: 13.03.2015

kisoft пишет:
это в дальнейшем позволяет быстро заменить номер пина без поиска всех мест где он используется.

Это то понятно, и это относится к обеим формам записи.

В каком случае может пригодится чтение из ячейки памяти, в которую записана константа с номером пина?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

мне лично пины больше через define нравится объявлять по нескольким причинам

#define led  10 // 1 вариант
int   led =10; // 2 вариант

1. в 1 варианте нельзя поменять значение led таким образом led=9, а во втором варианте легко

2. 2 вариант для объявления переменных, и можно случайно перепутать переменную с пином "константой". можно конечно через const объявить. но все же лучше отличать. так как через const также объявляются константы. а тут и то и другое константы. каша короче

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ассемблерный код для варианта #define

000002e6 <setup>:
     2e6:	61 e0       	ldi	r22, 0x01	; 1
     2e8:	85 e0       	ldi	r24, 0x05	; 5
     2ea:	0c 94 78 01 	jmp	0x2f0	; 0x2f0 <pinMode>

000002ee <loop>:
     2ee:	08 95       	ret

Аналогично для варианта const:

000002e6 <setup>:
     2e6:	61 e0       	ldi	r22, 0x01	; 1
     2e8:	8d e0       	ldi	r24, 0x0D	; 13
     2ea:	0c 94 78 01 	jmp	0x2f0	; 0x2f0 <pinMode>

000002ee <loop>:
     2ee:	08 95       	ret

Найдите здесь чтение из ячейки памяти.

Поскольку Ваш вопрос я не понял, могу сказать, только то, что  const int - это не переменная, а константа и разница в этом есть, константа или переменная. Константы могут располагаться в памяти (как решит компилятор/оптимизатор), но чаще оптимальней подставить их прямо в код, нежели читать откуда то.

А вот переменные, как правило (но не всегда), могут занимать место в памяти.

 

funakoshi
Offline
Зарегистрирован: 13.03.2015

:)) Какой ассемблер? У меня и без него голова кипит.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ну Вы в состоянии посмотреть, даже не понимая, что текст идентичен.
Могу сказать, что здесь нет чтения, две загрузки констант в регистры и вызов pinMode. Всё.

Sloper
Sloper аватар
Offline
Зарегистрирован: 30.03.2015

С дефайнами имхо код читабельнее: константы в раделе дефайн, а переменные в разделе инициализации.

alexs1507
Offline
Зарегистрирован: 04.09.2019

Я вот тоже столкнулся с такой проблемой. Очень большая разница между использованием #define и const

Совершенно непонятно почему этот код не работает:

#include <LiquidCrystal.h>
LiquidCrystal lcd (2, 3, 4, 5, 6, 7);

#define trigPin 12
#define echoPin 11

//const int trigPin = 11;
//const int echoPin = 12;
      
long duration;
int distanceCm, distanceInch;

void setup() {
Serial.begin (9600);
lcd.begin(16,2); 
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}

void loop() {
  
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);
distanceCm= duration*0.034/2;
distanceInch = duration*0.0133/2;

lcd.setCursor(0,0); // Sets the location at which subsequent text written to the LCD will be displayed
lcd.print("Distance: "); // Prints string "Distance" on the LCD
lcd.print(distanceCm); // Prints the distance value from the sensor
lcd.print("  cm");
    
      Serial.print("Длительность: ");
      Serial.println(duration);
      
      Serial.print("Расстояние до объекта: ");
      Serial.print(distanceCm);
      Serial.println(" см.");


delay(100);}

в таком виде он работает очень странно (даже если вручную вместо trigPin и echoPin по тексту вписать 11 и 12 соответственно), дистанцию или ноль показывает или неверно (завышенно раз в 10),

а вот если написать const int trigPin = 11;  const int echoPin = 12; все работает четко, интересно, что при этом длина скомпилированного кода одинаковая, отличаются только несколько байтов

кто может пояснить почему?

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

У меня все скомпилировалось в 1.8.8

Скетч использует 4246 байт (13%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 290 байт (14%) динамической памяти, оставляя 1758 байт для локальных переменных. Максимум: 2048 байт.

 

alexs1507
Offline
Зарегистрирован: 04.09.2019

Была ошибка в коде. Сорри

#define trigPin 12
#define echoPin 11

//const int trigPin = 11;
//const int echoPin = 12;

перепутаны номера пинов.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

А я подумал не компилируется))