Всем привет. Был очень хороший вопрос от подписчика, который на мой взгляд заслуживает отдельной темы. О ней сегодня и пойдет речь.
В проектах на базе микроконтроллеров AVR (семейство ATmega) часто требуется оцифровывать аналоговые сигналы — например, с датчиков температуры, освещённости или положения. Для этого служит встроенный аналого‑цифровой преобразователь (АЦП). В этой статье разберём, как настроить АЦП в Freerun‑режиме (непрерывное преобразование) и управлять им через регистры с учётом актуальных технических требований.
Что такое Freerun‑режим
В Freerun‑режиме АЦП автоматически запускает новое преобразование сразу после завершения предыдущего. Это удобно для:
- непрерывного мониторинга аналоговых сигналов;
- построения осциллографов или спектроанализаторов;
- систем, где важна минимальная задержка между измерения gef.
В отличие от одиночного режима (Single Conversion), здесь не нужно программно инициировать каждое преобразование — микроконтроллер делает это сам.
Основные регистры АЦП ATmega
Управление АЦП осуществляется через набор регистров (адреса зависят от модели ATmega, уточняйте в даташите). Ключевые регистры:
- ADCSRA (ADC Control and Status Register A) — управление и статус:
- ADEN (бит 7) — включение АЦП;
- ADSC (бит 6) — старт преобразования (в Freerun не используется);
- ADATE (бит 5) — разрешение автоматического запуска преобразований (устанавливаем в 1 для Freerun);
- ADIF (бит 4) — флаг завершения преобразования;
- ADIE (бит 3) — разрешение прерывания по завершению АЦП;
- ADPS2..0 (биты 2…0) — делитель тактовой частоты АЦП.
- ADCSRB (ADC Control and Status Register B) — дополнительные настройки:
- ACME (бит 5) — относится к аналоговому компаратору (не влияет на работу АЦП);
- ADTS2..0 (биты 2…0) — выбор источника триггера для автоматического запуска (в Freerun должны быть установлены в 000).
- ADMUX (ADC Multiplexer Selection Register) — выбор канала и опорного напряжения:
- REFS1..0 (биты 7…6) — источник опорного напряжения (AVCC, внутренний ИОН, внешний);
- ADLAR (бит 5) — выравнивание результата (0 — правое, 1 — левое);
- MUX4..0 (биты 4…0) — номер аналогового входа (ADC0–ADC7).
- ADCL/ADCH (ADC Data Registers) — результат преобразования (10 бит):
- ADCL — младшие 8 бит результата (при правом выравнивании);
- ADCH — старшие 2 бита результата в битах 0…1 (при правом выравнивании).
Настройка АЦП в Freerun‑режиме
Пошаговый алгоритм:
Включите АЦП и разрешите автоматический запуск:
ADCSRA |= (1 << ADEN) | (1 << ADATE);
Выберите опорное напряжение, выравнивание и канал в ADMUX:
ADMUX = (1 << REFS0); // AVCC как опорное, правое выравнивание, канал ADC0
REFS0=1, REFS1=0 — опорное напряжение = AVCC;
ADLAR=0 — правое выравнивание результата (по умолчанию);
MUX4..0=00000 — канал ADC0 (по умолчанию).
Настройте тактовую частоту АЦП.
Частота АЦП должна быть в диапазоне 50–200 кГц (оптимально ~100 кГц). Тактовая частота контроллера делится на коэффициент из ADPS2..0. Для тактовой частоты 16 МГц рекомендуемый делитель — 128:
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Делитель 128 → 16 МГц / 128 = 125 кГц
Разрешите прерывание (опционально):
ADCSRA |= (1 << ADIE);
sei(); // Разрешить глобальные прерывания
Примечание: вызов sei() разрешит глобальные прерывания. Если в проекте уже есть sei(), дублировать его не требуется.
Запустите непрерывное преобразование:
В Freerun‑режиме преобразование начинается автоматически после установки ADATE=1 и ADTS=000 (по умолчанию в ADCSRB).
Обработка результатов
Результат АЦП (10 бит) читается из регистров ADCL и ADCH. Важно сначала прочитать ADCL, затем ADCH — это гарантирует корректность данных при правом выравнивании.
Пример чтения без прерываний:
Пример с прерыванием:
Примечание: флаг ADIF автоматически сбрасывается при входе в ISR, явное сбрасывание не требуется.
Типичные ошибки и советы
- Некорректная частота тактирования АЦП.
- Если частота выше 200 кГц, снижается точность. Проверьте делитель в ADPS2..0. Для 16 МГц оптимально использовать делитель 128 (125 кГц).
- Несинхронизированное чтение ADCL/ADCH.
- Всегда читайте ADCL первым при правом выравнивании! Иначе результат может быть некорректным.
- Отсутствие задержки после переключения каналов.
- При смене аналогового входа добавьте задержку ~10 мкс для стабилизации сигнала.
- Шумы в опорном напряжении.
- Используйте конденсатор номиналом 0,1 мкФ между AVCC и AGND для фильтрации помех.
- Переполнение приёмного буфера при высокой частоте преобразований.
- Если обработка данных медленнее, чем частота АЦП, используйте DMA (если доступно) или снизьте частоту тактирования АЦП.
- Неправильное выравнивание результата.
- При левом выравнивании (ADLAR=1) результат помещается в старшие 8 бит ADCH, а ADCL можно не читать. При правом выравнивании (ADLAR=0) требуется чтение обоих регистров.
Пример полной инициализации
Заключение.
Настройка АЦП в Freerun‑режиме через регистры даёт максимальный контроль над процессом преобразования. Ключевые моменты:
- правильно выберите опорное напряжение и канал;
- подберите делитель тактовой частоты АЦП (рекомендуется 128 для 16 МГц);
- учитывайте выравнивание результата (ADLAR);
- обрабатывайте результаты через прерывания или polling;
- следите за порядком чтения ADCL и ADCH при правом выравнивании.
Такой подход позволяет создавать высокопроизводительные системы сбора данных на базе ATmega без использования высокоуровневых библиотек. Всегда сверяйтесь с даташитом конкретной модели микроконтроллера, так как адреса регистров и доступные функции могут отличаться.
P.S.Небольшие уточнения (не ошибки, а стилистические/технические нюансы, специально вынесла отдельной ссылкой ниже, предвидя вопросы в комментариях):
О делителе частоты
В тексте указано:
«Для тактовой частоты 16 МГц рекомендуемый делитель — 128: 16 МГц / 128 = 125 кГц». Уточнение:
Частота АЦП — это не просто деление тактовой частоты МК, а частота тактирования самого АЦП. В даташитах явно указано, что для максимальной точности она должна быть 50–200 кГц. 125 кГц — оптимальный выбор, но при других тактовых частотах МК делитель подбирается так, чтобы частота АЦП оставалась в диапазоне 50–200 кГц.
О sei()
«Если в проекте уже есть sei(), дублировать его не требуется». Дополнение:
sei() — это макрос из <avr/interrupt.h>, устанавливающий бит I в регистре SREG. Это поможет новичкам.
О выравнивании (ADLAR)
В разделе «Типичные ошибки» упомянуто левое выравнивание, но нет примера кода. Для полноты:
// При ADLAR=1 (левое выравнивание) читаем только ADCH
uint8_t result_8bit = ADCH;
О конденсаторе для AVCC
Конденсатор должен быть установлен как можно ближе к выводам AVCC и AGND микроконтроллера.
О задержке при переключении каналов
Минимальное значение:
«Задержка должна быть не менее 1–2 мкс для стабилизации входного сигнала».