Какой формат вывода PINxn на atmega328p?

Я написал этот простой код для запуска на своем Arduino:

#ifndef F_CPU
#define F_CPU 16000000UL // тактовая частота 16 МГц
#endif

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  Serial.begin(9600);
  DDRD = 0x00;
  PORTD = 0x80; //активируем подтягивающий резистор на первом выводе порта D

  while (1)
  {
    Serial.print(PIND);
  }
  return 0;
}

Я просто устанавливаю порт D в качестве входа и считываю значение в цикле. Результат PIND — 253. Что представляет это число? это в десятичных дробях? где можно посмотреть их список? Как я могу увидеть двоичное подавление вывода PIN-кода (их 8 бит). Я не хочу использовать сдвиг битов.

, 👍1

Обсуждение

К вашему сведению, я запустил ваш код на своем MEga2560 и постоянно получаю ошибку 11111111. Возможно, вам стоит попробовать другой блок PORT или даже другой Arduino., @Sener

Я только что попробовал PORTB, и там все 1 111111 (побочный вопрос, почему порт B имеет только 6 бит?). Так что же здесь происходит с PORTD, сломанная плата?, @Joseph a


4 ответа


2

Serial.print(PIND, BIN); запишет значение в PIND в последовательный порт в представлении Base-2.

,

поэтому 253 - это десятичное число (11111101 в двоичной системе счисления). Разве оно не должно быть 1000 0000, поскольку только контакт 1 преобразован в вход? Что означает это число?, @Joseph a

Это зависит от того, что вы подключили ко всем контактам PORTD. Если только к контакту 7 что-то подключено, а у остальных подтягивающий резистор не включен, они плавающие и могут иметь любое значение., @jose can u c

Я только что включил подтягивание на всех PORD с помощью PORTD = 0xFF;, к которым ничего не подключено, и он все еще выводит 11111101, @Joseph a


0

Из таблицы данных Atmega 323p: «Запись логической единицы в PINxn переключает значение PORTxn независимо от значения DDRxn», что, вероятно, не то, что вы хотели сделать. Чтобы прочитать текущее состояние регистра D, нужно прочитать PORTD, или

Serial.print(PORTD);

в вашем примере.

Обновление:

... для чего используется PIND...

PINx называется адресом входных контактов порта x, а примечание под ним гласит: «Запись в регистр контактов обеспечивает функцию переключения для ввода-вывода» и отсылает нас к общей схеме драйвера контактов (раздел 41.2 в моей копии таблицы данных). ). В этом разделе говорится, что «Запись логической единицы в PINxn переключает значение PORTxn независимо от значения DDRxn». Это единственная ссылка на этот реестр, которую я смог найти.

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

Кроме того, я нигде не пишу логическую единицу для PINxn, я просто читаю это

В таблице данных не упоминается, что считывается из порта, по крайней мере, я нигде не нашел, несмотря на то, что регистр PINx описан как чтение/запись, так что ваше предположение так же верно, как и мое! ¯\_(ツ)_/¯ Но чтобы прочитать данные порта, вам нужно прочитать его регистр PORTx.

Обновление 2:

6 & 7сопоставляются с выводами кристалла и не могут использоваться

Их можно использовать. Вы можете использовать их для ввода-вывода или для внешнего кристалла, но не для того и другого. Вопрос «почему?» Это, по праву, прерогатива инженеров Atmel, но я возьмусь за это и скажу, что на чипе можно разместить гораздо больше функций, чем места для физических контактов на корпусе. Поскольку количество выводов имеет большое значение, функции приходится дублировать на одних и тех же выводах; вы сможете выбрать то, что вам нужно. SPI, PWM или ввод-вывод на DIP B2 и 3; Сброс и ввод-вывод на C6; Таймер-счетчик 1 вход, ввод/вывод, & ШИМ на D5, для нескольких примеров. Почти каждый контакт имеет несколько возможных применений (заметными исключениями являются питание и заземление). В своих целях я выделяю для этих функций контакты Crystal, Reset и UART, но могу представить себе системы, которым может потребоваться переназначить любой из них.

,

тогда для чего в этом случае используется PIND? что представляет собой 253, почему использование PINB вместо этого дает мне правильный вывод, где все значения равны 1, а PORTD - нет., @Joseph a

Также я нигде не пишу логику 1 в PINxn, я просто читаю ее., @Joseph a

Быстрый вопрос, почему сопоставление портов Arduino с чипом Atmel не является прямым сопоставлением. Например, на PORTB 6 и 7 сопоставлены с выводами кристалла и не могут быть использованы, почему так? Что делать, если я хочу их использовать?, @Joseph a


0

Последовательный порт имеет контакты 0 и 1.
PORTD предназначен для контактов 0,1,2,3,4,5,6,7. В том-то и проблема: вы портите контакты последовательного порта.

Примечание. При использовании кристалла/резонатора/часов эти контакты отключаются от PORTB. Это означает, что вы можете использовать PORTB и читать и записывать в него 8 бит, кристалл будет продолжать работать.

,

То есть, по сути, мне не следует использовать PORTD для обеспечения безопасности входных данных?, @Joseph a

Быстрый вопрос, почему сопоставление портов Arduino с чипом Atmel не является прямым сопоставлением. Например, на PORTB, 16 и 7 сопоставлены с выводами кристалла и не могут быть использованы, почему так? Что, если я хочу их использовать?, @Joseph a

После вызова Serial.begin не меняйте ни один из этих двух битов в регистрах. Вы можете использовать остальные шесть бит. Функциональность каждого вывода фиксирована. При использовании кристалла вы больше не можете использовать эти же выводы для чего-то другого, поскольку они подключены к кристаллу. Я не уверен, понял ли я ваш вопрос., @Jot

вопрос в том, что у atmega328p 8 бит в порту B, а у Arduino 6 (2 порта зарезервированы для чего-то другого), почему так?, @Joseph a

Portb.6 и Portb.7 — это контакты для кристалла. Когда кристалл не используется, они могут быть обычными цифровыми контактами. Микросхема atmega не может назначить функцию другому контакту. Последовательный порт, кристалл, шина i2c, аналоговые входы — все это закреплено за определенными контактами. Однако один контакт может выполнять несколько разных функций., @Jot


0
byte valueB = PINB; // считывает значение порта B, D14-D19, в переменную valueB

Если вы тогда

Serial.print (valueB,BIN); 

вы увидите значения от D19 до D14 в двоичном формате или 0 и amp; 1 с. Я не думаю, что ведущие нули отображаются, так что это может немного сбить с толку.

Serial.print (valueB);

отобразит то же значение в десятичном виде. 253 = 0b11111101 0b указывает формат по основанию 2 (двоичный). 0x используется для шестнадцатеричного формата (от 0x00 до 0xFF от 0 до 255).

Если вы используете IDE и не меняли фьюзы с платы типа Uno/Nano, IDE ожидает кристалл или резонатор на PB7 & PB6, поэтому их чтение вернет бессмысленный результат, поэтому их можно замаскировать перед печатью.

valueB = valueB & 0b00111111;

Если на других выводах внутренние подтягивающие резисторы не включены или внешние подтягивающие или понижающие резисторы не используются, выводы являются «плавающими», а их низкий входной ток означает, что любой внешний заряд может легко изменить их показания - поэтому значениеB = PINB; будет иметь ошибочные результаты.

Если порт настроен на выходы, то все контакты могут быть записаны одновременно:

PORTB = 0b0011111111;  // например, устанавливаем высокий уровень от D19 до D14
,