AVR. Учебный курс. Использование аналогового компаратора

Есть почти в каждой AVRке, такая полезная приблуда как аналоговый компаратор. Это уже почти стандартное устройство и встречается очень часто во множестве разных контроллеров. Даже в древнем, как говно мамонта, АТ89С2051 он уже есть. Штучка прикольная, позволяет сравнивать два аналоговых сигнала и выносить свой вердикт 0 первый больше второго, 1 второй больше первого.

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

Например, на входе у нас 8 вольт. Со стабилитрона, рассчитанного на 3.3 вольта, выходит всегда одно и то же напряжение — 3.3 вольта. А с симметричного резистивного делителя выходит половина напряжения то есть 4 вольта. 4 это больше чем 3.3, (3.3 — 4 = -0.7 результат меньше нуля) с компаратора выходит 0

Теперь если просядет батарейка и напряжение снизится до 6 вольт, то с делителя будет уже 3 вольта, а с опорного как было 3.3 так и осталось. Зато теперь на компараторе ситуация в корне поменялась — 3 меньше чем 3.3 (3.3 — 3 = 0.3 результат больше нуля) , а значит на выходе у него будет 1

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

Настройка компаратора в контроллере AVR ATMega16
Для других моделей AVR все очень и очень похоже, просто мне так удобней. Если будет затруднение спросишь в комментах.
Мега16 имеет на борту компаратор, со входами AIN0(прямой вход) и AIN1(инверсный вход) Чтобы компаратор заработал его выводы нужно подключить на вход (DDR=0) и отключить подтяжку до единицы (PORT=0).

Регистр конфигураций компаратора ACSR
Биты:

  • ACD включение компаратора 0 включен, 1 выключен. По дефолту там ноль, а значит при старте компаратор включен.
  • ACBG — подключение к прямому входу компаратора внутреннего источника опорного напряжения (ИОН) на 1.22+(-)0.05V. Если 0 то ИОН не подключен.
  • ACO — бит результата. Собственно, это и есть выход компаратора.
  • ACI — флаг прерывания. Я думаю, что ты уже привык к тому, что в AVR есть прерывание на каждый чих. Компаратор не исключение. Устанавливается по событию, сбрасывается после ухода на обработчик либо программно, как всегда, записью в него 1.
  • ACIE — где есть прерывание там должен быть и бит разрешения. Это он и есть. Установив в 1 мы разрешаем прерывания от компаратора. По дефолту, естественно, нуль.
  • ACIC — подключение компаратора к схеме захвата таймера1. При попадании сигнала на схему захвата текущее значение с таймера тут же тырится в специальный регистр захвата, а таймер продолжает считать дальше. А в привязке к компаратору это удобно когда нужно измерять длительности сигналов.
  • Биты ACIS1:ACIS0 определяет условие возникновения прерывания от компаратора:
    • 00 — любое изменение на входе.
    • 01 — зарезервировано для следующих поколений
    • 10 — переход с 1 на 0
    • 11 — переход с 0 на 1

Вот за что люблю АТМеги так это за фарш! Даже свой собственный источник опорного напряжения есть. Так что из схемы со стабилитроном можно смело выкинуть все, что касается стабилитрона :) Оставив только делитель, ну и подобрав плечи резисторного делителя так, чтобы получить напругу на выходе чуть выше чем 1.22V.
Мало того, если в контроллере есть АЦП, то на вывод AIN1 можно подключить ЛЮБОЙ вход АЦП. Нереально круто! Для того, чтобы это сделать нужно:

  • В регистре SFIOR (регистр специальных функций) выставить бит ACME (вроде бы так ракеты назывались в мультике про койота и страуса ;) )
  • Выключить АЦП, сбросив бит ADEN в регистре настроек АЦП (ADCSRA)
  • В регистре ADMUX в разрядах MUX2:MUX1:MUX0 указать номер входа АЦП.

Пример:
В качестве примера я возьму своего робота. Сварганив ему систему контроля за питанием. Напряжение с аккумулятора проходит через делитель 1.5:10 в результате на 12 вольтах у нас на выходе будет (1.5/(1.5+10))*12=1.56 и только при просадке напруги до 9.5 вольт на выходе делителя будет ниже 1.22 вольта. Заюзаю пока неиспользованный вход PC5 (это вход ADC5)
Заправлю его через АЦП в компаратор, а в качестве опорного напряжения возьму встроенный ION который посажу на AIN0 изнутри. При просадке напряжения буду зажигать контрольную лампу.

Что нам нужно:
Для начала подключить ИОН — бит ACBG
Далее, бит прерывания — в обработчике прерываний я включу лампочку
Ну и выставить условие по которому будет прерывание с 0 на 1. Дело в том, что на плюс-вход компаратора идет 1.22 с ИОН, а на минус-вход пойдет 1.5 с делителя. В результате 1.22-1.5<0, следовательно на выходе 0. Ну, а как только ситуация поменяется будет 1.

1
2
3
4
5
6
7
8
9
10
11
; Инициализирую компаратор
	LDI	R16,(1<<ACBG)|(1<<ACIE)|(1<<ACIS1)|(1<<ACIS0)
	OUT	ACSR,R16	; Забрасываем в регистр
 
	IN	R16,SFIOR	; Достаем SFIOR
	ORI	R16,(1<<ACME)	; Выставялем в нем бит ACME
	OUT	SFIOR,R16
 
; АЦП у меня по дефолту вырублен, поэтому пока не напрягаюсь с его отключением
	LDI	R16,5		; подаю напругу на 5й вход АЦП
	OUT	ADMUX,R16

Ну и собственно все, осталось только добавить в программу переход по вектору

1
2
3
4
5
6
	.ORG	ACIaddr		; Analog Comparator
	RJMP	Battary_LOW
 
;И добавить где нибудь в программе обработчик прерывания
Battary_LOW:	LIGHT_ON	; Вызов макроса зажжения огня.
		RETI		; Выход из прерывания.

Или вот, второй пример. Попроще.

На компаратор подается два напряжения. Одно опорное, со стабилизатора 3.3 вольта демоплаты Pinboard. Второе с потенциометра, то которое мы сравниваем. Подаются напрямую на выводы компаратора AIN0 и AIN1
Когда напряжение с потенциометра выше чем 3.3 вольта с стабилизатора, то в компараторе у нас на выходе 0 (бит ACO=0). И наоборот. Также настроено прерывание так, чтобы при попадании в него происходила инверсия бита PD4 — на нем висит светодиод LED1

Код
Обработчик прерывания:

1
2
3
4
5
6
7
8
9
COMP_OK:	PUSHF				; Сохранили флаги
		PUSH	R17			; Сохранили R17
 
		INVB	PORTD,4,R17,R16		; Инвертировали бит PD4
 
		POP	R17			; Достали все из стека
		POPF				; И флаги тоже
 
		RETI				; Вышли

Инициализация периферии:

1
2
3
4
5
6
7
8
9
10
11
; Internal Hardware Init =======================================
 
;Comparator Init
		OUTI	ACSR,1<<ACIE|1<<ACIS1|1<<ACIS0	; Разрешаем прерывание
							; Ловим 0-1 переход.
; Ports Init
		SBI	DDRD,4
		SBI	DDRD,7
 
		SEI
; End Internal Hardware Init ===================================

Главная программа:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; Main =========================================================
Main:		IN	R16,ACSR	; Взяли состояние компаратора
		ANDI	R16,1<<ACO	; Оставили только бит состояния
 
		BST	R16,ACO		; Скопировали его в Т
		BLD	R16,7		; Выгрузили в 7й разряд R16
 
		IN	R17,PORTD	; Взяли значение из PORTD
		ANDI	R17,0b01111111	; Подавили значение 7го разряда
 
		OR	R17,R16		; Наложили на него значение ACO
 
		OUT	PORTD,R17	; Вернули значение в порт.
 
		RJMP	Main

Светодиод LED3 показывает состояние бита ACO, а LED1 фиксирует заходы в обработчик прерывания компаратора. При этом наблюдается мерзкий эффект — когда сравниваемые напряжения на входах компаратора очень близки, то возникает дребезг. Т.е. мельчайшие помехи уже начинают играть роль и перевешивают чашу весов компаратора то в одну то в другую сторону. Возникает жуткий дребезг. Этот дребезг надо подавлять программно. Скажем игнорировать изменения сигнала если он чаще чем раз в несколько миллисекунд.

На видео дребезг очень хорошо видно на экране осциллографа.

109 thoughts on “AVR. Учебный курс. Использование аналогового компаратора”

      1. В документации на ATmega8A говорится:
        ACBG: Analog Comparator Bandgap Select
        When this bit is set, a fixed bandgap reference voltage replaces the positive input to the Analog Comparator. When
        this bit is cleared, AIN0 is applied to the positive input of the Analog Comparator. See “Internal Voltage Reference”

        В Internal Voltage Reference:
        ATmega8A features an internal bandgap reference. This reference is used for Brown-out Detection, and it can be
        used as an input to the Analog Comparator or the ADC. The 2.56V reference to the ADC is generated from the
        internal bandgap reference.

        Про 1.22 не нашел. Такой цифры в документе вообще нет.

  1. Что-то я читаю даташит на мегу8 и не пойму…
    «ATmega8 features an internal bandgap reference. This reference is used for Brown-out Detection,
    and it can be used as an input to the Analog Comparator or the ADC. The 2.56V reference
    to the ADC is generated from the internal bandgap reference.»
    Так там 2.56В или 1.22 внутреннее опорное напряжение?

      1. “ATmega8 features an internal bandgap reference. This reference is used for Brown-out Detection,
        and it can be used as an input to the Analog Comparator or the ADC. The 2.56V reference
        to the ADC is generated from the internal bandgap reference.”

        Какая страница в даташите?

  2. «Теперь если просядет батарейка и напряжение снизится до 6 вольт, то с делителя будет уже 3 вольта, а с опорного как было 4 так и осталось.»

    «Со стабилитрона, рассчитанного на 3.3 вольта, выходит всегда одно и то же напряжение — 3.3 вольта.»

    Опечатка?

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

  3. Что-то я не понял. На http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh128/9.htm написано «Аналоговый компаратор сравнивает уровни напряжений на неинвертирующем входе AIN0 и инвертирующем входе AIN1. Если напряжение на неинвертирующем входе AIN0 превышает напряжение на инвертирующем входе AIN1, то выход аналогового компаратора ACO принимает единичное состояние.» Тут же все наоборот. Где же правда?

  4. Где-то читал, что при использовании встроенного АЦП выводы порта АЦП нельзя использовать на вывод, иначе это приведет к погрешности измерения, так вот вопрос: нельзя или не желательно? И к использованию входов АЦП как входов компаратора это тоже относится? т.е. если я сконфигурировал один вход АЦП как вход компаратора, могу ли я остальные выводы порта использовать на вывод?

    1. В смысле как входов компаратора? В режиме диф входа чтоль?

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

      1. В качестве входа компаратора: «Мало того, если в контроллере есть АЦП, то на вывод AIN1 можно подключить ЛЮБОЙ вход АЦП. Нереально круто!» — т.е. через мультиплексор АЦП один вход порта на компаратор, а остальным на вывод работать никто не запрещает? Спасибо за ответ.

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

      1. Вроде можно хоть 1000в, хоть переменного напряжения, но через резистор R=U/I=1000В/1ма(?)=1000 килоом. Диоды отправят этот +1 ма тока в источник питания, там его должны скушать другие нагрузки. Вытекающий -1 ма берется с «земли» не важно.
        Я так понимаю там диоды, положительное напряжение отправляют в питание, отрицательное в «землю». При небольших токах напрежения не превысят указанные в описании. Вопрос только в мощности тех диодов. Можно прикольнуться теоретически подать питание +5в на reset, 0 на вход какой-нибудь, мало кто поймет как оно работает от такого «паразитного» питания :)

  5. Напряжение батарейки можно проще мерить.
    Включаем АЦП. Опору переключаем на лапку AVcc, а номер канала измерения ставим = 14 (0x0E) (для меги48, уточняйте в даташите). В итоге вход АЦП подключается к внутренней опоре.
    Получаем работу от противного: мерием точный сигнал относительно плавающей опоры.
    Пусть батарейка заряжена до 2,2 вольт, опора в м48 == 1,1В. Значит АЦП вернёт 127 (256/2). При напряжении 3,3 вольта вернёт 85 (256/3).
    Без единой внешней детали получаем ЗНАЧЕНИЕ напряжения батареи, да ещё и достаточно точно.
    Способ работает (впрочем, это документированая фича АВР), реализовал в железе пару раз.

      1. Напряжение на батареи питания можно мерить RC цепочкой. Разряжаем конденсатор (транзистором или ножкой контроллера включенной на выход с 0 на выходе), ногу переключаем на вход. Конденсатор начинает заряжаться через резстор от источника питания, 0.1в, 0.2в ю… 1.0в, 1.1в, тут бац сработал компаратор! время заряда конденсатора пропорционально напряжению. От +2в конденсатор будет заряжаться в 100 раз дольше чем от +200. Кондер можно поставить от 10 пикофарад, 10 000 пикофарад или 10 микрофарад (лучше керамический), чем дольше заряжается тем точнее формально измерение. 5 тиков дадут точность 1/5, 5 млн. тиков 1/5 млн, 20 бит точности, реально конечно будут шумы компаратора, дрейф нуля, плавание емкости конденсатора и сопротивлений левых. Но сам принцип помоему верен. И контроллер может не только грубо сравнивать напряжение в норме или нет, но и взять его с точностю до микровольт, используя только компаратор :)
        Если условия еще более суровые, компаратора нету, можно использовать любой вход как компаратор, только напряжение сравнения там не такое точное 2в вроде. Переключились в ноль, кондер разрядили, переключились в Z ждем на входе еденицу и считаем тики. 100 тиков — 1В, 1000 тиков — 10В и тому подобное.
        Бысрые сигналы так мерить понятно что нельзя, а напряжения питания как-раз. И нога остается свободной частично, светодиод можно повесить например, на выход +5В светодиод горит, конденсатор не мешается, а резистор от внешнего напряжения только добавит яркости :)Для разных ATtiny может быть актуально )))

        1. Так себе способ. У конденсаторов разброс параметров значительно больше чем у резисторов. Значит надо либо подбирать C из кучки перед установкой, либо подбирать R, либо ставить подстроечник, либо вводить возможность юстировки в программу. Да и кода при таком способе больше :)

  6. Извини, но что то в описании компаратора, в даташите, фигурирует опорное напряжение 2,56 В.
    Cluster пишет что разобрался — у меня как то неполучаается.

      1. Согласен, но ссилка в даташите на эту величину идет как для АЦП так и для компаратора. А вот упоминания про 1.22 нигде ненашол. Я даже пробовал тупо искать значение 1.2 :(

        Ладна, покопаюсь нормально в доке, может пропустил чего типа «но если через … тагды все ОК»
        Спасибо за ответ !!!

        1. В даташите на Мега8535 идет отсыл на страницу 41, где описан Internal Voltage Reference и указано, что есть
          Bndgap reference voltage min1.15 typ1.23 max1.35V И используется он для схемы BOD, но при желании его можно замкнуть и на компаратор
          Как я понял, это напряжение от встроенного ИОН на 2.56 деленое пополам резисторами.

  7. Парни подскажите не могу понять.
    Использую Attiny 2313, могу ли я ногу AIN0 использовать как вход/выход, подключив к компаратору внутренний ИОН, напряжение проверять инверсным входом AIN1, при срабатывании компаратора ждать прерывания:
    outi ACSR,(3<<ACIS0)|(1<<ACIE)|(1<<ACBG)?

    То есть, можно ли работать с компаратором только по ноге AIN1?

    1. Может вопрос поставлен некорректно, попробую еще раз.
      Для моей программы компаратор не главное устройство, но желательное (дополнительные функции), но использовать оба входа нет возможности (не хватает лап для главного).
      Так вот, можно ли использовать внутренний ИОН, ногу AIN1 использовать как измерительный вход компаратора, при этом на ногу AIN0 повесить светодиод и периодически им помигивать?!.
      ;)

        1. С английским не знаком, пришлось почитать с помощью товарища. Ничего нет, написано, что либо используется внешний ИОН, либо внутренний. Ставил эксперимент в AVRStudio и Proteuse, не пошло (хотя, это может быть глюк Proteusa). Железяку пока не купил. :(

  8. Всем привет.
    Я новичок в области микроконтроллеров и меня тут возник такой вопрос, насколько я понял из даташита (atmega32), если в регистре SFIOR прописать 011, включить ADEN и ADATE (заодно и ADIE),то при прерывании на сравнение в счетчике0 в бит ADSC будет записываться 1 и АЦП начнет свою работу (и так каждый раз при прерывании счетчика0), для того чтоб все это дело проверить и не писать зря код, я запустил АВР студию и ручками проставил все значение и стал жать F11, но так и не увидел 1 в бите ADSC, так в чем же все таки проблема, может я чето не понял из даташита? да и при наведении курсора в аврСтудии на бит ADATE вылазет сообщение в котором много чего написано про таймер-счетчик2(что тоже не совсем понятно так-как в даташите указано 8 источников если бит ADATE установлен).
    Помогите кто может…

  9. Хотелось узнать подробней о схеме захвата. Попробывал реализовать — не срабатывает. Что я делал: включил компаратор, подключил к схеме захвата таймера1 битом ACIC, прерывания от компаратора выключил, прерывания по захвату в таймере — включил. Запускаю в студии. Пробую сначала в один момент вручную поставить флаг прерывания компаратора (самого-то прерывания, естественно не будет, в железе флаг-то появится и предполагаю, что произйдет работа схемы захвата). Ничего не меняется.
    Потом пробую флаг захвата таймера1 Input Capture Flag 1 вручную установить. Возникает прерывание. Но наблюдаю за изменением в регистраз ICR1H и ICR1L — ничего в них не менятся, как были нули так и остались. А по идеи там должно появить состояние региров TCNT1H и TCNT1L. Что я ещё забыл?
    Код залил сюда http://slil.ru/28285895
    DI HALT, кстати, я там переменную в ОЗУ объявил, можешь глянуть правильно или нет, и правильно ли я с ней работаю в прерывании. Компилятор вроде ошибок не нашёл.

  10. Здравствуйте. Прошу помощи по следующему вопросу:
    1) Собрал на mega8 вольтметр, который через com порт передает значение АЦП на компьютер и там строит график. Работает нормально если измеряет напряжение на полностью развязанном от сети источнике напряжения (батарейка).
    2) Подключил к схеме ЛАТР-выпрямитель-конденсатор-делитель 100/1 (на выходе 1 в) . Контроллеру тут же настала …она.
    3) Причина — согласно осцилограмме COM порт подводит к нулю контроллера реальную землю и соответственно на АЦП размах в 380 вольт. От лабораторного блока питания размах поменьше но все же гораздо выше 5 в.
    4) Вопрос в следующем — какие существуют способы решения.

  11. 1. Заземление компьютера (или включение в правильную евророзетку). Без заземления на корпусе компа ~120В и ток в толи мА
    2. Опторазвязка схемы, запитка схемы от неимпульсного БП, там теже фильтры из конденсаторов, лучше от батарейки или трансформатора (есть еще специальные трансы с малой емкостью между обмотками)

  12. такая проблема:
    сконфигурировал порты, настроил ACSR (выставил условие прерывания, разрешил прерывания, запустил компаратор, опорное внешнее). в аврстудио ковырял, ковырял — не срабатывает прерывание… если самому поставить флаг, то все отлично, а вот при изменении результата флаг почему-то не ставиться…
    подскажите пожалуйста, где может быть косяк? поставил платформу тиньки15, перед этим обновил среду до 4,17. может дело в студии?

  13. Ув, Di, второй день мучаюсь с компаратором в Меге32. Вроде бы работает, но крайне неустойчиво как-то. AIN0 подключен к внутреннему ИОН, на AIN1 — 2в. Суть проблемы — при включении питания компаратор часто срабатывает. Причем и при быстром выключении-включении ИП и в случае, если выключаю ИП и даю возможность емкостям разрядится. Как это привести в порядок? И еще вопрос, надо ли запрещать прерывания до (или на время) инициализации компаратора? И в какой последовательности правильно инициализировать начинку МК??

    1. Исходное состояние бита ACI (флаг прерывания) == 0, то есть сразу после разрешения глобальных прерываний прерывание компаратора срабатывает.
      Выход — сбросить бит ручками ПОСЛЕ инициализации компаратора:
      ACSR |= (1 << ACI);
      Записывать этот бит во время основной инициализации регистра ACSR не помогает, надо именно после полной инициализации компаратора, но до SEI.

  14. я только начал разбиратся с контроллерами…и есть такая задача сравнить освещение двух фотодиодов и если один освещен больше то начать вращать двигатель через Н-мост в одну сторону а если второй до в другую сторону….как посоветуете это сделать??? я думаю проще всего через компаратор…но в програмировании темболее на асме только начал разбираться…прошу накидать примерный текст программы (кому не впадло) с коментариями.
    Большое спасибо!!!

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

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

    1. Компаратор не показывате величину разницы, он показывает что одно больше другого. Успеет он и кондер обслужить. Другой вопрос успеет ли контроллер обработать это время?

      А чтобы ловить напряжение между чем то и чем то надо либо:
      -два компаратора
      -АЦП
      -Быстро менять опорное напряжение при прохождении контрольных точек.

      1. Никак не могу понять, что даст если быстро менять опорное напряжение? Ведь с конденсатора идет разряд напряжения, а если еще менять опорное, то будет что-то непонятное… И как можно поймать напряжение с помощью двух компараторов? DI HALT, будь добр — разъясни картину. Заранее благодарен.

          1. Идея такая: Имеется переменный резистор, сопротивление которого непрерывно меняется. Нужно сравнить два напряжения, снимаемых с этого переменного резистора с разницей во времени t (пусть для примера t=1 секунда). Подробнее: В данный момент времени t1 напряжение на резисторе U1, через некоторый промежуток времени (пусть для примера 1 секунда) на переменном резисторе будет напряжение U2. Нужно сравнить два этих напряжения U1 и U2. Но поскольку они различны во времени, то я хочу использовать для запоминания напряжения U1 конденсатор, а напряжение U2 будет как опорное. Таким образом, одно напряжение (U1)подается для сравнения с конденсатора, а второе непосредственно с переменного резистора. Но проблема в том, что напряжение с конденсатора непостоянное, т.к он будет разряжаться и мне нужно поймать самое максимальное напряжение на кондере. То есть, мне нужно сравнивать максимальное напряжение на конденсаторе(U1) и напряжение с переменного резистора (U2). Отсюда вопрос как это можно сделать? Возможно ли это сделать с помощью компаратора или есть другие варианты?

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

              Либо сделай АЦП из аналогового компаратора, как я уже писал в статье:
              http://easyelectronics.ru/avr-uchebnyj-kurs-delaem-acp-iz-analogovogo-komparatora.html

  16. Доброго дня!!!!

    Вопрос. Обязательно ли использовать прерывание по КОМПАРАТОРУ для запуска действия чего-то в прогамме или можно считывать бит ACO и по результату что-то в программе запустить? Задача простая: мигать, отслеживая состояние компаратора (значение бита ACO) . Если изменилось значение ACO, то мигать подругому. Или без прерывания никак? Сделал программу без прерывания, прошил tiny13 — работает! Или использование прерывания — красивый стиль написания программы?

    С уважением.

    1. Да нет конечно. Но сам посуди — в высокозагруженной программе тебе придется делать еще прорву разных вещей, а не только ждать флага. Конечно его можно и проверять, но как часто это будет происходить? И не прозеваешь ли ты важное событие, которое этот флаг может сигнализировать? А так, на прерываниях, у нас на всем готовом. КОгда надо позовут к обеду :)

  17. Здравствуйте!
    Полный бред какой-то с этим компаратором…

    batok=1;
    //lcd_putsf(«BAT OK»);
    delay_ms(800);
    ACSR=0x4A;
    SFIOR=0x00;
    delay_ms(800);
    #asm(«sei»)

    После RESET’a или включения питания, если на входе меньше 2.2В, срабатывает сразу после sei. Ровно 1 раз. На наводку слабо похоже: целый вольт все-таки…

    В какую сторону поковырять?

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

      1. Компаратор включен, положительный вход подключен к опорнику, прерывание по спаду…

        И главное, если начать с 5В и постепенно снижать напряжение, все срабатывает как надо — на 1.3В.

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

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

  18. добрый вечер. Возникла необходимость задействовать компаратор на tiny13. Решил попробывать в симуляторе для начала. В кодвижне пишу следующее:
    PORTB=0x00;
    DDRB=0x00;

    ACSR=1<<6 | 1<<1 | 1<1.
    компилирую и запускаю авр студию.
    в студие в регистр аcsr записываються биты 0 и 1, а так же остальные по 5тый.. А вот 6 не хочет записываться. Только если вручную поменять его значение. В чем ошибка, почему не пишиться 6 и 7 бит? Спасибо.

    1. Не понял, что вот такая конструкция не работает? :

      1
      
      ACSR = 1<<7|1<<6|1<<4|1<<3|1<<1 // устанавливаем биты 7,6,4,3,1

      Также обрати внимание на то, что в ACSR есть биты работающие ТОЛЬКО на чтение?
      Это биты 5 и 2

  19. глюк какой то — дома только что вставил свой же кусок кода и все заработало. в 6 бит 1 прописалась. а на роботе не записывался. сниму скриншот и покажу. и еще один вопрос:
    «Биты ACIS1:ACIS0 определяет условие возникновения прерывания от компаратора» — если задать этими битами условие срабаывания скажем 1->0 но без разрешения прерывания, компаратор будет отрабатывать переход 1->0 или будет просто работать и сравнивать ain0 ain1 ?

  20. Доброго времени суток всем!
    Вот поставил себе цель изучать МК семейства AVR, но что меня в основном сподвигнул этот сайт, за что вам всем (особенно DI HALT’у)!
    Дошёл до аналогового компаратора. В студии пишу следующий код:
    http://easyelectronics.ru/repository.php?act=view&id=54

    Если вручную установить 1 в ACI, то программа исправно уходит по вектору, попутно сбрасывая ACI. Но при попытке вручную установить бит ACO прерывания не происходит (ACI не поднимается). В чём может быть проблема?

    PS Начал изучать AVR не больше месяца назад, так что если глюк на поверхности, просьба сильно не ругать)

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

    1. Цеж симулятор. Он не отрабатывает уж прям на 100%. Проверь в железе (банально в обработчике прерываний диодом мигай и узнаешь зашло туда или нет) Ну и еще зависит от типа события на которое должна быть реакция прерывания компаратора (низкий уровень, фронт 01, фронт 10 и тыды)

      1. Вот это оперативность)

        Пока нахожусь в деревне, посему доступа к железу не имею вовсе(( Поэтому пока что студия + Proteus. В последнем, кстати, тоже программа не работает. Прерывание настроено на переход 10. При этом в самом протеусе видно в паузе, что при изменении уровня на AIN1 выше и ниже 1,22 В соответственно изменяется состояние бита ACO, но никаких действий (со стороны светодиода) не следует.
        А сам код хотя бы правильный?

        1. RJMP Init ;Переход на начало программы
          А где метка инит?

          Еще у тебя корявый обработчик прерывания — не сохраняет нихрена. Ни флагов ни регистров. Пока не критично, а потом будет косяк.

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

          1. Метка инит находится тут:
            http://easyelectronics.ru/repository.php?act=view&id=55

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

            ACO пробовал поднимать, делать несколько десятков тактов, потом опускать, снова такты, снова поднимать и т.д. Реакции — ноль((

        2. Отследи сейчас хотя бы вход в обработчик прерывани. Поэтому выбрось оттуда все кроме установки пина. Тупое поднятие бита. Есть прерывание — есть установка. А при стартовой инициализации сброс его.

          З.Ы.
          а протеус глючное УГ.

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

              А пока считай что оно работает нормально, а прерывание эмулируй чере АСИ

              1. Хм, странное дело… Сегодня утром врубил вместо AVR Simulator AVR Simulator2 с тем же самым кодом. В нём вручную менять ACO и ACI вообще нельзя. Ну да ладно. Откомпилировал, засунул в протеус, и О чудо! оно работает.
                Ради эксперимента вернулся к AVR Simulator, скомпилил, запустил в протеусе, и оно всё равно работает! Правда студия по прежнему не реагирует на установку и сброс ACO.
                После этого усложнил обработчик прерывания — и оно по прежнему работает.
                Это что же , значит даже если всё правильно напишешь, то студия может давать неверный hex на выходе? Или просто мои симуляторы сговорились…

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

  22. DI HALT доброго дня. Собрал в протеусе компаратор и написал код. Прерывание идет. Вот только хотел узнать (хотя выше спрашивали, но давно!). Не будет ли страшно если я в тиньке 13 включу источник опорного напряжения 1,1 на пин AIN0 и при этом настрою этот пин как на выход. Я написал кодик, в протеусе эта ножка на выход не отключая внутрений опрник работает вроде отлично 8) Компаратор тоже фурычит. После завтра буду пытаться в железе проверять. А то жалко тратить 2 ноги на компаратор для 13тиньки. Спасибо.

  23. Чёты лыжЫ у меня не едут…
    Сначала пробовал делать по правилам с прерыванием:
    код
    ADCSRA &= ~(1<<ADEN); // выключаю АЦП
    ACSR = (1<<ACBG)|(1<<ACIE)|(1<<ACIS1)|(1<<ACIS0); // включаю компаратор, прерывание и настраиваю на перепад с 0 на 1
    SFIOR |= (1<<ACME); // подключаю к компаратору коммутатор
    ADMUX = 6; // ставлю в коммутаторе шестой вход.

    ISR(ANA_COMP_vect) { // прерывание

    ON(LED);
    }

    Не входит…

    Попробовал тупо мониторить бит компаратора:
    код
    ADCSRA &= ~(1<<ADEN);
    ACSR = (1<<ACBG);
    SFIOR |= (1<<ACME);
    ADMUX = 6;

    if(ACSR & (1 << ACO) ) ON(LED);
    else OFF(LED);

    Всё равно не работает…

    Понятно, что лед исправен и зажигается из программы и АЦП по этому входу работает, показывает при наличии напряжения на делителе 3,42-4,08 вольт. Собственно ради этого компаратор на вход АЦП и завожу — чтобы включать его только тогда, когда напряжение на контроллируемом входе придёт в норму.

    Что не так?

  24. Насчёт «ACBG — подключение к прямому входу компаратора внутреннего источника опорного напряжения (ИОН) на 1.22+(-)0.05V. Если 0 то ИОН не подключен.» — то есть если выставить этот бит в 1, то с ноги прямого входа компаратора можно будет считывать это самое опорное напряжение? Просто собираюсь делать частотомер примерно синусоидального СИММЕТРИЧНОГО относительно нуля согнала, а чтоб можно было мерить, то надо сместить симметричный сигнал «вверх» на величину опорного напряжения же, не?..

  25. Здравствуйте Уважаемые. Помогите разобраться и написать 2ой пример на Си. Пишу код ниже, но кроме вечно горящего светодиода на PD7 ничего не получаю, меняю значения напряжения на входах ANI от 0 до 2,5В соответственно PD4 не реагирует.

    #include
    #include

    ISR (ANA_COMP_vect) {
    PORTD ^= (1<<PD4);
    }
    //ОСНОВНАЯ ФУНКЦИЯ
    int main(void) {
    //Инициализация переферии
    DDRD=(1<<PD4)|(1<<PD7);
    DDRB=(0<<PD2)|(0<<PD3);
    PORTB=(0<<PD2)|(0<<PD3);
    //ACIE-разрешаем прерывание от компаратора.ACIS1;ACIS0-Ловим 0-1
    ACSR=(1<<ACIE)|(1<<ACIS1)|(1<<ACIS0);
    while (1) {
    PORTD = (ACO<<PD7);
    }
    }

    С уважением Дмитрий.

  26. DHALT ! СПАСИБО ОООГРОМНЕЙШЕЕ !
    Перехожу с цифр. микросхем на современную и удобнейшую сферу микроконтролеров знать о которых у меня была просто мечтой. Я оставил программировать сайты на Jquery так я утратил интерес к такому делу . Но это помогло мне понять страшный язык скриптов также в мире микосхем-контролеров. Огромнейшее спасибо за разьяснение как докопаться до внутр . компаратора прямо из контролера. 15 лет назад я эксперементировал с разными схемотехниками компараторов. На ОУ,триг шмидта 155 серии ,спец-компараторах,генераторах по срыву .
    Протеус поставил в купе с АВР Студио. запускал и изменял коды некоторых программ на АСМ
    …. Спаибо за Ваши безценные статтьи !!!!

  27. Есть вопросик на засыпку,на счет схемы,если я перекину стабилитрон и резистор 1 на неинветируиший вход компаратора а на инветируший вход поставлю резистор 2 и 3,тоесть все получится наоборот,когда напряжение превисит 12 вольт допустим влючится сигнал и микроконтроллер отлючит ту или иную нагрузку например реле,так возможно сделать или нет?

  28. Помоги, пожалуйста. Пытаюсь заюзать компаратор на ATtiny24A и подключить его ко входу ADC0. Вот конфигурация:

    // Comparator
    ACSR |= 1<<ACBG // bangap reference voltage
    | 1<<ACIE; // Interrupt enable
    SBI(ADCSRB, ACME); // Comparator MUX enable
    CBI(ADCSRA, ADEN); // Disable ADC for use MUX
    ADMUX |= 0x00; // Connect PA0 to neg comp input

    Но на чихи на пине PA0 ни симулятор, ни Протеус никак не реагирует…

  29. Совсем не понял я что-то про подключение АЦП к компаратору — в чем заключается преимущество такого подключения? Ведь насколько я понимаю по любому надо подключать делитель напряжения к входам компаратора..

  30. У меня возникла такая идея, мне нужен 14-16 бит АЦП с одним каналом для измерения ОЧЕНЬ медленно меняющегося во времени, и мне бы не хотелось покупать внешний АЦП или просто нечем заняться))) поэтому возникла такая идея
    использовать R2R матрицу для формирования уровня, после чего я хочу на встроенный компаратор подать сформированный мною и измеряемый сигнал, так вот собственно вопрос, сможет ли компаратор обеспечить мне 14-16 может быть 20 бит точности в таком сравнении?

  31. В Proteus-е (версия 8.4) не захотело работать прерывание. Остальные прерывания работают. ACO с ACI выставляются, но на прерывание не переходит — идет дальше по коду. Собрал в железе — все нормально.

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