Чтение регистра портов и печать

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

PORTF &= B11101111

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

Наблюдение 0:

byte dat = PORTF;
Serial.print(dat,BIN);

производит один 0, где я ожидаю 8 0 как для байта. И даже когда я проверяю, правильно ли digitalRead получает 1 из PF5 или A2,

Наблюдение 1:

byte dat = PORTF;
Serial.print(dat,BIN);
Serial.print(dat,BIN);

выдает ошибку компилятора, например

...cores\arduino\Print.cpp: In function 'println.constprop':
...cores\arduino\Print.cpp:143:1: internal compiler error: Segmentation fault
}
^

, 👍1

Обсуждение

Чтобы воспроизвести проблему с компилятором, опубликуйте свернутый скетч, показывающий ошибку. И сообщите нам, какую систему ПК (Win, Linux, Mac) вы используете. [править] ваш вопрос, пожалуйста, не добавляйте дополнительную информацию в комментарий!, @the busybee

ошибка компилятора - это ошибка компилятора. используйте пакет плат Arduino 1.6.21. это неправильный способ работы с регистрами. а PORTF &= B11101111 равно PORTF = PORTF & B11101111. поэтому, если в PORTF все нули, результат равен нулю, @Juraj

https://arduinoprosto.ru/q/70104/adc-register-always-returning-high/70108#70108, @Juraj

Ошибка компилятора - это ошибка компилятора. Какую версию IDE вы используете? Если это не последняя версия, вы можете обновить ее., @Edgar Bonet

@EdgarBonet, это проблема avr-gcc, используемого в ядрах Arduino AVR 1.6.22 и 1.6.23. версия в ядре AVR 1.8.0 и 1.8.1 имеет проблему «переоптимизации». (1.8.0 была следующей после 1.6.23. 1.7.x была пропущена)., @Juraj

@Juraj: Что вы подразумеваете под «чрезмерной оптимизацией»? Очередная ошибка компилятора?, @Edgar Bonet

@EdgarBonet, этот https://arduinoprosto.ru/q/70597/function-parameter-of-type-int-not-working-as-expected#comment153249_70597 и еще один был на форуме Arduino, @Juraj


1 ответ


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

0

Функция Serial.print() и ее родственники отсекают все ведущие нули. Таким образом, 0b00001111 отображается как 1111, а 0b00000000 — как 0. Так что вы действительно получите то, что ожидаете. Просто печать другая.

Кроме того, при чтении PORTF вы фактически считываете состояние вывода контактов, как вы установили его ранее. Если вы хотите прочитать реальный входной уровень пинов, вы должны вместо этого прочитать PINF.

Хотя я не знаю, откуда взялась эта ошибка сегментации.

,