Регистр ADCH Arduino Uno завис на значении 255 при чтении из ISR

Я работаю над проектом, который в конечном итоге станет осциллографом. Я следую этому руководству. Мой код загружен здесь для получения дополнительных сведений.

В моем файле .ino я вызвал функции для настройки регистра так, чтобы у меня был таймер ISR, вызываемый с частотой 100 кГц и тактовой частотой АЦП 2 МГц. АЦП также настроен так, что результат сдвинут влево, поэтому ADCH содержит 8-битный результат. В отдельном файле .h у меня есть ISR ADC, который выглядит следующим образом:

ISR(ADC_vect)
{
  // Чтение 8-битного результата преобразования из ADCH.
  uint8_t byte0 = ADCL;
  uint8_t byte1 = ADCH;

  data_byte = byte1;
  flag = true;
}

Функция цикла() выглядит следующим образом:

void loop()
{
  if (flag == true)
  {
    //Serial.println("ISR HIT");
    Serial.println(data_byte);
    flag = false;
  }
}

Итак, когда вызывается ISR, для флага установлено значение true, и в функции цикла() я получаю уведомление с помощью «ISR HIT», напечатанного на последовательном мониторе, эта операция выполнена успешно.

Однако в моей функции .ino также есть изменчивая глобальная переменная, называемая data_byte (также объявленная как extern в файле .h), для которой я установил значение byte1. Когда byte1 выводится на последовательный монитор, результат:

255
255 
255 

Есть идеи, почему значение ADCH застряло на уровне 255? Мое оборудование представляет собой просто датчик освещенности, подключенный к контакту A0, 3,3 В и GND.

, 👍1

Обсуждение

На скорости 9600 бод отправка «ISR HIT» может осуществляться 120 раз в секунду. Вы хотите отправлять его 100000 раз в секунду., @Jot

Вы никогда не устанавливаете и не печатаете data_byte. Или, может быть, вы делаете это в версии программы, которую вы не публиковали. Если мы не можем увидеть код, нет смысла пытаться угадать, что может быть не так., @Edgar Bonet

@Jot Спасибо! Я не принял это во внимание. В идеале я бы установил скорость передачи данных на уровне ~800 000 бит/с (или выше), но сейчас я просто установил ее на 250 000, потому что мой последовательный монитор на моем компьютере не позволяет мне подняться выше., @CookieMonster317

@EdgarBonet Приношу извинения, я удалил этот фрагмент кода в целях отладки. Обновленный код находится в GitHub, и я обновил фрагменты кода в этом вопросе., @CookieMonster317

Ваша программа у меня работает: подключение AREF к 5 В и A0 к 3,3 В дает поток чисел около 187. Пожалуйста, покажите нам полную схему схемы, которую вы используете., @Edgar Bonet

@EdgarBonet Спасибо за ваш комментарий, я понял, в чем дело. Я предполагал, что в моей установке используется внутренний источник опорного напряжения 5 В, однако теперь я понимаю, что мне нужно подать напряжение на AREF (я подал напряжение с контакта 5 В), и теперь моя установка работает. Если бы вы написали это в качестве ответа, я бы с радостью принял, большое вам спасибо!, @CookieMonster317


1 ответ


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

0

Казалось бы, проблема кроется вот в чем:

// Устанавливаем в регистр все нули, начиная с Vref
// будет установлено внутреннее напряжение и
// используется аналоговый вывод A0.
ADMUX = 0x00;

Согласно таблице данных, биты REFS[1:0] регистра ADMUX выберите опорное напряжение как:

  • 00: AREF, внутреннее задание V отключено.
  • 01: AVCC с внешним конденсатором на выводе AREF
  • 10: зарезервировано.
  • 11: Внутренний источник опорного напряжения 1,1 В с внешним конденсатором на выводе AREF.

Установка этих битов на ноль означает, что теперь вы должны предоставить ваша собственная ссылка через контакт AREF. Если вы хотите использовать 5 В поставляются в качестве эталона, вам следует установить их на 01. Это подтверждается схема блока. Вот часть этой схемы относительно опорное напряжение:

частичная схема АЦП

Когда REFS0 равен нулю, выделенный транзистор не проводит ток, следовательно единственный способ обеспечить опорное напряжение — через контакт AREF.

,

Ответ принят! Еще раз спасибо за такой подробный и хорошо объясненный ответ., @CookieMonster317