Почему АЦП сообщает 0 в этом скетче?
Этот скетч всегда сообщает 0 для показаний АЦП.
Я думаю, что это окажется чем-то глупым, но я не могу найти источник. Я внимательно просмотрел линии АЦП, и они кажется правильными, так что, возможно, проблема с физическими соединениями или с тем, как я пытаюсь сообщить о выходе АЦП, или с порядком выполнения задач. Функции capture_FID()
и т. д. основаны на примере из раздела 9.2.4 книги Нормана Данбара Внутреннее устройство программного обеспечения Arduino. Единственная разница - это позиция ADCSRA |= (1 << ADEN);
, которую я переместил сразу после включения питания на основе этого ответить. Это не имело значения.
void init();
void setup() {
Serial.begin(115200);
capture_FID();
}
void loop() {
}
void capture_FID() {
volatile uint16_t ADC_output = 0; // максимальное значение 65536
config_ADC();
start_ADC();
for (int i = 1; i <= 5; i++) {
Serial.print("\ti = ");
Serial.print(i);
Serial.print(" value = ");
Serial.println(ADC_output);
}
stop_ADC();
}
// Конфигурация АЦП
void config_ADC() {
Serial.println("Configuring the ADC...");
PRR &= ~(1 << PRADC); // включаем АЦП
ADCSRA |= (1 << ADEN); // включаем АЦП
ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // замедляем ход часов
ADMUX = (0 << REFS1) | (1 << REFS0); // используем внутреннее опорное напряжение 5 В
ADMUX &= ~(1 << ADLAR); // выравниваем по правому краю 10-битный вывод в пространстве размером 2 байта/16 бит
ADMUX |= (0 << MUX3) | (0 << MUX2) | (0 << MUX1) | (0 << MUX0); // вход мультиплексора; используйте А0
DIDR0 |= (1 << ADC0D); // отключаем цифровой вход на контакт A0
ADCSRA |= (1 << ADIE); // устанавливаем прерывание для уведомления о доступности данных для дальнейшего использования
ADCSRA |= (1 << ADATE); // автозапуск включен
ADCSRB = 0; // автономный режим
delay(20); // ждем, пока напряжение стабилизируется
}
// Запускаем АЦП = начинаем сбор данных
void start_ADC() {
Serial.println("Starting the ADC...");
ADCSRA |= (1 << ADSC);
}
// Остановить АЦП = прекратить сбор данных
void stop_ADC() {
Serial.println("Stopping the ADC...");
ADCSRA |= (0 << ADSC);
}
ISR(ADC_vect) {
volatile uint16_t ADC_output; // максимальное значение 32767
ADC_output = ADCW;
}
Оборудование:
- Ардуино R3
- Ограничение 0,1 мкФ между GND и AREF
- Функциональный генератор PicoScope подает сигнал смещения 500 Гц, 500 мВ, 1 В; отрицательный выход подключен к GND на Arduino, положительный выход подключен к A0.
- Скетч, который не предполагает автономный запуск и автоматический запуск, который я нашел на сайте Ника Гаммона, работает нормально, так что с доской все в порядке. Это также означает, что с аппаратными подключениями и настройками области все в порядке.
@Bryan Hanson, 👍0
1 ответ
У вас есть две разные переменные с именем ADC_output
:
- один, который является локальным для
capture_FID()
и всегда равен нулю (никогда не является присвоено другое значение) - один локальный для
ISR(ADC_vect)
, который установлен, но никогда не используется.
Вы должны использовать только одну такую переменную.
В этом коде есть еще несколько проблем:
capture_FID()
печатает один и тот же результат несколько раз без проверка поступления новых данных- доступ к
ADC_output
за пределами ISR не защищен в критическом раздел - регистр ADC называется
ADC
, а неADCW
. ADCSRA |= (0 << ADSC)
не работает- нет смысла объявлять
init()
- наверное больше, я не до конца прочитал…
- Программирование микроконтроллера Attiny85 без arduino
- Заменить предохранители Arduino Uno (может ли Arduino Uno заменить свои собственные предохранители?)
- Arduino EEPROM сохраняет старые данные после прошивки новой программой
- Взаимодействие ADS8319 с Arduino UNO
- Ускорение двигателя постоянного тока с помощью ШИМ
- Как найти пиковое значение аналогового сигнала?
- Как преобразовать эту программу в сборку из c++
- Чтение сигнала 4-20 мА на ардуино
Ах, значит, проблема в моем ограниченном опыте работы с C. Позвольте мне немного покопаться. Спасибо., @Bryan Hanson