Программирование AVR AVR401: 8-битный АЦП на компараторе Mon, September 16 2019  

Поделиться

нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

AVR401: 8-битный АЦП на компараторе Печать
Добавил(а) microsin   

В этом апноуте (перевод [1]) описывается, как реализовать 8-разрядный АЦП на компараторе AVR с помощью минимального количества внешних компонентов. В микроконтроллере используется 5 выводов корпуса (см. рис. 1). Пример основан на AT90S1200, но можно использовать любой AVR, у которого есть компаратор.

AVR401 sch fig01

Рис. 1. Схема АЦП на основе компаратора.

Особенности предлагаемого АЦП:

• Очень дешевая реализация при довольно высокой точности (8 бит).
• Автокалибровка устраняет неточность используемых компонентов.
• Измеряемые напряжения от 0 до VCC.
• Максимальное время преобразования: 1.1 мс.

[Принцип работы]

Измерение напряжения основывается на измерении времени заряда конденсатора постоянным током до этого напряжения. Емкость заряжается постоянным током от генератора постоянного тока на транзисторе. По этой причине напряжение на конденсаторе растет линейно. Чтобы разрядить конденсатор, вывод порта AIN0 (PB0) настраивается как выход с выходным уровнем лог. 0. Опорное напряжение VCC/2 создается резистивным делителем Rref1 и Rref2. Когда порты PB2 и PB3 сконфигурированы как входы, опорное напряжение выключено, и уровень напряжения на выводе AIN1 (PB1) будет определяться входным напряжением Vin. Путем настройки портов PB2 и PB3 на выход и подачей на них 0 и 1, уровень на выводе AIN1 будет равен VCC/2 (если резисторы Rref1 и Rref2 одинаковые). Чтобы избежать ошибок измерения, входной резистор Rin должен быть как минимум в 100 раз больше, чем резисторы опорного напряжения Rref1 и Rref2.

Алгоритм преобразования АЦП следующий:

1. Включается опорное напряжение.
2. Включается заряд конденсатора, пока не будет достигнуто опорное напряжение. Время заряда измеряется (Tref).
3. Выключается опорное напряжение и разряжается конденсатор.
4. Включается заряд конденсатора, пока не будет достигнуто входное напряжение. Время заряда измеряется (Tin).

Цикл преобразования показан на рис. 2. Измерение времени выполнено на таймере/счетчике, который расширен до 9 бит с помощью прерывания переполнения таймера (Timer/Counter Overflow Interrupt).

AVR401 Conversion Cycle fig02

Рис. 2. Цикл преобразования.

Предположим, что VCC равно 5V. Соотношение между входным напряжением и опорным напряжением выражается формулой 1:

       Vref · Tin
Vin = ------------                                                   Формула 1
         Tref

Идеальный вывод преобразования - 8-битное число, где 0V соответствует 0 и 5V соответствует 255. Опорное напряжение Vref = VCC/2 таким образом соответствует 128. Формулу можно перезаписать так:

       Tin · 128
Vin = ------------                                                   Формула 2
         Tref

Однако из-за неточности резисторов опорное напряжение Vref может немного изменяться. Чтобы скомпенсировать это, можно выполнить калибровку путем подачи известного напряжения на вход, и сравнить его с опорным напряжением. Если поданное на вход напряжение точно 2.5V, то опорное напряжение Vref можно вычислить по формуле:

        Tref · Vcal     Tref · 128
Vref = ------------- = ------------                     Формула 3
           Tcal            Tcal

Программа AVR написана таким образом, что цикл калибровки запускается удерживанием вывода PB7 в лог. 1 при включении питания. Затем на вход подается напряжение калибровки, на PB7 устанавливается в лог. 0. Это запустит калибровку, и после её завершения значение опорного напряжения сохраняется в EEPROM. Во время нормальной работы АЦП опорное напряжение считывается из EEPROM, и входное напряжение вычисляется по формуле 1.

[Пример конфигурации]

Так как результат преобразования 8 бит, таймер должен обеспечивать счет как минимум до 9 бит, чтобы обеспечить требуемую разрешающую способность. Компоненты должны быть выбраны так, чтобы номинальное время заряда конденсатора до VCC составит около 256 шагов таймера. Поэтому допускается неточность в значении компонентов и при изменениях температуры, которая не приводит к изменению времени заряда больше, чем максимальный период таймера, или не приводит к слишком малому времени, что снижает разрешающую способность преобразования. Чтобы достичь нужной точности, должен использоваться коэффициент прескалера 8 или больше. Timer/Counter0 микроконтроллера AT90S1200 имеет разрядность только 8 бит, поэтому девятый бит должен обрабатываться программно. Следующий пример показывает, как можно выбрать значения компонентов.

Сначала определитесь с тактовой частотой, на которой работает AVR. Если используется кварц 4 МГц, то период тактов составит 250 нс. Если установить прескалер на CK/8, то таймер будет инкрементироваться каждые 2 мкс (250 нс * 8 = 2 мкс). Максимальный период 9-битного таймера составит = 512 * 2 мкс = 1024 мкс. Поэтому установим 2 * TREF на 512 мкс.

Заряд конденсатора постоянным током описывается следующей формулой:

      I
ΔV = --- · Δt                               Формула 4
      C

Мы можем найти требуемый ток, когда будут известны емкость конденсатора, дельта времени и дельта напряжения известны:

     ΔV · C
I = --------                                 Формула 5
       Δt

Конденсатор будет заряжаться до VCC = 5 V, и с конденсатором 220 мкФ генератор тока на транзисторе должен предоставить ток 2.15 мА. Значение RB зависит от коэффициента передачи транзистора hFE. Для транзистора BC558A структуры pnp, значение hFE может быть в диапазоне 125 .. 250. Этот транзистор идеален для нашего случая, потому что любой его возможный hFE подойдет. Чтобы гарантировать, может использоваться любой hFE из диапазона BC558A, в вычислениях используется среднее значение hFE = 188. Результирующий ток базы составит 11.4 мкА.

Транзистор включается путем подачи лог. 0 на ножку порта PB7. Этими значениями тока напряжение база-эмиттер VBE составит около 0.6V. Резистор базы можно найти по формуле:

      VCC + VBE       4.9V
RB = ----------- = ---------- = 430 кОм                           Формула 6
         IB         11.4 мкА

Прим. переводчика: в этой реализации применен очень некачественный источник тока, который сильно зависит от температуры.

Опорное напряжение генерируется делителем цепочки резисторов Rref1 и Rref2. Rin должен быть намного больше этих двух резисторов, чтобы входное напряжение не влияло на опорное. Подойдут номиналы 100 кОм для Rin и 1 кОм для каждого из Rref1 и Rref2.

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

На рис. 3 показана измеренная линейность для кварца 4 МГц и номиналов компонентов, вычисленных в этом примере.

AVR401 Measured Linearity fig03

Рис. 3. Измеренная линейность.

[Реализация]

Программа состоит из нескольких подпрограмм на ассемблере. Подпрограммы reference и convert обрабатывают заряд и интервалы времени. После того, как они выполнят свои действия, основная программа должна произвести нужные вычисления. Это осуществляется двумя подпрограммами, выполняющими деление и умножение, div17u и mul9 соответственно. Также есть две задержки, используемые другими подпрограммами и основной программой. Они используются для полного разряда конденсатора и генерации задержки между преобразованиями.

reference. Подпрограмма reference разряжает конденсатор, включает транзистор и заряжает конденсатор, пока его напряжение не достигнет уровня опорного напряжения. При этом измеряется время между началом заряда и моментом, когда не сравняются напряжения на входах компаратора. Затем конденсатор снова разряжается. Полученное время зарядки будет использоваться позже вместе с временем, которое даст подпрограмма convert, чтобы можно было на основе этих интервалов времени вычислить входное напряжение.

Таблица 1. Характеристики подпрограммы reference.

Параметр Значение
Размер кода 24 слова
Количество тактов ядра Зависит от опорного напряжения
Использование регистров Младшие регистры не используются.
Используется 2 старших регистра.
Используется одна глобальная переменная.

Таблица 2. Использование регистров подпрограммой reference.

Регистр Вход Внутри Выход
R17     Tref - хранит время, за которое конденсатор зарядится до опорного напряжения.
R18   TH - старшая часть счетчика таймера  
R20   temp  

AVR401 Flow Chart for reference fig04

Рис. 4. Алгоритм подпрограммы reference.

input. Подпрограмма input измеряет входное напряжение. Он включает транзистор и заряжает конденсатор до напряжения, эквивалентного входному. Затем конденсатор разряжается. Время, за которое заряжался конденсатор, сохраняется в Tin.

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

Таблица 3. Характеристики подпрограммы input.

Параметр Значение
Размер кода 19 слов
Количество тактов ядра Зависит от входного напряжения
Использование регистров Используется 2 младших регистра.
Старшие регистры не используются.
Используется одна глобальная переменная.

Таблица 4. Использование регистров подпрограммой input.

Регистр Вход Внутри Выход
R14     TinH - старшая часть времени, за которое конденсатор зарядится до входного напряжения.
R15     TinL - младшая часть времени, за которое конденсатор зарядится до входного напряжения.
R20   temp  

AVR401 Flow Chart for input fig05

Рис. 5. Алгоритм подпрограммы input.

T0_int. Это обработчик прерывания таймера, здесь только инкрементируется переменная TH, чтобы реализовать 16-разрядный таймер. Используется только 9 бит счетчика этого таймера.

Таблица 5. Характеристики обработчика прерывания T0_int.

Параметр Значение
Размер кода 2 слова
Количество тактов ядра 9, включая код инструкции возврата reti.
Использование регистров Младшие регистры не используются.
Старшие регистры не используются.
Используется одна глобальная переменная.

mpy9u. Эта подпрограмма реализует умножение 9 x 8 бит. 9-разрядный множитель должен быть сохранен во флаге переноса (это будет старший бит, MSB) и регистре mp9u. Множимое сохраняется в регистре mc9u. Результат помещается в "C:m9uH:m9uL", для него используются те же регистры, что и входные регистры подпрограммы деления. Подпрограмма mpy9u основана на подпрограмме умножения mpy8u, описанной в апноуте AVR200 [2].

Таблица 6. Характеристики подпрограммы mpy9u.

Параметр Значение
Размер кода 11 слов
Количество тактов ядра 83
Использование регистров Используется 3 младших регистра.
Старшие регистры не используются.
Используется одна глобальная переменная.
Используется один флаг переноса C.

Таблица 7. Использование регистров подпрограммой mpy9u.

Регистр Вход Внутри Выход
R0 mc9u - множимое    
R1 mp9u - множитель   m9uL - младшая часть результата
R2     m9uH - старшая часть результата
Флаг переноса C 9-й бит множителя   17-й бит результата
R20   temp - используется как счетчик цикла  

div17u. Эта подпрограмма осуществляет деление 17/16 бит. 17-битное делимое должно быть сохранено в переменной (C:didH:didL) где флаг переноса самый значимый бит. Делитель сохраняется в переменной (divH:divL). Результат сохраняется в (resH:resL), и остаток в (remH:remL). Подпрограмма div17u основана на подпрограмме div16u, описанной в апноуте AVR200 [2].

Таблица 8. Характеристики подпрограммы div17u.

Параметр Значение
Размер кода 18 слов
Количество тактов ядра 209 минимум, 292 максимум
Использование регистров Используется 6 младших регистров.
Старшие регистры не используются.
Используется одна глобальная переменная.
Используется один флаг переноса C.

Таблица 9. Использование регистров подпрограммой div17u.

Регистр Вход Внутри Выход
R1 didL - младшая часть делимого   dresL - младшая часть результата
R2 didH - старшая часть делимого   dresH - старшая часть результата
Флаг переноса C 17-й бит делимого    
R3 divL - младшая часть делителя    
R4 divH - старшая часть делителя    
R5     remL - младшая часть результата
R6     remH - старшая часть результата

Пример программы. В приведенном примере программы постоянно повторяются преобразования. Сначала измеряется время для зарядки конденсатора до опорного напряжения, затем измеряется время зарядки до входного напряжения. Результат выводится в порт D (PD7..PD0) и порт B (PB4, MSB). Перед выводом результат инвертируется, чтобы для отображения результата светодиодами можно было управлять логическим нулем. Этот процесс преобразования повторяется в бесконечном цикле.

Для выполнения калибровки вывод PB7 при включении питания должен быть в лог. 1, и конденсатор разряжен. После этого нужно подать на вход калибровочное напряжение 2.5V, после чего перевести PB7 в лог. 0. Откалиброванное значение Vref сохраняется в EEPROM, откуда оно вычитывается при обычном включении питания (без калибровки).

Таблица 10. Общая производительность.

Параметр Значение
Размер кода 43 слова - только подпрограммы реализации АЦП (без mpy9u и div17u).
147 слов - полный код вместе с тест-программой.
Использование регистров Используется 9 младших регистров.
Используется 5 старших регистров.
Указатели не используются.
Использование прерываний Timer/Counter0 Overflow Interrupt
Использование периферийных устройств Timer/Counter0
Analog Comparator
Ножки портов для АЦП: PB3 .. PB0 и PB7
Ножки портов для вывода результата: PD7 .. PD0 и PB4 (только в тест-программе)

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

Чтобы еще повысить точность, цепочка делителя напряжения для генерации опорного напряжения может быть заменена настоящим генератором опорного напряжения. Тогда можно измерять изменения VCC путем подключения его к делителю напряжения и далее ко входу.

[Ссылки]

1. AVR401: 8-bit Precision A/D Converter site:microchip.com.
2. AVR200: Multiply and Divide Routines site:microchip.com.
3. AVR400: АЦП на основе компаратора.
4. 190109AVR401.ZIP - документация, исходный код.

 

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


Защитный код
Обновить

Top of Page