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.

  • По дефолту там стоит 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][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 (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<<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[00000]</B>Сигнал на вход идет с нулевого канала АЦП.

 

А что дальше делать? А ничего! Сидеть и ждать прерывания!
Когда оно придет процессор кинет на вектор и дальше уже можно либо переписать данные из 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.

222 thoughts on “AVR. Учебный курс. Использование АЦП”

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

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

    2. АЦП — это аналог не компаратора, а цифрового вольтметра со шкалой 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 до питающего.

        1. Нет проблем. Вот, навскидку, из тех, что я просматривал пару лет назад и легко найти в продаже:
          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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  7. Использую 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 бит мне будет маловато…
    растолкуйте пожалуйста что к чему…

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

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

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

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

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

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

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

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

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

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

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

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

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

    1. Если у меня тактовая частота МК = 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?

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

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

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

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

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

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

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

      Покажи код.

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

      2. 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
        1. В глаза ничего криминального не бросается. Код топорный но явных затыков нет.

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

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

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

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

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

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

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

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

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

      1. Сегодня разбрался метдом тыка с этим. Кроче из проги убрал инициализацию порта С на ввод побитово
        (то есть 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. Теперь не могу понять, как же оно все таки не давало нрмально рабтать?

        1. Потому что

          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

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

      1. ответ разработчиков «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 :)»

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

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

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

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

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

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

              1. Очевидно замучаю и мёртвого. с вопросом о ручном запуске разобрался и нарыл в даташите на 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 в во время следующего такта после начала прерывания (в фриране) то следующее вычисление будет производится с нового пина…
                Я ничего не напутал ?

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

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

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

  22. позвольте понаглею и спрошу
    как узнать какой 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 руб.
    как вообще понять до какой частоты.. и на какие еще штуки можно смотреть
    спасибо

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  26. Здравствуйте! Написал программу для Меги 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

    1. >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, то квардартика там уже не будет, но значение в регистре останется. То же проявляется, если квадратик руками снять. :(

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

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

  28. 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), то может добавите этот момент в статью (там где пишете про выравнивание результата)?

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

      1. Может DDR=0 PIN=0
        И раз уж затронулась тема, имеет ли смысл выставлять PORT если DDR = 0
        и наоборот выставлять PIN если DDR =1
        К примеру что бы настроить ВХОД или ВЫХОД до изменения состояния DDR ?

        1. При DDR=0 PORT управляет подтяжкой. Так что влияние есть.

          Выставлять PIN особо смысла не имеет. Это регистр для чтения. Но! В некоторых новых AVR (не во всех) запись в PIN ведет к инверсии PORT в режиме DDR=1

  30. И тем не менее неполучилось((((.Хотел в 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,0x06
    ldi Temp2,0x1A
    ldi Temp1,0x80

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

    rjmp reset

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  33. Есть кусок кода. Начало программы, поэтому здесь отключено прерывание от АЦП

    LDS R16,ADCSRA
    SBR R16,(1<
    rjmp _wait ; -> крутиться здесь

    ; …по окончании первого ADC…
    _End: LDS R16,ADCSRA
    SBR R16,(1<<ADIF)
    STS ADCSRA,R16 ; сброс флага, чтоб вдруг ниже не возникло прерывание

    LDS R16,ADCSRA
    SBR R16,(1<<ADIE)
    STS ADCSRA,R16 ; включаю прерывание

    Прогоняю в Студии. По идеи в железе как только закончилось преобразование бит ADSC сбрасывается в 0 сам. Предположим я сам ставлю бит ADIF как будто преобразование закончилось. И сам же сбрасываю бит ADSC. Но на следущей команде ADSC опять становится в «1» и так постоянно. Это глюк Студии или я что-то делаю не так?

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

  34. Собственно у меня есть обработчик прерываний и брейк там стоял. И студия туда и попадает :) Я надеюсь мой вариант кода корректен. Вот весь вопрос в том и возник — почему такое происходит. Мне так показалось, что из-за сохраняющегося бита ADSC. Далее по программе есть еще один запуск, но он происходит в обработчика прерывания от таймера. И АЦП правильно срабатывает и попадает в свое прерывание. Кстати! Еще вопрос — Студия сама эмулирует окончание преобразования (после определенного количества тактов согласно даташиту — первое 25, последующие — через 13, если не ошибаюсь), или мне ткнуть бит вручную надо?

  35. В моем примере, когда прерывание отключено окончание преобразования я имитирую установкой бита ADIF (мышкой). А после окончания этого кода, когда я включаю прерывание, брейк на обработчике прерывания возникает аж где-то через 400us, что явно долго для одного преобразования, но очень быстро, видимо, для момента когда оно по программе у меня должно появиться… :)

    1. А прерывания отключать не надо. Иначе хер знает как там логика сработает. Ведь бит сбрасывается поди тогда, когда идет переход на обработчик. Либо аппаратно (надо шит почитать) А то что по времени не укладывается в реальные цифры — это имхо пофигу. Симулятор может и гнать на этот счет. Главное чтобы он сам интеррупт делал.

  36. Собственно, тот код стоит в начале прораммы. (забыл, кстати, контроллер указать — ATmega48) А нужен он мне что-бы 2-е и следующие за ним выполнялись за 13 (помоему), а не 25 тактов, как первое. Чтоб точно знать время последующих преобразований. Либо тогда мне в обработчике ради первого преобразования надо городить какие-то условия. Оно (первое) мне по моменту выборки-хранения не подойдет. Вот я так хочу от него избавиться — сделать первое фиктивное преобразование и чтоб оно не вызывало прерываний. Поэтому в начале и отключено. А вот сразу после этого кода я прерывания от АЦП разрешаю. Собственно бит ADIF я потом сам сбрасываю, записав в него «1».
    «Ведь бит сбрасывается поди тогда, когда идет переход на обработчик» — когда-то на другом примере и прерывании я заметил, что он сбрасывается после выхода из обработчика :) Наверное тоже какая-то фича Студии…

    1. А в железе то работает? Проверить просто — в обработчике прерываня дрыгаешь ногой и зыришь осциллом частоту сработки прерывания.

      1. Железа пока нет :D Собственно за частоту я наверное не волнуюсь. А смутило меня сохранение бита ADSC, который должен бы по идеи и даташиту сбрасываться как толко закончилось преобразование. Ну думаю тут особенность программы

  37. Я так понял, что устанавливая делитель частоты, задаем частоту работы самого АЦП и следовательно частоту выборок. Но если сделать частоту выше 200 кГц, точность будет ниже 10 разрядов. А поскольку она и так 8, то ничего страшного. 260 кГц АЦП, 20 кГц выборок, около 8 кГц макс. частота сигнала. Речь, видимо, будет вполне разборчивой.

  38. Непонятно из каких соображений для меги32 в регистре SFIOR переименованы биты (ADTS2..0).

    Из m32def.inc:
    ;SFIOR
    .equ RPDD =7
    .equ RPDC =6
    .equ RPDB =5
    .equ RPDA =4
    .equ ACME =3
    .equ PUD =2
    .equ PSR2 =1
    .equ PSR10 =0

    Хотя в даташите под него всё по старинке

  39. привет!
    купил я себе ADS1100 — это 16 битный АЦП у которого есть дифференциальный вход. Но мне нужно измерять однополярное напряжение (0…5В), я так понял, ножку VIN– нужно посадить на землю?

  40. Всем доброго времени суток!
    Разрабатываю один девайс на меге 128 с графическим дисплеем мелт6116… меряю напряжение по трём фазам в электросети — вроде всё не плохо тока одна проблема — на выводах ацп плавает какоето левое напряжение притом разное в зависимости какой вывод ацп 0…7 выводы. у меня LC фильтр у питания ацп, внутренний ион на 2.56…выводы сконфигурированы на вход без подтягивающих резюков… думал помехи отпаивал все и вся… короче отпаял выходы ацп от платы и померял напряжение на выводах ацп контроллера где 3,5 portf5 в где 1 в port f 2, ну думал помехи всётаки мощные откудато, и подтянул резюком на 1 колоом к земле вывод где 3,5в и всёравно напряжение около 0,15в.
    Не пойму в чём дело по идее должно 0в а откуда беруться эти напряжения не пойму может надо выводы на вход переделать или что его там.

      1. Di — блин вопрос жизни и смерти…. согласен тут много бла- бла… на atmega128 на вывводах PortF0-PortF7(Это выводы АЦП) «плавает» какое то напряжение 1-3,5 вольт . которое трудно подтянуть даже резистором в 1 колоом. Не могу понять откуда эти напряжения. наводок ни каких нету , выводы отпаял загнул померял вольтметром — примерно 3 вольт откуда не пойму!

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

          1. Почти да — вешаю резюк на 1 коло всеравно примерно 0.2 вольт. А на счёт дорожек я вообще ножки отпаял и замерял ноги не присоединённой к плате…. но ничё извиняюсь за кипиш , вобщем повтыкал ночь даташиты — ничё не нашёл потом чуйка сказала повтыкать какие доп функции есть на ногах ацп контроллера, оказалось что на этих ногах есть житаг…. отключил в фузах житаг и-О чудо левые напряжения исчезли как их и небыло! Всё вобщем гут если не считать тока 3 дня и нервишек)

  41. А вот если, ATtiny45 питается от аккумулятора Lion 3,7v и нет других элементов вокруг контроллера (есть полевик подключенный затвором к PB1 который должет отключать аккумулятор при снижении V менее 3,2v). Mожно ли измерять как то напряжение этого аккумулятора, не довешивая на ноги ничего ?

  42. Несколько практических вопросов.
    1) Каков будет результат измерения если измеряемый сигнал больше ИОНа? 1023 или прошлый коректный?
    2) По даташиту, входное сопротивление по входу Аref — 32ком. Если выключаем АЦП, то этот вывод отключается, или продолжает потреблять?

      1. 2) 32к — входное сопротивление. т.е. между Аref и землей. Если не трудно (у вас же есть пинбоард) измерьте потребление по этому входу при выключенном АЦП, компараторе и встроенного ИОНа.

        1. Домой приеду замеряю. Вообще давно хочу сделать пост по энергопотреблению, с замером всего и вся в разных режимах.

          1. Спасибо.
            Кой какие опыты по потреблению в слеепе есть.
            например включение внутреннего ИОНа добавляет 20мка потребления.(мега16а) мелочь, но в слеепе существенно.
            на потребление в слеепе не оказывают влияния выводы в
            1. выход с нулём
            2. вход с внутренней и внешней подтяжкой
            3. вход посаженый на землю через резистор
            (искал во что переводить выводы для наименьшего потребления)

  43. В даташите меги16 есть фраза:
    The differential input channels are not tested for devices in PDIP Package. This fea-
    ture is only guaranteed to work for devices in TQFP and QFN/MLF Packages
    Кто-нибудь пробовал в диповском корпусе использовать дифференциальный вход ацп? Как оно?
    И еще: насколько я понял по даташиту в меге8 дифф-входа нет?

  44. Написал прог. АЦП CodeVision

    #include

    interrupt [15] void ocs (void)
    {
    //breakpoint
    ADCSR.6=1;

    }

    void main (void)
    {
    ADCSR=0b10001111;
    ADMUX=0;
    ADCSR.6=1;
    #asm(«sei»);
    while (1)
    {

    }

    }

    Запустил её у avrstudio не пойму почему так много тактов происходит ??? 1673 Ведь АЦП должно за 13 тактов + прерывание пару тактов. Проверяю так запустил у avrstudio нажимаю START DEBUGGIN поставил breakpoint и проганяю от breakpoint до breakpoint и в итоге получаеться 1673 тактов ??? помогите пожалуйста

    1. В железе проверял? Если нет, то разговаривать не о чем. Но вообще первое преобразование после смены канала/включения длится дольше.

          1. Все понял ADCSR=0b10001111; не правильно нужно 10001000 что то завтыкал(((( теперь за 30 тактов работает … Тоже вроде что то много получаеться для прерывание 17 тактов и 13 для АЦП

  45. 1673 — это каких тактов? Прцессора? По даташиту есть 25, 13, 13,5 тактов, но это тактов _блока АЦП_, а не кварца. А блок АЦП должен работать на частотах от 50 до 200кГц для более или менее точных результатов. Задается прескалером при настройке АЦП.
    «для прерывание 17 тактов» — в смысле сам обработчик столько занимает? А 13 это для АЦП? Тогда всё пушисто получается.
    И по поводу «преобразование после смены канала/включения» то что оно длиться дольше. Первое — да. Согласно даташиту. А вот при смене канала — там ничего вроде не написано.Упоминается про переход к дифференциальному каналу

  46. Здарова! Есть вопрос по атмеге48, конкретно, которая у меня стоит. Правильно ли она работает или нет. А вопрос весь в следующем. В модуле АЦП у нее при настройке выбран внешний опорник. Решил я это опорное напряжение завести с операционика, да еще сгладить RC цепочкой. Но вот ткнулся тестером к выходу ОУ, т.е. на вход, так сказать, RC цепочки и на выход её, т.е. к выводу подключения Uref меги. И заметил разность напряжений. Эта разница при установленном резюке соответствовала току через вывод ref где-то от 1мА до 3мА в зависимости от напряжения. Что это — малое входное сопротивление по этому входу или полуубитый вход?

    1. А как сконфигурирован референс вход изнутри? И есть ли на нем напряжение без подключения?

  47. Референс изнутри не сконфигурирован. Вывод ref сконфигурирован для внешнего опорника
    OUTIm ADMUX,(0<<REFS1)|(0<<REFS0)|(0<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0)
    где OUTIm

    .MACRO OUTIm
    LDI R16,@1
    STS @0,R16
    .ENDMACRO

    Да, кстати, получились одни нули, можно было это строчку и не писать )

    В качестве внешнего опорника выступает ОУ через RC-цепочку. Напряжение на его выходе меняется, но не случайно, а по известному мне закону, но оно постоянное в процессе измерения. Так вот из-за этой RC-цепочки, а точнее из-за резистора я и заметил разность напряжений. И кстати осциллом тоже видно, что оно разное по обе стороны цепочки и подозревать некую переменную насадку, из-за которой возможно тестер показывал разные результаты, не приходится.

  48. Может кому будет полезно.
    Погонял и я немного верхом на АЦП. Но, к сожалению, похоже наткнулся на вот эту багу меги 8 — http://easyelectronics.ru/podklyuchenie-mikrokontrollera-likbez.html (где про нее варнинг большими буквами). В общем-то, пока контроллер ничего особого не делает, напряжение, замеряемое АЦП, выглядит достаточно пристойно, хотя конечно +-1МЗР на 8 битах не очень радует, но это я бы еще стерпел. Но как только я врубаю выход ШИМ (на нем пока висит тупо светодиод небольшой, ток выхода получается миллиампер 10-15) — в районе 2/3 шкалы у АЦП начинается аццкая жесть… Измерения начинает колбасить +-(30-40) единиц по 8-битной шкале. Если (не меняя ШИМ) сдвинуть входное напряжение вниз от 2/3 шкалы — вроде его перестает колбасить. Только нафиг надо вниз сдвигаться, точность жеж потеряется. :( В общем не дело это.

    И в итоге получается, что реализовать на меге8 одновременно ШИМ (будет рулить 2 мощными полевиками) и вменяемый АЦП не удастся?

    1. судя по описанию бага, лучше выбрать другой МК для вашей задачи. Хотя, если очень хочется, можно попробовать оперировать маленькими токами (светодиод через усилитель) +хорошие (порядка 100мкФ) сглаживающие конденсаторы…

      1. > лучше выбрать другой МК для вашей задачи
        Склоняюсь к тому же — чем геморроиться с кривым кристаллом и городить вокруг него не пойми что, лучше взять другой мк и получить то же самое, но без всякого гемора. А кроме того, при любом из этих раскладов нынешняя плата отправляется в мусор. :(
        В общем, спасибо, хотелось подтверждения свежего взгляда со стороны.

      2. Вчера пришла моя плата Pinboard. Естественно («у кого что болит»), первый эксперимент на ней был поставлен именно этот. :) Как и следовало ожидать, на вкрученной туда меге16 все ок. Теперь буду втыкать ШИМ на реальной нагрузке, вот тогда и посмотрим окончательно, что из этого всего получится…

        1. Закон силы Энтони: Не тратьте силы, возьмите молоток побольше! :)
          Неужели и тут он применим? :)
          А мне пришла платка на at90usb168… К сожалению, без пинов, но погляжу, что из нее получится :)

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

      1. Возможно и в питании, но я пока не соображу, где меня кидают. Буду дальше копать, есть еще мысли…
        А в 48-й или 88-й этого косяка в кристалле точно нет? Корпус TQFP кстати.

        1. Сейчас сам не проверю — на руках нет ни той ни другой, но на форуме говорили, что там все ок.

          1. От и у меня ж нету. :) А так бы уже попробовал… Зато есть 16-я и платы с наклеенным фоторезистом с подходящим к концу сроком годности. :)

  49. Шеф, подскажи по непрерывному преобразованию!
    Вот я взял tiny45, сконфигурировал непрерывное, разрешил прерывание по окончанию (надо результат обработать и ждать следующего). В итоге прерывание выполняется один-единственный раз, после него бит ADSC оказывается сброшен и преобразование прекращается. Пошарил на avrfreaks — там говорят что-то вроде «использовать прерывания совместно с непрерывным преобразования не правильно».
    Что-то не врубаюсь: как тогда правильно? Периодически чекать флажок завершения?..

    1. А ты где проверял? В студии? там непрерывное глючит. В железе же работает нормально. И вполне допустимо использовать непрерывное вместе с прерыванием по окончании. А иначе как актуальные данные то забирать?

      1. > там непрерывное глючит
        Ах вот оно в чем дело… Я тоже хотел повеситься на прерывание при непрерывном преобразовании, чтобы не задача через диспетчер крутилась. Но в студии получил какой-то загон, решил что чо-то не догоняю в инициализации и забил, оставил через диспетчер. Да и потом подумал, что мне все равно не один канал надо будет контролировать, так что непрерывное опять-таки отпадает.
        Да, опыт не пропьешь. :) Спасибо за ценную инфу.

        1. Много каналов хорошо мультиплексить через то же прерывание по окончании. Меняя канал в обработчике и запуская преывание заново :)

          1. Так а при непрерывном разве можно переключать каналы? Или ты имеешь в виду запускать в ручном режиме, просто переключение канала и следующий замер запускать прямо в прерывании?

            1. В непрерывном низя. Но кто мешает этот непрерывный сделать самому, вручную? Прям в прерывании.

              1. Ясно, этакий «квазинепрерывный» режим. :) Скорее всего так и сделаю, вполне нормально выглядит. По крайней мере по сравнению с той базой 1С, которая у меня щас на работе перед глазами на втором мониторе, и в которую хочется плюнуть и ударить битой 5 раз. :)

              2. А вроде и «зя». Другое дело, что следующий результат будет соответствовать всё равно предыдущему каналу. А вот уже следующее уже новому. Это если я правильно понял перевод на русский описания atmega128 с gaw.ru:
                «В режиме автоматического перезапуска канал необходимо выбирать перед началом первого преобразования. Переключение канала происходит аналогично — в течение одного такта синхронизации АЦП после записи лог. 1 в ADSC. Но самым простым методом является ожидание завершения перового преобразования, а затем переключение канала. Поскольку следующее преобразование уже запущено автоматически, то следующий результат будет соответствовать предыдущему каналу. Последующие преобразования отражают результат для нового канала»
                Так что теоретически можно, но польза плохая. Лучше менять канал перед запуском, например, в том же прерывании.

  50. F1 люди не могу совладвть с мегой128 подключаю к ней тачскрин и немогу сконфигурировать выход там порт f и sbi cbi не катят
    —————————————————————————-
    ldi r16,0b11111110
    sts ddrf,r16
    ldi r16,0b00001010
    sts portf,r16

    ldi r16,0b00100000 опорки нет, сдвиг влево, пин 0
    sts ADMUX,r16

    ldi r16,0b10000111 включение ацп делитель 128
    sts ADCSRA,r16

    ldi r16,0b11000111 включение ацп и расчет делитель 128
    sts ADCSRA,r16

    lds r16,ADCH читаем и пусто
    ——————————————————————————-
    и фиг ничего не валиться по хорошему в хай-Z надо 0-й пин кинуть а как?

    1. cbi sbi работают только до 1F IO адреса. Порт А лежит где то в районе 28 адреса т.е. намного дальше. Туда только через чтение-модификацию-запись. Т.е. сделал все верно, через sts

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

      1. пробывал по прерыванию как писали выше указывал биты ADCSRA генерировать флаги

        WaitADC
        sbis ADCSRA,ADIF
        rjmp WaitADC
        с таким раскладом ваще прога виснет ;(
        после пробывал задержку после mux и включения вычислений до 1сек про 13MHZ эт просто вечность один фигничего
        Может есть какой-то пример чтоб понять как иммено mega128 работает с ацп?

        1. Да не надо ждать флаг прерывания. Настрой обработчик прерывания, разреши их и вперед. В обработчике выгребешь данные с ацп.

          1. всё оказалось сложно! во первых надо на mega128 шить фъюз M103C на выкл тогда он начитает работать как mega128 после sts portf,r16 не катит только ТАК: sts 0x62,r16 может кому пригодиться! да еще столкнулся с одной ерундой на сеноре по X и по Y сопротивление порядка 400-500 ом и на mega88 если подать на X1 (+) X2 (-)то всё можно было мерить по Y а тут ножка дующая (+) просаживаеться почти в 0 ;( это особенности архитектуры или мне так повезло? и надо ставить подтяжку?

  51. Уважаемый мэтр.
    У меня тут такое кино с моделированием АЦП Меги8 в Proteuse.
    АЦП запускается в однократном режиме через определенное количество переполнений Таймера0. И мне кажется вполне обоснованным в промежутках отправлять проц поспать. Согласно многочисленным источникам флаг ADIF, вызывающий прерывание, аппаратно сбрасывается после возникновения последнего. И следующее преобразование инициируется установкой бита ADSC. Но у меня почему-то оно возникает постоянно, как
    будто включено постоянное преобразование. Т.е. постоянное бурбуление.
    А когда убираю sleep – все нормально.
    cycle:
    ldi temp,1<<SE
    out MCUCR,temp;
    sleep
    rjmp cycle
    Может подскажите где я гоню. Заранее пасиба.

    1. Напиши разработчикам протеуса. Там такая прорва глюков в моделях, что говорить о том, что там что то не работает…

      Проверь в железе.

    1. Случайно грохнул твой коммент.

      А проблема точно программная? На этом значении нет колебаний измеряемой величины?

      1. Дублирую комент….

        Здравствуй, DI HALT!

        Пол года назад я уже обращался к тебе с некоторыми вопросами и очень благодарен за то , что ты не оставил их без внимания. В итоге мне удалось создать, то что хотел. Спустя некоторое время (как это обычно и бывает) в программе обнаружился «глюк» природа которого для меня загадка… Буду очень рад если подскажешь в чём может быть дело, а если нет времени или просто влом, то скажешь хотя бы где копать…

        Итак, кратко ввожу в курс дела. Контроллер Tiny13A, Fcpu=2,4 МГц, опора АЦП — питание (2 В). За питание отвечает tps73101 от Txas Instruments, в общем опора хорошая.
        На входе тини медленно изменяющийся аналоговый сигнал (от 0 до 2 В). На выходе импульсы длительностью от 50 мкс до 5000 мкс (F=200 Гц – и не меняется). Чем меньше сигнал на входе тем короче импульс. Во всём диапазоне импульсы стабильны, но в одной точке ( примерно 780 отсчётов АЦП = 1,5 вольта = 2800 мкс) они начинают дрыгаться туда-сюда (+/- 4-5 отсчетов примерно). Причём эффект то есть, то нет. Я ставил на входе переменный резистор между землёй и питаловом. Всё равно дрыгаются…. хотя сигнал на входе постоянный. Интересно , что при выключении и включении питания дрыганья периодически , то пропадали, то появлялись снова. Теперь о том как я измеряю : всё поделено на три диапазона 0-2000 мкс, 2001-3000 мкс и 3001-5000 мкс. Если импульс до 2000 мкс, то после его спада замеряю АЦП 32 раза, усредняю и кладу в ОЗУ , где хранятся значения измерений за последние 16 импульсов. Потом суммирую 16 изм из ОЗУ делю на 16 и получаю усреднённое значение АЦП за 512 измерений. Вот такой изврат. Если импульс от 2001 до 3000 мкс , то после спада провожу 16 измерений АЦП (на большее времени ни хватит). А если импульс от 3001 до 5000 мкс, то после фронта импульса провожу 32 измерения и учитываю это время. Ниже привожу текст подпрограммы , которая всё это делает. …. Да. Я пробовал усреднять по 8 и по 32 импульсам… Всё равно дрыгается в той же точке… Тогда решил на участке от 2001 до 3000 мкс (где всё и происходит) мерить 16 раз после фронта и 16 после спада, и усреднять по 32. Но стало ещё хуже. Теперь этот эффект стал не периодическим, а постоянным, и выкл вкл питаня не влияет. Бьюсь с этим злом уже две недели… Мозги уже клинит…. Помоги плиз.

        Ingor-ru.

        1. Да мог не дублировать, он у меня в почте остался.

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

        2. Проблемма похоже программная… или какая-то специфика ацп контроллера. Я смоделировал эту ситуацию на макете… на ацп подавал сигнал с подстроечного резистора… всё тоже самое… и в той же точке… на нескольких образцах… Может какая нелинейность в характеристике ацп… в датащите есть что-то по поводу нелинейности ацп, ток я не врубился….. и Сократ не помог… :(

          1. Промониторь сырой выход АЦП напрямую, как я те советовал выше. Так хоть поймешь у тебя лажа на входе или в алгоритме. Ну и вместо тупого среднего лучше применять метод скользящего усреднения. Чуток сложней, но зато нет потери скорости. Благо у тебя есть ОЗУ.

            1. Спасибо! Попробую что-нить в этом духе… Кстати я и использую скользящее усреднение. Возможно ты имеешь ввиду средневзвешенное усреднение. Когда более старым измерениям придаётся меньший вес , а более новым больший?

            2. День добрый!

              Спасибо за подсказку про R2R! Быстро отрезвляет! :)))

              У меня ещё один вопросик. Есть небходимость в изучении ATXmega32a4, а я кроме tiny13 и динозаврика AT90S2313 ничего не терзал… С СИ тож не дружу.. Может встречал какую-нить литературу по этому семейству на русском языке? Как у Евстифеева по тини или что-то в этом духе.
              Копал в инете, но всё как-то урывками либо для сильно продвинутых. Есть конечно описание: http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh_xmega_a/index.htm Мозг закипает через 5 минут чтения… А вот что и как по простому , да с примерами на асме…. нифига не нашёл..

              Заранее спасибо.

              P.S. У меня недавно программатор сдох. Спаял USBasp по быстрому … офигенная штука…. :) За него отдельное СПАСИБО!!!

              1. Настоятельно рекомендую подружиться с Си и посмотреть в сторону STM32. Т.к. хмега имхо тупиковый вариант который популярным не станет. Атмел сама его зарубила своим тупым маркетингом.

                А) Перебои с поставками заставили критически посмотреть в сторону этой платформы
                Б) Хсерия есть только для мег128 и около того, т.е. для больших корпусов. Младшее семейство в 40 или 28 ножечных, не говоря уже о тини как то не наблюдается.
                В) дороже и слабей по сравнению с стм32
                Г) требует особый прогрмматор с поддржкой PDI

                Так что если выбирать между тем какой большой чип вывбрать — хмегу или стм32, то я даже не сомневаюсь. Стм32 кроет хмегу как бык овцу. Для малых же решений аналогов авр для себя я не вижу.

                1. Согласен. Хмега проигрывает. Но мне нужн контроллер с 12 бит ацп, 12 бит цап, 16 бит таймером, питаловом от 2 вольт и ног чтоб было хотяб штук 14. А стм32 с ЦАП на борту далеко не все… Начиная тока с 64-ножек… Больно здоровенные они… у хмеги хотяб 44 ноги.. всяко меньше… Может ещё куда нибудь глянуть?….

  52. Доброго времени суток всем. Особый респект Di…
    собственно под твоим не видимым руководством прошел путь от «что такое мк» до сегодня…
    вообщем возник вопрос связанный с АЦП, но косьвенно вот код CVAVR:

    #include
    #include
    #include
    #include
    #include
    #define DD_PLUS PINB.0
    #define DD_MINUS PINB.1

    #define Vref 1000
    #define KBDELAY delay_ms(500) //задержка переключения рядов опроса на клавиатуре
    #define SWDELAY delay_us(1000)
    // Alphanumeric LCD Module functions
    #asm
    .equ __lcd_port=0x15 ;PORTC
    #endasm
    #include
    #define ADC_VREF_TYPE 0x20

    unsigned char lcd_string[20];
    unsigned char Overload=10;
    unsigned char res=50, res_last;
    unsigned int adc_data_last, adc_data, RESALT;

    void writebuff();

    // Read the AD conversion result
    unsigned int read_adc(unsigned char adc_input)
    {
    ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
    // Delay needed for the stabilization of the ADC input voltage
    delay_us(10);
    // Start the AD conversion
    ADCSRA|=0x40;
    // Wait for the AD conversion to complete
    while ((ADCSRA & 0x10)==0);
    ADCSRA|=0x10;
    adc_data=ADCH;
    writebuff();
    }
    void regulator (void)
    {unsigned char k=174, Kreg=2; //коэффициент преобразования в напряжение 1,74 мВ*с2/м
    unsigned int Ris_volt, reg_overload, volt, Ureg;

    volt=ceil(((RESALT*Vref)/256)+0.5);
    Ris_volt=volt*100; // для отрисовки значения после запятой умножим на 100

    reg_overload=(Ris_volt/k); // вычисли значение перегрузки через коэффициент K=1,74 mV/m/c2
    //Zn = (X-Y)*Kи + Z(n-1) Где; X – задание. Y – обратная связь.
    //Kи – коэффициент интегрирования.Zn – управляющее воздействие в текущем программном цикле.
    //Z(n-1) – управляющее воздействие в предыдущем программном цикле.
    //П-регулятор формула: М = Кр(Хзад — Хизм)
    Ureg = ((Overload*100-reg_overload)*Kreg)/100;
    res_last=255-Ureg;
    if (res_last>255){
    res_last=255;}

    if (res_last0)
    {
    Overload—;
    }
    else
    {
    Overload==0; //чтобы не перескочить через 0
    };
    break;
    case 2:
    if (Overloadadc_data)
    {
    RESALT=adc_data_last; // берем прошлое значение выгружаем
    adc_data_last=0;
    adc_data=0;
    }

    else {
    adc_data_last=adc_data;
    read_adc(0);
    };

    regulator();
    #asm(«sei») // ставим разрешение на прерывания
    keyboard();
    };

    void main(void)
    {
    PORTB=0x03;
    DDRB=0x00;
    PORTC=0x00;
    DDRC=0x00;
    PORTD=0x00;
    DDRD=0xff;
    PORTD=0x50;
    TCCR0=0x00;
    TCNT0=0x00;
    TCCR1A=0x00;
    TCCR1B=0x00;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
    ASSR=0x00;
    TCCR2=0x00;
    TCNT2=0x00;
    OCR2=0x00;
    MCUCR=0x00;
    TIMSK=0x00;
    ACSR=0x0B;
    SFIOR=0x08;
    ADMUX=ADC_VREF_TYPE & 0xff;
    ADCSRA=0xA4;
    SFIOR&=0x1F;
    lcd_init(20);
    lcd_clear();
    #asm(«sei»)

    while (1)
    {
    keyboard();
    };
    };
    это проба регулятора, еще как бэ в процессе, так вот при оцифровке сигнала с ADC0 ищем максимум входного сигнала, а потом обрабатываем значение, студия показывает что в DATA memory ничиная с 0458 0459 сохраняются значения и постепенно занимается все свободное пространство вместе с тем что было отведено под переменные, соответственно поисходит сбой и виснет МК. Не пойму почему ведь я не сохраняю промежуточные данные. ПЛЗ Хелп.

    1. Так трудно сказать. Код — каша нечитабельная. Еще и форматирование побил, не чтобы в кодохранилище наше кинуть и ссылку дать. Скорей всего у тебя гдет не проверяется размер буфера. От того данные валятся от сих и до границы памяти. А также как то криво настроена АЦП (на непрерывное преобразование?) и каждая сработка пихает данные в буфер. Вот туда и копай.

      1. Ну я еще не волшебник ….
        Спасибо за наводку. Нашел, у меня сразу присваиваю значение регистра,
        adc_data=ADCH;
        writebuff();
        а нужно выгрузить из регистра, return ADCH.
        return ADCH;
        writebuff();
        пошел учиться дальше…

  53. Привет.
    Возникла пара вопросов.
    1) Есть некий датчик. По даташиту выходное напряжение 2,7-5,5. Я так понимаю нужно поставить резистор, чтобы на нем падали 2,7В, получаем диапазон 0-2,8. Ставим ИОН на 2,8 и дальше работаем. Ход мысли верный или где-то наступил на грабли?

    2) А как поступить если будет несколько (в моем случае три) разных датчиков, и соответственно опорные напряжения нужны будут разные (2,8; 3,1; и примерно 3,5 )? Ставить самое большое и потом отбрасывать часть отсчетов при вычислениях или есть другие пути?

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

  54. Помогите с таким вопросом: делаем выравнивание по левому краю,из ADCH берем 8битный результат.
    Как этот результат преобразовать в 3 десятичных разряда для вывода на 7сегментный индикатор или на LCD.

    1. Ищи алгоритм bin2bcd преобразование.

      А если на сях, то просто:
      sotni = value/100;
      deci = (value%100)/10;
      edin = (value%100)%10;

  55. Добрый день!

    Подскажите, ставлю в AVRStudio выравнивание АЦП по левому краю, т.е. ADLAR = 1, но почему-то не могу руками выставить никакой код во время отладки (debugging). Выставляется только по правому краю значения. Почему? Это косяк или что-то упустил из виду?

    Спасибо.

  56. Добрый день. Интересует следующий вопрос. Для отслеживания напруги на литиевом аккуме, на нем постоянно висит резистивный делитель на 100 и 300 к, что дает нам утечку где-то 10 мкА, что не очень критично. Среднюю точку этого делителя я завожу на АЦП, в атмегу8. Питание на атмегу подается через управляемый стаб LP2980-3,3 (либо ADP3309). Проблема в чем — когда стаб отключен, то через этот резистивный делитель и вход ацп на линию питания пролазит где-то 1 вольт. Убираю делитель — все по нулям. Как-то нехорошо выходит. Или ставить полевик, чтобы он открывался только при включении стаба, или еще как-то, но как избавиться от этого паразитного питания?

  57. да, скорее всего так и поступлю в будущем, но сейчас уже 4 платы ждут сборки. Решил пока забить на это дело, резисторы воткнул по 470К, утечка незначительна, но напруга все равно лезет — 0,6 вольта.

  58. Как лучше поступить с выводом AREF, если в качестве ИОНа используется напряжение питания? Оставить не подключенным, или соединить с питанием? (мега16.)

  59. Сталкнулся с такой проблемой. МК Atmega8-16PU (DIP28), 16Mhz. Настраиваю АЦП, считываю поочередно значения с каналов АЦП0 ->АЦП5 (все 6 каналов). А вот значения от ацп проходят со смешением по каналам. Поясню, значение с АЦП5 выводится как-будто с АЦП0 снято. АЦП1 как будто с АЦП2, ну и так далее. Не могу найти где ошибка. листинг настройки прилагаю http://easyelectronics.ru/repository.php?act=view&id=126, ну а в программе использую вот так:

    /////////////////////////////
    unsigned int c0=ACP(0);
    _delay_ms(10);

    unsigned int c1=ACP(1);
    _delay_ms(10);

    unsigned int c2=ACP(2);
    _delay_ms(10);

    unsigned int c3=ACP(3);
    _delay_ms(10);

    unsigned int c4=ACP(4);
    _delay_ms(10);

    unsigned int c5=ACP(5);
    _delay_ms(10);

    nlcdStringXYP(13,2,white, black, PSTR(«САП»)); Dig_4(19,2,c0);
    nlcdStringXYP(13,4,white, black, PSTR(«АКБ»)); Dig_4(19,4,c1);
    nlcdStringXYP(1,3,white, black, PSTR(«НАПРЯЖЕНИЕ»));

    nlcdStringXYP(12,6,white, black, PSTR(«LM317»)); Dig_4(19,6,c2);
    nlcdStringXYP(12,8,white, black, PSTR(«L7805»)); Dig_4(19,8,c3);
    nlcdStringXYP(12,10,white, black, PSTR(«Вент»)); Dig_4(19,10,c4);
    nlcdStringXYP(1,8,white, black, PSTR(«СЕНСОР «));

    nlcdStringXYP(1,12,white, black, PSTR(«СИЛА ТОКА»)); Dig_4(19,12,c5);

  60. Люди добрые.
    У меня в AVR studio в симуляции, не хочет начинаться преобразование «по условию». не реагирует ни на переход в sleep-режим(ADC_noise), ни на флаги прерываний таймера(пробовал по OVF и comp.
    С кодом проблем не увидел, инициализирую для каждого случая верно, режимы одиночного и непрерывного(без условий) преобразования работают. Отдельно принудительной установкой ADSC запускается. Установка же этого бита по условию не происходит.
    Студия вообще моделирует такие вещи?

  61. Добрый день! В ассемблере я чайник, поэтому не пинайте сильно, пожалуйста. Пытаюсь скомпилировать код из приведенного вами первого примера, но что-то не получается. Я раскомментировала все строки, и компилятор выдает ошибку: ADEN — Unknown instructiion or macro. Почему он не знает этот бит? В подключаемом файле m26def.inc есть его описание. Что я делаю не так?
    И еще вопрос. Где после инициализации находятся данные, снятые с АЦП?

    1. Все, я поняла — раскомментровать было ошибкой. Теперь все компилируется. Остался главный вопрос — как получить данные, снятые с АЦП?

      1. Данные с АЦП сваливаются в регистровую пару 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 — по левой.

  62. Подскажи ДИ:
    как настроить и опрашивать АЦП, в теле while{…} без прерываний, скажем 10 раз в секунду..
    Нужно оцифровывать вход АЦП… от 0..5В
    и от значения выгонять частоту.. так вот если использовтаь прерывания по АЦП то получаются «окна» в частоте.. чуть направьте, голова не варит(

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

  63. вопрос по инициализации ИОН

    > По дефолту там стоит REFS1..0 = 00 — внешний ИОН, подключенный к входу AREF

    т.е. по идее, сразу после «запуска» — АЦП инициализируется с внешним ИОНом?

    тогда, небольшая непонятка
    отрабатываю/разбираюсь с АЦП в arduino-nano
    если не инициализировать ион командой

    analogReference(EXTERNAL);

    то, по умолчанию Aref сконфигурирован на работу от «какого то» внутреннего источника (т.к. на нем, в таком случае, болтается напряжение, видимо около 5В, которое «утекает» на внешн. цепь с внешним TL341)

    если принудительно вставляем

    analogReference(EXTERNAL);

    то все нормально :о)

    какие будут идеи?
    спасибо

    1. А если без ардуино? У нее же в загрузчике может быть какая угодно инициализация. В конце концов тебе никто не запрещает ничего не делая взять и выплюнуть этот регистр в уарт и посмотреть что там изначально лежит.

  64. билин жешь, ну точно! совсем забыл про «дефолт инициализацию в загрузчике как им там взаблагоразумится»

    спааасииибооо!!!

  65. В мануале говорится, что точность при оптимальной частоте 2 младших разряда, и » If a lower resolution than 10 bits is needed, the input clock frequency to the ADC can be higher than 200kHz to get a higher sample rate». Как при повышении частоты понять, какая точность будет у итоговых измерений?

Добавить комментарий

Ваш e-mail не будет опубликован.

Перед отправкой формы:
Human test by Not Captcha