Стандартный analogRead(A0) работает так:
- Запускает преобразование.
- Ждет 104 мкс (пока АЦП закончит).
- Возвращает результат.
Проблема: Пока вы ждете, процессор простаивает. А если вам нужно читать 6 датчиков 1000 раз в секунду — процессор будет занят только чтением!
Хак: Переключаем АЦП в режим непрерывного преобразования (Free-Running Mode). В этом режиме АЦП сам постоянно преобразует аналоговый сигнал в цифру, а вы просто читаете готовый результат из регистра, когда он вам нужен.
Настройка регистров АЦП:
void setupADC_FreeRunning() {
// Настраиваем A0 (PC0) как аналоговый вход
DDRC &= ~(1 << PC0); // Пин как вход
PORTC &= ~(1 << PC0); // Отключаем подтяжку
// Настройка АЦП:
ADMUX = (1 << REFS0); // Опорное напряжение = AVCC (5В)
// Выбираем канал 0 (A0) — по умолчанию 0
ADCSRA = (1 << ADEN) | // Включаем АЦП
(1 << ADATE) | // Включаем Auto-Trigger (Free-Running)
(1 << ADIE) | // Включаем прерывание по завершению
(1 << ADPS2) | (1 << ADPS1); // Делитель 64 (частота 250 кГц)
ADCSRB = 0; // Режим Free-Running (по умолчанию)
sei(); // Разрешаем прерывания
ADCSRA |= (1 << ADSC); // Запускаем первое преобразование
}
// Обработчик прерывания — срабатывает КАЖДЫЙ раз, когда АЦП готов!
ISR(ADC_vect) {
uint16_t adcValue = ADC; // Читаем результат (0-1023)
// Делаем что-то с данными
// Например, обновляем ШИМ на пине 9 в реальном времени
OCR1A = adcValue >> 2; // Преобразуем 10-бит в 8-бит для ШИМ
}
void loop() {
// АЦП работает в фоне!
// Можно делать что угодно, например, выводить данные на дисплей
// или отправлять по UART раз в секунду
}
Результат: Вы получаете обновление значения датчика 77 000 раз в секунду (при частоте 250 кГц) без затрат процессорного времени! Идеально для аудио-визуализаторов или систем стабилизации.