Принцип работы ацп микроконтроллера. Аналого-цифровой преобразователь микроконтроллеров AVR. Аналого-цифровой преобразователь с поразрядным уравновешиванием

Любой микроконтроллер общается с периферийными устройствами при помощи портов ввода/вывода. При этом он способен “воспринимать” только цифровые сигналы – логический ноль или единицу. Например, у МК ATmega8 при напряжении питания 5 В логический ноль – это напряжение лежащие в интервале от 0 до 1,3 В, а единица – от 1,8 до 5 В. Довольно часто в радиолюбительской практике возникает необходимость измерять напряжения, которое может принимать любое значение в диапазоне от нуля до уровня напряжения питания. Для этих задач в составе всех микроконтроллеров AVR имеется аналого-цифровой преобразователь.


Не вникая в подробности устройства АЦП, представим его типовым черного ящика. На вход АЦП идет аналоговый сигнал, а на выходе его имеем последовательность цифровых значений. АЦП имеет огромное число различных характеристик, из них можно выделить такие как: разрешающая способность, абсолютную точность, предельная частота дискретизации и диапазон входных напряжений.

Разрешающая способность или разрешение – эта характеристика АЦП помогает различать два значения входного сигнала. Определяется как величина обратная наибольшему числу кодовых комбинаций АЦП на выходе. У нашего МК АЦП десяти разрядный, поэтому максимальное число возможных кодовых комбинаций будет равно 2 10 = 1024 , а его разрешающая способность равна 1/1024 от полной шкалы допустимых входных напряжений.

Для правильной работы АЦП требуется источник опорного напряжения (ИОН). По отношению к которому, АЦП измеряет сигналы поступающие на его вход. МК AVR позволяют в роли ИОН применять напряжение питания, их внутренний опорный источник на 2,56 В, а напряжение на выходе AREF (внешний ИОН).

Так как наша схема запитана от 5 В, тогда 1/1024 от всей шкалы получится 0,0048 В или около 5 мВ. С таким шагом АЦП будет определять уровень входного напряжения. Если два ближайших значения на входе преобразователя будут отличаться друг от друга на величину менее 5 мВ, АЦП будет считать равными. На практике разрешающая способность любого АЦП ограничена шумами.

Абсолютная точность АЦП это отклонение реального преобразования от идеального. Это составной результат нескольких погрешностей преобразователя. Математически описывается в количестве младших значащих разрядов (LSB). Максимальная абсолютная погрешность АЦП «Atmega8» равна 1.5 LSB. Для нашего случая абсолютная точность равна 2 × 5 мВ = ±10 мВ

Предельная частота дискретизации это есть быстродействие АЦП, которое измеряется в Гц или количестве выборок за секунду (SPS – samples per second). Для МК AVR она равна15 kSPS (килло семплов за секунду).

На порт В - МК AVR подключен типовой ЖК дисплей 16х2. Выводы AREF и AVCC подключены к питающему напряжению 5В. Это и есть ИОН. На порт С Atmega к нулевому разряду подключен контакт с вольтметром и переменным сопротивлением для изменения уровня входного напряжения. Наша задача в этом учебном примере следующая: Мы хотим вывести на ЖК экран величину напряжения, аналогичную измерению вольтметра.

Переходим к программированию запускаем новый проект в программе . В настройках Chip выбираем МК Atmega8, частоту выставляем 4,00000000 MHz. (см. пример с мигающим светодиодом). Переходим во вкладку LCD выбираем PORTB. И сохраняем проект под названием ADC (аббревиатура АЦП на забугорном языке). Вначале необходимо добавить две директивы препроцессора для работы с текстом и задержкой. Для этого после директивы LCD вставим две строки.

#include
#include

Первая строка необходима для задержек, а вторая для работы дисплея с текстом. Далее создаем массив для промежуточного хранения форматированного текста. После текста в коде, пишем.

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

Теперь настроим сам АЦП. Для этого после настройка компаратора запишем следующее.

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off

ACSR=0x80;
SFIOR=0x00;

ADMUX=0; // Первая строка, № порта.
ADCSR=0x85; // Вторая строка настройка АЦП. (в двоичной системе x85=10000101)

Для того чтоб начать работу с АЦП у МК имеется регистр ADCSR. Вот, что в нем находится.

0-й бит ADPS0 Настройка частоты преобразования
1-й бит ADPS1 -/-/-
2-й бит ADPS2 -/-/-
3-й бит ADIE Разрешение прерывания
4-й бит ADIF Флаг прерывания
5-й бит ADFR Выбор работы АЦП. 1-непрерывный либо 0-по запуску ADSC
6-й бит ADSC Запуск преобразование 1-старт. После преобразования сбрасывается в ноль аппаратно.
7-й бит ADEN Разрешение работы АЦП 1-да 0-нет

Для включения в АЦП записываем 1 в 7-й разряд, 0 в 6-й, 5-й, 3-й и 4-й разряды. Теперь подбираем частоту, т.к у нас кварц на 4000 кГц, то нам его надо поделить (для стабильной работы АЦП его требуется тактировать частотой в диапазоне 50 кГц - 200 кГц), чуть ниже представлена таблица коэффициентов деления.

Возьмем коэффициент делителя на 32, получим частоту 125 кГц, что вполне достаточно для стабильной работы АЦП. Итак, в регистр ADCSR нам надо записать значение 10000101.

С настройками АЦП надеюсь понятно. Теперь давайте выведем в первой строке на экране наши намерения. Для этого после инициализации LCD дисплея запишем строчку. lcd_putsf("Work with ADC");

// LCD module initialization
lcd_init(16);
lcd_putsf("Work with ADC"); // Выводим запись

Теперь при старте программы В МК увидим эту надпись. Далее в бесконечном цикле пишем тело основной программы.

while (1)
{
delay_ms(20); // Задаем задержку в 20 миллисекунд
ADCSR |= 0x40; // Записываем 1 в ADSC
data = ADCW; // Вычитываем значение
V = (float) data*0.0048828; // Переводим в вольты
sprintf(string, "Data: %1.2f", V); // форматируем
lcd_gotoxy(0,1); // Выставляем курсор
lcd_puts(string); // Выводим значение

delay_ms(20); задержку на 20 миллисекунд.
ADCSR |= 0x40; битное ИЛИ. Число 0х40 в бинаре выглядит так 0b01000000. Если мы проведем по битное ИЛИ с 0х85 (0b10000101), то у нас в 6-й разряд запишется 1. Для того, чтобы началось преобразование в 6-й разряд нужно записать 1. А после преобразование он сбросится в 0 аппаратно.
data = ADCW; После преобразования микроконтроллер записывает полученное значение в ADCW. Вот оттуда мы его и возьмем
V = (float) data*0.0048828; Преобразуем полученное значение в вольты, т.к ИОН=5В, а значение регистра 1024, то мы 5/1024=0.0048828 получим коэффициент напряжения. Минимальная величина напряжения будет при минимальном значении регистра ADCW. То есть если в нем будет значение 1, то напряжение будет 0.0048828 В. Поэтому в строке, данные ADCW перемножаем на это значение - 0.0048828. Слово float в скобке используется для того чтобы преобразовать переменную data из целочисленной в вещественную с плавающей точкой.
sprintf(string, "Data: %1.2f", V); Заносим значение напряжения в массив string с последующим форматированием. Сначала впишем Data: . После ставим знак процента. 1.2f - говорит о том что мы хотим вывести на экран один знак до запятой и два знака после, а буква f означает, что это значение вещественным с плавающей точкой.
lcd_gotoxy(0,1); Курсор в нулевую позицию во второй строке.
lcd_puts(string); Выводим значение на дисплей.

Перед тем как собрать проект нужно сделать небольшие настройки в CodeVisionAVR. В меню нажимаем "Project->Configure" и в открывшемся окне переходим во вкладку "C Compiler", затем в левом нижнем углу меняем значение (s)printf Features: с int, width на float, width, precision.

Результат работы программы на рисунке ниже:


Архив с проектом для CodeVisionAVR и Proteus вы можете скачать по зеленой ссылке выше. Затем распакуйте архив в корень диска С и проект можно запускать.

Отличительные особенности:

  • 10-разрядное разрешение
  • Интегральная нелинейность 0.5 мл. разр.
  • Абсолютная погрешность ±2 мл. разр.
  • Время преобразования 65 - 260 мкс.
  • Частота преобразования до 15 тыс. преобр. в сек. при максимальном разрешении
  • 8 мультиплексированных однополярных входов
  • 7 дифференциальных входных каналов
  • 2 дифференциальных входных канала с опциональным усилением на 10 и 200
  • Представление результата с левосторонним или правосторонним выравниванием в 16-разр. слове
  • Диапазон входного напряжения АЦП 0…VCC
  • Выборочный внутренний ИОН на 2.56 В
  • Режимы одиночного преобразования и автоматического перезапуска
  • Прерывание по завершении преобразования АЦП
  • Механизм подавления шумов в режиме сна

ATmega128 содержит 10-разр. АЦП последовательного приближения. АЦП связан с 8-канальным аналоговым мультиплексором, 8 однополярных входов которого связаны с линиями порта F. Общий входных сигналов должен иметь потенциал 0В (т.е. связан с GND). АЦП также поддерживает ввод 16 дифференциальных напряжений. Два дифференциальных входа (ADC1, ADC0 и ADC3, ADC2) содержат каскад со ступенчатым программируемым усилением: 0 дБ (1x), 20 дБ (10x), или 46 дБ (200x). Семь дифференциальных аналоговых каналов используют общий инвертирующий вход (ADC1), а все остальные входы АЦП выполняют функцию неинвертирующих входов. Если выбрано усиление 1x или 10x, то можно ожидать 8-разр. разрешение, а если 200x, то 7-разрядное.

АЦП содержит УВХ (устройство выборки-хранения), которое поддерживает на постоянном уровне напряжение на входе АЦП во время преобразования. Функциональная схема АЦП показана на рисунке 108.

АЦП имеет отдельный вывод питания AVCC (аналоговое питание). AVCC не должен отличаться более чем на ± 0.3В от VCC. См. параграф “ ”, где приведены рекомендации по подключению этого вывода.

В качестве внутреннего опорного напряжения может выступать напряжение от внутреннего ИОНа на 2.56В или напряжение AVCC. Если требуется использование внешнего ИОН, то он должен быть подключен к выводу AREF с подключением к этому выводу блокировочного конденсатора для улучшения шумовых характеристик.

Рисунок 108 - Функциональная схема аналогово-цифрового преобразователя

Принцип действия

АЦП преобразовывает входное аналоговое напряжение в 10-разр. код методом последовательных приближений. Минимальное значение соответствует уровню GND, а максимальное уровню AREF минус 1 мл. разр. К выводу AREF опционально может быть подключено напряжение AVCC или внутренний ИОН на 1.22В путем записи соответствующих значений в биты REFSn в регистр ADMUX. Несмотря на то, что ИОН на 2.56В находится внутри микроконтроллера, к его выходу может быть подключен блокировочный конденсатор для снижения чувствительности к шумам, т.к. он связан с выводом AREF.

Канал аналогового ввода и каскад дифференциального усиления выбираются путем записи бит MUX в регистр ADMUX. В качестве однополярного аналогового входа АЦП может быть выбран один из входов ADC0…ADC7, а также GND и выход фиксированного источника опорного напряжения 1,22 В. В режиме дифференциального ввода предусмотрена возможность выбора инвертирующих и неинвертирующих входов к дифференциальному усилителю.

Если выбран дифференциальный режим аналогового ввода, то дифференциальный усилитель будет усиливать разность напряжений между выбранной парой входов на заданный коэффициент усиления. Усиленное таким образом значение поступает на аналоговый вход АЦП. Если выбирается однополярный режим аналогового ввода, то каскад усиления пропускается

Работа АЦП разрешается путем установки бита ADEN в ADCSRA. Выбор опорного источника и канала преобразования не возможно выполнить до установки ADEN. Если ADEN = 0, то АЦП не потребляет ток, поэтому, при переводе в экономичные режимы сна рекомендуется предварительно отключить АЦП.

АЦП генерирует 10-разрядный результат, который помещается в пару регистров данных АЦП ADCH и ADCL. По умолчанию результат преобразования размещается в младших 10-ти разрядах 16-разр. слова (выравнивание справа), но может быть опционально размещен в старших 10-ти разрядах (выравнивание слева) путем установки бита ADLAR в регистре ADMUX.

Практическая полезность представления результата с выравниванием слева существует, когда достаточно 8-разрядное разрешение, т.к. в этом случае необходимо считать только регистр ADCH. В другом же случае необходимо первым считать содержимое регистра ADCL, а затем ADCH, чем гарантируется, что оба байта являются результатом одного и того же преобразования. Как только выполнено чтение ADCL блокируется доступ к регистрам данных со стороны АЦП. Это означает, что если считан ADCL и преобразование завершается перед чтением регистра ADCH, то ни один из регистров не может модифицироваться и результат преобразования теряется. После чтения ADCH доступ к регистрам ADCH и ADCL со стороны АЦП снова разрешается.

АЦП генерирует собственный запрос на прерывание по завершении преобразования. Если между чтением регистров ADCH и ADCL запрещен доступ к данным для АЦП, то прерывание возникнет, даже если результат преобразования будет потерян.

Запуск преобразования

Одиночное преобразование запускается путем записи лог. 1 в бит запуска преобразования АЦП ADSC. Данный бит остается в высоком состоянии в процессе преобразования и сбрасывается по завершении преобразования. Если в процессе преобразования переключается канал аналогового ввода, то АЦП автоматически завершит текущее преобразование прежде, чем переключит канал.

В режиме автоматического перезапуска АЦП непрерывно оцифровывает аналоговый сигнал и обновляет регистр данных АЦП. Данный режим задается путем записи лог. 1 в бит ADFR регистра ADCSRA. Первое преобразование инициируется путем записи лог. 1 в бит ADSC регистра ADCSRA. В данном режиме АЦП выполняет последовательные преобразования, независимо от того сбрасывается флаг прерывания АЦП ADIF или нет.

Предделитель и временная диаграмма преобразования


Рисунок 109 – Предделитель АЦП

Если требуется максимальная разрешающая способность (10 разрядов), то частота на входе схемы последовательного приближения должна быть в диапазоне 50…200 кГц. Если достаточно разрешение менее 10 разрядов, но требуется более высокая частота преобразования, то частота на входе АЦП может быть установлена свыше 200 кГц.

Модуль АЦП содержит предделитель, который формирует производные частоты свыше 100 кГц по отношению к частоте синхронизации ЦПУ. Коэффициент деления устанавливается с помощью бит ADPS в регистре ADCSRA. Предделитель начинает счет с момента включения АЦП установкой бита ADEN в регистре ADCSRA. Предделитель работает пока бит ADEN = 1 и сброшен, когда ADEN=0.

Если инициируется однополярное преобразование установкой бита ADSC в регистре ADCSRA, то преобразование начинается со следующего нарастающего фронта тактового сигнала АЦП. Особенности временной диаграммы дифференциального преобразования представлены в “ ”.

Нормальное преобразование требует 13 тактов синхронизации АЦП. Первое преобразование после включения АЦП (установка ADEN в ADCSRA) требует 25 тактов синхронизации АЦП за счет необходимости инициализации аналоговой схемы.

После начала нормального преобразования на выборку-хранение затрачивается 1.5 такта синхронизации АЦП, а после начала первого преобразования – 13,5 тактов. По завершении преобразования результат помещается в регистры данных АЦП и устанавливается флаг ADIF. В режиме одиночного преобразования одновременно сбрасывается бит ADSC. Программно бит ADSC может быть снова установлен и новое преобразование будет инициировано первым нарастающим фронтом тактового сигнала АЦП.

В режиме автоматического перезапуска новое преобразование начинается сразу по завершении предыдущего, при этом ADSC остается в высоком состоянии. Времена преобразования для различных режимов преобразования представлены в таблице 95.


Рисунок 110 – Временная диаграмма работы АЦП при первом преобразовании в режиме одиночного преобразования


Рисунок 111 – Временная диаграмма работы АЦП в режиме одиночного преобразования


Рисунок 112 – Временная диаграмма работы АЦП в режиме автоматического перезапуска

Таблица 95 – Время преобразования АЦП

Каналы дифференциального усиления

Если используются каналы дифференциального усиления, то необходимо принять во внимание некоторые особенности.

Дифференциальные преобразования синхронизированы по отношению к внутренней синхронизации CKАЦП2, частого которого равна половине частоты синхронизации АЦП. Данная синхронизация выполняется автоматически интерфейсом АЦП таким образом, чтобы выборка-хранение инициировалась определенным фронтом CKАЦП2. Если преобразование (все одиночные преобразования и первое преобразование в режиме автоматического перезапуска) инициировалось пользователем, когда CKАЦП2 находился в низком лог. состоянии, то его длительность будет эквивалента однополярному преобразованию (13 тактов синхронизации АЦП). Если преобразование инициируется пользователем, когда CKАЦП2 равен лог. 1 , оно будет длиться 14 тактов синхронизации АЦП вследствие работы механизма синхронизации. В режиме автоматического перезапуска новое преобразование инициируется сразу по завершении предыдущего, а т.к. в этот момент CKАЦП2 равен лог. 1, то все преобразования, которые были автоматически перезапущены (т.е. все, кроме первого), будут длиться 14 тактов синхронизации АЦП. Усилительный каскад оптимизирован под частотный диапазон до 4 кГц для любых коэффициентов усиления. Усиление сигналов более высоких частот будет нелинейным. Поэтому, если входной сигнал содержит частотные составляющие выше частотного диапазона усилительного каскада, то необходимо установить внешний фильтр низких частот. Обратите внимание, что частота синхронизации АЦП не связана с ограничением по частотному диапазону усилительного каскада. Например, период синхронизации АЦП может быть 6 мкс, при котором частота преобразования канала равна 12 тыс. преобр. в секунду, независимо от частотного диапазона этого канала.

Изменение канала или выбор опорного источника

Биты MUXn и REFS1:0 в регистре ADMUX поддерживают одноступенчатую буферизацию через временный регистр. Этим гарантируется, что новые настройки канала преобразования и опорного источника вступят в силу в безопасный момент для преобразования. До начала преобразования любые изменения канала и опорного источника вступаю в силу сразу после их модификации. Как только начинается процесс преобразования доступ к изменению канала и опорного источника блокируется, чем гарантируется достаточность времени на преобразование для АЦП. Непрерывность модификации возвращается на последнем такте АЦП перед завершением преобразования (перед установкой флага ADIF в регистре ADCSRA). Обратите внимание, что преобразование начинается следующим нарастающим фронтом тактового сигнала АЦП после записи ADSC. Таким образом, пользователю не рекомендуется записывать новое значение канала или опорного источника в ADMUX до 1-го такта синхронизации АЦП после записи ADSC.

Особые меры необходимо предпринять при изменении дифференциального канала. Как только осуществлен выбор дифференциального канала усилительному каскаду требуется 125 мкс для стабилизации нового значения. Следовательно, в течение первых после переключения дифференциального канала 125 мкс не должно стартовать преобразование. Если же в этот период преобразования все-таки выполнялись, то их результат необходимо игнорировать.

Такую же задержку на установление необходимо ввести при первом дифференциальном преобразовании после изменения опорного источника АЦП (за счет изменения бит REFS1:0 в ADMUX).

Если разрешена работа интерфейса JTAG, то функции каналов АЦП на выводах порта F 7…4 отменяется. См. табл. 42 и “Альтернативные функции порта F”.

Входные каналы АЦП

При переключении входного канала необходимо учесть некоторые рекомендации, которые исключат некорректность переключения.

В режиме одиночного преобразования переключение канала необходимо выполнять перед началом преобразования. Переключение канала может произойти только в течение одного такта синхронизации АЦП после записи лог. 1 в ADSC. Однако самым простым методом является ожидание завершения преобразования перед выбором нового канала.

В режиме автоматического перезапуска канал необходимо выбирать перед началом первого преобразования. Переключение канала происходит аналогично - в течение одного такта синхронизации АЦП после записи лог. 1 в ADSC. Но самым простым методом является ожидание завершения перового преобразования, а затем переключение канала. Поскольку следующее преобразование уже запущено автоматически, то следующий результат будет соответствовать предыдущему каналу. Последующие преобразования отражают результат для нового канала.

При переключении на дифференциальный канал первое преобразование будет характеризоваться плохой точностью из-за переходного процесса в схеме автоматической регулировки смещения. Следовательно, первый результат такого преобразования рекомендуется игнорировать.

Источник опорного напряжения АЦП

Источник опорного напряжения (ИОН) для АЦП (VИОН) определяет диапазон преобразования АЦП. Если уровень однополярного сигнала свыше VИОН, то результатом преобразования будет 0x3FF. В качестве VИОН могут выступать AVCC, внутренний ИОН 2,56В или внешний ИОН, подключенный к выв. AREF. AVCC подключается к АЦП через пассивный ключ. Внутреннее опорное напряжение 2,56В генерируется внутренним эталонным источником VBG, буферизованного внутренним усилителем. В любом случае внешний вывод AREF связан непосредственно с АЦП и, поэтому, можно снизить влияние шумов на опорный источник за счет подключения конденсатора между выводом AREF и общим. Напряжение VИОН также может быть измерено на выводе AREF высокоомным вольтметром. Обратите внимание, что VИОН является высокоомным источником и, поэтому, внешне к нему может быть подключена только емкостная нагрузка.

Если пользователь использует внешний опорный источник, подключенный к выв. AREF, то не допускается использование другой опции опорного источника, т.к. это приведет к шунтированию внешнего опорного напряжения. Если к выв. AREF не приложено напряжение, то пользователь может выбрать AVCC и 2.56В качестве опорного источника. Результат первого преобразования после переключения опорного источника может характеризоваться плохой точностью и пользователю рекомендуется его игнорировать.

Если используются дифференциальные каналы, то выбранный опорный источник должен быть меньше уровня AVCC, что показано в табл. 136.

Подавитель шумов АЦП

АЦП характеризуется возможностью подавления шумов, которые вызваны работой ядра ЦПУ и периферийных устройств ввода-вывода. Подавитель шумов может быть использован в режиме снижения шумов АЦП и в режиме холостого хода. При использовании данной функции необходимо придерживаться следующей процедуры:

  1. Убедитесь, что работа АЦП разрешена и он не выполняет преобразования. Выберите режим одиночного преобразования и разрешите прерывание по завершении преобразования.
  2. Введите режим уменьшения шумов АЦП (или режим холостого хода). АЦП запустит преобразование как только остановится ЦПУ.
  3. Если до завершения преобразования не возникает других прерываний, то АЦП вызовет прерывание ЦПУ и программа перейдет на вектор обработки прерывания по завершении преобразования АЦП. Если до завершения преобразования другое прерывание пробуждает микроконтроллер, то это прерывание обрабатывается, а по завершении преобразования генерируется соответствующий запрос на прерывание. АЦП остается в активном режиме пока не будет выполнена очередная команда sleep.

Обратите внимание, что АЦП не отключается автоматически при переводе во все режимы сна, кроме режима холостого хода и снижения шумов АЦП. Поэтому, пользователь должен предусмотреть запись лог. 0 в бит ADEN перед переводом в такие режимы сна во избежание чрезмерного энергопотребления. Если работа АЦП была разрешена в таких режимах сна и пользователь желает выполнить дифференциальное преобразование, то после пробуждения необходимо включить, а затем выключить АЦП для инициации расширенного преобразования, чем будет гарантировано получение действительного результата.

Схема аналогового входа для однополярных каналов представлена на рисунке 113. Независимо от того, какой канал подключен к АЦП, аналоговый сигнал, подключенный к выв. ADCn, нагружается емкостью вывода и входным сопротивлением утечки. После подключения канала к АЦП аналоговый сигнал будет связан с конденсатором выборки-хранения через последовательный резистор, сопротивление которого эквивалентно всей входной цепи.

АЦП оптимизирован под аналоговые сигналы с выходным сопротивлением не более 10 кОм. Если используется такой источник сигнала, то время выборки незначительно. Если же используется источник с более высоким входным сопротивлением, то время выборки будет определяться временем, которое требуется для зарядки конденсатора выборки-хранения источником аналогового сигнала. Рекомендуется использовать источники только с малым выходным сопротивлением и медленно изменяющимися сигналами, т.к. в этом случае будет достаточно быстрым заряд конденсатора выборки-хранения.

По отношению к каналам с дифференциальным усилением рекомендуется использовать сигналы с внутренним сопротивлением до нескольких сотен кОм. Следует предусмотреть, чтобы в предварительных каскадах формирования аналогового сигнала ко входу АЦП не вносились частоты выше fАЦП/2, в противном случае результат преобразования может быть некорректным. Если вероятность проникновения высоких частот существует, то рекомендуется перед АЦП установить фильтр низких частот.


Рисунок 113 – Схема аналогового входа

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

  1. Выполняйте путь аналоговых сигналов как можно более коротким. Следите, чтобы аналоговые сигналы проходили над плоскостью (слоем) с аналоговой землей (экраном) и далеко от проводников, передающих высокочастотные цифровые сигналы.
  2. Вывод AVCC необходимо связать с цифровым питанием VCC через LC-цепь в соответствии с рис. 114.
  3. Используйте функцию подавления шумов АЦП, внесенных работой ядра ЦПУ.
  4. Если какой-либо из выводов АЦП используется как цифровой выход, то чрезвычайно важно не допустить переключение состояния этого выхода в процессе преобразования.


Рисунок 114 – Подключение питания АЦП

Методы компенсации смещения

Усилительный каскад имеет встроенную схему компенсации смещения, которая стремится максимально приблизить к нулю смещение дифференциального измерения. Оставшееся смещение можно измерить, если в качестве дифференциальных входов АЦП выбрать один и тот же вывод микроконтроллера. Измеренное таким образом остаточное смещение можно программно вычесть из результата преобразования. Использование программного алгоритма коррекции смещения позволяет уменьшить смещение ниже одного мл. разр.

Определения погрешностей аналогово-цифрового преобразования

n-разрядный однополярный АЦП преобразовывает напряжение линейно между GND и VИОН с количеством шагами 2n (мл. разрядов). Минимальный код = 0, максимальный = 2n-1. Основные погрешности преобразования являются отклонением реальной функции преобразования от идеальной. К ним относятся:

Смещение – отклонение первого перехода (с 0x000 на 0x001) по сравнению с идеальным переходом (т.е. при 0.5 мл. разр.). Идеальное значение: 0 мл. разр.


Рисунок 115 – Погрешность смещения

После корректировки смещения погрешность усиления представляет собой отклонение последнего перехода (с 0x3FE на 0x3FF) от идеального перехода (т.е. отклонение при максимальном значении минус 1,5 мл. разр.). Идеальное значение: 0 мл. разр.


Рисунок 116 – Погрешность усиления

Интегральная нелинейность (ИНЛ) . После корректировки смещения и погрешности усиления ИНЛ представляет собой максимальное отклонение реальной функции преобразования от идеальной для любого кода. Идеальное значение ИНЛ = 0 мл. разр.


Рисунок 117 - Интегральная нелинейность (ИНЛ)

Дифференциальная нелинейность (ДНЛ) . Максимальное отклонение между шириной фактического кода (интервал между двумя смежными переходами) от ширины идеального кода (1 мл. разр.). Идеальное значение: 0 мл. разр.


Рисунок 118 - Дифференциальная нелинейность (ДНЛ)

Погрешность квантования . Возникает из-за преобразования входного напряжения в конечное число кодов. Погрешность квантования- интервал входного напряжения протяженностью 1 мл. разр. (шаг квантования по напряжению), который характеризуется одним и тем же кодом. Всегда равен ±0.5 мл. разр.

Абсолютная погрешность . Максимальное отклонение реальной (без подстройки) функции преобразования от реальной при любом коде. Является результатом действия нескольких эффектов: смещение, погрешность усиления, дифференциальная погрешность, нелинейность и погрешность квантования. Идеальное значение: ±0.5 мл. разр.

Результат преобразования АЦП

По завершении преобразования (ADIF = 1) результат может быть считан из пары регистров результата преобразования АЦП (ADCL, ADCH).

Для однополярного преобразования:

где V вх – уровень напряжения на подключенном к АЦП входу;

Vион –напряжение выбранного источника опорного напряжения (см. табл. 97 и табл. 98). Код 0x000 соответствует уровню аналоговой земли, а 0x3FF - уровню напряжения ИОН минус 1 шаг квантования по напряжению. При использовании дифференциального канала

V pos - напряжение на неинвертирующем (инвертирующем) входе; V neg - коэффициент усиления; V ref - напряжение выбранного ИОН.

Результат представляется в коде двоичного дополнения, начиная с 0x200 (-512d) до 0x1FF (+511d). Обратите внимание, что при необходимости быстро определить полярность результата достаточно опросить старший бит результата преобразования (ADC9 в ADCH). Если данный бит равен лог. 1, то результат отрицательный, если же лог. 0, то положительный. На рисунке 119 представлена функция преобразования АЦП в дифференциальном режиме.

В таблице 96 представлены результирующие выходные коды для дифференциальной пары каналов (ADCn - ADCm) с коэффициентом усиления Ку и опорным напряжением VИОН.


Рисунок 119 – Функция преобразования АЦП при измерении дифференциального сигнала

Таблица 96 – Связь между входным напряжением и выходными кодами

V АЦПn Считываемый код Соответствующее десятичное значение
V АЦПm + V ИОН /Ky 0x1FF 511
V АЦПm + 0.999 V ИОН / Ky 0x1FF 511
V АЦПn + 0.998 V ИОН / Ky 0x1FE 510
... ...
V АЦПm + 0.001 V ИОН / Ky 0x001 1
V АЦПm 0x000 0
V АЦПm - 0.001 V ИОН / Ky 0x3FF -1
... ...
V АЦПm - 0.999 V ИОН / Ky 0x201 -511
V АЦПm – V ИОН / Ky 0x200 -512

Пример: Пусть ADMUX = 0xED (пара входов ADC3 - ADC2, Ку=1, Vион=2.56В, результат с левосторонним выравниванием), напряжение на входе ADC3 = 300 мВ, а на входе ADC2 = 500 мВ, тогда:

КодАЦП = 512 * 10 * (300 - 500) / 2560 = -400 = 0x270

С учетом выбранного формата размещения результата (левосторонний) ADCL = 0x00, а ADCH = 0x9C. Если же выбран правосторонний формат (ADLAR=0), то ADCL = 0x70, ADCH = 0x02.

Регистр управления мультиплексором АЦП– ADMUX

Разряд 7 6 5 4 3 2 1 0
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0 ADMUX
Чтение/запись Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп.
Исх. значение 0 0 0 0 0 0 0 0

Разряд 7:6 – REFS1:0: Биты выбора источника опорного напряжения

Данные биты определяют какое напряжение будет использоваться в качестве опорного для АЦП (см. табл. 97). Если изменить значения данных бит в процессе преобразования, то новые установки вступят в силу только по завершении текущего преобразования (т.е. когда установится бит ADIF в регистре ADCSRA). Внутренний ИОН можно не использовать, если к выводу AREF подключен внешний опорный источник.

Таблица 97 – Выбор опорного источника АЦП

Разряд 5 – ADLAR: Бит управления представлением результата преобразования

Бит ADLAR влияет на представление результата преобразования в паре регистров результата преобразования АЦП. Если ADLAR = 1, то результат преобразования будет иметь левосторонний формат, в противном случае - правосторонний. Действие бита ADLAR вступает в силу сразу после изменения, независимо от выполняющегося параллельно преобразования. Полное описание действия данного бита представлено в “Регистры данных АЦП – ADCL и ADCH”.

Разряд 4:0 – MUX4:0: Биты выбора аналогового канала и коэффициента усиления

Данные биты определяют какие из имеющихся аналоговых входов подключаются к АЦП. Кроме того, с их помощью можно выбрать коэффициент усиления для дифференциальных каналов (см. табл. 98). Если значения бит изменить в процессе преобразования, то механизм их действия вступит в силу только после завершения текущего преобразования (после установки бита ADIF в регистре ADCSRA).

Таблица 98 – Выбор входного канала и коэффициента усиления

MUX4..0 Однополярный вход Неинвертирующий дифференциальный вход Инвертирующий дифференциальный вход Коэффициент усиления, Ку
00000 ADC0 Нет
00001 ADC1
00010 ADC2
00011 ADC3
00100 ADC4
00101 ADC5
00110 ADC6
00111 ADC7
01000 Нет ADC0 ADC0 10
01001 ADC1 ADC0 10
01010 ADC0 ADC0 200
01011 ADC1 ADC0 200
01100 ADC2 ADC2 10
01101 ADC3 ADC2 10
01110 ADC2 ADC2 200
01111 ADC3 ADC2 200
10000 ADC0 ADC1 1
10001 ADC1 ADC1 1
10010 ADC2 ADC1 1
10011 ADC3 ADC1 1
10100 ADC4 ADC1 1
10101 ADC5 ADC1 1
10110 ADC6 ADC1 1
10111 ADC7 ADC1 1
11000 ADC0 ADC2 1
11001 ADC1 ADC2 1
11010 ADC2 ADC2 1
11011 ADC3 ADC2 1
11100 ADC4 ADC2 1
11101 ADC5ADC21
Нет111110В(GND)
11110 1.23В (VBG)

Регистр А управления и статуса АЦП – ADCSRA

Разряд 7 6 5 4 3 2 1 0
ADEN ADSC ADFR ADIF ADIE ADPS2 ADPS1 ADPS0 ADCSRA
Чтение/запись Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп. Чт./Зп.
Исх. значение 0 0 0 0 0 0 0 0

Разряд 7 – ADEN: Разрешение работы АЦП

Запись в данный бит лог. 1 разрешает работу АЦП. Если в данный бит записать лог. 0, то АЦП отключается, даже если он находился в процессе преобразования.

Разряд 6 – ADSC: Запуск преобразования АЦП

В режиме одиночного преобразования установка данного бита инициирует старт каждого преобразования. В режиме автоматического перезапуска установкой этого бита инициируется только первое преобразование, а все остальные выполняются автоматически. Первое преобразование после разрешения работы АЦП, инициированное битом ADSC, выполняется по расширенному алгоритму и длится 25 тактов синхронизации АЦП, вместо обычных 13 тактов. Это связано с необходимостью инициализации АЦП.

В процессе преобразования при опросе бита ADSC возвращается лог. 1, а по завершении преобразования – лог. 0. Запись лог. 0 в данный бит не предусмотрено и не оказывает никакого действия.

Разряд 5 – ADFR: Выбор режима автоматического перезапуска АЦП

Если в данный бит записать лог. 1, то АЦП перейдет в режим автоматического перезапуска. В этом режиме АЦП автоматически выполняет преобразования и модифицирует регистры результата преобразования через фиксированные промежутки времени. Запись лог. 0 в этот бит прекращает работу в данном режиме.

Разряд 4 – ADIF: Флаг прерывания АЦП

Данный флаг устанавливается после завершения преобразования АЦП и обновления регистров данных. Если установлены биты ADIE и I (регистр SREG), то происходит прерывание по завершении преобразования. Флаг ADIF сбрасывается аппаратно при переходе на соответствующий вектор прерывания. Альтернативно флаг ADIF сбрасывается путем записи лог. 1 в него. Обратите внимание, что при выполнении команды "чтение-модификация-запись" с регистром ADCSRA ожидаемое прерывание может быть отключено. Данное также распространяется на использование инструкций SBI и CBI.

Разряд 3 – ADIE: Разрешение прерывания АЦП

После записи лог. 1 в этот бит, при условии, что установлен бит I в регистре SREG, разрешается прерывание по завершении преобразования АЦП.

Разряды 2:0 – ADPS2:0: Биты управления предделителем АЦП

Данные биты определяют на какое значение тактовая частота ЦПУ будет отличаться от частоты входной синхронизации АЦП.

Таблица 99 – Управление предделителем АЦП

Регистры данных АЦП – ADCL и ADCH

ADLAR = 0:

Разряд 15 14 13 12 11 10 9 8
- - - - - - ADC9 ADC8 ADCH
ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0 ADCL
7 6 5 4 3 2 1 0
Чтение/запись Чт. Чт. Чт. Чт. Чт. Чт. Чт. Чт.
Чт. Чт. Чт. Чт. Чт. Чт. Чт. Чт.
Исх. значение 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

ADLAR = 1:

Разряд 15 14 13 12 11 10 9 8
ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADCH
ADC1 ADC0 - - - - - - ADCL
7 6 5 4 3 2 1 0
Чтение/запись Чт. Чт. Чт. Чт. Чт. Чт. Чт. Чт.
Чт. Чт. Чт. Чт. Чт. Чт. Чт. Чт.
Исх. значение 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

По завершении преобразования результат помещается в этих двух регистрах. При использовании дифференциального режима преобразования результат представляется в коде двоичного дополнения.

Если выполнено чтение ADCL, то доступ к этим регистрам для АЦП будет заблокирован (т.е. АЦП не сможет в дальнейшем модифицировать результат преобразования), пока не будет считан регистр ADCH.

Левосторонний формат представления результата удобно использовать, если достаточно 8 разрядов. В этом случае 8-разрядный результат хранится в регистре ADCH и, следовательно, чтение регистра ADCL можно не выполнять. При правостороннем формате необходимо сначала считать ADCL, а затем ADCH.

ADC9:0: Результат преобразования АЦП

Данные биты представляют результат преобразования.

Многие AVR имеют на борту АЦП последовательного приближения.
АЦП это десятиразрядное, но при точности +/- 2 минимально значащих разрядов его можно смело считать восьмиразрядным:) Так как в младших двух разрядах всегда мусор какой то, не похожий на полезный сигнал. Тем не менее это неплохой инструмент для контроля напряжения, в восьмиразрядном режиме имеющий 256 отсчетов и выдающее частоту дискретизации до 15кГц (15 тысяч выборок в секунду).

Конфигурация источника
Сигнал в АЦП подается через мультиплексор, с одного из восьми (в лучшем случае, часто бывает меньше) входов. Выбор входа осуществляется регистром ADMUX , а точнее его битами MUX3…MUX0 . Записанное туда число определяет выбраный вход. Например, если MUX3..0 = 0100 , то подключен вывод ADC4 .

Кроме того, существует несколько служебных комбинаций битов MUX , использующихся для калибровки.
Например, 1110 подключает к АЦП внутренний источник опорного напряжения на 1.22 вольта . А если записать в MUX3..0 все единицы, то АЦП будет изнутри посажено на землю. Это полезно для выявления разных шумов и помех.

У старших AVR семейства Mega (8535, 16, 32, 128) есть возможность включить АЦП в режиме дифференциального входа . Это когда на два входа приходят разные напряжения. Одно вычитается из другого, да еще может умножаться на коэффициент усиления. Зачем это нужно? А, например, когда надо замерить перекос напряжения измерительного моста. У какого-нибудь тензомоста при входном напряжении в пять вольт выходные сигналы будут различаться между собой всего лишь 30мВ, вот и поймай его. А так подал на диф вход, подогнал нужный коэффициент усиления и красота!

Таблицу значений MUX3..0 для диф включения я не буду тут приводить, она находится легко в даташите, зовется она «Input Channel and Gain Selections «. Я поясню лишь один тонкий момент. В режиме выбора диф входа встречаются такие комбинации как: первый вход ADC0 и второй вход тоже ADC0 ну и коэффициент усиления еще. Как так? Ведь для диф входа нужно два разных входа! Вначале подумал опечатка, поднял даташит на другую АВРку — та же ботва. Потом повтыкал в текст ниже и понял — это для калибровки нуля. Т.е. перед началом съема диф данных нам нужно закоротить входы, чтобы понять, что же у нас ноль. Так вот, комбинация когда два входа подключены к одной ноге это и есть та самая калибровочная закоротка входов. Делаешь первое преобразование на такой фигне, получаешь смещение нуля . А потом вычитаешь его из всех полученных значений, что резко повышает точность.

Мультиплексирование каналов осуществляется только после того, как завершится преобразование, поэтому можно смело запускать АЦП на обсчет входных значений, записывать в MUX3..0 параметры другого входа, и готовится снимать данные уже оттуда.

Выбор опорного сигнала
Это максимальное напряжение, которое будет взято за максимум при измерениях. Опорное напряжение должно быть как можно стабильней, без помех и колебаний — от этого кардинальным образом зависит точность работы АЦП . Задается он в битах REFS1..0 регистра ADMUX .

  • По дефолту там стоит REFS1..0 = 00 — внешний ИОН , подключенный к входу AREF . Это может быть напряжение со специальной микросхемы опорного напряжения, или же со стабилитрона какого, если нужно замерять небольшое напряжение, заметно меньшее чем напряжение питания, скажем от 0 до 1 вольт, то чтобы было точнее, и чтобы оно не затерялось на фоне пятивольтового питания, то на AREF мы заводим опорное напряжение в 1 вольт.
  • REFS1..0 = 01 — тут просто берется напряжение питания. У всех почти Мег с АЦП есть вход AVCC — вот это напряжение питания для AЦП и порта на который это АЦП повешено. Подавать туда плюс питания желательно через LC фильтр, чтобы не было искажений.
  • REFS1..0 = 11 — внутренний источник опорного напряжения на 2.56 вольт . Честно говоря, качество этого источника мне сильно не понравилось. С ним показания АЦП плавают как говно в проруби. Но если невозможно обеспечить гладкую и стабильную подачу напряжения на AREF или AVCC то прокатит. Кстати, внутренний ИОН подключен к выводу AREF так что можно повесить туда кондер и попробовать его чуть чуть сгладить. Немного, но помогает.
Выбор режима запуска преобразования
В регистре SFIOR под АЦП отведено аж три бита. ADTS2..0 которые управляют режимами запуска АЦП .
  • По дефолту ADTS2..0 = 000 и это значит, что преобразование идет в непрерывном режиме. Ну или по ручному запуску.
  • ADTS2..0 = 001 — запуск АЦП от аналогового компаратора. Удобно блин. Например, чтобы не замерять постоянно входную величину, а запрограммировать компаратор на то, что как только у него вылезет что-либо выше порога, так тут же захватывать это дело на АЦП .
  • ADTS2..0 = 010 — запуск от внешнего прерывания INT0
  • ADTS2..0 = 011 — по совпадению таймера T0
  • ADTS2..0 = 100 — по переполнению таймера Т0
  • ADTS2..0 = 101 — по совпадению с таймера Т1
  • ADTS2..0 = 110 — По переполнению таймера Т1
  • ADTS2..0 = 111 — По событию «захват» таймера Т1
Скорость работы АЦП
Частота выборки АЦП задается в битах предделителя ADPS2…0 регистра ADCSR . Саму таблицу можно поглядеть в даташите на соответствующий МК, скажу лишь то, что самая оптимальная точность работы модуля АЦП находится в пределах 50…200кГц , поэтому предделитель стоит настраивать исходя из этих соображений. С повышением частоты точность падает.

Прерывания.
Естественно у АЦП есть прерывания. В данном случае это прерывание по окончанию преобразования. Его можно разрешить битом ADIE , а внаглую вручную палится оно по флагу ADIF (регистр ADCSRA ). Флаг ADIF автоматом снимается при уходе на вектор прерывания по АЦП .

Данные с АЦП сваливаются в регистровую пару ADCH:ADCL откуда их можно забрать. Причем тут есть один прикольный момент. Регистровая пара то у нас ведь 16ти разрядная, а АЦП имеет разрядность 10бит . В итоге, лишь один регистр занят полностью, а второй занимает лишь оставшиеся два бита. Так вот, выравнивание может быть как по правому краю — старшие два бита в ADCH , а младшие в ADCL , либо по левому — старшие биты в ADCH , а два младших бита в ADCL .

[x][x][x][x][x][x]: или : [x][x][x][x][x][x]


Зачем это сделано? А это выборка разрядности так оригинально организована. Как я уже говорил, в младших разрядах все равно мусор и шумы (по крайней мере я от них так и не смог избавиться, как ни старался) . Так вот. Делаем выравнивание по левому краю. И загребаем старшие разряды только из регистра ADCH , а на младший забиваем. Итого, у нас число отсчетов становится 256. За выравнивание отвечает бит ADLAR в регистре ADMUX 0 — выравнивание по правой границе, 1 — по левой.

Запуск преобразования в ручном или непрерывном режиме.
Для запуска преобразования нужно вначале разрешить работу ADC , установкой бита ADEN в регистре ADCSR и в том же регистре ткнуть в бит ADSC . Для запуска непрерывного преобразование (одно за другим) нужно также выставить бит ADFR (ADATE в некоторых AVR ).

Повышение точности уходом в спячку.
Для повышения точности, чтобы внутренние цепи АЦП не гадили своими шумами, можно запустить АЦП в спящем режиме . Т.е. проц останавливается, все замирает. Работает только WatchDog и блок АЦП . Как только данные сосчитаются, генерируется прерывание которое будит процессор, он уходит на обработчик прерывания от АЦП и дальше все своим чередом.

А теперь приведу парочку примеров простой инициализации и работы с АЦП . Микроконтроллер ATMega16

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <Сигнал на вход идет с нулевого канала АЦП.

; Мой любимый макрос для записи в порты:)))) .MACRO outi LDI R16,@1 OUT @0,R16 .ENDM ; ADC Init - Инициализурем АЦП. Это можно сунуть куда - нибудь в начало кода OUTI ADCSRA,(1<Сигнал на вход идет с нулевого канала АЦП.

А что дальше делать? А ничего! Сидеть и ждать прерывания!
Когда оно придет процессор кинет на вектор и дальше уже можно либо переписать данные из ADCH:ADCL в другое место, либо какую простенькую обработку тут же, не отходя от кассы, замутить. Вроде усреднения.

Вариант два, с уходом в спячку. В принципе, все то же самое, только нужно выключить автоматический перезапуск конвертирования. Далее в регистре MCUCR в битах SM2..0 выбрать режим ADC Noise Reduction SM2..0 = 001 , а после, сразу же после запуска послать процессор в спячку командой SLEEP . Как только он уснет заработает АЦП, сделает преобразование и проснется на прерывании.

Выглядит это так:

; ADC Init - Инициализурем АЦП. Это можно сунуть куда - нибудь в начало кода OUTI ADMUX,0b01000101 ;А тут выбираем откуда брать будем сигнал;REFS -- 0b000101 первые два бита - напряжение с входа AVCC ;ADLAR --0b0100101следующий бит выравнивание по правому краю;MUX -- 0b010Сигнал на вход идет с 5й ноги. OUTI MCUCR,0b10010000 ; Выставил биты спящего режима в Noise Reduction ; А это уже тело главной программы Main Prog: OUTI ADCSRA,(1<

Ну и, для повышения точности, следует соблюдать ряд правил по подключению питания к АЦП модулю, например подавать напряжение на вход AVCC через дроссель, ставить конденсаторы и земли побольше вокруг. Об этом все есть в даташите. Я же скоро выложу пример рабочей программы — примера для АЦП и UART .


Описание работы Аналого-цифрового преобразователя.
Прерывания от АЦП

ATMega16 содержит в себе 10-битовый АЦП, вход которого может быть соединён с одним из восьми выводов Port A. АЦП Mega16, как и любому другому АЦП, нужно опорное напряжение для целей сравнения со входным (если измеряемое равно опорному, то получаем максимальный код в двоичном виде). Опорное напряжение подаётся на вывод ADRef или может использоваться внутренний генератор с фиксированным напряжением 2,65 В. Полученный результат можно представить в таком виде:

АЦП включается установкой бита ADEN в регистре ADCSRA. После преобразования, 10-битный результат оказывается в 8-битных регистрах ADCL и ADCH. По умолчанию, младший бит результата находится справа (то есть в bit 0 регистра ADCL, так называемое правое ориентирование). Но порядок следования битов на левое ориентирование можно сменить установив бит ADLAR в регистре ADMUX. Это удобно, если требуется получить 8-битовый результат. В таком случае требуется прочитать только регистр ADCH. В противном случае, Вы должны сначала прочитать регистр ADCL первым, а ADCH вторым, чтобы быть уверенным в том, что чтение этих двух регистров относится к результату одного преобразования.

Одиночное преобразование может быть вызвано записью бита ADSC в регистр ADCSRA. Этот бит остаётся установленным всё время, занимаемое преобразованием. Когда преобразование закончено, бит автоматически устанавливается в 0. Можно также начинать преобразования по событиям из разных источников. Модуль АЦП также может работать в режиме "свободного полёта". В таком случае АЦП постоянно производит преобразование и обновляет регистры ADCH и ADCL новыми значениями.

Для выполнения преобразования модулю АЦП необходима тактовая частота. Чем выше эта частота, тем быстрее будет происходить преобразование (оно, обычно, занимает 13 тактов, первое преобразование занимает 25 тактов). Но чем выше частота (и выше скорость преобразования), тем менее точным получается результат. Для получения максимально точного результата, модуль АЦП должен тактироваться частотой в пределах от 50 до 200 КГц. Если необходим результат с точностью менее 10 бит, то можно использовать частоту больше 200 КГц. Модуль АЦП содержит делитель частоты, чтобы получать нужную тактовую частоту для преобразования из частоты процессора.

Регистр ADMUX задаёт входной контакт порта A для подключения АЦП, ориентирование результата и выбор опорной частоты. Если установлен бит ADLAR, то результат лево-ориентирован. Опорная частота от внутреннего генератора задаётся выставленными в 1 битами REFS1 и REFS0. Если оба бита сброшены, то опорная частота берётся от контакта AREF. В случае, если REFS1=0 а REFS0=1, опорная частота берётся от AVCC с внешним конденсатором, подключенным к AREF. Выбор контакта ввода выполняется следующим образом:

Регистр контроля и статуса АЦП ADCSRA :

Бит ADEN=1 включает модуль АЦП.
Запись единицы в ADSC запускает цикл преобразования. В режиме "свободного полёта" запись единицы запускает первое преобразование, последующие запускаются автоматически.
ADIF - флаг прерывания АЦП. Этот бит устанавливается в 1 когда АЦП завершено преобразование и в регистрах ADCL и ADCH находятся актуальные данные. Этот флаг устанавливается даже в том случае, если прерывания запрещены. Это необходимо для случая программного опроса АЦП. Если используются прерывания, то флаг сбрасывается автоматически. Если используется программный опрос, то флаг может быть сброшен записью лог.1 в этот бит.
ADIE - Если в этом бите установлена единица, и прерывания разрешены глобально, то при окончании преобразования будет выполнен переход по вектору прерывания от АЦП.
Биты ADPS2..0 задают коэффициенты предделителя частоты:


Урок 22

Часть 2

Изучаем АЦП

Сегодня мы продолжаем изучать очень интересную технологию, а для микроконтроллера — периферию — аналго-цифровой преобразователь или как его называют АЦП . В нашего занятия мы познакомились, что такое вообще АЦП, также познакомились, как он организован в контроллере AVR, а также создали новый проект и настроили его.

Дальнейшая задача — реализация АЦП в нашем проекта.

Ну и чтобы нам данную задачу выполнить, нам нужны будут определённые функции для обращения к АЦП контроллера.

Для этого зайдём в файл adc.c и создадим функцию инициализацию нашего АЦП

#include "adc.h"

//—————————————-

void ADC_Init ( void )

{

}

Также создадим на данную функцию прототип в хедер-файле adc.h для видимости её из внешних модулей, а также заодно и посмотрим всё содержимое данного файла

#ifndef ADC_H_

#define ADC_H_

#include "main.h"

void ADC_Init ( void );

#endif /* ADC_H_ */

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

Начнем с управляющего регистра

void ADC_Init ( void )

ADCSRA |= (1<< ADEN )

|(1<< ADPS2 )|(1<< ADPS1 )|(1<< ADPS0 ); //Делитель 128 = 64 кГц

Это не две строки, а одна, так писать в студии можно и даже нужно, так как код становится понятнее. А одна, потому что нет символа конца строки — точки с запятой.

Здесь мы включили бит ADEN , тем самым включили вообще модуль АЦП, а также установили делитель на 128, тем самым, помня то, что частота тактирования у нас 8 МГц и разделив её значение на 128, мы получили работу АЦП на частоте 64 кГц, что вполне нормально и надёжно, до 200 граничных далеко. Как видим, ничего сложного в инициализации регистра нет.

Также ещё в данной функции нам необходимо выбрать канал, к которому мы будем подключать измеряемое напряжение. У нас судя по схеме канал 0, поэтому соответствующий MUX мы и включим. А соответствующий MUX — это все нули в данных битах, поэтому ничего-то и включать не надо. Но мы ещё помним, что в регистре ADMUX у нас помимо всего прочего есть и управляющие биты, а именно биты REFS1 и REFS0, с помощью которых мы установим в качестве источника опорного напряжения внутренний источник на 2,56 вольта, а ADLAR мы не используем

ADCSRA |= (1<< ADEN ) // Разрешение использования АЦП

|(1<< ADPS2 )|(1<< ADPS1 )|(1<< ADPS0 ); //Делитель 128 = 64 кГц

ADMUX |= (1<< REFS1 )|(1<< REFS0 ); //Внутренний Источник ОН 2,56в, вход ADC0

Ну вот, в принципе, и вся инициализация.

Вызовем эту функцию в главном модуле программы в функции main() где-нибудь вот тут

LCD_ini (); //Инициализируем дисплей

ADC_Init (); //Инициализируем АЦП

clearlcd (); //Очистим дисплей

Ну и также нам нужна будет в модуле adc.c ещё одна функция, которая будет инициализировать непосредственно начало процесса аналого-цифрового преобразования в нашем ADC

unsigned int ADC_convert ( void )

{

}

Само собой нужен будет в хедер-файле прототип на неё

void ADC_Init ( void );

unsigned int ADC_convert ( void );

Данная функция нам вернёт значение из регистровой пары ADC , которая и будет содержать величину нашего электрического сигнала в единицах, выражающих отношение измеряемого сигнала к опорному и умноженных на количество возможных отрезков, которых у нас 1023, ну или 1024. Насчёт этого ходят много слухов, но в технической документации на контроллер в расчетной формуле содержится именно 1024. Но это нам не так важно.

Включим преобразование с помощью бита ADSC

unsigned int ADC_convert ( void )

ADCSRA |= (1<< ADSC ); //Начинаем преобразование

Теперь нам надо как-то отследить тот момент, когда данное преобразование закончится. А делается это достаточно легко с помощью мониторинга того же бита ADSC, который по окончании процесса преобразования сам сбрасывается в 0 (When the conversion is complete, it returns to zero). Отслеживается данный бит с помощью условного цикла

ADCSRA |= (1<< ADSC ); //Начинаем преобразование

while (( ADCSRA & (1<< ADSC )));

Ну и по окончании вернём результат в виде беззнаковой величины

while (( ADCSRA & (1<< ADSC ))); //проверим закончилось ли аналого-цифровое преобразование

return ( unsigned int ) ADC ;

Вернёмся теперь в нашу главную функцию main() и создадим там локальную переменную для хранения результата преобразования для дальнейшей с ним работы

int main ( void )

unsigned int adc_value ;

Вызовем функцию преобразования, которая нам положит в нашу переменную результат преобразования

while (1)

adc_value = ADC_convert (); //Вызовем преобразование

Setpos (0,0);

Давайте сначала отобразим данную сырую величину, хотя бы посмотрим, что в ней есть. За основу мы пока возьмём код из наших часов, функция sprintf на помощь придёт в более поздних занятиях, время её пока не пришло и нам надо вообще понять, как преобразовываются символы. Это нам ой как пригодится в программировании светодиодных индикаторов

Setpos (0,0);

sendcharlcd ( adc_value /1000+0x30);

sendcharlcd (( adc_value %1000)/100+0x30); //Преобразуем число в код числа

sendcharlcd (( adc_value %100)/10+0x30); //Преобразуем число в код числа

sendcharlcd ( adc_value %10+0x30); //Преобразуем число в код числа

Delay_ms (500);

Здесь мы разбиваем по цифрам четырёхзначную величину.

Теперь мы соберём код, прошьём контроллер и посмотрим наши результаты, покрутив резистор на 10 килоом

Вот так вот оно всё и работает.

Теперь давайте ещё на дисплее попробуем отобразить всё в вольтах, чтобы определить, какое у нас всё-таки напряжение на центральном контакте нашего переменного резистора. Для этого создадим переменную плавающего типа

unsigned int adc_value ;

float n ;

Также забудем про существование функции sprintf и попробуем получить плавающий тип на дисплее программным путём. Для этого сначала преобразуем наш сырой результат в плавающий тип явным образом, то есть та же цифра будет, но только тип другой, не забыв, конечно, перед этим поставить курсор в нужное место на дисплее. Для этого существует понятие в языке СИ явного преобразования типов и разделим преобразованный результат на 400

sendcharlcd ( adc_value %10+0x30); //Преобразуем число в код числа

setpos (8,0);

n = ( float ) adc_value / 400;

Тут, конечно, возникает вопрос, а почему мы делим именно на 400. А вот почему.

Это ничто иное как 1024, разделённое на 2,56, то есть на наше опорное напряжение. Видимо, не зря разработчики контроллера выбрали именно такую величину опроного напряжения, чтобы всё делилось без остатка. Почему мы именно такое деление применяем. А потому что у нас есть формула в технической документации

Вот поэтому и мы и вычислили её самую последнюю часть. Осталось теперь лишь только перевернуть ещё наоборот, выразив отсюда входное напряжение, так как неизвестное у нас именно оно. И мы получим, что оно будет у нас равно ADC, делённому на 400, что мы, собственно и сделали выше в коде. Я думаю, всё предельно стало теперь всем понятно.

Осталось самое интересное — отобразить всё это на экран, зная, то.что мы не можем работать с дисплеем с плавающим типом. А оказывается всё просто. Всё решается вот таким кусочком кода

N = ( float ) adc_value / 400;

sendcharlcd (( unsigned char ) n +0x30); //Преобразуем число в код числа

sendcharlcd ("."); //Преобразуем число в код числа

sendcharlcd ((( unsigned char ) ( n *10))%10 +0x30); //Преобразуем число в код числа

sendcharlcd ((( unsigned char ) ( n *100))%10 +0x30); //Преобразуем число в код числа

Delay_ms (500);

Не пугайтесь, сейчас мы всё тут разрулим.

Сначала мы обратным преобразованием типов отсекаем вооще всю дробь и, зная, что дальше 9 мы не уйдём и у нас будет только одна цифра, да мы даже и дальше 2 тут не уйдём, у нас максимум 2,56, мы просто отображаем данную цифру.

Потом мы умножаем наш результат, преобразованный к плавающему типу на 10, тем самым, передвигаем запятую на один разряд в нём вправо и, преобразовав результат вычисления обратно в целочисленный тип, берём из него известным образом младшую цифру и отображаем её на дисплее после запятой.

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

Вот и всё!

Собираем код, прошиваем контроллер и смотрим наши интересные результаты, крутя наш резистор

Post Views: 6 917