Настройка опорного напряжения АЦП ATtiny88

Я пишу простое приложение, которое считывает напряжение с аналогового входа 0. Вот код:

#define OUT 5
#define ADC 0

void setup() {
  ADMUX &= (0<<REFS0); //Установка внутреннего опорного напряжения 1,1 В
}

// процедура цикла выполняется снова и снова вечно:
void loop() {
  // считываем входной сигнал на аналоговом выводе 0:
  int sensorValue = analogRead(0);
  float voltage = sensorValue * (1.1 / 1023.0);
  if (voltage>0.5) {
    digitalWrite(OUT,HIGH);
  } else {
    digitalWrite(OUT,LOW);
  }
}

Когда я подаю 1 В на ADC0, вывод OUT низкий. Похоже, что опорное напряжение установлено неправильно. Когда я устанавливаю VREF на VCC (5 В), все работает нормально.

Я не могу найти ошибку. Буду признателен за любую помощь:)

Редактировать:

Ссылка на техническое описание: http://www.atmel.com/images/doc8008.pdf

, 👍3


2 ответа


0

В разделе настроек вам нужно установить или очистить все соответствующие биты в admux.

,

1

Заявление

ADMUX &= (0<<REFS0);

Выполняет операцию И между текущим значением ADMUX и нулем, в результате чего получается нулевое значение, и оно сохраняется в ADMUX.

Чтобы очистить бит REFS0 в ADMUX, не затрагивая остальную его часть, обычно вместо этого говорят

ADMUX &= ~(1<<REFS0);

который выполнит операцию AND своего значения с дополнением 1<<REFS0.

Однако вам следует использовать утверждение

analogReference(INTERNAL);

вместо настройки ADMUX напрямую. Один из первых операторов, выполняемых в исходном коде analogRead(), это

ADMUX = (analog_reference << 6) | (pin & 0x07);

что переопределяет выбор ссылок, сделанный путем простого изменения ADMUX.

Параметры INTERNAL и DEFAULT для analogReference() выбирают либо внутренний опорный сигнал запрещенной зоны 1,1 В, либо аналоговый опорный сигнал по умолчанию, Vcc.


Правка 1: Если вы заменили ADMUX &= (0<<REFS0) на analogReference(INTERNAL) в настройке, и это все еще не работает, вам нужно будет применить более мощные средства отладки. Например, проверьте, что вы правильно скомпилировали скетч и что вы правильно его загрузили. Проверьте, что AVCC подключен к Vcc, желательно через фильтр нижних частот , как указано в разделах §1.1.2 и §17.9 «Методы аналогового шумоподавления» в техническом описании. Затем попробуйте несколько входных напряжений, чтобы увидеть, на каком уровне загорается светодиод. Если он никогда не загорается, поищите проблемы со светодиодом, используя простой скетч, например Blink. Если он загорается постоянно при каком-то входном напряжении, выясните, какой опорный сигнал применяется.


Правка 2: По-видимому, исходный код analogRead() отличается для деталей ATtiny по сравнению с другими. Код, который я вижу для него в ... /arduino/avr/cores/arduino/wiring_analog.c [ваш путь может отличаться], выглядит следующим образом (я опустил некоторые комментарии и пустые строки).

uint8_t analog_reference = DEFAULT;
void analogReference(uint8_t mode) {
  analog_reference = mode;
}

int analogRead(uint8_t pin) {
  #if defined( CORE_ANALOG_FIRST )
    if ( pin >= CORE_ANALOG_FIRST ) pin -= CORE_ANALOG_FIRST; // разрешить номера каналов или контактов
  #endif
  ADC_SetVoltageReference( analog_reference );
  ADC_SetInputChannel( pin );
  ADC_StartConversion();
  while( ADC_ConversionInProgress() );
  return( ADC_GetDataRegister() );
}

Некоторые функции и константы ADC_... определены в ... avr/cores/tiny/core_adc.h; и то, какое определение ADC_SetVoltageReference() используется, зависит от условной компиляции. Для окончательной проверки того, как analogReference() определен для вашей части, найдите analogReference() в листинге сборки вашей программы. Получите этот листинг, как объяснено в нескольких ответах Arduino SE, например, в параграфе «Создание листингов сборки» в конце моего ответа на вопрос № 33033. Кроме того, в ветке forum.arduino.cc от конца апреля 2016 года есть обсуждение чтения входов АЦП на микроконтроллерах; не знаю, относится ли это к делу.

,