Хорошая практика одновременного назначения контактов сдвигового регистра?
Я новичок в работе с битовыми регистрами и пытаюсь установить входные и выходные значения некоторых контактов. Пример кода, который у меня есть, делает это следующим образом::
DDRD |= (1 << 2);
DDRD |= (1 << 4);
DDRD &= ~(1 << 5);
PORTD |= (1 << 2);
PORTD &= ~(1 << 4);
PORTD &= ~(1 << 5);
У меня два вопроса:
Это часть кода, в котором я пытаюсь определить время разрядки конденсатора между контактами 2 и 4. В файлах справки Arduino упоминается, что может быть полезно одновременное срабатывание обоих контактов. Следовательно: возможно ли сделать
DDRD |= B00010100;
иPORTD |= B00000100;
или объединить первые три строкиDDRD
так, чтобы это происходит одновременно или его нужно вызывать отдельно?Почему это
PORTD &= ~(1 << 4)
, а неPORTD |= ~(1 << 4);
Может ли это противоречить предыдущему состоянию PORTD.
@Letshin, 👍1
Обсуждение1 ответ
Лучший ответ:
DDRD |= (1 << 2); DDRD |= (1 << 4);
Эквивалентно этому:
DDRD |= (1 << 2) | (1 << 4);
Однако я предпочитаю bit
, потому что он делает сдвиг за вас:
DDRD |= bit(2) | bit(4);
Почему это
PORTD &= ~(1 << 4)
, а неPORTD |= ~(1 << 4);
PORTD &= ~(1 << 4)
немного выключает. Сначала вы инвертируете смысл бита с помощью оператора дополнения до единицы (~), а затем с помощью и это означает, что все биты сохраняются, кроме этого одного. Так что это в основном отключает бит 4. Если вы использовали |=
, все остальные биты были включены.
Эквивалентный код:
PORTD &= ~bit(4);
Исходя из вашего примера, вы имели в виду бит 5, а не бит 4.
PORTD |= (1 << 2); PORTD &= ~(1 << 4); PORTD &= ~(1 << 5);
Это включает бит 2, выключает биты 4 и 5, а остальные оставляет без изменений.
Спасибо. В этом случае DDRD &= B00000000; DDRD |= B00010100; аналогичный результат...
Если вы делаете DDRD &= B00000000;
, то вы устанавливаете все биты на ноль. Таким образом, простым эквивалентом приведенного выше будет:
DDRD = B00010100;
Это прямое назначение, поэтому вам не нужно очищать какие-либо биты.
Или вы можете написать:
DDRD = bit(2) | bit(4);
Знаете ли вы, работает ли бит() быстрее или чище по сравнению с 1 << Икс; или мне лучше подключить прицел, чтобы проверить это самому?
Он точно такой же. bit
— это просто #define
в файле Arduino.h, как показано ниже:
#define bit(b) (1UL << (b))
Поэтому все, что он делает, это избавляет вас от написания скобок и оператора сдвига влево. Он расширяется до того же, что вы писали, и, следовательно, будет выполняться с той же скоростью и занимать тот же объем памяти.
Спасибо. В этом случае DDRD &= B00000000; DDRD |= B00010100;
имеет результат, аналогичный вашему DDRD |= бит(2) | бит (4); DDRD &= бит(3) | bit(6);
На мой взгляд, это сначала устанавливает все на вход, а затем устанавливает биты 2 и 4 на выход. Недостаток заключается в том, что он меняет все остальные настройки из-за первого раздела «DDRD &= B00000000»?, @Letshin
Смотрите расширенный ответ., @Nick Gammon
Спасибо. Знаете ли вы, работает ли bit()
быстрее или чище по сравнению с 1 << x
; или мне лучше подключить прицел, чтобы проверить это самому?, @Letshin
@Letshin Смотрите дополнительный абзац в ответе., @Nick Gammon
- 74HC595 не работает должным образом
- я не могу работать над своим небольшим проектом
- C++ против языка Arduino?
- Как использовать SPI на Arduino?
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- Ошибка: expected unqualified-id before 'if'
- Что лучше использовать: #define или const int для констант?
- Функции со строковыми параметрами
(1 << 4)
это00010000
, они взаимозаменяемы...~(1 << 4)
является обратным11101111
... подумайте о том, что делает функция ИЛИ и что делает функция И, @jsotolaтак это происходит мгновенно
... возможно, вы хотели сказатьодновременно
, @jsotolaХорошо спасибо. Написание этого в упрощенной форме помогает. Поскольку & возвращает 1 только в том случае, если a = 1 и b = 1, следовательно, 0 & 0 = 0 и 1 & 0 = 0, что именно то, что мы хотим, независимо от того, что произойдет. С другой стороны, 1 и 1 = 1, поэтому все, что включено, остается включенным, а 0 и 1 = 0, поэтому то, что было выключено, остается выключенным., @Letshin
Да, извините одновременно. Я цитировал страницу справки Arduino, но не добавлял ее контекст. Если я синхронизирую разрядку конденсатора между контактами 2 и 4, есть ли преимущество в одновременном срабатывании обоих контактов вместо того, чтобы делать это построчно? например, B00010100 по сравнению с каждым контактом в отдельности?, @Letshin
Его контекст для вопроса. Оригинал, потому что я не знаю, как это влияет на тайминги. Судя по вашему отзыву, мой вопрос был неправильно сформулирован. Я внес соответствующие поправки. Спасибо., @Letshin