AVR. Учебный курс. Использование АЦПPrint This Post

Автор DI HALT
Опубликовано 20 Ноя 2008 
Рубрики: AVR. Учебный курс
Метки: ,

Многие 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.

Выбор режима запуска преобразования
В регистре SFIOR под АЦП отведено аж три бита. ADT2..0 которые управляют режимами запуска АЦП.

Скорость работы АЦП
Частота выборки АЦП задается в битах предделителя ADPS2…0 регистра ADCSR. Саму таблицу можно поглядеть в даташите на соответствующий МК, скажу лишь то, что самая оптимальная точность работы модуля АЦП находится в пределах 50…200кГц, поэтому предделитель стоит настраивать исходя из этих соображений. С повышением частоты точность падает.

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

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

[x][x][x][x][x][x][9][8]:[7][6][5][4][3][2][1][0] или [9][8][7][6][5][4][3][2]:[1][0][x][x][x][x][x][x]

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

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

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

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

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<<ADEN)|(1<<ADIE)|(1<<ADSC)|(1<<ADATE)|(3<<ADPS0)
	; Итак что тут у нас:
	; ADEN = 1 - разрешаем АЦП
	; ADIE = 1Разрешаем прерывания. 
	; ADSC = 1 Запускаем преобразование (первое, дальше автоматом)
	; ADATE = 1 Непрерывные последовательные преобразования, одно за другим.
	; ADPS2..0 = 3 Делитель частоты на 8 - так у меня получается оптимальная частота. 
 
	OUTI	ADMUX,0b01000101
	;А тут выбираем откуда брать будем сигнал
	;REFS -- 0b[01]000101 первые два бита - напряжение с входа AVCC
	;ADLAR --0b01[0]00101следующий бит выравнивание по правому краю
	;MUX -- 0b010[00101]</B>Сигнал на вход идет с 5й ноги.

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
; ADC Init - Инициализурем АЦП. Это можно сунуть куда - нибудь в начало кода
 
	OUTI	ADMUX,0b01000101
	;А тут выбираем откуда брать будем сигнал
	;REFS -- 0b[01]000101 первые два бита - напряжение с входа AVCC
	;ADLAR --0b01[0]00101следующий бит выравнивание по правому краю
	;MUX -- 0b010[00101]</B>Сигнал на вход идет с 5й ноги.
 
	OUTI	MCUCR,0b10010000
	; Выставил биты спящего режима в Noise Reduction
 
 
; А это уже тело главной программы
Main Prog:
	OUTI	ADCSRA,(1<<ADEN)|(1<<ADIE)|(1<<ADSC)|(0<<ADATE)|(3<<ADPS0)
	; Подготовили АЦП
	SLEEP		; Свалились в спячку, как только Хрюша со Степашей скажут нам 
			; Баю-бай так врубится молотилка АЦП, затем придет Фреди Крюг...
			; в смысле запрос на прерывание и проц резко проснется

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

Комментарии

120 комментариев на «AVR. Учебный курс. Использование АЦП»


  1. _riko_ 20 Ноя 2008 8:29

    На сколько я понял, АЦП - это цифровой вариант аналогового компаратора? Ведь по существу и внешнее опорное напряжение они снимают с одной ножки . Только компаратор оперирует с сравнением чистого напряжения, а АЦП - с его 8-и битным аналогом… Я правильно понял? И какие еще могут быть примеры применения АЦП ?

    nwanomaly__

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

    SWG

    АЦП - это аналог не компаратора, а цифрового вольтметра со шкалой 0-1023. Если опору взять 1,024v, цена деления будет 1mV.
    Погрешность определяется погрешностью опоры и шумами, плюс +-1 младшего разряда. Например, в специальном малошумящем режиме, когда на время измерения большинство цифровой начинки на время измерения переводится в спящий режим, у PIC гарантируется погрешность преобразования +_1 последнего разряда по всей шкале. В переводе на привычный язык - это точность 0,1% !
    Вы когда-нибудь видели аналоговый прибор такой точности? Даже в 8-битном режиме (0-255) точность получается 0,4% ! Аналоговые приборы 0,5 процента имели зеркальные шкалы, нехилые размеры, и использовались как образцовые, для поверки менее точных. Большинство же тестеров имеет погрешность 1 - 2,5% и более, в зависимости от вида измерений. Для точных преобразователей есть много очень стабильных микросхем - источников опорного напряжения от 1,024 до 10в. Самый простой и дешевый - TL431, регулируется от 1,2v до питающего.

    DI HALT

    Да, тока осталось сделать точный ИОН с погрешностью менее 0.1%

    SWG

    Нет проблем. Вот, навскидку, из тех, что я просматривал пару лет назад и легко найти в продаже:
    Mикросхемы опорного напряжения:
    Тип UA допуск ($)
    ICL8069 1.2 +-0.01% 3,63
    LH0070 10.000 -+0.02% 18,15
    LM336 2.5 +-1% 3.08 ц 154-212T
    LM336 5 +-1% 3.08
    LM9140BYZ 2.5 +-0.5% 8.48
    LM9140BYZ 5 +-0.5% 8.48
    LT1021DCN 5 +-0.05% 12.37
    LT1431CZ 5 +-1% 5.48
    TL431C 2.5-36 30ppm/C 1.51 ц 23-38T
    REF02CN8 5 +-0.3% 9.14
    ZN404 2.45 +-3% 2.16

    Есть куча других, просто эта шпаргалка оказалась под руками.

    DI HALT

    А еще есть TLE2426 - клевый распополамиватель напряжения. Хорошо подходит для создания виртуальных нулей в однополярных схемах.

    emelja

    не обязательно иметь точный ИОН. главное, что бы он был стабилен. тогда готовое устройство можно откалибровать (подстроичными элементами или программно)по внешнему образцовому прибору.

    п.с. чуть выше SWG путает разрешающую способность и точность. вернее не делает разницы между ними

    SWG

    Если производителем гарантирована точность +-1 единица младшего разряда, то разницы между разрешающей способностью и точностью действительно нет. Главное - не потерять ее, а это уже зависит и от ИОН, и от монтажа, и от допуска и стабильности резисторов делителя, и т.д.
    В своем ходовом контроллере я и использовал как раз тот факт, что хотя у интегральных стабилизаторов разброс напряжения стабилизации несколько процентов, в то же время при постоянной и неполной нагрузке, при входном напряжении намного больше выходного, (10,5-14,2v/5v), и небольшом интервале температур (работа в помещении) стабильность выходного напряжения стабилизатора вполне достаточна для моей задачи контроля состояния аккумулятора, а отклонение от 5v легко компенсируется подстройкой входного делителя.
    10, а не 8 бит результата преобразования я использовал тоже не для получения высокой точности, а чтобы не потерять ее в процессе пересчета и округления. Всегда предпочитаю иметь несколько лишних разрядов, которые в конце можно отбросить, тем более что в процессе пересчета диапазон значений всегда укладывается в пределы двух байт (WORD). Конечное максимально допустимое значение (0-149) - укладывается уже в один байт, так и хранится и пересылается.


  2. _riko_ 20 Ноя 2008 12:57

    Точно!! =) А ведь так оно и есть! … и как я сразу то не выехал

    Респект SWG за идеально разжеванный ответ! ))


  3. YurkaM 20 Ноя 2008 22:18

    А ещё для повышения точности и уменьшения шума, возможно будет полезным не подключать никакие нагрузки на остальные ножки порта. Т.е. если меряем на входе ADC0, то остальные выводы (PA1…PA7) - только на ввод, кнопки там, датчики.. но не светодиоды!

    nwanomaly__

    читал книжку по аврам.
    про ацп там одна из последних глав. запомнилось, что кроме программных штучек для повышения точности и необходимой обвязки (вроде LC и прочего) требуется и разводка специальная. вроде разделения аналоговой и цифровой земли, “толстые” дорожки и прочее… вот про это хотелось бы поподробнее, т.к. там одни слова и функциональные схемы.
    как это живьём выглядит, хотя бы в лайоуте?

    SWG

    Все довольно просто. Быстро привыкаешь, потом уже это сидит в подсознании.
    Гляньте, например, плату моего ходового контроллера. Там у меня есть и силовые цепи от 2х движков с ШИМ, и задействован АЦП в 10 битном режиме для контроля напряжения аккумулятора. Дорожки короткие, достаточно широкие, шины земли и питания имеют большую площадь, движки включены на выход L293 через индуктивно-емкостные фильтры, пути протекания токов двигателей проходят далеко от малосигнальных цепей. Напряжение батареи поступает на вход АЦП через делитель 1:3, что дает макс. входное напряжение 5в при напряжении на батарее 15в. Реально оно не превысит 14,5в даже в режиме заряда, так что измерение проводится в пределах последней трети шкалы. Слишком большая точность мне не нужна, поэтому я в качестве опорного напряжения использовал напряжение питания. Нагрузка стабилизатора около 30мА и практически не меняется, стабильность его достаточно хороша, а разброс напряжения стабилизации легко компенсируется подстройкой входного делителя. Измеренное значение программно умножаю на 15, прибавляю 50 (для округления) и делю целочисленно на 100. В результате получаю, например, 127 при 12,7V на батарее. Для калибровки достаточно подключить достаточно точный цифровой вольтметр к батарее и отрегулировать делитель так, чтобы выдаваемые значения напряжения соответствовали показаниям образцового прибора. Достаточно выставить в 1 точке, линейность преобразования достаточно высока. Только и делов. Программа на Паскале - всего несколько строчек. Работает уже пару месяцев, показания достаточно точны и стабильны. По RS232 результат измерения поступает в комп, где и отображается на виртуальном отладочном пульте.

    dima_m

    Так а где плату то глянуть? Я бы с удовольствием глянул как грамотно развести аналоговую и цифровую землю. Судя по твоим комментариям в разных статьях у тебя опыту вагон и маленькая тележка.

    dima_m

    Сори, случайно только что наткнулся на плату то на сайте. Профессионально сделана ничего не скажешь.

    DI HALT

    Какую именно плату? Я далеко не везде делал аналоговую землю. Обычно я на точность АЦП редко заморачиваюсь.

    dima_m

    Это я про плату которую SWG для робота сделал. Которую он выше описывает.
    “Робот на контроллере PIC от swg”, сказать честно я в легком шоке. Профессионализм SWG реально впечатляет. Да человек со временем может много чего достичь в области которой он занимается постоянно.


  4. zyxman 23 Ноя 2008 2:40

    Привет!
    Спасибо за интересную статью!
    Вот фраза: “Как я уже говорил, в младших разрядах все равно мусор и шумы (по крайней мере я от них так и не смог избавиться, как ни старался)” - а пробовал делать усреднение по множеству отсчетов?

    DI HALT

    Делал усреднение по 256. Както не особо заметен результат был :/ Возможно, конешн, сторонняя наводка, но провод до самого АЦП идет экранированным кабелем тупо с резистора, задающего напряжение.

    emelja

    не знаю как (я не программер) но коллеги из aduc814 (если не ошибаюсь там 12-разрядный АЦП последовательного приближения) программно выжимали разрешение 1/20000. я с помощью аналогового калибратора (В1-12) проводил испытания их разработки и при 2В на входе, приращение в 0,1 мВ отслеживалось великолепно.

    zyxman

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

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


  5. webkirov2 23 Ноя 2008 8:03

    Не знал куда написать, поэтому написал сюда.
    Есть ли на сайте описание, как программно реализовать на МК что-то вроде дешифратора на микросхеме серии ИД. Вообщем, проще говоря, как к микроконтроллеру подключить семисегментный индикатор, и желательно не один, а, к примеру, 3 индикатора (три цифры)?

    DI HALT

    А что так сложно? ;) Берешь и пишешь!

    Самый простой способ это сделать в памяти таблицу. В ячейке с смещением 0 - 7-код нуля, в ячейке с смещением 1 7-код 1 и так далее.

    После, делаешь Bin2Dec конверсию и по таблице (косвенной адресацией по смещению) переводишь ее в 7сег код и уже гонишь в порт.


  6. pfa230.livejournal.com 23 Ноя 2008 8:38

    Экспериментирую с АЦП в ATMega8. Проблема в том, что порт имеет сопротивление порядка 20 Ом, соответственно, ток через него доходит до 80мА. Cконфигурирован как высокоимпедансный вход (если это имеет значение). Не сгорел, ибо меряет. Куда копать?

    DI HALT

    Не должно так быть. Раз Hi-Z конфигурация, значит сопротивление его должно быть высоко и ни о каких 20 омах не должно быть и речи. Может пробило?

    Попробуй пропустить сигнал через повторитель на ОУ (подать сигнал на +вход ОУ, а на -вход подать напрямую с выхода, без всяких резисторов).

    pfa230.livejournal.com

    Сомневаюсь, что могло пробить - выше 5 вольт в схеме взяться просто неоткуда. Попробую на другую ногу АЦП повесить.
    Может, я что-то не так понимаю, но ведь у ОУ достаточно большое внутреннее сопротивление - соответственно, падение на этих 20 омах будет около 0, разве нет?

    DI HALT

    Наводка или статика.

    Входное сопротивление ОУ можно считать бесконечным, следовательно, минимальные воздействия измерительной цепи на источник напряжения. Выходной же каскад ОУ довольно мощный и возможно таки прокачает тебе этот 20омный вход. Но, повторюсь, 20ом это слишком мало! Что то не так.

    Собственно у МК в режиме высокого импенданса сопротивление тоже в гигаомы.

    pfa230.livejournal.com

    С грустью признаю, что я осел.
    Перепутал порты. Не обратил внимания, как мой порт АЦП был сконфигурирован, но сильно подозреваю, что как вывод. Теперь все работает.


  7. testicq 04 Фев 2009 16:14

    Чет не понял я - внутренний ИОН на 1,22 или 2,56 вольта? а то в статье и так и так написано.

    DI HALT

    на 1.22 вольта это ИОН от аналогово компаратора. Его можно просто подать на вход. Его нельзя юзать в качестве референса. А 2.56 это ИОН от ацп. Его можно подать только на референс, но нельзя завернуть на вход.

    testicq

    не понял - как это? можно подать на вход, но нельзя юзать как референс.
    если мы подадим на один из входов компаратора, то он и будет референсным (опорным напряжением). может я чето не понимаю?

    DI HALT

    ИОН который служит референсом для компаратора может быть входным сигналом для АЦП (например в тестовых целях), но не может быть опорным сигналом для АЦП. Равно как и наоборот. АЦП и компаратор это два разных блока. Погляди на структуру в даташите.

    testicq

    да, я смотрел - это 2 разных блока. а я спрашивал про компаратор и его же ИОН. теперь я понял о чем речь


  8. meshugger 04 Фев 2009 22:31

    Использую ATMega16.
    Застрял на этапе использования АЦП в режиме с дифференциальными входами. Выставляю ADLAR = 1, т.о. выравниваниие по левому краю. Подаю результат в PortB, в итоге на 3м МК вместо 8-разрядного получается 7-разрядное число. Никак не могу разобраться в чем тут дело. Думал связано с использованием 2 входов, т.е. в целом в ADC-Data-Register вместо 10 хранится 9 разрядное число. Пытался считывать 7 гипотетических старших битов склеивать со старшим из младших - ничего хорошего не вышло: даже даташитовское “When ADCL is read, the ADC Data Register is not updated until ADCH is read.” не помогло, число в ADC-Data-Register перестало изменяться.
    В даташите нарыл следующее: If differential channels are used, the result is presented in two’s complement form - после чего запутался еще больше (7-битное число хоть и было 7-битным, но с увеличением разности напряжения на PA0 и PA1 росло, после применения neg к результату в ADCH стало уменьшатся).
    128 бит мне будет маловато…
    растолкуйте пожалуйста что к чему…


  9. Flint 08 Фев 2009 14:58

    Насколько я понял из даташита - для режима сна при АЦП нужно не только установить биты: OUTI MCUCR,0b00010000 (SM2 SM1 SM0 == 001), но и бит SE тоже должен быть уже установлен. Вот даже перевод с gaw.ru про Atmega128 (про другие мк наверняка также): “Для перевода микроконтроллера в один из шести режимов сна необходимо предварительно установить бит SE в регистре MCUCR, а затем выполнить инструкцию SLEEP. Биты SM2, SM1 и SM0 регистра MCUCR задают в какой именно режим будет переведен микроконтроллер”. А в выше приведенном примере этого вроде нет

    DI HALT

    Да, конечно же. SE не даст процессору уснуть. Забыл про этот бит совсем :) Исправил. Кстати, рекомендуется его устанавливать непосредственно перед командой sleep во избежание. =)

    www.google.comprofilesevgen.ru79

    ошибка.в OUTI MCUCR,0b10010000
    надо: OUTI MCUCR,0b01010000

    т.к. SE бит - 6, а не 7. кривовато сделали нумерацию в amtel….


  10. Vadim 15 Фев 2009 18:14

    Если установлен бит непрерывного преобразования,оно не прекращается
    даже на время обработки прерывания?

    DI HALT

    Да именно так. АЦП это же независимый от ядра блок.


  11. Vadim 15 Фев 2009 19:40

    Я вот тут вольтметр пробую сделать.
    Использовал усреднение описанное в примере,
    все получилось,показания на дисплее меняются 0-1023.
    Но это я задействовал один вход ацп,а как поступить если надо
    снять показания со второго канала?

    DI HALT

    ОЧевидно же. Заказал разовое преобразование. Получил результат. Сменил номер ацп в MUX регистре, заказал еще одно преобразование. Получил второй результат.


  12. and 22 марта 2009 17:28

    Здравствуйте.
    Гонял АЦП на MEga8. Данные из АЦП читал с выравниванием по левому краю (т.е. 8 старших из десяти, соответственно бит ADLAR=1) но почему то последний бит тоже скакал на +-1 Получается, что погрешность преобразования АЦП не +-2 бита а +-3 бита, это нормально или нет?

    DI HALT

    А ты все требования по экранированию сигнальных линий, фильтрации питания, разведению аналоговой и цифровых земель выполнил? ;)))))

    and

    Не просто на макетной платке проводками прицепился :)

    DI HALT

    Ну вот. Позырь последний пост про наводки, где лампочки сами зажигались. Увидишь какое дерьмо летает в эфире. Так что 3 МЗР это еще ОЧЕНЬ круто. У меня в таких условиях плясало 5-6 разрядов.

    and

    ок спасибо!


  13. shooroop 31 марта 2009 5:52

    Отличная статья. Вообще отличный портал. Можно почерпнуть много информации как теоретической, так и практической. Спасибо большое!
    Только вот маленький вопросик возник, может кто вразумит:
    “…неплохой инструмент для контроля напряжения…выдающее частоту дискретизации до 15кГц (15 тысяч выборок в секунду)…” и “…Частота выборки АЦП задается в битах предделителя ADPS2…0…находится в пределах 50…200кГц…”. Как это? Или 15 кГц это при использовании всех входных каналов АЦП по очереди, т.е. на каждый канал 15 кГц частота дискретизации, а если используется один канал то можно уже задать конкретную частоту? Правильно я понимаю?

    DI HALT

    Нет частота дается на один канал. Просто делится частота системного кварца. А коэффициент деления задается в битах адпс2,,0

    shooroop

    так и все-таки. в мануале к мега8 написано что частота выборок АЦП до 15 кГц, а вручную можно установить 200 кгц. как это понимать? что имеется ввиду?

    DI HALT

    При выборке до 15кГц, как я понимаю, гарантируется точность 2МЗР, но никто не запрещает тебе разогнать ацп до предела, поставив соответствующий делитель частоты.


  14. Flint 31 марта 2009 21:21

    50…200кГц - это частота работы самого блока АЦП, по аналогии с 8-мью или, например, 16-тью мегагерцами тактовой частоты самого ядра процессора. 15 кГц - это количество 10-ти битных результатов с указанной в даташите точностью. Т.е. получается в секунду подобных результатов можно получить 15000 штук. Можно получить больше при той же частоте работы блока АЦП, но результат будет менее точным, 8 бит, а то и 6.
    Кстати, я тут эксперимент провел на Меге48. При Ref в 2,8В я установил напряжение на аналоговом входе такое, что результат при 10-ти битном режиме получился равен 9-ти. И через УАРТ его на комп для наблюдения. Так вот я не заметил флуктуаций этого значения около этого результата. Все время шло 9, а ведь напряжение в вольтах получается то маленьким (кондюк на вход АЦП специально не ставил). Хотя то что я там наваял с УАРТ’ом мне не очень нравится - какие-то повторы цифр идут (скорости согласованы), и еще наверное не очень быстро как мне хотелось оно выдавало на комп результаты. Из-за этих повторов ставил delay, чтоб как-то заставить более или менее работало. Может что с буфером там получалось… Надо бы получше сделать, а то все это на скорую руку делал.

    dima_m

    Если у меня тактовая частота МК = 4000000 Гц, то как правильно выбрать коэффициент предделителя блока АЦП битами ADPS2…0? Учитывая что нужно уложиться в оптимальную частоту преобразования от 50 до 200 кГц. Из даташита коэффициенты только такие 2,4,8,16,32,64,128. Делим 4000000 Гц на 2 = 2000 кГц, многовато. Делим на 4 = 1000кГц опять много. Делим на 16 = 250кГц, много. Делим на 32 = 125 кГц, подходит. На 64 = 62.5Кгц тоже подходит. Делим на 128 = 31.24 кГц уже мало. Получается при частоте кварца 4МГц подходят только два результата битов ADPS2…0, это 101 и 110. Так что ли? А это число 15000 выборок в секунду, от чего оно зависит? Как его можно регулировать? Делать быстрее медленнее. С помощью кода в AVR?

    dima_m

    Ага, понял чем выше частота ядра АЦП тем больше и выборка.


  15. Ridik911 06 Апр 2009 14:35

    15 кГц - это количество 10-ти битных результатов с указанной в даташите точностью.
    ——–
    тогда невижу смысла в 50…200кГц если невозможно коректно увидеть импульс скажим с частотой в 30КГц в 10 разрядности (соглашусь что 8 хватит но никак не ниже)
    или я непонял чтото..
    тоесть мы можем использовать даже 200кГц но разрядность будет очень малым (на вскидку 4).
    почему так происходит - непонимаю я… откуда такая зависимость зачем она..

    Ridik911

    я уже мечтал что максимальная частота от кварца на 16МГц получится 16МГц/10бит=1.6ЬГц (ну округлим некоторыми возможностями = 1МГц) - тоесть хотел сделать осцилограф на этом для прослушки ультразвука (импульсные источники сигнала не только 20к-200к но и более - ШИМ импульсы например которые и повыше 300к встречаются) и сверх того до 1МГц.. АнНет

    DI HALT

    Разрядность будет те же 10 бит, только в младших битах будет мусор.

    А ты думал чего цифровые осциллографы такие дорогие? ;)))) Там зверские высокоскоростные АЦП стоят. Которые составляют 95% стоимости.

    Ridik911

    да.. а я еще к томуже глаз положил на атини13 (35 рублей).. мдя наивный я


  16. Flint 12 Апр 2009 14:36

    Ridik911, представь себе звукою плату в компе. Ты записываешь звук через линейный вход ее. Если в настройках записывающей программы ты указываешь писать с частотой дискретизации 44100Гц, 16бит, моно (это для простоты объяснения), то ты получишь звуковую дорожку, где каждый отсчет (выборка) размером 16бит следует через каждые 1/44100 сек. При этом спектр входгого сигнала перед этим обрежется до частоты 22000Гц приблизительно, а на самом деле чуть пониже (это сделано для получения правильного преобразования) Так и здесь, достаточно точные 10бит ты получишь только неспеша, то есть если будешь получать только 15 тыс выборок в секунду. Ими можно и звук оцифровать, но верхняя частота на входе АЦП должна быть не больше 15000/2 Гц И это в лучшем случае


  17. SATS 17 Апр 2009 0:06

    Уважаемый,DI HALT,у меня возникла проблема.мучаюсь над ней уже месяц.
    Задача такая: моя мега8535 в цикле опрашивает 10 дискретных датчиков и один аналоговый, из этого всего лепит 11 пассылок (10 для дискр и 1 для аналогов)и пересылает их ПК. У меня же все работает только по отдельности (когда опрашиваються отдельно дискр. и отдельно аналог. датчики). Стоит только подключить АЦП ко всему этому, все начинает бочить((((. Думаю что проблема в АЦП. Пробовал два режима работы АЦП. В одиночном режиме - все работает, а аналоговые велечины не опашиваются. В циклическом режиме- АЦП рабтает,но блакирует работу всех дискретных портов.

    DI HALT

    Телепаты в отпуске, но могу предположить, что прерывание АЦП срывает стек. Причем, в постоянке это делает, вызывая перезапуск МК.

    Покажи код.

    SATS

    А если прерывания от АЦП заглушены?
    Вот то , что у меня запраграммированно в регистре ADCSRA: (1<<ADEN)|(0<<ADIE)|(1<<ADSC)|(1<<ADFR)|(3<<ADPS0) . Может тут что -то ни так?
    Вопрос. Может мне стоит перед пересылкой по Уарту останавливать работу Ацп?

    SATS

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    
    .include "m8535def.inc"
    .list
    .def INIT1=R16
    .def INIT2=R17
    .def TEMP=R18
    .DEF PEREM=R19
    .def DANNOE=R21
    .def A=R22
    .def B=R23
    .def C=R24
    .def D=R26
     
    .CSEG
    .ORG 	0x0000						; Проц стартует с нуля, но дальше идут вектора 
    RJMP 	Reset						; прерываний, поэтому отсяюда сразу же прыгаем 
    									; на начало программы. На метку Reset
     
     
     
    .org	INT0addr	; External Interrupt 0
    reti
    .org	INT1addr	; External Interrupt 1
    reti
    .org	OC2addr		; Timer/Counter2 Compare Match
    reti
    .org	OVF2addr	; Timer/Counter2 Overflow
    reti
    .org	ICP1addr	; Timer/Counter1 Capture Event
    reti
    .org	OC1Aaddr	; Timer/Counter1 Compare Match A
    reti
    .org	OC1Baddr	; Timer/Counter1 Compare Match B
    reti
    .org	OVF1addr	; Timer/Counter1 Overflow
    reti
    .org	OVF0addr	; Timer/Counter0 Overflow
    reti
    .org	SPIaddr		; SPI Serial Transfer Complete
    reti
    .org	URXCaddr	; USART, RX Complete
    ;RJMP	UART_RX
    reti
    .org	UDREaddr	; USART Data Register Empty
    reti
    .org	UTXCaddr	; USART, TX Complete
    ;RJMP	UART_TX
    reti
    .org	ADCCaddr	; ADC Conversion Complete
    ;RJMP	ADC_OK
    reti
    .org	ERDYaddr	; EEPROM Ready
    reti
    .org	ACIaddr		; Analog Comparator
    reti
    .org	TWIaddr		; Two-wire Serial Interface
    reti
    .org	INT2addr	; External Interrupt Request 2
    reti
    .org	OC0addr		; TimerCounter0 Compare Match
    reti
    .org	SPMRaddr	; Store Program Memory Read
    reti
    .org	INT_VECTORS_SIZE	; size in words
    reti
     
    ;============================== НАЧАЛА ИНИЦИАЛИЗАЦИИ ПЕРЕФЕРИИ ===================================================
     
    Reset:	
    		lds temp,high(RAMEND)
    		out SPH,temp
    		lds temp,low(RAMEND)
    		out SPL,temp		
     
    		ldi INIT2,0b01100011 	;иннициализация АЦП
    		out	ADMUX,INIT2
    		ldi R20,(1<<ADEN)|(0<<ADIE)|(1<<ADSC)|(1<<ADFR)|(3<<ADPS0);разрешение АЦП частота дескретизации 125кГц
    		out	ADCSRA,R20	; Запуск непрерывного преобразования (бит ADFR)
     
     
    USART_Init:                	   		;начинаем инициализировать USART
    		ldi init1,0x67				;эта скорость передачи кода 9600бод (ошибка пефредачи 0,2%) при 16 МГц кварца 
    		ldi init2,0					
             							;Установка скорости передачи
    		out UBRRL,init1			
    		out UBRRH,init2
    									;Включения приемника и передатчика
    		ldi init1,(1<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<TXCIE)	;Разрешение приема и передачи, запрет прерываний
    		out UCSRB,init1
    									;Установка формата кадра: 8 бит данных, 1 стоповых бита
     		ldi init1,(1<<URSEL)|(0<<USBS)|(1<<UCSZ0)|(1<<UCSZ1)
    		out UCSRC,init1             ;Пасылка кадра данных длиной 5-8 бит
    		ldi B,0b00000001			; константа для идентификации состояния тумблера
    		ldi C,0b00000000			;---|----|----|----|---|---
     
    ; Иннициализация портов на вход	
    		LDI perem,0x00
    		;OUT DDRA,perem	
    		OUT DDRD,perem
    		OUT DDRB,perem
    		OUT DDC0,perem
    		OUT DDC1,perem
    		OUT DDC2,perem
    		OUT DDC3,perem
    		OUT DDC4,perem
    		OUT DDC5,perem
    		OUT DDC6,perem
    		OUT DDC7,perem
     
    ;======================ВЫЧИСЛЕНИЯ КОДОВ ИЗ ОРГАНОВ УПРАВЛЕНИЯ КОНТРОЛЛЕРА МАШИНИСТА=======================
     
    	;1 пасылка. начинаем вычислять код позиции     
    M:		IN  A,PIND						;переменные в регистре порта А хронятся только в
    		 								;в 6 старших битах, два младших задействованы под RS-232
    		 								;опрос порта А					
    USART_Transmit_Position:		
    		sbis UCSRA,UDRE					;Ожидание, пока буфер передачи очистися
    		rjmp USART_Transmit_Position
    		out  UDR,A						;Начинается передача кода позиции
     
       	;2 пасылка. начинаем вычислять код реверса
     
    		IN A,PINB						;2 бит отданны под  реверс,остальные под програмирование процессора
     
    USART_Transmit_Revers:		
    		sbis UCSRA,UDRE					;Ожидание, пока буфер передачи очистися
    		rjmp USART_Transmit_Revers
    		out UDR,A						;Начинается передача кода реверса
     
       	;3 пасылка. начинаем вычислять код состояния 1 тумблера
     
    USART_Transmit_Tumb1:	
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb1
    		SBIC PINC,0
    		RJMP TUMB1 
    		OUT  UDR,C
     
       	;4 пасылка. начинаем вычислять код состояния 2 тумблера
    M1:						
    USART_Transmit_Tumb2:
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb2
    		SBIC PINC,1
    		rjmp TUMB2
    		OUT UDR,C
     
    	;5 пасылка. начинаем вычислять код состояния 3 тумблера
    M2:						
    USART_Transmit_Tumb3:
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb3
    		SBIC PINC,2
    		rjmp TUMB3
    		OUT UDR,C	
     
    	;6 пасылка. начинаем вычислять код состояния 6 тумблера
    M3:						
    USART_Transmit_Tumb4:
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb4
    		SBIC PINC,3
    		rjmp TUMB4
    		OUT UDR,C	
     
    	;7 пасылка. начинаем вычислять код состояния 7 тумблера
    M4:						
    USART_Transmit_Tumb5:
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb5
    		SBIC PINC,4
    		rjmp TUMB5
    		OUT UDR,C
    	;8 пасылка. начинаем вычислять код состояния 8 тумблера
    M5:						
    USART_Transmit_Tumb6:
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb6
    		SBIC PINC,5
    		rjmp TUMB6
    		OUT UDR,C
     
    	;9 пасылка. начинаем вычислять код состояния 9 тумблера
    M6:						
    USART_Transmit_Tumb7:
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb7
    		SBIC PINC,6
    		rjmp TUMB7
    		OUT UDR,C
     
    	;10 пасылка. начинаем вычислять код состояния 10 тумблера
    M7:						
    USART_Transmit_Tumb8:
    		sbis UCSRA,UDRE
    		rjmp USART_Transmit_Tumb8
    		SBIC PINC,7
    		rjmp TUMB8
    		OUT  UDR,C
     
    ;11 пасылка. начинаем вычислять код состояния давления в магистрале
    ADC_start:	
    		sbis UCSRA,UDRE				;Ожидание, пока буфер передачи очистися
    		rjmp ADC_start
    		IN D,ADCH
    		OUT UDR,D					;передача кода с датчика давления
    RJMP M								;окончание цикла, перехд на его начало
     
    TUMB1:	OUT UDR,B
    		RJMP M1
    TUMB2:	OUT UDR,B
    		RJMP M2
    TUMB3:	OUT UDR,B
    		RJMP M3
    TUMB4:	OUT UDR,B
    		RJMP M4
    TUMB5:	OUT UDR,B
    		RJMP M5
    TUMB6:	OUT UDR,B
    		RJMP M6
    TUMB7:	OUT UDR,B
    		RJMP M7
    TUMB8:	OUT UDR,B
    		RJMP ADC_start
    RJMP M
    DI HALT

    В глаза ничего криминального не бросается. Код топорный но явных затыков нет.

    Хм. Возможно дело у тебя не в АЦП. Т.к. она тут не связана ваще. Трассировать пробовал? Прогони ее в трассировке позырь где у тебя затыки.

    DI HALT

    Единственно что я тебе советую:

    Включи прерывания АЦП. И Данные с АЦП бери в прерывании и там вкладывай в какую нибудь переменную. Только внимательней. Следи чтобы эта переменная нигде не юзалась больше. А в процедуре ADC_start спокойно бери значение из этой переменной. Так правильней.


  18. SATS 17 Апр 2009 1:50

    Трассировка это в смысле график с АЦП рисует? Эта та прога - Терминал, что ты приводил? То ее я пробовал. Отдельно АЦП на ней рисует безупречный график. А когда зашит вот этот код, выходит полная ерунда.

    DI HALT

    Нет, запустить в AVR Studio эмуляцию выполнения и пошагово выполнить всю программу, увидишь где у тебя что отсылается и где у тебя какой затык.


  19. SATS 17 Апр 2009 2:10

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

    DI HALT

    Это странно. У тебя там единственное место где программа затыкается - ожидание уарта. И при чем тут ваще АЦП? Попробуй вместо показания АЦП просто слать в уарт произвольный байт. Эксперементируй в общем.


  20. SATS 17 Апр 2009 2:46

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

    DI HALT

    Не, ты не убирай тот кусок. Оставь условия как есть. Закомментируй только строку с копированием данных из регистра АЦП. И вставь туда чо нибудь другое из той же оперы, Скажем IN из порта какого нибудь. Будет работать?

    SATS

    Сегодня разбрался метдом тыка с этим. Кроче из проги убрал инициализацию порта С на ввод побитово
    (то есть OUT DDC0,perem
    OUT DDC1,perem
    OUT DDC2,perem
    OUT DDC3,perem
    OUT DDC4,perem
    OUT DDC5,perem
    OUT DDC6,perem
    OUT DDC7,perem) и все зарабтало.Просто заменил на OUT DDRC,perem. Теперь не могу понять, как же оно все таки не давало нрмально рабтать?

    DI HALT

    Потому что

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    		OUT DDRD,perem
    		OUT DDRB,perem
    		OUT DDC0,perem
    		OUT DDC1,perem
    		OUT DDC2,perem
    		OUT DDC3,perem
    		OUT DDC4,perem
    		OUT DDC5,perem
    		OUT DDC6,perem
    		OUT DDC7,perem

    Какая то невьебенная хуета. Как я ее проглядел при первом просмотре :/. Сам посуди, ты пытается в БИТ засунуть БАЙТ!

    А теперь смотри как это выглядело если развернуть все макроопределения:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    		OUT DDRD,R16
    		OUT DDRB,R16
    		OUT 0x00,R16
    		OUT 0x01,R16
    		OUT 0x02,R16
    		OUT 0x03,R16
    		OUT 0x04,R16
    		OUT 0x05,R16
    		OUT 0x06,R16
    		OUT 0x07,R16

    Таким образом, ты забил совершенно левыми значением порты с 00 по 07
    А конкретно в:

    1
    2
    3
    4
    5
    6
    7
    8
    
    .equ	ADMUX	= 0x07
    .equ	ADCSRA	= 0x06
    .equ	ADCL	= 0x04
    .equ	ADCH	= 0x05
    .equ	TWDR	= 0x03
    .equ	TWAR	= 0x02
    .equ	TWSR	= 0x01
    .equ	TWBR	= 0x00

    Побитово порты устанавливаются командами
    SBI IOPORT,BIT
    и
    CBI IOPORT,BIT

    SATS

    Блин, какой ты молочага. Я прокрутил, проанализировал все это. Все так и есть. Спасибо, санцей))))


  21. shooroop 05 мая 2009 18:45

    Есть еще один вопросик. Может, конечно, не в тему, но все-таки про АЦП и АВР. Вот тут http://mkeia.com/Oscyloskopy/moc1k_en.htm есть девайс со схемами и прошивкой. Вообщем суть вопроса вот в чем: указано что ацп делает 250 тысяч выборок в секунду при 10-битном разрешении. Каким образом такое может быть достигнуто?

    DI HALT

    Врут

    shooroop

    ответ разработчиков “Yes it is possible. There is a little degradation of resolution, but works fine.”
    на вопрос “Still, a final true resolution? 10-bit or 8?” был получен ответ “about 9 :)”

    DI HALT

    Ну вот о чем и речь. Теперь они уже согласны на 9бит, плюс 3МЗР на помехи. В итоге имеем 6.

    Снять 10 бит на 250кгц это элементарно - взял и считал, вот только что из этих 10 бит будет ценной инфой, а что мусором?


  22. Inc_Dec_i 06 мая 2009 15:30

    Посоветуйте как заставить АЦП работать во free running mode, т.е. чтобы он в циклическом режиме поочереди перебирал все 8 ног. Я устанавлию нужную ногу в регистре ADMUX битами MUX3…MUX0, но он все-равно настырно берет значение только с первой ноги, хотя в регистре лежит уже другое значение. Может я еще чего забыл где включить\настроить. Контроллер AVR ATmega8535

    DI HALT

    А нельзя во фриранне перебирать ноги. Только вручную. Запустил. В прерывании переменил ногу, еще раз запустил. И так далее.

    Inc_Dec_i

    Ясно, спасибо. Непонятно только зачем он тогда нужен вообще:)

    DI HALT

    Как это зачем? Врубить непрерывный опрос одного канала. Чтобы не заморачиваться на повторный запуск.

    holyavko

    А как тогда его запускать вручную, если в ADTS нет такого понятия, и по дефолту он в фриране?

    holyavko

    А как тогда его запускать вручную, если в ADTS нет такого понятия, и по дефолту он в фриране? или нужно как раз во фриране его и пускать, а после выполнения первого преобразования перезапускать с новым значением MUX ???

    holyavko

    Очевидно замучаю и мёртвого. с вопросом о ручном запуске разобрался и нарыл в даташите на 48 мегу следующий прикол
    If Auto Triggering is used, the exact time of the triggering event can be indeterministic. Special
    care must be taken when updating the ADMUX Register, in order to control which conversion
    will be affected by the new settings.
    If both ADATE and ADEN is written to one, an interrupt event can occur at any time. If the
    ADMUX Register is changed in this period, the user cannot tell if the next conversion is based
    on the old or the new settings. ADMUX can be safely updated in the following ways:
    a. When ADATE or ADEN is cleared.
    b. During conversion, minimum one ADC clock cycle after the trigger event.
    c. After a conversion, before the Interrupt Flag used as trigger source is cleared.
    When updating ADMUX in one of these conditions, the new settings will affect the next ADC
    conversion.
    Что в кратце означает, что если поменять ADMUX в во время следующего такта после начала прерывания (в фриране) то следующее вычисление будет производится с нового пина…
    Я ничего не напутал ?

    DI HALT

    Проще сделать так:

    Включаешь АЦП на одиночное преобразование (бит ADFR(ADATE) сбросшен) тогда АЦП делает только ОДНО преобразование и генерит прерывание. В этом прерывании ты правишь адмух и запускаешь следующее преобразование. У тебя получается как бы фриран, но со сменой каналов.

    holyavko

    меня в варианте мучает вопрос того, что проц постоянно будет инициализировать ацп, то есть время расчета следующего значения увеличивается в 2 раза, а у меня мысль следующая, взять свободный таймер который запускать на тем же делителем что и ацп, и собственно запускать сразу после получения первого значения с значением компаратора …например 1, то есть на 2-3 такте АЦП он должен сработать. учитывая что делитель частоты на таймере АЦП у меня стоит на 1/64 я так понимаю что для обработки значений результатов вычисления 64 такта должно хватить… ну я так думаю во всяком случае )))

    DI HALT

    А какой контроллер то?

    holyavko

    mega48p


  23. Ridik911 13 мая 2009 23:04

    позвольте понаглею и спрошу
    как узнать какой ADC можно использовать как обычный АЦП потомучто мне непонятно это:
    AD9220AR Complete 12-Bit 1.5/3.0/10.0 MSPS Monolithic A/D Converters
    AD9200ARS Complete 10-Bit, 20 MSPS, 80 mW CMOS A/D Converters
    а стоят до 200 руб.
    как вообще понять до какой частоты.. и на какие еще штуки можно смотреть
    спасибо

    DI HALT

    Любой из. Тока это внешние АЦП


  24. LeoAbyss 26 июля 2009 21:02

    Здравствуйте, господа! :) Подскажите, пожалуйста, как подключить датчик (24В, 4-20мА) к АЦП 0-5В?

    DI HALT

    Пусти ток с датчика на резистор (где то в 1к) и на землю. А падение напряжения с этого резистора заведи на АЦП.

    Не так давно был пост про датчики и средства измерения. Отмотай ленту сайта от начала, думаю в пределах первых двух страниц найдешь :) ТАм более подробно.

    LeoAbyss

    Большое спасибо! Если я правильно посчитал, то нужно не 1 кОм, а где-то 250 Ом?
    тогда 20мА = 5В.. 4мА = 1В.. Верно, или закон Ома мне повторить следует? :) Да, и еще. Нельзя ли в описание программатора на УСБ выложить его фотки сверху и снизу, и добавить номенклатуру компонентов?

    DI HALT

    Да, все верно.

    Может и сделаю перечень. А фотки сверху и снизу есть там.

    LeoAbyss

    Добрый день! Очередной вопрос чайника. :) В чем разница между источниками опорного напряжения? У меня есть на 5 вольт и на 4.096. Какой предпочтительнее использовать? Токи и напряжения все те же: 24 В, 4-20 мА.

    DI HALT

    ИОН нужен для задания опорного (максимального) значения для АЦП. Соответственно чем он ближе к величине измеряемого напряжения тем лучше — более рационально используется шкала АЦП.
    Но ИОН не может быть больше напряжения питания МК

    LeoAbyss

    Спасибо. Значит если АЦП меряет 0-5 В, то и ИОН нужен на 5 вольт? АЦП внешнее, если это важно.

    DI HALT

    АЦП меряет от 0 до ИОН, но не выше питания.

    Если твой сигнал меняется от 0 до 5, то и ИОН должен быть не ниже 5. Если сигнал меняется от 0 до 2, то поставив ИОН на 5 ты теряешь 3/5 шкалы АЦП впустую. Т.к. мерять он может до 5, а сигнал реально только до 2х достигнет. В этом случае ион лучше сделать на 2 вольта. Либо входной сигнал снормировать на ОУ


  25. Sh@dow 01 Авг 2009 19:09

    А может так быть что на входе ацп напряжение 90миливольт (относительно земли)?По идее ноль должен быть.


  26. Sh@dow 01 Авг 2009 19:10

    А может так быть что на входе ацп напряжение 90миливольт (относительно земли)?По идее ноль должен быть.Это когда вход просто в воздухе висит ни к чему не подключен.

    DI HALT

    Ноль может быть только в одном случае — когда вход лежит на земле.

    Когда же он висит в воздухе, то на нем наводится черти что. Обычно это черти что предстает в виде синуса 50Гц и амплитудой около 2.5-3вольт. Это наводки.

    Sh@dow

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

    Sh@dow

    100 милливольт Ж)

    DI HALT

    Сопротивление входа АЦП мегаоммы. Сответственно последовательно с ним наушники вешать бессмысленно.

    Да и нафига ты наушники туда еще втыкаешь? У них сопротивление в порядки ниже чем у АЦП. Так что либо одно либо другое.


  27. Sh@dow 01 Авг 2009 20:48

    Бля,я ошибся не последовательно а параллельно :d
    Последовательно нет смысла врубать.


  28. tomba 16 Авг 2009 21:47

    Здравствуйте! Написал программу для Меги 8, которая снимает показания АЦП и передает в порт B. Только в порт B она почему-то всегда выдает пятерку (0000 0101), как в АВРСтудии так и в Протеусе. Что неправильно в коде? И ещё: не запускается в симуляторе беспрерывное преобразование. Никто не сталкивался с этим? Спасибо.

    ;Иницализация
    OUTI DDRB, 0b11111111
    OUTI ADMUX, 0b01000000
    OUTI ADCSRA, 0b11111011

    ;Основа

    main: RJMP main

    ;Обработчик прерывания по оконч. преобразования

    Gotov:
    CLI
    OUTI PORTB, ADCH
    OUTI ADCSRA, 0b11111011
    SEI
    rjmp main

    stein

    >OUTI ADCSRA, 0b11111011
    Вот это будет работать так, как ты хочешь (запись 0b11111011 в регистр ADCSRA).

    А вот это:
    >OUTI PORTB, ADCH
    запишет не значение регистра ADCH в регистр PORTB, а _адрес_ регистра ADCH в регистр PORTB.
    Адрес ADCH и есть 00000101 (т.е. 5). Если ты пользуешь AVR Studio, то там в панели I/O View, там где черно-белые такие квардратики (биты), есть колонка Address, значение в которой отображает адрес регистра.

    В твоем случае макрос OUTI должен выглядеть так:
    .macro
    in r16,@1
    out @0,r16
    .endmacro

    Кури команду in. Юстировка по левому краю? А назвезда ты измеренное напряжение с ADCH пихаешь в PORTB? В r16-r31 надо пихать (например).

    Вот кстати, о птичках. Заметил тут жука в АВР Студио. Если в режиме отладки отметить квадратик в ADCH руками, потом запустить Run, остановить, перекючиться посмотреть другую группу регистров, а потом полезть смотреть опять ADCH, то квардартика там уже не будет, но значение в регистре останется. То же проявляется, если квадратик руками снять. :(


  29. PavelOrel 04 Ноя 2009 19:17

    Если используешь подавление шума, в обработчике прерывания АЦП надо что-то писать?
    Уточняю порядок:
    1 Ставим ADEN и ADIE и все настройки
    2 Запускаем ADSC (у меня одиночные преобразования будут)
    3 SLEEP
    И вот он проснётся по прерыванию и дальше по программе замолотит, можно не волноваться?


  30. Nazi 30 Дек 2009 3:10

    DI HALT, подскажи пожалуйста, как посчитать, что будет в ADCH и ADCL, если знаем напряжение на входе.

    DI HALT

    Подели опорное напряжение на разрядность ацп. Получишь вес одной единицы. Дальше делишь входное напряжение на вес и получаешь искомое.

    Nazi

    спасибо!


  31. vadlm 16 Янв 2010 22:31

    DI. хотел спросить на счет последовательности считывания результата. В датшите сказано
    “When ADCL is read, the ADC Data Register is not updated until ADCH is read. Conse-
    quently, if the result is left adjusted and no more than 8-bit precision is required, it is
    sufficient to read ADCH. Otherwise, ADCL must be read first, then ADCH.”

    Т.е. я так понимаю, что если уже готово новое значение измерения (непрерывное преобразование 10bit с выравниванием вправо), то пока не прочитаешь ADCH от прежнего измерения, то новый значение не запишется в ADCH:ADCL. Т.е. если сначала пытаться читать ADCH, а уже потом ADCL есть вероятность прочитать из ADCL результаты нового измерения, что уже является ошибкой. Если это так (я 10bit читаю именно так - сначала ADCL,а уже потом ADCH), то может добавите этот момент в статью (там где пишете про выравнивание результата)?


  32. DIMA040891 17 марта 2010 2:59

    ААА ммм)) непонятно порты задействованные под АЦП настраивать как?? На выход или на вход??

    DI HALT

    На вход. Без подтяжки. т.е. DDR=0 PORT=0


  33. DIMA040891 18 марта 2010 3:08

    И тем не менее неполучилось((((.Хотел в ATmega8 задействовать АЦП. АЦП должен измерять напряжение раз в 0,5 С на вывоже ADC0 (PC0), затем прочитав это значение из ADCH (выравнивание влево) вывести значение в остальные вывода порта C. PC1-PC5 подключены светодиоды. Почемуто непроисходит ничего , светодиоды негорят Напряжение на ADC0 беру с переменного резистора, который соиденён с источником питания МК. Помогите разобраться кто может.

    .

    .

    .

    ldi Temp,low(RamEnd) ;установка указателя стека
    out SPL,Temp
    ldi Temp,high(RamEnd)
    out SPH,Temp

    ldi Temp,0b11111110
    out DDRC,Temp

    ldi Temp,0b00101000
    out PORTC,Temp

    ldi Temp,0b11100000
    out ADMUX,Temp; выбор канала, а так же выравнивание влево(бит 5),+(биты 6 и 7)
    ; включение опорного напряжения внутреннего источника

    ldi Temp,0b10000101
    out ADCSRA,Temp; старший бит вкл АЦП, младшие - предделитель

    reset: sbi ADCSRA,ADSC ; уст бит “старт преобразования”

    WaitADC:

    sbis ADCSRA,ADIF
    rjmp WaitADC
    ; тут отсчет готов…
    in Temp1,ADCH ; ст байт

    out PORTC,Temp1

    ldi Temp3,0×06
    ldi Temp2,0×1A
    ldi Temp1,0×80

    Delay: subi Temp1,1;ждём 0,5С
    sbci Temp2,0
    sbci Temp3,0
    brcc Delay

    rjmp reset

    DI HALT

    А прогон в студии что дает? Не встает флаг?

    DIMA040891

    Честно говоря я непонимаю о как прогоне и о каком флаге идёт речь??

    DI HALT

    э… а как ты вообще пишешь код?

    Набил десяток команд, откомпплировал, лишь бы скомпилилось без ошибок, зашил. Если не работает сидим и тупим в код. Так?

    Открою тебе страшную тайну. АВР студия может пошагово выполнять программу на ассемблере, показыая содержимое всех регистров, флагов и периферии. Более того, можно брейкпоинты ставить в коде и ловить всякие редкие события, вроде срабатывания прерываний и прочее.

    О флаге завершения преобразования.


  34. DIMA040891 18 марта 2010 19:16

    Во Во!! Точно так и делаю!!!!))
    Про по шаговое выполнение AVR Studio программы вы кажется писали в одной из статей, ща попробую найти.
    МК потребляет ток 8…10mA-это немного?? Я АЦП никак не мог попортить?? А и ещё несовсем ясно при измерении в недиферинциальном режиме возможно ли использовать встроенный усилитель x10??

    И вот ещё вы писали что посдедние 2 разряда в результате АЦП это мусор и данные там недийствительные, а есть же AVR у которых 12 разрядов, что тогда там последние 4 разряда врут чтоли??

    DI HALT

    А что там искать вторая кнопка после компиляции.

    8..10мА довольно много, если конечно светодиодов не понавешано и они не горят.

    Нельзя, он только для дифрежима.

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

    У какого из авр 12 разрядный АЦП?


  35. DIMA040891 19 марта 2010 2:01

    ммм да ))) прикольная штука!! Надо в ней по подробней разобраться!!
    С программой разобрался(ну т.е. помогли)!! метку reset нетуда воткнул((

    Теперь новая проблема возникла(( Все разряды скачут,загорается то 3 то 4 светодиода, практически без остановки (только старший вроде как одекватно держиться)-это может быть вызванно слабым источником питания??

    А про 12 разрядный АЦП в книге читал: Юрий Ревич стр.207, 5-я строчка :)))))
    А к вам на сай попасть всё сложнее и сложнее, вечером вообще нриально, уж больше часа долблюсь))))

Оставьте свой отзыв

Вы должны войти, чтобы оставлять комментарии.


Материалы сайта являются авторскими. Копирование и публикация материалов без активной ссылки на первоисточник запрещено.

Реклама: