enum - выбор следующего шага?

Тема в разделе "Arduino & Shields", создана пользователем ИгорьК, 13 май 2014.

  1. ИгорьК

    ИгорьК Гуру

    Суть ясна. Иметь переменную и сопоставлять с перечислением.
    Навороченности нет особо. Просто два флага по-разному меняют режимы. Привык управлять кнопкой по короткому и длинном нажатию.
     
  2. NR55RU

    NR55RU Гик

    Почти во всех книгах по С++ что я читал, и в частности даже в той которую я сейчас читаю "С++ лекции и упражнения" Автор: Стивен Права, рекомендуется отдавать предпочтение именно константам с const а не определенным через #define, в поддержку этого приводятся такие аспекты как: явное указание типа и контроль области видимости.
    Хотя как и вопрос с арифметикой в перечислениях это остается делом вкуса, const или #define, но хорошие авторы рекомендуют, вероятно стоит прислушиваться :)
     
  3. Mitrandir

    Mitrandir Гуру

    Только вот вопрос. Как компилятор транслирует константы? Они не лягут в ОЗУ?
     
  4. это тоже что и переменная, только с флагом для чтения.


    зы\ меня умеляют обсуждения чистоты ардуино кода)
     
  5. NR55RU

    NR55RU Гик

    Если я в чем то не прав, надеюсь меня поправят.

    Что делает препроцессор с #define, по сути он просто выполняет функцию поиска и замены, это как сказать в любом текстовом редакторе найди эту строку и замени ее на эту.
    Таким образом если мы пишем код:
    Код (Text):
    #define FOO = 1;
    if ( someVar == FOO );
    То компилятор получит к обработке такой код:
    Код (Text):
    if( someVar == 1 );
    То есть компилятор вообще понятия не имеет что существует препроцессор.
    Следовательно #define "облегчает" работу лишь программиста но никак не влияет на компилятор.
    Для компилятора эта единица такая же константа которая будет размещена в соответствующей области памяти.

    Я понимаю о чем вы, но чуть чуть с вами не соглашусь.
    Дело в том что к правильному стилю программирования необходимо приучать себя всегда и везде, если конечно задача не требует осознанных "жертв" для достижения цели.
    Люди часто пишут код по принципу "работает и ладно" благодаря чему это "и так сойдет" начинает все чаще и чаще давать о себе знать.
    Гораздо проще зная и понимая "хорошие практики" написать код их нарушающий если это требуется, чем с отсутствующими знаниями о "хорошей практике" написать хороший код :)
    Просто лично моё мнение, если что-то делаешь, старайся делать это хорошо, и не важно пишешь ты функцию из 10 строк для Арудина или работаешь над полноценным приложением из кучи классов.
    Это помогает вырабатывать "хоршие" привычки и заставляет работать мозги :)
     
  6. Корней

    Корней Гик

    Ох...
     
  7. NR55RU

    NR55RU Гик

    На самом деле не совсем так, константное значение располагается в специально отведенной компилятором области памяти из которой позволяется только считывать значения, таким образом если компилятор обнаружит попытку кода изменить значения в рамках данной области памяти он выдаст ошибку.
     
    Последнее редактирование: 16 май 2014
  8. Mitrandir

    Mitrandir Гуру

    К
    Компилятор может оптимизировать код, подставив значения вместа использования...
     
  9. Корней

    Корней Гик

    Как бы покороче...
    Если, при использовании, константа в #define не попадает в ОЗУ, то и аналогичное использование переменной с модификатором const не приведет к расходованию ОЗУ, так как, обычно, компилятору разрешено оптимизировать размещение на основе модификатора const.

    А если вместо #define констант можно использовать enum, то ОЗУ в полной безопасности :)
     
    Последнее редактирование: 16 май 2014
  10. Mitrandir

    Mitrandir Гуру

  11. thearr

    thearr Нерд

    Компилятор ардуино расчитан на малые объемы ОЗУ, поэтому значения констант подставляются также как и макро, это легко проверить скомпилировав скетчи с объявлением const и #define и посмотрев в логах, сколько памяти требуется для хранение переменных. Также, например, структуры не выравниваются по тем же причинам.
     
  12. veoramid

    veoramid Нуб

    Доброго времени суток! Подскажите, пожалуйста, как правильно описать массив и обращаться к элементам массива по именам?

    Речь идет о том, что есть задача настраивать контроллер через modbus. Обращение к регистрам modbus чаще всего идет через массив. Мне было бы интересно этот массив использовать и для хранения переменных, что бы не плодить 2 копии переменных, но обращаться по имени. Например:
    if (МассивПеременных["Минуты"] == 59) {МассивПеременных["Минуты"] = 0;}
     
  13. fogary

    fogary Гик

    Структуры Вас не устраивают? Если кол-во полей и их назначение не меняется, то должно подойти.
    Например:
    Код (C++):
    struct MB_Time
    {
        uint8_t hour;
        uint8_t minute;
        uint8_t second;
    };

    MB_Time mb_tm;

    . . .

    if (mb_tm.minute == 59) {mb_tm.minute = 0;}
     
    Tomasina нравится это.
  14. veoramid

    veoramid Нуб

    Вот тут: http://arduino.ru/forum/programmirovanie/modbus-rs485-gotovyi-shild
    я взял библиотеку, в которой нужно сформировать массив и скормить библиотеке.

    uint16_t au16data[11]; // массив данных modbus

    У меня возникло 2 вопроса.
    Первый: как этот массив формировать "разумно", что бы потом по коду было понятно и можно было быстро менять, если что.
    Второй: как сократить количество переменных, занимаемых в ОЗУ (не хранить 2 копии одних и тех же данных).

    Когда то в паскале я делал многомерный массив, к которому обращался чем-то на подобие enum. В этом массиве было текстовое название переменной (для файла настроек), короткое название для вывода на экран во время настройки, минимальное, максимальное, и значение по умолчанию. Все перечисленное - таблица в памяти программ, не ОЗУ. А еще был массив в ОЗУ, который и был собственно нужными переменными.

    Теперь пытаюсь сделать что-то похожее на Arduino (Си).
     
  15. fogary

    fogary Гик

    Если хотите именно через именованные индексы, то, как вариант, через #define создать нужное кол-во пар "имя - индекс".
    Код (C++):
    #define index1 0
    #define index2 1
    ...
    au16data[index1] = ...
    au16data[index2] = ...
    Про память, ОЗУ, несколько копий и многомерный массивы - что-то совсем не понял вопроса.
     
  16. Tomasina

    Tomasina Сушитель лампочек Модератор

    именованные индексы проще как раз через enum, всего одна строка:
    Код (C++):
    enum{OFF, ON, YEAR, MONTH, DAY, HOUR, MINUTE, SECOND};
    Мне вот непонятно зачем ТС хочет сделать так:
    Код (C++):
    if (value[MINUTE] == 59)  {value[MINUTE]  = 0};
     
  17. veoramid

    veoramid Нуб

    Если погуглить "таблица параметров modbus" и посмотреть картинки, то можно увидеть много таблиц с большим количеством параметров. Предположим, что параметров 100 штук. Когда работает диспетчеризация по последовательному каналу связи, то к параметрам идет обращение по адресу 0...65535. Создается таблица, в которой говорится, например, что по 10му адресу будут минуты, по 11 адресу будут часы, по 12 адресу будет, например, температура.

    При работе главный-второстепенный всегда идет запрос-ответ. Это время. Поэтому, если возможно, делают запрос групповой. Т.е. если главному устройству надо знать время и температуру, то запрашивают, обычно, группу параметров (в моем случае с адреса 10 3x2=6 байт.

    В программе подчиненного, когда ему приходит запрос, он передает 6 байт из массива данных. Если говорить, что у нас 100 виртуальных ячеек по 2 байта, то у нас есть виртуальный массив из 200 байт. Этот массив нужно сформироваьт.

    Как? Один вариант. У нас есть 200 переменных и массив на 200 слов (всего 400 байт ОЗУ) и мы делаем подпрограмму, которую вызываем раз в секунду и формируем массив au16data[10] = MINUTE; au16data[11] = HOUR; au16data[12] = TEMP*10; тогда протокол связи выгребает 6 байт начиная с 20 байта массива au16data[11]

    Или каждый раз, когда идет запрос на определенный адрес запускать подпрограмму, которая будет, например, оператором case выдавать нужное значение в буфер.

    ---

    Поскольку я начинал программировать с ассемблера, то я привык распределять память чуть не вручную (Точнее в моем первом контроллере было 128 байт и они все были распределены вручную - там был счет даже не на байты, а на биты). Поэтому я не вижу никаких проблем (в ассемблере) разместить переменную MINUTE по адресу x, переменную HOUR по адресу x+2, переменную Temp по адресу x+4. и когда приходит запрос извне по modbus, давать ему начальный адрес массива (x) - пусть выбирает все, что ему надо.

    Т.е. мне надо переменные MINUTE, HOUR, Time*10... разместить один-за другим в реальной памяти и знать начальный адрес в памяти переменной MINUTE.

    Мне кажется в массиве это сделать проще всего.