Хорошая практика одновременного назначения контактов сдвигового регистра?

Я новичок в работе с битовыми регистрами и пытаюсь установить входные и выходные значения некоторых контактов. Пример кода, который у меня есть, делает это следующим образом::

DDRD |= (1 << 2);                   
DDRD |= (1 << 4);                   
DDRD &= ~(1 << 5);                   
PORTD |= (1 << 2);  
PORTD &= ~(1 << 4);         
PORTD &= ~(1 << 5);  

У меня два вопроса:

  1. Это часть кода, в котором я пытаюсь определить время разрядки конденсатора между контактами 2 и 4. В файлах справки Arduino упоминается, что может быть полезно одновременное срабатывание обоих контактов. Следовательно: возможно ли сделать DDRD |= B00010100; и PORTD |= B00000100; или объединить первые три строки DDRD так, чтобы это происходит одновременно или его нужно вызывать отдельно?

  2. Почему это PORTD &= ~(1 << 4), а не PORTD |= ~(1 << 4);Может ли это противоречить предыдущему состоянию PORTD.

, 👍1

Обсуждение

(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


1 ответ


Лучший ответ:

2
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