DigitalRead аналогого входа AVR

LittleBuster
Offline
Зарегистрирован: 08.01.2015

Решил переписать библиотеку DHT на Си функции для Uno, но столкнулся с проблемой. Нужно считать состояние аналогого порта A1 (PINC1) как цифрового и узнать 1 или 0 там.

uint8_t laststate = PINC & (1 << PINC1);

почему-то неправильно считывает. Я не знаю что она выдаёт, но если заменить digitalRead(15) на ту конструкцию, то градусник начинает выдавать бредовые значения типа -837. Может кто подсказать?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Если вам просто прочесть порт, то команда laststate=PINC&2;

LittleBuster
Offline
Зарегистрирован: 08.01.2015

Вообще проерка не реагирует, нули показывает на градуснике

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

LittleBuster, вы так пишите, словно проблема нулей на градуснике лежит на этой команде :) Я забыл сразу уточнить, результат чтения команды таким способом будет "вес" бита у нулевого он единица, у первого соответственно 2. Если вам нужен в ответе 0 или 1 то команду нужно немного изменить ((PINC&2)>>1)

LittleBuster
Offline
Зарегистрирован: 08.01.2015

dimax пишет:

LittleBuster, вы так пишите, словно проблема нулей на градуснике лежит на этой команде :)

Ну дык да, я уже переписал и протестировал остальные участки кода, проблема только здесь:

for <....>
while (digitalRead(_pin) == laststate) {
   counter++;
   delayMicroseconds(1);
   if (counter == 255) {
      break;
   }
}
laststate = digitalRead(_pin);

как только меняю digitalRead-ы здесь на регистры, термометр сразу чушь начинает показывать

единственное что удалось заменить так это 2ой digitalRead на

uint8_t tmp = PINC & (1 << _pin); //Здесь _pin уже регистровый (не тот что в дижитале)
if (tmp > 0)
   laststate = 1;
else
 laststate = 0;

И всё работает. Причём именно через знак ">" потому, что там почему-то число больше 1 всегда, но если я таким же костылём заменяю 1ый digitalRead, то опять начинает показывать бред.

Ваши советы тоже не помогают.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Почему там больше единицы я вам объяснил, -вы читаете "вес" первого бита, который равен 2. Чессно гря не знаю что вам сказать, по идее команда (PINC&2)>>1     полный аналог команды digitalRead(A1);

LittleBuster
Offline
Зарегистрирован: 08.01.2015

Чудеса да и только...

так ничё не работает: -3275 градуса

while (1) {
      uint8_t tmp = (PINC&2)>>1;
      if (tmp != laststate) { break; }

      counter++;
      delayMicroseconds(1);
      if (counter == 255) {
        break;
      }
    }
    laststate = (PINC&2)>>1;

А так всё правильно показывает

while (1) {
      uint8_t tmp = digitalRead(15);
      if (tmp != laststate) { break; }

      counter++;
      delayMicroseconds(1);
      if (counter == 255) {
        break;
      }
    }
    laststate = (PINC&2)>>1;

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

LittleBuster, у меня только одна версия -временная рассинхронизация. Не спроста там стоит мелкий делай(). Учитывая что прямое чтение порта в несколько раз быстрее чем digitalRead возможно что цикл counter пролетает не дождавшись нужного состояния.  Добавьте паузу или положите counter в uint16, с делайте раза в  ?  больше.

PS: хотя если counter собирает байты из входящих данных, то его конечно менять нельзя. Значит только увеличивать delay()

LittleBuster
Offline
Зарегистрирован: 08.01.2015

dimax пишет:

LittleBuster, у меня только одна версия -временная рассинхронизация. Не спроста там стоит мелкий делай(). Учитывая что прямое чтение порта в несколько раз быстрее чем digitalRead возможно что цикл counter пролетает не дождавшись нужного состояния.  Добавьте паузу или положите counter в uint16, с делайте раза в  ?  больше.

PS: хотя если counter собирает байты из входящих данных, то его конечно менять нельзя. Значит только увеличивать delay()

Спасибо Большое Вам доброй души человек.

подбором нашёл delayMicroseconds(3) псле чтения, всё работает как часы.