чтобы не думать в каких случаях писать ";", а в каких нет, заключают в цикл do...while(0)
pokk писал(а):#define crBegin static int state=0; switch(state) { case 0:
#define crReturn(i,x) do { state=i; return x; case i:; } while (0)
#define crFinish }
Попробуйте так писать - в этом случае Вам не страшен ни какой макрос и ни какие запятые. И при этом Вы четко видите границы каждого блока, входящего в ту или иную часть условия/цикла.
Или ленитесь пару лишних скобок поставить? )
Кстати, Вы в макросе после ptr++; забыли поставить знак переноса строки - может поэтому у Вас и не компилируется.
Последний раз редактировалось Pink-Pank Вт дек 16, 2014 07:12:17, всего редактировалось 2 раза.
Это если у вас if не вложенный. А если вложенный в другой if, то может и скомпилиться, только программа будет работать не правильно. Долго ошибку искать будете. Особенно используя макросы.
Пример:
if(y)
if (x) smthToDo(x); // Здесь точка с запятой завершает внутренний условный блок (наш макрос) и компилятор считает, что следующее за выражением else относится к внешнему условному блоку. else return x;
З.Ы. Не так давно 2 дня искал в программе ошибку.. Работала не так, как надо. Оказалось прошляпил точку с запятой после цикла while.. Думал, компилятор взбесился..
Вот это макросы! А не секрет, как эта магия работает?
COKPOWEHEU,Я где-то приводил ссылку откуда их взял.
Если вкратце, то весь код должен находится внутри макросов crBegin crFinish
макрос crReturn(1,0); позволяет выйти из функции с сохранением место выхода и после вызова функции ещё раз мы перейдём в сохранённое место.
Если смотреть на тот код который приводил выше то функция Process_scan_Key_FSM крутится в главном цикле с аналогичными функциями т.е 1 итерация главного цикла примерно 200-700 тактов
Спойлер
unsigned char Process_scan_Key_FSM(unsigned char *data){
unsigned char temp;
//------------INIT---------------
crBegin *data=0; // Вход
Set_but_OK // выставляем на мультиплексоре адрес кнопки ОК
crReturn(1,0); // Выходим из функции с сохранением точки выхода
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
// При следующем заходе в функцию переместимся суда
// при этом произойдёт задержка(на 1 проход главного цикла) на переключение мультиплексора.
Key_code2.OK=CTR_IN; // Считаем установившееся значение
Set_but_ESC // выставляем на мультиплексоре адрес кнопки ESC
crReturn(2,0); // Выходим из функции с сохранением точки выхода
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
Key_code2.ESC=CTR_IN;
Set_but_UP
crReturn(3,0);
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
Key_code2.UP=CTR_IN;
Set_but_DW
crReturn(4,0);
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
Key_code2.DW=CTR_IN;
//-------------------------------
crFinish
*data=1;
return Key_code2;
}
По переменной *data я смотрю когда произойти полный опрос всех кнопок тогда же можно и начинать работать с переменной Key_code2 (правда в данной реализации у меня сделано всё наоборот по хорошему через return надо смотреть о завершении работы функции а через data выдавать данные)
Если развернуть все макросы то получится обычный switch case
Спойлер
#define crReturn(x) do { state=__LINE__; return x; case __LINE__:; } while (0)
Самое полезное что я нашёл если передавать в функцию структуру с state. То получается можно запустить одну и туже функцию на параллельную обработку разных данных.
Pink-Pank писал(а):Кстати, Вы в макросе после ptr++; забыли поставить знак переноса строки - может поэтому у Вас и не компилируется.
да, забыл, но я говорил о другом же
Pink-Pank писал(а):if (x)
{
smthToDo(x);
}
можно так писать. А если кто другой твой макрос попробует использовать без {} будет капец )
Я вообще их стараюсь не использовать, но иногда это оправдано, и тогда do...while(0) самый надёжный вариант
А если кто другой твой макрос попробует использовать без {} будет капец
Да, Ваш вариант с этой точки зрения надежнее, но человек, который не ставит фигурных скобок нарвется на ошибку где-то еще. )
Поэтому я себя приучил ставить их повсеместно в условных блоках и циклах, даже если внутри них всего один оператор. Так еще более надежно, да и нагляднее! )
Да и прежде, чем что-то использовать - желательно разобраться, как оно работает. )
Pink-Pank писал(а):Поэтому я себя приучил ставить их повсеместно в условных блоках и циклах, даже если внутри них всего один оператор. Так еще более надежно, да и нагляднее! )
Это всё частный случай привычки.
Я, например, стараюсь не ставить лишних скобок, по этому макросы всегда заключаю в do{}while(0).
Ну а что касается остальных макросов ТС'а , это уже, имхо, - перебор Они только путают читающего его код...
Всем привет. Можете подсказать как сделать чтобы при прерывании INT0 сначала считывался eeprom а потом исходя из данных в нем выполнялся код в прерывании?
Добавить в начало кода прерывания процедуру чтения. Либо подробнее опишите задачу. При возникновении прерывания контроллер сохраняет адрес возврата в стеке и прыгает по заданному адресу, где расположен прыжок на обработчик.
С этим более-менее разобрался. А посоветуйте, устройство будут выключать примерно 20 раз в день, и флаг состояния будет сохранятся в eeprom, соответственно 20 раз) на долго ли хватит памяти, и как увеличить её ресурс?
Один из способов : "размазывать" запись по доступному свободному объему EEPROM . Но тогда к зписываемой информации добавится еще счетчик-указатель. При чтении : находим запись с самым большим номером, считываем информацию из этого блока. При записи : находим запись с самым большим номером, инкрементируем номер, запись делаем уже ПОСЛЕ найденного места. Естественно, учитываем, что буфер кольцевой. Достаточно сумбурно изложил ?
Согласно даташиту, количество циклов перезаписи у EEPROM 100000. Если перезаписывать 20 раз в день, этого хватит на 100000 / 20 = 5000 дней > 13 лет. Это без учета программных извращений и это гарантируется производителем. На практике раза в 3 больше. Кроме того, можно организовать резервное питание на батарейках или конденсаторах, и на время отключения основного засыпать. Или использовать внешнее статическое ОЗУ с собственным резервным питанием.
С НАСТУПАЮЩИМ!!!
Ребят, укусила собака бешеная замутить стробоскоп в последний день. Ставлю в тиньку 13 единственный код, а она мне хрень выдаёт, хотя в протеусе всё пашет.
К порту B к нулевому пину подведён IRLR2905 через резюк в 130 Ом, а к нему СД 10W.
Проще некуда. Но мигает эта хрень только с одним интервалом, а не с разными, как указано в коде.
От чего такое может быть?
Вы на глаз отличаете интервалы меньше 150мс? Может, всё работает именно как надо? Хорошо бы осциллографом на ножке посмотреть (DDRB.0, надеюсь, тоже выставлен на выход?).
Всем привет! Как организовать вывод данных в разные порты, разные биты посредством массива, типа array[]={PORTD.1, PORTC.0, PORTB.7} (но така работать не будет). А как иначе? Помогите, кто знает