AVR определяет контакты с помощью struct или #define - PullRequest
0 голосов
/ 07 мая 2018

Я видел, как многие люди говорили: «всегда используйте #define для определения контактов и портов чего-либо в библиотеке», и в настоящее время я тоже так делаю. Но я рассматриваю возможность использования структуры вместо этого метода.

Я использую пример сменного регистра и его библиотеки

Что я вижу как профессионал

  • Простое управление множеством сменных регистров с помощью одной библиотеки
  • Вам не нужно ничего менять в исходных файлах библиотеки

Что я вижу как против

  • Занимает место (в отличие от #define)
  • Может потребоваться больше времени для вычислений, потому что вы должны учитывать, что для каждого регистра сдвига могут использоваться разные порты, и вам нужно проверить, что

Знаете ли вы больше плюсов или минусов за использование структуры вместо некоторых #defines? И считаете ли вы минусы чем-то, что перевешивает плюсы достаточно сильно, чтобы вы никогда не использовали структуру (даже когда она не критична по времени или пространству)?

1 Ответ

0 голосов
/ 07 мая 2018

Следующий код устанавливает вывод AVR (PD1) на высокий уровень (при условии, что он уже включен как выход):

PORTD |= (1 << 1);

Компилятор AVR GCC хорош для компиляции подобного кода в одну инструкцию сборки AVR (с именем sbi), но только если он точно знает во время компиляции, в какой регистр вы записываете (PORTD), и что бит, который вы устанавливаете (бит 1).

Существует множество преимуществ использования одной инструкции вместо нескольких инструкций для установки бита:

  • Требуется меньше места для кода.
  • Работает быстрее.
  • Это безопасно делать даже в том случае, если может выполняться прерывание, которое изменяет один и тот же регистр, поскольку шаги чтения, изменения и записи выполняются в одной инструкции, которая не может быть прервана.

Если вы используете макросы препроцессора, определенные с помощью #define, для определения ваших выводов, то после запуска препроцессора ваш код будет выглядеть так же, как и код выше, и должен скомпилироваться в одну инструкцию.

С другой стороны, если вы используете структуры для определения выводов и динамически передаете эти структуры в свою библиотеку, есть большая вероятность, что компилятор не сможет выполнить эту оптимизацию.

Вот ссылка, где вы можете увидеть оба метода установки пин-кода и увидеть, что метод struct намного менее эффективен:

https://godbolt.org/g/mkxHc2

Обратите внимание, что существует много других способов задания и управления выводами, помимо двух методов, обсуждаемых здесь. Библиотеки Arduino обычно представляют контакты в виде одного числа, а затем вызывают функции, такие как pinMode и digitalWrite, для управления указанным контактом. (Реализации pinMode и digitalWrite довольно неэффективны и должны отключать прерывания, но их можно улучшить.)

Более продвинутый метод заключается в использовании параметров шаблона C ++ для задания выводов, как в FastGPIO library .

...