Макросы
- Войдите на сайт для отправки комментариев
Ср, 30/01/2019 - 17:53
Проблема следующая!
Пытаюсь подправить библиотеку (CyberLib) чтобы можно было работать с переменными и в цыкле.
Если с D_In, D_Out, D_High, D_Low и D_Inv все нормально - подстановка происходит, что видно на прилагаемом коде, - то если запросить D_Read - выдает ошибку, хотя делал также как и с остальными.
Вопрос - Почему верхние макросы подставляют значение а последний не хочет.
(Текст Ошибки под макросом)
//Эти 2(два) макроса работают
#define D_In(x) if(x==10) DDRB &=B11111011;
#define D_Out(x) if (x==0) DDRD |=B00000001;\
else if (x==1) DDRD |=B00000010;\
else if (x==2) DDRD |=B00000100;\
else if (x==3) DDRD |=B00001000;\
else if (x==4) DDRD |=B00010000;\
else if (x==5) DDRD |=B00100000;
//Здесь макрос тоже работает
#define D_Inv(x) switch(x){\
case 0: PORTD ^=B00000001; break;\
case 1: PORTD ^=B00000010; break;\
case 2: PORTD ^=B00000100; break;\
case 3: PORTD ^=B00001000; break;\
case 4: PORTD ^=B00010000; break;\
case 5: PORTD ^=B00100000; break;\
}
// А ВОТ с этим проблема хотя и сделан по ВЫШЕ подобному и который работает без ошибки.
//Если раскоментировать 42_ю (buton1 = D_Read(10);) строку - идет ошибка (указана под макросом в коментарии)
#define D_Read(x) switch(x){\
case 10: ((PINB & B00000100)>>2); break;\
case 11: ((PINB & B00001000)>>3); break;\
case 12: ((PINB & B00010000)>>4); break;\
case 13: ((PINB & B00100000)>>5); break;}
//main.ino:42: error: expected primary-expression before 'switch'
//main.ino:42: error: expected `;' before 'switch'
void setup()
{
for(int i=2; i<6; i++)
{
D_Out(i); //Понимаю что правильнее DDRх - но делал для проверки работы в цыкле с переменной
}
}
void loop()
{
static bool poz = 0;
static bool buton1 = 0;
//buton1 = D_Read(10);
if(!buton1)
{
for(int i=3; i<6; i++)
{
D_Inv(i);
poz = !poz;
if(poz)
{
i--;
}
delay(1000);
}
}
//D_Beep(13, 1000, 10);
}
Код рабочий - ели закоментировано чтение ПИНА
Смотрел библиотеку ув.Arhat, вот что он пишет -
"При указании номера пина в переменной - этот подход НЕ РАБОТАЕТ! Макрос развернется в код, склеивающий название переменной с текстом макроса и Вы получите сообщение о синтаксических ошибках и только.
Такой подход имеет место быть, поскольку все пины Ардуино имеют жесткую привязку к своим функциям, особенно специальным и, соответственно, всегда явно известны при разработке скетчей."
Вот сижу и думаю почему приведенный ниже код работает - может это и есть ошибка.
Пока думал над вопросм, для D_Read нашол такое решение, правда сменить пин можно только по дефайну -
Хоть чтото не надо переписывать по всему коду
#define button 12
//Эти 2(два) макроса работают
#define D_In(x) if(x==10) DDRB &=B11111011;
#define D_Out(x) if (x==0) DDRD |=B00000001;\
else if (x==1) DDRD |=B00000010;\
else if (x==2) DDRD |=B00000100;\
else if (x==3) DDRD |=B00001000;\
else if (x==4) DDRD |=B00010000;\
else if (x==5) DDRD |=B00100000;
//Здесь макрос тоже работает
#define D_Inv(x) switch(x){\
case 0: PORTD ^=B00000001; break;\
case 1: PORTD ^=B00000010; break;\
case 2: PORTD ^=B00000100; break;\
case 3: PORTD ^=B00001000; break;\
case 4: PORTD ^=B00010000; break;\
case 5: PORTD ^=B00100000; break;\
}
#define D_Read(x) _D_READ(x)
#define _D_READ(x) dread_D##x
#define dread_D10 ((PINB & B00000100)>>2)
#define dread_D11 ((PINB & B00001000)>>3)
#define dread_D12 ((PINB & B00010000)>>4)
#define dread_D13 ((PINB & B00100000)>>5)
void setup()
{
for(int i=2; i<6; i++)
{
D_Out(i); //Понимаю что правильнее DDRх - но делал для проверки работы в цыкле с переменной
}
D_In(button);
}
void loop()
{
static bool poz = 0;
if(D_Read(button))
{
for(int i=3; i<6; i++)
{
D_Inv(i);
poz = !poz;
if(poz) i--;
delay(1000);
}
}
//D_Beep(13, 1000, 10);
}
Но вопрос по первому коду остается Открытым - ПОЧЕМУ?
Но, Вы же своими кейсами убили саму идею киберлиба! У Вас хоть переменная, хоть константа - одной командой не получится.
Делать надо так, чтобы при константе получалась лдна команда, а при переменной - короткое вычисление. Возмите DigitalPins - там это уже сделано
vosara - а вы попробуйте сами выполнить подстановку вместо компилятора
Вот что получается:
buton1 = switch(x){ case 10: ((PINB & B00000100)>>2); break;\ case 11: ((PINB & B00001000)>>3); break;\ case 12: ((PINB & B00010000)>>4); break;\ case 13: ((PINB & B00100000)>>5); break;} }неудивительно, что компилятор ругается
vosara - а вы попробуйте сами выполнить подстановку вместо компилятора
Вот что получается:
buton1 = switch(x){ case 10: ((PINB & B00000100)>>2); break;\ case 11: ((PINB & B00001000)>>3); break;\ case 12: ((PINB & B00010000)>>4); break;\ case 13: ((PINB & B00100000)>>5); break;} }неудивительно, что компилятор ругается
Смотрите как я вижу работу макроса. Возможно я ошибаюсь - поправте
#define D_Out(x) if (x==0) DDRD |=B00000001;\ else if (x==1) DDRD |=B00000010;\ else if (x==2) DDRD |=B00000100;\ #define D_Inv(x) switch(x){\ case 1: PORTD ^=B00000010; break;\ case 2: PORTD ^=B00000100; break;\ } #define D_Read(x) switch(x){\ case 10: ((PINB & B00000100)>>2); break;\ case 11: ((PINB & B00001000)>>3); break;\ } void setup(){ D_Out(2);//Кампилятор перед кампиляцией должен заменить эту строчку на DDRD |=B00000100;//и похоже он это делает } void loop(){ D_Inv(2);//Кампилятор перед кампиляцией должен заменить эту строчку на PORTD ^=B00000100;//и похоже он это делает buton = D_Read(10)//Кампилятор перед кампиляцией должен заменить эту строчку на buton = ((PINB & B00000100)>>2)//А вот здесь облом }[quote=vosara]
Кампилятор перед кампиляцией должен заменить эту строчку на
на
[\quote]
Неправильно. Макрос, это всего лишь текстовая подстановка, никакие блоки кода в момент подставновки не вычисляются.
На место вашего D_Read(10) будет подставлен не конкретный кэйс из свитча, а весь блок свитча целиком, и что в итоге выйдет - я написал в сообщении #2 выше
Вычисляются ПОСЛЕ подстановки. Т.е. при подстановке блок должен быть корректным.
А значит Вам тут надо использовать не switch, а тернарный оператор. Посмотрите, наконец DigitalPins, там всё это сделано.
#define D_Out(x) if (x==0) DDRD |=B00000001;\ else if (x==1) DDRD |=B00000010;\ else if (x==2) DDRD |=B00000100;\ #define D_Inv(x) switch(x){\ case 1: PORTD ^=B00000010; break;\ case 2: PORTD ^=B00000100; break;\ } #define D_Read(x) switch(x){\ case 10: ((PINB & B00000100)>>2); break;\ case 11: ((PINB & B00001000)>>3); break;\ } void setup(){ D_Out(2);//Кампилятор перед кампиляцией должен заменить эту строчку на //DDRD |=B00000100;//и похоже он это делает } void loop(){ D_Inv(2);//Кампилятор перед кампиляцией должен заменить эту строчку на //PORTD ^=B00000100;//и похоже он это делает delay(1000); }vosara - да с чего вы взяли. что он свитч не тянет? - тянет точно так же
Замените свою строчку 24 на
и убедитесь в наличии точно той же ошибки, как в прошлом случае
Да Ошибка. Спасибо!