Можно ли использовать другие 4 бита в другом режиме для 4-битных данных? - PullRequest
0 голосов
/ 26 февраля 2019

Итак, я пишу C-программу для интерфейса LCD на 4-битном режиме данных.Однако мне было интересно, смогу ли я использовать другие 4 бита, чтобы сделать что-то еще, например, внешнее прерывание.Чтобы быть более точным, я использую PORTD для линий данных на Arduino, однако мне также нужен вывод PD2, чтобы использовать прерывание INT0 (кнопка).В моей программе я заметил, что я продолжал устанавливать младшие 4 бита на 0 при отправке команд:

PORTD = cmd & 0xf0;
flashLCD();
PORTD = (cmd & 0x0f) << 4;

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

uint8_t initial_state = PORTD;
PORTD = (cmd & 0xf0) | (initial_state & 0x0f);
flashLCD();
PORTD = ((cmd & 0x0f) << 4) | (initial_state & 0x0f)

Он отправляет cmd на ЖК-дисплей, однако он по-прежнему не отвечает на прерывание.Я хотел знать, есть ли что-то, что я не принимаю во внимание, или моя логика неверна.Спасибо.

Edit: Nvm Я понял это.Моя библиотека LCD сбрасывала регистр портов на 0 всегда, даже когда в 4-битном режиме, поэтому другие неиспользуемые порты также сбрасывались.Я просто изменил библиотеку, чтобы я мог использовать другие порты в 4-битном режиме.

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Вы правильно заметили, что другие биты можно сохранить с помощью битовых операций

PORTD = (PORTD & 0x0F) | (high_bits << 4);

Но!эта строка будет скомпилирована в несколько машинных инструкций:

  1. загрузить значение PORTD в регистр
  2. выполнить побитовое И в регистре
  3. загрузить high_bits в другой регистр
  4. выполнить другие вычисления (сдвиг влево на старшие биты и т.представьте, где-то между 1 и 6 срабатывает прерывание, оно останавливает выполнение кода и меняет младшие биты PORTD.После завершения процедуры прерывания программа продолжает выполняться, и она перезаписывает все 8-ые биты PORTD тем, что было сохранено в регистрах до прерывания, перезаписывая тем самым младшие биты PORTD, отбрасывая все изменения, сделанные в процедуре прерывания.

    Итак, существует два подхода к выполнению операции записи в атомарный PORTx.

    Первое: просто отключить прерывание на время обновления регистра PORTx:

    uint8_t old_sreg = SREG; // save SREG register (including I flag)
    cli(); // clear I flag, thus prohibiting interrupts
    PORTD = (PORTD & 0x0F) | (high_bits << 4); // perform the operation
    SREG = old_sreg; // restoring SREG and I flag, if it was set before
    

    Второй подход работает только на новых ядрах AVR (например, ATmega328, 1284, 2560 и т. Д.), Но не будет работать на старых (ATmega8, 32 и т. Д.).Обратитесь к техническому описанию, I / O-порты -> Порты как General Digital I / O -> Toggling the Pin раздел.Запись в биты PINx инвертирует соответствующие биты PORTx.Используя его, можно обновлять только требуемые биты регистра PORTx, оставляя другие нетронутыми, что устраняет необходимость блокировки прерываний.Это может быть полезно в критичной ко времени среде, где прерывание должно срабатывать как можно быстрее.

    PIND = (PORTD ^ (high_bits << 4)) & 0xF0;
    

    Конечно, это будет работать, если будет гарантировано, что прерывание может изменить только другие (в этом примере - младшие) битыПОРТД.Если прерывание также может записывать в тех же битах, то это может привести к неожиданным результатам, поэтому будьте осторожны.

0 голосов
/ 26 февраля 2019

Я не знаю, какие контроллеры (ATmega / AVR и т. Д.) Используются на Arduino, и вы даже не указываете, какой из них вы используете.

Но обычно порты и выводы портов могут быть настроены нарежим ввода или вывода.Поскольку вы выдает 4 бита через PORTD, я предполагаю, что весь 8-битный порт (все выводы порта) сконфигурирован как выходной.

Вы должны рассмотреть ваше руководство, если определенные выводы всего порта могут быть выходнымидругие могут быть входными выводами одновременно и как.

Будьте осторожны при переключении ввода / вывода всего порта между ними, это может иметь побочные эффекты, например нежелательные переходы HL / LH.У меня было это однажды с выходным чипом 8255. Это вызвало перезагрузку моего графического ЖК-дисплея из-за подключенной линии сброса ЖК-дисплея.

...