Как запретить компилятору Arduino объединять изменение выводов порта в одну операцию

c

Я хочу установить выходное значение одного вывода, а затем установить другое выходное значение вывода, чтобы два вывода меняли значение один за другим. Однако компилятор оптимизирует два вызова, чтобы сменить оба контакта за один раз.

ПОРТД |= _BV(0); // устанавливаем pd0 в высокое ПОРТД |= _BV(1); // устанавливаем pd1 в высокое ПОРТД &= ~(_BV(1)); // устанавливаем pd1 на низкий уровень

Два контакта одновременно становятся высокими. Я попытался вставить NOP между ними, но это не меняет поведение.

(Изначально я собирался включить снимок экрана осциллографа, чтобы показать, что происходит — так я узнал (или получил неправильное представление), что два контакта меняются одновременно. Но фотография не смещалась с моего Nexus 7, чтобы я мог получить к нему доступ с моего ноутбука.)

, 👍1

Обсуждение

Я не могу повторить это поведение. Какая версия GCC используется?, @Ignacio Vazquez-Abrams

Какое приложение требует, чтобы эти контакты включались один за другим, но так быстро, что вам не нужен какой-либо код, чтобы вызвать задержку между ними?, @BrettAM

Круто - есть стековый обмен Arduino! Спасибо модам за перенос вопроса., @mackenir

Похоже, я просто запутался здесь, поскольку поведение, которое я видел, невоспроизводимо., @mackenir

(то есть другими)., @mackenir

Конечно, я не эксперт по O-скопам, но, учитывая, что смена выводов при отдельных вызовах все равно будет происходить за десятки наносекунд, сможет ли прицел точно определить разницу ?, @BrettAM

Что ж, при тестировании этого как собственного скетча я вижу, что все работает правильно - задержки между изменениями сигнала очевидны., @mackenir


1 ответ


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

7

Конечно, я не могу повторять то, что вы говорите. Небольшой фрагмент кода:

void setup() {
    PORTD |= _BV(0);
    PORTD |= _BV(1);
    PORTD &= ~(_BV(1));
}

void loop() {
}

компилируется в:

000000a6 <setup>:
  a6:   58 9a           sbi 0x0b, 0 ; 11
  a8:   59 9a           sbi 0x0b, 1 ; 11
  aa:   59 98           cbi 0x0b, 1 ; 11
  ac:   08 95           ret

000000ae <loop>:
  ae:   08 95           ret

Очевидно, что это два отдельных набора битов, за которыми следует бит очистки.

Я использую UECIDE, для которого настроено использование GCC 4.3.2

Если вместо этого я переключусь на GCC 4.8.1, сгенерированный код будет идентичен.

Даже включив полную оптимизацию -O3, я все равно получаю те же результаты.

Так как же определить, что это происходит одновременно?

,

Что имеет смысл, поскольку ячейка памяти была объявлена как энергозависимая., @Ignacio Vazquez-Abrams

Я думаю, что использую Arduino IDE 1.06, но мне нужно будет проверить, когда я вернусь домой., @mackenir

Я наблюдал изменение двух контактов на осциллографе, но мне придется сделать шаг назад и провести тест с удаленным Arduino Micro из проекта, над которым я работаю. Похоже, я просто ошибаюсь., @mackenir

Тот же код, сгенерированный здесь с avr-gcc 5.4.0., @Edgar Bonet