CodeVision AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: CodeVision AVR в вопросах и ответах

Сообщение COKPOWEHEU »

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 }


Вот это макросы! А не секрет, как эта магия работает? Особенно восхищает вот эта конструкция (смысловые блоки выделил форматированием).

Код: Выделить всё

switch(state){
 case 0:
  do{state=i; return x;
     case 1:;
  }while(0);
}
Удивительно, но оно работает!
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение BCluster »

Pink-Pank писал(а):Вообще не понимаю, зачем там do while, если в условии стоит 0?


Код: Выделить всё

#define smthToDo(ptr) do { \
ptr++;
ptr->destroy = 0; \
} while (0)

if (x)
   smthToDo(x);
 else
   return x;


Попробуйте скомпилировать этот код без do...while(0)
точка с запятой перед else вызовет ошибку компиляции, придется писать уже так:

Код: Выделить всё

#define smthToDo(ptr) { \
ptr++;
ptr->destroy = 0; }
if (x)
   smthToDo(x)
 else
   return x;

чтобы не думать в каких случаях писать ";", а в каких нет, заключают в цикл 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 }


а вот это, простите, уже слишком. Бред, имхо
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение ARV »

а с каких пор точка с запятой перед else вызывает ошибку?!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение Pink-Pank »

Код: Выделить всё

if (x) 
{
   smthToDo(x);
}
else
{
   return x;
}


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

Или ленитесь пару лишних скобок поставить? )

Кстати, Вы в макросе после ptr++; забыли поставить знак переноса строки - может поэтому у Вас и не компилируется. ;)
Последний раз редактировалось Pink-Pank Вт дек 16, 2014 07:12:17, всего редактировалось 2 раза.
Fucking static initialization order fiasco
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: CodeVision AVR в вопросах и ответах

Сообщение COKPOWEHEU »

а с каких пор точка с запятой перед else вызывает ошибку?!
Всегда при использовании обычных фигурных скобок

Код: Выделить всё

if(x){x=2;};else x=1;
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение Pink-Pank »

Это если у вас if не вложенный. А если вложенный в другой if, то может и скомпилиться, только программа будет работать не правильно. ;) Долго ошибку искать будете. Особенно используя макросы.
Пример:

if(y)
if (x) smthToDo(x); // Здесь точка с запятой завершает внутренний условный блок (наш макрос) и компилятор считает, что следующее за выражением else относится к внешнему условному блоку.
else return x;

З.Ы. Не так давно 2 дня искал в программе ошибку.. Работала не так, как надо. Оказалось прошляпил точку с запятой после цикла while.. Думал, компилятор взбесился..
Fucking static initialization order fiasco
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: CodeVision AVR в вопросах и ответах

Сообщение pokk »

Вот это макросы! А не секрет, как эта магия работает?

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;
//----------
        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
Спойлер

Код: Выделить всё

unsigned char Process_scan_Key_FSM(unsigned char *data){
unsigned char temp;
static int state=0;
 switch(state) {
      case 0:   *data=0;
        Set_but_OK             // выставляем на мультиплексоре адрес кнопки ОК   
      state=1;            //crReturn(1,0)
      return 0;             //crReturn(1,0)
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>             
      case 1:               //crReturn(1,0)
         Key_code2.OK=CTR_IN;  // Считаем установившееся значение   
         Set_but_ESC          // выставляем на мультиплексоре адрес кнопки ESC   
         state=2;         //crReturn(2,0)
         return 0;          //crReturn(2,0)
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>             
      case 2:                 //crReturn(2,0)
         Key_code2.ESC=CTR_IN;
         Set_but_UP      
         state=3;         //crReturn(3,0)
         return 0;          //crReturn(3,0)
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>                      
      case 3:               //crReturn(3,0)
         Key_code2.ESC=CTR_IN;
         Set_but_UP   
         state=4;
         return 0;                   
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>                      
//......case 4:      
      }          //crFinish

//----------                                           
         *data=1;
        return  Key_code2;
}

Можно ещё заменить в макросе i на номер строки __LINE__ тогда можно вообще забыть про индексы case

Код: Выделить всё

#define crReturn(x) do { state=__LINE__; return x; case __LINE__:; } while (0)


Самое полезное что я нашёл если передавать в функцию структуру с state. То получается можно запустить одну и туже функцию на параллельную обработку разных данных.

Код: Выделить всё

#define ccrBegin(pt)  switch((pt)->lc) { case 0:
#define ccrReturn(x) do { (pt)->lc=__LINE__; return x; case __LINE__:; } while (0)
#define ccrFinish } (pt)->lc=0;

Хотя такое можно сделать и без макросов
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение BCluster »

Pink-Pank писал(а):Кстати, Вы в макросе после ptr++; забыли поставить знак переноса строки - может поэтому у Вас и не компилируется.

да, забыл, но я говорил о другом же :)
Pink-Pank писал(а):if (x)
{
   smthToDo(x);
}

можно так писать. А если кто другой твой макрос попробует использовать без {} будет капец )
Я вообще их стараюсь не использовать, но иногда это оправдано, и тогда do...while(0) самый надёжный вариант
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение Pink-Pank »

А если кто другой твой макрос попробует использовать без {} будет капец

Да, Ваш вариант с этой точки зрения надежнее, но человек, который не ставит фигурных скобок нарвется на ошибку где-то еще. )
Поэтому я себя приучил ставить их повсеместно в условных блоках и циклах, даже если внутри них всего один оператор. Так еще более надежно, да и нагляднее! )
Да и прежде, чем что-то использовать - желательно разобраться, как оно работает. )
Fucking static initialization order fiasco
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение Аlex »

Pink-Pank писал(а):Поэтому я себя приучил ставить их повсеместно в условных блоках и циклах, даже если внутри них всего один оператор. Так еще более надежно, да и нагляднее! )
Это всё частный случай привычки.
Я, например, стараюсь не ставить лишних скобок, по этому макросы всегда заключаю в do{}while(0).
Ну а что касается остальных макросов ТС'а , это уже, имхо, - перебор :roll: Они только путают читающего его код...
Аватара пользователя
Alexen
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб ноя 09, 2013 23:43:50
Откуда: Запорожье

Re: CodeVision AVR в вопросах и ответах

Сообщение Alexen »

Всем привет. Можете подсказать как сделать чтобы при прерывании INT0 сначала считывался eeprom а потом исходя из данных в нем выполнялся код в прерывании?
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: CodeVision AVR в вопросах и ответах

Сообщение COKPOWEHEU »

Добавить в начало кода прерывания процедуру чтения. Либо подробнее опишите задачу. При возникновении прерывания контроллер сохраняет адрес возврата в стеке и прыгает по заданному адресу, где расположен прыжок на обработчик.

Код: Выделить всё

rjmp RESET
rjmp INT0
...
INT0:
...
reti
Аватара пользователя
Alexen
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб ноя 09, 2013 23:43:50
Откуда: Запорожье

Re: CodeVision AVR в вопросах и ответах

Сообщение Alexen »

С этим более-менее разобрался. А посоветуйте, устройство будут выключать примерно 20 раз в день, и флаг состояния будет сохранятся в eeprom, соответственно 20 раз) на долго ли хватит памяти, и как увеличить её ресурс?
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: CodeVision AVR в вопросах и ответах

Сообщение Jack_A »

Один из способов : "размазывать" запись по доступному свободному объему EEPROM . Но тогда к зписываемой информации добавится еще счетчик-указатель. При чтении : находим запись с самым большим номером, считываем информацию из этого блока. При записи : находим запись с самым большим номером, инкрементируем номер, запись делаем уже ПОСЛЕ найденного места. Естественно, учитываем, что буфер кольцевой. Достаточно сумбурно изложил ? :)
Изображение
Вложения
45-32.JPG
(7.04 КБ) 672 скачивания
Последний раз редактировалось Jack_A Вт дек 30, 2014 18:09:57, всего редактировалось 2 раза.
Аватара пользователя
Alexen
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб ноя 09, 2013 23:43:50
Откуда: Запорожье

Re: CodeVision AVR в вопросах и ответах

Сообщение Alexen »

Да в принципе смысл понятен, осталось попробовать как то сделать:)
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: CodeVision AVR в вопросах и ответах

Сообщение COKPOWEHEU »

Согласно даташиту, количество циклов перезаписи у EEPROM 100000. Если перезаписывать 20 раз в день, этого хватит на 100000 / 20 = 5000 дней > 13 лет. Это без учета программных извращений и это гарантируется производителем. На практике раза в 3 больше. Кроме того, можно организовать резервное питание на батарейках или конденсаторах, и на время отключения основного засыпать. Или использовать внешнее статическое ОЗУ с собственным резервным питанием.
Аватара пользователя
isx
Поставщик валерьянки для Кота
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Re: CodeVision AVR в вопросах и ответах

Сообщение isx »

С НАСТУПАЮЩИМ!!! :beer:
Ребят, укусила собака бешеная замутить стробоскоп в последний день. Ставлю в тиньку 13 единственный код, а она мне хрень выдаёт, хотя в протеусе всё пашет.

Код: Выделить всё

 PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(125);
         
        PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(65);
       
        PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(25);
       
        PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(125);
       
        PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(25);
         
        PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(25);
       
        PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(65);
       
        PORTB.0 = 1;
        delay_ms(50);
        PORTB.0 = 0;
        delay_ms(25);

К порту B к нулевому пину подведён IRLR2905 через резюк в 130 Ом, а к нему СД 10W.
Проще некуда. Но мигает эта хрень только с одним интервалом, а не с разными, как указано в коде.
От чего такое может быть?
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Вы на глаз отличаете интервалы меньше 150мс? Может, всё работает именно как надо? Хорошо бы осциллографом на ножке посмотреть (DDRB.0, надеюсь, тоже выставлен на выход?).
Combatos
Открыл глаза
Сообщения: 63
Зарегистрирован: Пн дек 29, 2014 21:29:32

Re: CodeVision AVR в вопросах и ответах

Сообщение Combatos »

Всем привет! Как организовать вывод данных в разные порты, разные биты посредством массива, типа array[]={PORTD.1, PORTC.0, PORTB.7} (но така работать не будет). А как иначе? Помогите, кто знает
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: CodeVision AVR в вопросах и ответах

Сообщение uk8amk »

Никак.
Такой фокус не проканает, поскольку у AVR отдельные биты не адресуются.
Если для вас это очень важно - переходите на ARM(там есть bit-band).
Ответить

Вернуться в «AVR»