Регистр АЦП всегда возвращается высоким

Независимо от напряжения в точке A0, программное обеспечение всегда возвращает высокое значение (1023).

volatile unsigned char* ADmux = (unsigned char*) 0x7C;
volatile unsigned char* ADCSRa = (unsigned char*) 0x7A;
volatile unsigned char* ADCSRb = (unsigned char*) 0x7B;
volatile unsigned char* ADCh = (unsigned char*) 0x79;
volatile unsigned char* ADCl = (unsigned char*) 0x78;
int Voltage;

void adc_init()
{
  *ADmux = 0x00; // установка всего регистра в 0, в частности установка Refs1 и refs0 в 0, что означает, что опорное напряжение равно AREF
  *ADCSRa = 0b10000111; // Устанавливает самый значимый бит равным 1, что является битом включения АЦП, а 3 наименее значимых бита являются прескаляром, который равен 128

}

unsigned int adc_read( unsigned char adc_channel)
{
  *ADmux = *ADmux | 0b00000000;// установите биты mux равными 0, чтобы проверить A0 независимо от того, что такое adc_channel
  *ADCSRa = *ADCSRa | 0b01000000; // установите высокий бит ADSC для начала преобразования

  while(*ADCSRa & 0b01000000);//подождите, пока ADSC не опустится, указанное преобразование будет завершено

  return ADC; //возвращаемые биты в регистрах ацп
}


void setup() {
   // поместите свой установочный код здесь, чтобы запустить один раз:
   Serial.begin(9600);
   adc_init(); // инициализирует ацп
}

void loop() {
  // поместите свой основной код здесь, чтобы запускать его повторно:

  Voltage = adc_read(0b00000); // вызовы adc_read

  Serial.print(Voltage); // печатает показания напряжения
  Serial.write("\n");

}

А вот схема схемы:

schematic

Я прочесал главу 26 документа atmega2560 и описания каждого регистра, но я в растерянности. Почему содержимое регистров ацп всегда заполняется цифрами 1 независимо от напряжения на а0?

, 👍2

Обсуждение

что вы читаете, если удаляете R1?, @jsotola

@jsotola он все еще читает 1023, @ClockwerkSC

Какую IDE вы используете, если таковая имеется? Убедитесь, что MUX5, at ADCSRB: 3 установлен в 0, а также ADTS2:0 at ADCSRB 2:0, чтобы включить режим свободного хода., @towe

Я заставил программу работать, установив refs0 в 1. Таким образом, это означает, что опорное напряжение переключилось с AREF на AVCC. Кто-нибудь знает, почему это небольшое изменение заставляет его работать? Разве AREF не 5V по умолчанию?, @ClockwerkSC

@towe Я использую стандартную Arduino IDE., @ClockwerkSC


2 ответа


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

5

Во-первых, позвольте мне дать несколько советов по стилю программирования. Нет смысла определять собственные переменные для доступа к аппаратным регистрам: avr-libc делает это за вас, вам просто нужно #include <avr/io.h>. На самом деле, вам не нужно #включать что-либо: Arduino IDE автоматически #включает Arduino.h , который, в свою очередь #включает avr/io.h.

Далее, тот же avr-libc также определяет макросы для битовых имен, поэтому вам не нужно явно записывать двоичные числа в свой собственный код (который подвержен ошибкам). И пара полезных макросов, которые вы можете использовать, чтобы сделать код немного более читабельным. Например:

void adc_init()
{
    ADMUX  = _BV(REFS0);  // Ссылка на АЦП = AVCC
    ADCSRA = _BV(ADEN)    // включить АЦП
           | _BV(ADPS2)   // установить прескалер на 128
           | _BV(ADPS1)   // то же самое
           | _BV(ADPS0);  // то же самое
}

unsigned int adc_read(unsigned char adc_channel)
{
    ADMUX   = _BV(REFS0) | (adc_channel & 7);  // выбрать канал
    ADCSRA |= _BV(ADSC);  // начало преобразования

    // Преобразование завершается, когда ADSC становится низким.
    loop_until_bit_is_clear(ADCSRA, ADSC);

    return ADC;  // возврат регистра данных ацп
}

А теперь давайте ответим на ваш вопрос. Когда вы устанавливаете значения REFS0 и REFS1 равными 0, опорное напряжение указывается как “AREF, внутреннее В REF выключен ”. Подразумевается, что вы должны принести свой собственный эталон напряжения и подключить его к контакту AREF. В противном случае AREF остается как плавающий вход. Это проиллюстрировано на схеме АЦП. Вот соответствующая часть:

AREF input MOSFET

Как вы видите здесь, REFS0 используется для подключения AREF к одной из других возможных ссылок: либо AVCC, либо внутренней запрещенной зоне. Если REFS0 равен нулю, то транзистор, изображенный выше, выключен, а AREF остается плавающим.

,

2

Каковы значения сопротивления для R1 и LDR1? Их соотношение будет определять напряжение при А0. Если соотношение их сопротивлений слишком велико (например, 100:1), то любой свет, измеренный LDR1, приведет лишь к небольшому изменению измеряемого напряжения. Если разница достаточно велика, то напряжение также может казаться постоянно низким или высоким. Если у вас есть мультиметр, проверка напряжения этой цепи делителя может помочь определить, что происходит.

https://learn.sparkfun.com/tutorials/voltage-dividers/all

,