Аналого-цифровой преобразователь МК ATmega8

Просмотров: 133433Комментарии: 18
Электроника. СхемотехникаAVR.Начинающим

Давайте попробуем разобраться с АЦП микроконтроллера. Для этого я выбрал ATmega8. Вы можете взять какой нибудь другой и по такой же схеме разобраться с ним. Почитав даташит можно найти разные особенности АЦП у разных МК. Но мы пока не будем вдаваться в подробности, а просто разберемся, куда что записать и откуда что считать. И рассмотрим основные характеристики АЦП МК. 

Итак, в МК ATmega8 имеется встроенный 10-битный АЦП.  Что значит 10-битный? Это значит что входное напряжение от GND до Uвх будет линейно разбито на 210 частей. Минимальный код равен 0, максимальный 210-1 = 1023.  Например, у нас максимальное входное напряжение на входе МК составляет 5В. Значит шаг измерения составляет 5/1023=0.0049, т.е. 4.9мВ. У МК имеется 6 каналов АЦП для корпуса DIP28 (PORTC) и 2 дополнительных канала АЦП для корпуса TQFP и QFN/MLF. Напряжение на одном из входов измеряется относительно опорного напряжения.  Измеренное напряжение преобразуется в 10-битное число и сохраняется в регистрах ADCL и ADCH. Вот нам и встретились первые два регистра АЦП. ADCH – старший байт результата измерения, ADCL – младший байт результата измерения. В МК предусмотрено два режима работы: непрерывное и однократное преобразование. В непрерывном режиме АЦП периодически измеряет входное напряжение и по окончании преобразования записывает результат в регистры ADCL и ADCH. В режиме однократного преобразования мы должны инициировать каждое преобразование самостоятельно.  Мы вкратце рассмотрели основные характеристики ATmega8. Теперь давайте разберем, как же произвести все установки, чтобы АЦП заработал так, как нам нужно.

В МК ATmega8 номер вывода подключенного к входу АЦП задается с помощью регистра ADMUX - регистр мультиплексора АЦП. Давайте посмотрим какие биты за что отвечают в этом регистре. 

Биты 7:6 – REFS1:REFS0. Биты выбора опорного напряжения. Если мы будем менять эти биты во время преобразования, то изменения вступят в силу только после текущего преобразования. В качестве опорного напряжения может быть выбран AVcc (напряжение источника питания), AREF или внутренний 2.56В источник опорного напряжения.
Рассмотрим какие же значения можно записать в эти биты:
REFS1:REFS0 
00    AREF
01    AVcc, с внешним конденсатором на AREF
10    Резерв
11    Внутренний 2.56В  источник, с внешним конденсатором на AREF
Бит 5 – ADLAR. Определяет как результат преобразования запишется в регистры ADCL и ADCH.
ADLAR = 0
ADLAR = 1
Как можно видеть при ADLAR = 0 в ADCH записываются два старших бита (2 MSB), а остальные в ADCL. А при ADLAR = 1 в ADCH записываются 8 старших битов (8 MSB), а два младших (2 LSB) в ADCL. Это удобно, если для точности ваших измерений достаточно 8-ми старших бит преобразования.
Биты 3:0 – MUX3:MUX0 – Биты выбора аналогового канала.
MUX3:0
0000      ADC0
0001      ADC1
0010      ADC2
0011      ADC3
0100      ADC4
0101      ADC5
0110      ADC6
0111      ADC7
Если вы хотите проверить несколько каналов, то можно изменить соответствующие биты в регистре ADMUX и канал сменится сразу же по окончании текущего преобразования. Т.е. в режиме непрерывного преобразования мы можем легко произвести сканирование нужных каналов. Просто меняя номер канала во время преобразования – следующее преобразование начнется на новом канале.

Для большего понимания рассмотрим пример.  У нас источником опорного напряжения является AREF (REFS7:6 - 00). И для данного измерения выбираем 0-й канал (MUX3:MUX0 – 0000). Таким образом записав в ADMUX значение 00000000  мы и получим требуемые настройки.
Остальные установки находятся в регистре ADCSR - регистр контроля и состояния АЦП. В МК ATmega8 он называется ADCSRA.


Бит 7 – ADEN. Разрешение АЦП.
0 – АЦП выключен
1 – АЦП включен
Бит 6 – ADSC. Запуск преобразования (в режиме однократного
преобразования)
0 – преобразование завершено
1 – начать преобразование
Бит 5 – ADFR. Выбор режима работы АЦП
0 – режим однократного преобразования
1 – режим непрерывного преобразования
Бит 4 – ADIF. Флаг прерывания от АЦП. Бит устанавливается, когда преобразование закончено.
Бит 3 – ADIE. Разрешение прерывания от АЦП 
0 – прерывание запрещено
1 – прерывание разрешено
Прерывание от АЦП генерируется (если разрешено) по завершении преобразования.
Биты 2:1 – ADPS2:ADPS0. Тактовая частота АЦП
ADPS2:ADPS0
000         СК/2
001         СК/2
010         СК/4
011         СК/8
100         СК/16
101         СК/32
110         СК/64
111         СК/128

Рассмотрим пример. Частота нашего МК равна 4,096Мгц. Мы хотим выбрать частоту АЦП меньше 200кГц. Этому соответствует СК/32 = 128кГц (ADPS2:ADPS0 - 101). Разрешим прерывания от АЦП (ADIE = 1) и будем работать в режиме однократного  преобразования (ADFR = 0). Само собой ADEN = 1, т.к. только включенный МК будет измерять напряжение на входе. Учитывая все выше сказанное в ADCSRA будет записано следующее значение – 10001101 (0х8D).

Хотелось бы отметить, что для достижения полной 10-битной точности рекомендуется использовать частоты ниже 200кГц. Частоты выше 200кГц можно использовать если точность не важна, а важна скорость. Например, при частоте 1МГц получаем 8-битное разрешение, а при 2МГц – 6-битное.

А теперь в качестве примера приведу функцию инициализации АЦП и функцию, которая будет возвращать измеренное значение на указанном канале. Мне нравится больше писать на Си, поэтому код будет приведен на Си.

//функция инициализации
void ADC_init()
{
//воспользуемся значениями регистров, определенными ранее
         ADMUX = 0x00;
         ADCSRA = 0x8D;
}
//функция получает в качестве аргумента номер канала и
возвращает значение на входе 
unsigned int ADC_result(unsigned char adc_input)
{
         ADMUX=adc_input | (ADMUX & 0xF0);
//задержка для стабилизации входного напряжения
         _delay_us(10);
//начинаем преобразование (ADSC = 1)
         ADCSRA | = 0x40;
         while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
        ADCSRA|=0x10;//устанавливаем ADIF
        return ADCW;//ADCW - содержит ADCH и ADCL как нам нужно
}
ADCW определен в файле МК (например, iom8.h в WINAVR). Посмотрите, ради интереса, как он там определен. Чтобы получить значение в Вольтах (например для вывода на экран) нужно умножить полученное значение на шаг измерения. Для рассмотренных выше 4.9мВ:

Напряжение в Вольтах = 0.0049*ADC_result(номер канала)

Кстати, эти функции одинаково выглядят как в WINAVR, так и в CodeVisionAVR (обозначения регистров совпадают). Только в CodeVisionAVR нужно _delay_us() заменить на delay_us. 
Еще есть режим при котором проц уходит в спящий режим и своими шумами не мешает АЦП, а АЦП работает. По окончании преобразования АЦП генерит прерывание и проц просыпается. Но об этом как-нибудь в другой раз, а то и так уже не каждый дочитает до конца.
Вот собственно и все, что хотел сказать. Сделал описания регистров как в даташите, чтобы приобщающиеся к этому интересному делу сразу привыкали к тому, что их ждетsmile. Если хотите измерять более точно ставьте внешний АЦП, но в любом случае полезная вещь и приятно, что АЦП встроен в микроконтроллер. Вы очень просто можете сделать, например, тот же вольтметр (см. avrproject.ru).
P.S. Всегда смотрите даташит!smile

Комментариев: 18 RSS

1 Алена 30-08-2011 05:16

Спасибо большое, очень помогла информация!!!))

2 Алексей 02-12-2011 05:14

Отличная статья! Все кратко и доходчиво. Неделю со справочником пытался понять как конфигурировать и без толку. А тут сразу все стало на свои места. Спасибо огромное.

3 Віталій 24-01-2012 01:33

ADCSRA|=0x10;//устанавливаем ADIF

Це лишнє. Коли ADIF=1 проскакуєм цикл while((ADCSRA & 0x10)==0);

4 Санек 22-04-2012 17:59

полезная информация

но хотелось бы поподробнее найти про данный мк.

просто в даташите технический английский и не все понятно

5 Михалыч 24-04-2012 21:50

Санек

Прошу прощения, но английский язык даташитов для микроконтроллеров AVR самый простой по стравнению с даташитами других микроконтроллеров. я, в своё время, с нулевыми знаниями за неделю по оригинальным даташитам сворганил нечто работающее, даже с таймерами и прерываниями. Если совсем туго, есть даташит для ATmega128(по инету полно ссылок, ответ я не нашел приравнивается к я не искал). Очень большая часть даташитов на АВР микроконтроллеры идентична, читаем вышеуказанный на русском, а особенности не тяжело понять и на английском языке. Если начинаете очень рекомендую книгу Программирование на языке С для AVR и PIC микроконтроллеров. Шпак Ю.А. Если непонятно даже после прочтения энной, либо Вам просто лень читать и разбираться, либо микроконтроллеры это не Ваше. Я не придираюся, просто не люблю когда задают вопросы и плодят ветки по темам которые в инете разжеваны до безобразия. ATmega8 Atmega16 ATtiny2313 и ещё многие очень популярны, по этому не ленитесь, а читайте и программируйте и разбирёйтесь на раз два три.

6 Константин 04-06-2012 17:57

ADMUX=adc_input | (ADMUX & 0xFF); мм я еще нновичок и может ошибаюсь.. сразу извините..... но по мойму надо переписать это так ADMUX=adc_input | (ADMUX & 0xF0) 0xF0---обнуляет первые 4 бита

7 Dmitry 05-06-2012 22:42

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

10 Вусал 04-10-2012 18:24

Здравствуйте, очень хотелось бы знать, можно ли на той же атмеге8 организовать несколько АЦП, хотя бы программно? Если нет, какие вы видите решения данной проблемы?

11 Dmitry 05-10-2012 00:00

в mega8 можно использовать минимум 6 каналов АЦП.

13 Mick 18-06-2013 20:00

Привет. Не могли бы объяснить следующее: верно ли, что:

AVCC - подаём Uпитания, такое же, как на VCC? Внутренний источник питания - схема, которая питается от ноги VCC и даёт 2.56В внутри самого контроллера. И вопрос, что подавать на AREF и что это вообще за нога?

14 Антон 04-11-2013 05:09

Читайте внимательно даташит, вы никогда не заставите работать АЦП меги8 на 1Мгц а на 2Мгц тем более... внимательно перечитайте даташит про тактирование и время преобразование!

15 GiG 31-03-2014 15:06

Небольшая опечатка. "Биты 2:1 – ADPS2:ADPS0" Должно быть Биты 2:0

16 Иван 08-06-2014 22:20

А почему нет примера ??? почему не описали пример ??

17 Александр 14-12-2015 12:28

При использовании АЦП, например на порту 1, то настраивать порт на вход без подтягивающего резистора?

18 Александр 01-02-2016 17:30

Есть вопросы. Делаю подсветку приборки в авто на Меге8. Задействован канал АЦП по которому будет ШИМом регулироваться яркость. АЦП будет брать напряжение с реостата. Т.е. покрутил ручкой, яркость убавилась. Вопросы такие. Я использую 8-бит. АЦП, 125КГц. АЦП настроен опорное напряжение на AVCC. На AREF нужно конденсатор вешать? и какой номинал? От VCC на AVCC можно просто дорожку кинуть или лучше через какой то фильтр?

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Вы можете войти под своим логином или зарегистрироваться на сайте.

(обязательно)