ADC: аналого-цифровой преобразователь микроконтроллера
[Home] [< Prev: Микроконтроллер + DAC + быстрый синус] [Next: ADC. Описание регистров >]

ADC: аналого-цифровой преобразователь микроконтроллера

Аналогово-цифровой преобразователь (ADC, analog-to-digital converter) - устройство, преобразующее величину входного аналогового сигнала в цифровой код.

Микроконтроллеры из линейки устройств STM32F100xx имеют 12-битовый ADC последовательного приближения на переключаемых конденсаторах (в соответствии с методом последовательного приближения, преобразование выполняется за несколько шагов, требуется по одному шагу на каждый бит результата). Вход ADC может быть подключён к одному из 18 каналов, из них 16 - внешние входы, 2 - внутренние источники сигнала.

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

Простой пример использования ADC
Основные свойства и возможности ADC
Функциональное описание
Тактовый сигнал для ADC
Самокалибровка
Включение и отключение ADC
Выбор канала
Выравнивание данных
Продолжительность выборки
Запуск преобразования
Режим однократного преобразования
Режим непрерывного преобразования
Режим сканирования
Режим прерывистого преобразования
   Регулярная группа
   Инжектируемая группа
Инжекция
   По внешнему сигналу
   Автоинжектирование
Сторожевая схема
Встроенный датчик температуры
Прерывания от ADC
Регистры ADC



Простой пример использования ADC

Прежде всего, небольшой пример иллюстрирующий использование ADC в программах. Подробное описание возможностей ADC смотрите далее.

// Пример кода для измерения напряжения на встроенном источнике
// опорного напряжения.
#include <stm32f10x.h>

// Если мы хотим обрабатывать прерывания от ADC,
// нам потребуется определить обработчик:
extern "C" void ADC1_IRQHandler()
{
    // Анализируем флаги и выясняем причину прерывания,
    // выполняем какие-то действия...
    
    // Сбрасываем флаги - младшие 5 бит регистра.
    ADC1->SR&=~0x1F;
}

int main()
{
    // Настраиваем приоритет прерывания от ADC и разрешаем обработку
    // (не требуется, если обработка прерываний не планируется).
    NVIC_SetPriority(ADC1_IRQn, (1<<__NVIC_PRIO_BITS)-1);
    NVIC_EnableIRQ(ADC1_IRQn);

    // Включаем тактирование ADC, используемых портов ввода/вывода и
    // другой периферии микроконтроллера.
    RCC->APB2ENR|=RCC_APB2ENR_ADC1EN;

    // Включаем ADC и внутренние аналоговые каналы:
    // термометр и встроенный источник опорного напряжения.
    ADC1->CR2|=ADC_CR2_ADON|ADC_CR2_TSVREFE;

    // Для полной готовности ADC и внутренних источников сигнала
    // требуется время, используем его для выполнения настроек.
    
    // Задаём используемый канал (первый элемент группы),
    // канал 17 (встроенный источник опорного напряжения).
    ADC1->SQR3&=~0x1F;
    ADC1->SQR3|=17;
    
    // Задаём продолжительность выборки для канала 17:
    // 239.5 тактов = 20мкс при тактовой частоте ADC 12МГц.
    ADC1->SMPR1|=7<<21;
    
    // Запустим фиктивное преобразование и дождёмся его завершения
    // для формирования достаточно продолжительной задержки.
    ADC1->CR2|=ADC_CR2_ADON;
    while((ADC1->SR&ADC_SR_EOC)==0);
    // Сброс флага завершения.
    ADC1->SR&=~ADC_SR_EOC;
    
    // Запускаем самокалибровку ADC и ждём её завершения.
    ADC1->CR2|=ADC_CR2_CAL;
    while(ADC1->CR2&ADC_CR2_CAL);

    // ADC готов к работе и откалиброван.
    // Измерим напряжение на встроенном источнике опорного напряжения.
    ADC1->CR2|=ADC_CR2_ADON;
    while((ADC1->SR&ADC_SR_EOC)==0);

    uint16_t d0=ADC1->DR;  // Чтение из DR сбрасывает флаг EOC.
    
    // Теперь можем определить напряжение питания микроконтроллера
    // (если Vref(+)=Vdd):
    float Vdd=1.2*4069/d0;

    // Чтобы разрешить генерацию прерывания от ADC при установке
    // каких-либо флагов в регистре ADC1->SR, необходимо установить
    // соответствующий разрешающий бит, например:
    ADC1->CR1|=ADC_CR1_EOCIE;
    
    // Завершение следующего преобразования приведёт к
    // генерации прерывания:
    ADC1->CR2|=ADC_CR2_ADON;

    while(true)
    {}
}

Основные свойства и возможности ADC

Функциональное описание

На рисунке в предельно упрощённом виде изображена блок-схема аналого-цифрового преобразователя микроконтроллера.

Блок-схема аналого-цифрового преобразователя микроконтроллера из линейки STM32F100xx Рис. 1

Аналоговые узлы микроконтроллера (ADC и DAC) имеют отдельный от цифровых узлов вывод питания - вывод аналогового питания VDDA и отдельный общий (аналоговый) вывод VSSA=0, что позволяет снизить уровень помех для аналоговых узлов со стороны цифровых цепей устройства. Несмотря на наличие нескольких групп выводов для подключения питания, документация требует равенства потенциалов всех общих выводов и всех выводов питания (допускается расхождение не более 50 мВ). Так что не удастся использовать разные напряжения питания для цифровых и аналоговых узлов микроконтроллера. Для получения требуемого согласования напряжений, проще всего использовать общий источник питания, при этом вывод VDDA может быть подключён к этому источнику через дополнительный фильтр (например, LC-фильтр).

Цифровые устройства микроконтроллера требуют напряжения питания не менее 2 В, но если используется аналоговая периферия микроконтроллера, требуется более высокое напряжение питания - не менее 2.4 В.

Для работы преобразователей ADC и DAC необходим источник опорного напряжения. В зависимости от реализации микроконтроллера, в качестве такого источника используется либо напряжение аналогового питания, либо отдельные выводы VREF+, VREF- (отдельные выводы доступны обычно у микроконтроллеров в корпусах с большим количеством выводов). Если доступен вывод VREF-, то он должен быть подключен к общему аналоговому выводу. Если доступен вывод VREF+, то его подключают к источнику с напряжением в пределах от 2.4 В до VDDA, где VDDA - напряжение аналогового питания. Наличие отдельного вывода для подключения источника опорного напряжения позволяет достичь ещё большей точности и стабильности преобразователей ADC и DAC - стабильность и отсутствие шума в опорном сигнале ещё важнее, чем качество аналогового питания.

С помощью аналогового мультиплексора вход ADC подключается к одному из источников сигнала. В микроконтроллерах линейки STM32F100xx это может быть внешний вывод микроконтроллера (сконфигурированный как аналоговый вход) или внутренний источник сигнала. В качестве внутреннего источника может выступать датчик температуры микроконтроллера или встроенный источник опорного напряжения VREFINT (номинальное напряжение 1.2 В с точностью не хуже 40 мВ и температурной нестабильностью не более 10 мВ во всём диапазоне рабочих температур). Наличие встроенного источника опорного напряжение позволяет выполнять калибровку ADC и осуществлять точные измерения в абсолютных величинах напряжения, вне зависимости от стабильности напряжения питания или источника напряжения, к которому подключён вывод VREF+. Если VREF+=VDDA, то можно рассчитывать напряжение питания микроконтроллера, просто замеряя напряжение на встроенном источнике опорного напряжения!

Всего, таким образом, имеется 18 каналов, с которых ADC может получать информацию - 16 внешних и 2 внутренних.

Аналоговые каналы ADC и соответствующие им внешние выводы MCU
Номер канала Имя вывода (основная функция) Номер канала Имя вывода (основная функция)
ADC1_IN0 PA0 ADC1_IN8 PB0
ADC1_IN1 PA1 ADC1_IN9 PB1
ADC1_IN2 PA2 ADC1_IN10 PC0
ADC1_IN3 PA3 ADC1_IN11 PC1
ADC1_IN4 PA4 ADC1_IN12 PC2
ADC1_IN5 PA5 ADC1_IN13 PC3
ADC1_IN6 PA6 ADC1_IN14 PC4
ADC1_IN7 PA7 ADC1_IN15 PC5

Выводы микроконтроллера, которые в качестве альтернативной функции могут использоваться как аналоговые входы, являются несовместимыми с уровнем сигнала 5 В, что следует учитывать, если вывод используется как цифровой вход/выход. Подробнее о совместимости с уровнем сигнала 5 В (FV, five-volt tolerant) можно посмотреть в "GPIO: порты ввода/вывода общего назначения".

ADC1_IN16 - канал, используемый для подключения к датчику температуры.
ADC1_IN17 - канал, используемый для подключения к встроенному источнику опорного напряжения VREFINT.

На вход ADC можно подавать сигнал с напряжением в пределах от 0 до VREF+. В результате преобразования на выходе ADC будет сформировано целое число от 0 до 2N-1, где N - разрядность ADC; в случае N=12 полученный результат будет находиться в пределах от 0 до 0xFFF=4095. Получаемое число прямо пропорционально величине входного напряжение. Если в результате преобразования получено значение D, то входное напряжение V может быть рассчитано как
V=VREF+*D/2N=VREF+*D/4096.

Точное значение VREF+ может быть неизвестно, особенно если в микроконтроллере в качестве VREF+ используется напряжение аналогового питания VDDA, которое может быть не вполне стабильно, например, при батарейном питании устройства. Даже если используется стабилизация напряжения питания, при серийном производстве в разных устройствах напряжение будет получаться разным из-за разброса параметров стабилизаторов.

В подобных случаях можно воспользоваться встроенным источником опорного напряжения VREFINT. Пусть в результате измерения напряжения на встроенном источнике, получили значение D0, тогда
VREFINT=VREF+*D0/4096
или
VREF+=4096*VREFINT/D0=4096*1.2/D,
с учётом того, что VREFINT=1.2 В.

Если VREF+=VDDA, то заодно мы сможем определить напряжение питания микроконтроллера, причём делаем это чисто программно.

Теперь можем измерять напряжения интересующих нас сигналов:
V=VREF+*D/4096=VREFINT*D/D0,
V=1.2*D/D0.

Тактовый сигнал для ADC

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

Аналого-цифровой преобразователь (ADC) микроконтроллеров из линейки STM32F100xx подключён к шине высокоскоростных устройств APB2 и синхронизируется тактовым сигналом этой шины через выделенный прескалер с программно управляемым коэффициентом деления, который можно задать равным 2, 4, 6 или 8 (2 - значение после сброса). Поэтому максимальная частота тактового сигнала для ADC равна 12 МГц (если выбрана частота тактового сигнала APB2 равной 24 МГц и делитель прескалера ADC равным 2).

Тактовый сигнал ADC включается установкой бита ADC1EN в регистре RCC_APB2ENR:

    // Включаем тактовый сигнал ADC.
    RCC->APB2ENR|=RCC_APB2ENR_ADC1EN;

Подробнее о тактовых сигналах и управлении ими рассказано здесь: "Тактовые сигналы микроконтроллеров STM32F100xx".

Самокалибровка

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

Калибровка запускается установкой бита CAL в регистре ADC_CR2. Сброс бита происходит аппаратно, когда калибровка завершается. По завершению калибровки, коды калибровки сохраняются в регистре ADC_DR.

Примечания.
1. Рекомендуется выполнять калибровку после каждого включения питания микроконтроллера.
2. Калибровку запускают при отключённом ADC; перед калибровкой ADC должен находиться в отключённом состоянии (ADON=0) не менее двух тактов ADC. По-крайней мере так говорится в руководстве (RM0041; Reference manual; STM32F100xx advanced ARM-based 32-bit MCUs; Doc ID 16188 Rev 4), вот цитата:
Before starting a calibration the ADC must have been in power-off state (ADON bit = '0') for at least two ADC clock cycles.
На самом деле, как показали эксперименты с микроконтроллером STM32F100RBT6B, при выключенном ADC калибровка не происходит и бит CAL никогда не будет сброшен. В то время как при включённом ADC калибровка успешно выполняется.

Включение и отключение ADC

После включения тактового сигнала, можно включить питание ADC. Это делается установкой бита ADON в регистре ADC_CR2. Для включения ADC требуется некоторое время (параметр tSTAB в документации, для STM32F100xx составляет от 0 до 1 мкс).

    // Включаем ADC.
    ADC1->CR2|=ADC_CR2_ADON;

    // Делаем паузу не менее 1 мкс.
    // .....
    
    // Запускаем калибровку.
    ADC1->CR2|=ADC_CR2_CAL;
    
    // Ждём завершения калибровки (или работаем в это
    // время с другими периферийными устройствами).
    while(ADC1->CR2&ADC_CR2_CAL);

Повторная запись 1 в бит ADON запустит процесс преобразования. Остановить преобразование и отключить ADC можно сбросом бита ADON, в отключённом состоянии потребляемый ADC ток крайне мал.

Выбор канала

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

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

В микроконтроллерах STM32F100xx можно задать две группы каналов: регулярную (от 1 до 16 каналов) и инжектируемую (от 1 до 4 каналов). Выбор используемой группы зависит от способа запуска ADC. Программный запуск записью 1 в бит ADON всегда запускает регулярное преобразование (преобразование для канала из регулярной группы). Внешний сигнал запускает регулярное или инжектируемое (из инжектируемой группы) преобразование, в зависимости от источника сигнала. Сколько будет выполнено последовательных преобразований в ответ на один запуск - одно или для каждого канала в группе, или для части каналов в группе, зависит от режима ADC, заданного его настройками.

Можно сказать, что группа каналов - это просто список с номерами каналов, с которыми будет работать ADC, размер списка и его содержание задаётся программно с помощью регистров ADC_SQRx (регулярная группа), ADC_JSQR (инжектируемая). Группа может содержать номера любых каналов в любом порядке, одни и те же номера могут повторяться. Например можно задать такую группу для выполнения последовательности преобразований: Ch3, Ch8, Ch2, Ch2, Ch0, Ch2, Ch2, Ch15. Понятно, что группа может состоять и из единственного элемента, если требуется работать только с одним каналом.

Организация каналов в группы позволяет минимизировать размер кода для перехода от канала к каналу при работе с несколькими источниками сигнала за счёт автоматизации выбора каналов в групповых операциях преобразования. Мы можем один раз задать группу каналов, после чего для выполнения целой последовательности преобразований потребуется только лишь однократный запуск ADC.

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

В функциональном отношении регулярная и инжектируемая группы не эквивалентны друг другу. Рассмотрим основные свойства этих групп.

В случае модификации регистров ADC_SQRx или ADC_JSQR, текущая последовательность преобразований прерывается и при последующем старте ADC начинается заново с учётом новых групп.

Выравнивание данных

Полученное в результате преобразования с помощью ADC значение может быть сохранено в регистре с выравниванием вправо или выравниванием влево, в зависимости от значения бита ALIGN регистра ADC_CR2. Значение после сброса 0 соответствует выравниванию вправо.

В случае регулярного преобразования, результат содержит 12 бит, который дополняется до размера 16-битового регистра четырьмя нулями (четыре 0 слева при выравнивании вправо или четыре 0 справа - при выравнивании влево).

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

Выравнивание вправо
Регулярное преобразование
0 0 0 0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0  
Инжектируемое преобразование
SEXT SEXT SEXT SEXT D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0  
Выравнивание влево
Регулярное преобразование
D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 0 0 0 0  
Инжектируемое преобразование
SEXT D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 0 0 0  

Продолжительность выборки

Полный процесс преобразования аналогового сигнала в цифровой код включает в себя два основных этапа: выборку сигнала, когда конденсатор выборки-хранения в ADC заряжается от источника сигнала; и собственно процесс преобразования методом последовательного приближения, в результате чего получаем значение напряжения на конденсаторе выборки-хранения в цифровой форме. Этап последовательного приближения имеет фиксированную продолжительность, если его измерять в периодах тактового сигнала ADC и составляет 12.5 тактов для 12-разрядного преобразователя. Продолжительность выборки можно настраивать программно. Точность измерений очень сильно зависит от правильно заданной продолжительности выборки, за это время конденсатор должен успеть с требуемой точностью зарядиться до напряжения источника сигнала через внутреннее сопротивление источника сигнала и внутреннее сопротивление аналогового ключа в схеме выборки в ADC. Чем больше внутреннее сопротивление источника сигнала, тем больше потребуется времени для заряда конденсатора.

Продолжительность выборки сигнала может быть задано независимо для каждого канала с помощью регистров ADC_SMPR1, ADC_SMPR2 (подробнее - в разделе с описанием регистров). Минимальное значение составляет 1.5 такта ADC. Продолжительность выборки можно изменять как за счёт изменения количества тактов, затрачиваемых на выборку, так и за счёт изменения тактовой частоты ADC (а значит и периода тактового сигнала). Тактовая частота определяется программируемым коэффициентом деления прескалера ADC, а также выбором частоты тактового сигнала шины APB2.

С учётом сказанного, общее время преобразования (в тактах) составляет:
Tconv=Tsampling+12.5;
минимальное время преобразования 14 тактов получим при использовании времени выборки в 1.5 такта:
Tconv(min)=1.5+12.5=14=1.17 мкс (в случае, если частота тактового сигнала ADC равна 12 МГц).

Для приблизительной оценки требуемого времени (продолжительности) выборки, мы можем считать схему выборки-хранения линейной RC-цепью, где сопротивление R - сумма внутреннего сопротивления источника сигнала RAIN и сопротивления аналогового ключа RADC схемы выборки в замкнутом состоянии, ёмкость C - ёмкость конденсатора схемы выборки, C=CADC. В течении времени выборки происходит заряд конденсатора от источника сигнала с напряжением VAIN. Будем считать , что VAIN неизменно в течении выборки, тогда напряжение на конденсаторе, как известно, изменяется по закону: $$ V_C=V_{AIN}+(V_{C0}-V_{AIN})e^{-\frac t{RC}}, $$ в нашем случае напряжение на конденсаторе в начальный момент VC0=0 и $$ V_C=V_{AIN}-V_{AIN}e^{-\frac t{RC}}. $$ За время выборки ts конденсатор зарядится до напряжения VC(ts), разность между напряжением сигнала и напряжением на конденсаторе в конце выборки составит $$ dV=V_{AIN}e^{-\frac{t_s}{RC}}. $$ Эта разность определяет ошибку, вносимую на фазе выборки. Из формулы видим, что ошибка тем больше, чем больше величина измеряемого напряжения, наибольшее значение получим при максимально допустимом значении входного напряжения VAIN=VREF+: $$ dV=V_{REF+}e^{-\frac{t_s}{RC}}. $$ Предположим, мы хотим чтобы наибольшая ошибка выборки не превышала 1/2 LSB, тогда можем определить минимальную продолжительность выборки: $$ dV \le 1/2 LSB, \\ dV \le \frac 1 2 \frac{V_{REF+}}{2^N}, \\ V_{REF+}e^{-\frac{t_s}{RC}} \le \frac 1 2 \frac{V_{REF+}}{2^N}, \\ -t_s \le RC \ln \frac 1{2^{N+1}}, \\ t_s \ge RC(N+1)\ln 2; $$ здесь ts - продолжительность выборки; R=RAIN+RADC - сумма внутреннего сопротивления источника сигнала и сопротивления аналогового ключа в схеме выборки; C=CADC - ёмкость конденсатора в схеме выборки-хранения ADC; N - разрядность ADC, в нашем случае N=12.

В соответствии с документацией, для микроконтроллеров STM32F100xx:
RADC не превышает 1 кОм;
CADC не превышает 8 пФ.

Продолжительность выборки ts можно выразить через количество тактов ADC на выборку Ts: ts=Ts/fADC, где fADC - тактовая частота ADC (12 МГц по умолчанию).

Полученное для продолжительности выборки выражение можно записать в виде: $$ T_s \ge f_{ADC} (R_{AIN}+R_{ADC})C(N+1)\ln 2. $$ Или же по заданной продолжительности выборки мы можем оценить максимально допустимое внутренне сопротивление источника сигнала: $$ R_{AIN} \le \frac{T_s}{f_{ADC}C(N+1)\ln 2}-R_{ADC}. $$

Аналогичным образом можно получить формулы для других значений максимальной ошибки. Например, если требуется, чтобы ошибка выборки не превышала 1/4 LSB, должно выполняться условие: $$ R_{AIN} \le \frac{T_s}{f_{ADC}C(N+2)\ln 2}-R_{ADC}. $$

Рассмотрим, например, случай, когда fADC=12 МГц, CADC=8 пФ, RADC=1 кОм, допустимая погрешность выборки - не более 1/2 LSB. Тогда, в зависимости от количества тактов, выделяемых на выборку (задаётся соответствующим каналу битовым полем SMPx[2:0] регистров ADC_SMPR1, ADC_SMPR2), допускается внутреннее сопротивление источника сигнала не более:

SMPx[2:0] Ts, тактов ts, мкс RAIN, кОм
000 1.5 0.125 0.73
001 7.5 0.625 7.7
010 13.5 1.125 15
011 28.5 2.375 32
100 41.5 3.46 47
101 55.5 4.625 >50*
110 71.5 5.96
111 239.5 20.0

* В документации микроконтроллера требуется, чтобы внутреннее сопротивление источника сигнала не превышало 50 кОм, так что для последних строк таблицы, с ростом времени выборки мы не можем рассчитывать на рост максимально допустимого внутреннего сопротивления источника. Зато при фиксированном сопротивлении источника, с ростом времени выборки будем уменьшать ошибку выборки.

С помощью регистра ADC_SMPR1 задаём продолжительность выборки для каналов 10..17 (по 3 бита на канал), регистр ADC_SMPR2 задаёт продолжительность выборки для каналов 0..9. Чтобы изменить время выборки для одного из каналов, не затрагивая остальных, можно использовать примерно такой код:

    // Здесь N - номер канала, ts - трёхбитовый код времени выборки.
    
    // В случае, если N=0..9:
    ADC1->SMPR2&=~(7<<3*N);  // Сброс битов.
    ADC1->SMPR2|=ts<<3*N;    // Установка нового значения.
    
    // В случае, если N=10..17.
    ADC1->SMPR1&=~(7<<3*(N-10));  // Сброс битов.
    ADC1->SMPR1|=ts<<3*(N-10);    // Установка нового значения.

С учётом наличия у портов ввода/вывода тока утечки, который, в соответствии с документацией, по абсолютной величине ограничен сверху величиной 1 мкА, желательно иметь источник сигнала с минимально возможным внутренним сопротивлением, чтобы минимизировать ошибку из-за падения напряжения на внутреннем сопротивлении от тока утечки. Так, при сопротивлении источника сигнала порядка 700 Ом, падение напряжения на внутреннем сопротивлении при токе утечки 1 мкА уже составляет около 1 LSB, т.е. превышает ошибку сэмлирования при минимальном времени выборки.

Эквивалентная схема ADC микроконтроллера (по отношению к источнику сигнала) Рис. 2

Можно сделать внутреннее сопротивление источника сигнала очень низким, если воспользоваться повторителем сигнала на операционном усилителе. Впрочем, тут не всё однозначно: ошибка из-за падения напряжения на малом выходном сопротивлении повторителя от тока утечки становится незначительной, ошибка сэмплирования также существенно уменьшается; с другой стороны, появляются ошибки, вносимые самим повторителем, например, ошибка из-за наличия напряжения смещения. В то же время, ток утечки для портов микроконтроллера может быть на порядки меньше максимально возможных, заявленных в документации значений (особенно вдали от максимальной рабочей температуры).

На рис. 2 изображена эквивалентная схема ADC как нагрузки для источника сигнала. На схеме учтены конденсатор выборки-хранения CADC, сопротивление ключа в схеме выборки RADC, ток утечки - в виде выделенного элемента - источника тока IL, источник сигнала как последовательно соединённые идеальный источник напряжения VAIN и резистор, моделирующий внутреннее сопротивление RAIN. На точность измерений также оказывает влияние паразитная ёмкость Cparasitic, включающая в себя ёмкость монтажа и контактной площадки, зависящая от разводки печатной платы. В случаях, когда требуется высокая точность, следует учитывать наличие паразитной ёмкости. Правда, это связано с известными трудностями, ёмкость может быть оценена только после разводки печатной платы и то, весьма приближённо. Для грубых оценок, паразитная ёмкость может быть принята равной 7 пФ (т.е. она сравнима с ёмкостью CADC, а значит, действительно значительно влияет на точность).

Запуск преобразования

Запуск преобразования осуществляется либо программно, либо внешним сигналом. Для программного запуска следует записать 1 в бит ADON регистра ADC_CR2 при включённом ADC. Если изменяется любой бит регистра ADC_CR2, не считая ADON, то преобразование не запускается. Это сделано для того, чтобы можно было модифицировать настройки, управляемые регистром ADC_CR2, не вызывая ложных запусков ADC.

Программный старт запускает преобразование для канала из регулярной группы.

Внешним сигналом запуска процесса преобразования может быть сигнал от таймера или сигнал с внешнего вывода микроконтроллера (через контроллер внешних прерываний/событий - EXTI, external interrupt/event controller). Чтобы разрешить запуск ADC внешним сигналом, следует установить в регистре ADC_CR2 бит EXTTRIG для разрешения запуска регулярных и JEXTTRIG для разрешения запуска инжектируемых преобразований. Битовые поля EXTSEL[2:0] и JEXTSEL[2:0] этого регистра определяют источник сигнала, который будет запускать соответственно регулярное и инжектируемое преобразование. Далее в таблице перечислены возможные варианты:

Внешний сигнал для регулярных преобразований
EXTSEL[2:0] Источник Тип
000 TIM1_CC1 event Внутренний сигнал от встроенного таймера
001 TIM1_CC2 event
010 TIM1_CC3 event
011 TIM2_CC2 event
100 TIM3_TRGO event
101 TIM4_CC4 event
110 EXTI line 11 Внешний вывод
111 SWSTART Программно управляемый бит
Внешний сигнал для инжектируемых преобразований
JEXTSEL[2:0] Источник Тип
000 TIM1_TRGO event Внутренний сигнал от встроенного таймера
001 TIM1_CC4 event
010 TIM2_TRGO event
011 TIM2_CC1 event
100 TIM3_CC4 event
101 TIM4_TRGO event
110 EXTI line 15 Внешний вывод
111 JSWSTART Программно управляемый бит

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

Внешним сигналом запуска преобразования может быть программная установка бита SWSTART или JSWSTART в регистре ADC_CR2 (смотрите последние строки приведённых выше таблиц). Особенно эта возможность полезна при работе с инжектируемыми преобразованиями, для которых не предусмотрено непосредственного программного запуска.

Режим однократного преобразования

В этом режиме ADC выполняет одно преобразование при каждом запуске. Этот режим используется в том случае, если сброшен бит CONT регистра ADC_CR2 и бит SCAN регистра ADC_CR1 (значение по умолчанию, эти биты сброшены после сброса микроконтроллера), т.е. если не включен какой-либо другой режим. Запуск преобразования осуществляется записью 1 в бит ADON регистра ADC_CR2 (при включённом ADC) - в этом случае выполняется преобразование для очередного элемента из регулярной группы.

Возможен запуск преобразования внешним сигналом, в этом случае выполняется регулярное или инжектируемое преобразование, в зависимости от источника сигнала. При запуске внешним сигналом должен быть сброшен бит DISCEN/JDISCEN, так как при установленном бите произойдёт старт в прерывистом режиме*.

В режиме однократного преобразования, независимо от размера и состава заданной группы каналов, всегда используется один и тот же канал:
в случае регулярного преобразования - заданный битами SQ1[4:0] регистра ADC_SQR3 (это 5 младших битов регистра);
в случае инжектируемого преобразования - заданный битами JSQ1[4:0] регистра ADC_JSQR (5 младших битов регистра).

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

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

Когда процесс аналого-цифрового преобразования завершается, происходит следующее:

После этого ADC останавливается до следующего запуска.

В неиспользуемые при однократном инжектируемом преобразовании регистры ADC_JDR2, ADC_JDR3, ADC_JDR4 помещаются значения -ADC_JOFR2, -ADC_JOFR3, -ADC_JOFR4 соответственно (0, если эти регистры смещения содержат значения 0).

Режим непрерывного преобразования

Режим выбирается установкой в 1 бита CONT в регистре ADC_CR2. В этом режиме после первого запуска (записью 1 в бит ADON регистра ADC_CR2 или внешним сигналом)начинается автоматический последовательный запуск однократных преобразований. Все выполняемые действия во время каждого преобразования, начиная от выбора канала и заканчивая сохранением результата выполняются точно также, как для однократного. Отличие только в том, что не происходит остановки ADC и когда завершается одно преобразование, сразу же, автоматически, запускается следующее. Работа в режиме непрерывного преобразования будет продолжаться до тех пор, пока установлен бит CONT.

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

После выполнения каждого преобразования устанавливаются соответствующие флаги завершения и генерируется прерывание, если установлен разрешающий бит.

Режим сканирования

Выбор режима осуществляется установкой бита SCAN в регистре ADC_CR1. В этом режиме однократный запуск ADC приводит к выполнению всей последовательности преобразований в группе (в регулярной или инжектируемой, в зависимости от способа запуска), после чего ADC останавливается. Однако, если установлен бит CONT, преобразования не будут завершены при достижении последнего канала в группе, а будут продолжены с начала выбранной группы, т.е. ADC будет работать в режиме непрерывно-сканирующего преобразования.

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

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

Регулярная группа определяется с помощью регистров ADC_SQR1, ADC_SQR2, ADC_SQR3. Битовое поле SQx задаёт номер канала для преобразования с номером x в последовательности, x=1, 2, 3, ..., 16; в поле L регистра ADC_SQR1 помещают уменьшенное на 1 общее количество элементов в группе; инициализации подлежат только задействованные элементы SQx группы. Первым в последовательности выполняется преобразование для канала с номером SQ1, затем для SQ2 и т.д. до номера L+1 включительно.

Определение инжектируемой группы имеет особенность: если размер группы меньше максимального (меньше 4 элементов), то группа задаётся старшими элементами регистра ADC_JSQR, а младшие остаются неиспользованными. Например, чтобы задать группу из 2-х элементов, задают элементы JSQ3, JSQ4 и длину JL=2-1=1, при этом элементы JSQ1, JSQ2 остаются незадействованными. Но при этом порядок записи в регистры данных остаётся обычным: первый результат последовательности пишется в ADC_JDR1, второй - в ADC_JDR2 и т.д. Так, в нашем примере, битовое поле JSQ3 содержит номер канала, первого в последовательности преобразований и результат преобразования для этого канала будет помещён в ADC_JDR1; вторым в последовательности будет канал JSQ4, результат будет помещён в ADC_JDR2. В неиспользуемые при сканировании регистры данных (если размер группы меньше 4) будут помещены значения, противоположные смещениям для данных регистров, т.е. значения вида -JOFRx.

Режим прерывистого преобразования

Регулярная группа

Режим используется для выполнения короткой очереди из n преобразований, n<=8, которая является частью последовательности, заданной регистрами ADC_SQRx.

Этот режим включается установкой бита DISCEN в регистре ADC_CR1. Длина очереди n, выполняемой в ответ на каждый запуск ADC определяется битами DISCNUM[2:0] регистра ADC_CR1, n=DISCNUM+1. Запуск преобразования осуществляется только внешним сигналом (external trigger).

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

Установка флагов завершения преобразования происходит после каждого преобразования (в то время как в документации заявлено, что только после завершения всех преобразований в группе).

Пример. Задана последовательность преобразований из 8 элементов (длина всей последовательности, как обычно определяется битами L[3:0] регистра ADC_SQR1, элементы последовательности задаются с помощью регистров ADC_SQRx):
0, 1, 2, 3, 6, 7, 9, 10.
Длина выполняемой за один раз очереди n=3 (DISCNUM[2:0]=2), тогда в результате последовательных запусков будут выполняться следующие преобразования:
1-й запуск: последовательность преобразований 0, 1, 2;
2-й запуск: последовательность преобразований 3, 6, 7
3-й запуск: последовательность преобразований 9, 10 и подготовка к переходу на начало группы;
4-й запуск: последовательность преобразований 0, 1, 2
и т.д.

ADC запоминает, на каком элементе группы завершилось выполнение последней очереди преобразований. Если запускать преобразования записью 1 в бит ADON, то будут выполняться одиночные преобразования (не следующие очереди, очередь запускается только внешним сигналом!), причём в качестве используемого канала будет выбран именно тот канал, на котором завершилось выполнение последней очереди (если все элементы группы были исчерпаны при выполнении последней очереди, то будет использоваться канал, соответствующий первому элементу группы). Это отличается от обычного поведения одиночного преобразования при сброшенном бите DISCEN.
Это недокументированные особенности, не следует их использовать! Эти особенности описаны здесь только потому, что являются потенциальным источником ошибок!

Инжектируемая группа

Этот режим включается установкой бита JDISCEN в регистре ADC_CR1. Режим может использоваться для выполнения последовательности, заданной регистром ADC_JSQR по одному преобразованию на каждый внешний сигнал запуска. Когда все преобразования в инжектируемой группе будут выполнены, при следующем запуске произойдёт переход на начало группы. Полный размер группы и её элементы определяются соответствующими полями регистра ADC_JSQR.

Состав группы и использование регистров данных для записи результатов аналогичны режиму сканирования в инжектируемой группе (если размер группы меньше максимальной, используются старшие элементы регистра ADC_JSQR). Запись результатов происходит для первого элемента группы - в ADC_JDR1, для второго - в ADC_JDR2 и т.д.

Пример.
состав группы: 1, 2, 3;
1-й запуск: преобразование для канала 1;
2-й запуск: преобразование для канала 2;
3-й запуск: преобразование для канала 3;
4-й запуск: преобразование для канала 1
и т.д.

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

Инжекция

По внешнему сигналу

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

Для использования инжекции, в регистре ADC_CR1 бит JAUTO должен быть сброшен, бит SCAN - установлен.
1. Запускаем преобразование для каналов регулярной группы. Это можно сделать установкой бита ADON в регистре ADC_CR2 или внешним сигналом запуска.
2. Если в процессе выполнения последовательности преобразований в регулярной группе будет получен внешний сигнал запуска инжектируемого преобразования, текущее преобразование будет прервано и начнётся выполнение последовательности преобразований из инжектируемой группы в режиме сканирования.
3. После завершения преобразований из инжектируемой группы, продолжится выполнение преобразований из регулярной группы, начиная с прерванного преобразования.

Примечание. Когда используется инжекция по внешнему сигналу запуска, необходимо обеспечить, чтобы интервал между сигналами запуска был больше, чем продолжительность выполнения инжектируемой последовательности. Например, если длительность последовательности составляет 28 тактов ADC (это соответствует двум преобразованиям со временем выборки в 1.5 такта), минимальный интервал между сигналами запуска должен быть 29 тактов ADC.

Автоинжектирование

Если установлен бит JAUTO, то последовательность преобразований для инжектируемой группы выполняется автоматически при завершении выполнения преобразований для регулярной группы. Эту функцию можно использовать для получения последовательности преобразований длиной до 20 каналов.

В этом режиме следует отключить запуск инжекции внешним сигналом.

Если в дополнение к биту JAUTO будет установлен бит CONT, по завершению преобразований из инжектируемой группы, автоматически продолжится выполнение преобразований из регулярной группы в непрерывном режиме.

При переключении с регулярной последовательности на инжектируемую, автоматически вставляются задержки длительностью 2 такта ADC (если используется делитель прескалера 2) или 1 такт (если делитель равен 4, 6 или 8).

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

Сторожевая схема

ADC микроконтроллеров STM32F100xx содержит сторожевую схему, которая может обнаруживать выход результата преобразования на одном или нескольких каналах за пределы заданной области значений. Если сторожевая схема включена и в результате преобразования для одного из контролируемых каналов было получено значение меньше минимального порога или больше максимального порога, то будет установлен флаг AWD. Также будет сгенерировано прерывание ADC, если это разрешено установкой бита AWDIE.

Минимальный порог задаётся регистром ADC_LTR (low threshold register), максимальный - регистром ADC_HTR (high threshold register). Регистры являются 16-битными, используются младшие 12 бит этих регистров, независимо от выбранного варианта выравнивания данных, так как сравнение значений в сторожевой схеме происходит до выполнения выравнивания.

Включение и конфигурирование сторожевой схемы производится с помощью следующих битов регистра ADC_CR1: AWDSGL, AWDEN, JAWDEN, в некоторых случаях также AWDCH[4:0].

Единичное значение бита AWDEN включает контроль за регулярными преобразованиями, а бита JAWDEN - за инжектируемыми (если оба бита сброшены, сторожевая схема отключена). Если бит AWDSGL сброшен, контролируются преобразования выбранного типа для всех каналов, а если установлен, то контролируется результат преобразования только для одного конкретного канала, номер которого задан битами AWDCH[4:0]. При включённом режиме контроля за одним каналом также делается различие между регулярными преобразованиями и инжектируемыми.

Выбор каналов для контроля сторожевой схемой
Контролируемые преобразования Биты регистра ADC_CR1, управляющие сторожевой схемой
AWDSGL AWDEN  JAWDEN
Отключено x 0 0
Все инжектируемые 0 0 1
Все регулярные 0 1 0
Все 0 1 1
Заданный канал* в случае инжектируемого преобразования 1 0 1
Заданный канал* в случае регулярного преобразования 1 1 0
Заданный канал* в случае любого преобразования 1 1 1

* Канал выбирается с помощью битов AWDCH[4:0].

Встроенный датчик температуры

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

Для того, чтобы использовать датчик температуры или встроенный источник опорного напряжения, подключённые к внутренним каналам 16 и 17, эти каналы должны быть предварительно включены установкой бита TSVREFE в регистре ADC_CR2. Для включения датчика температуры требуется время от 4 до 10 мкс.

Рекомендуемое время выборки при работе с датчиком температуры равно 17.1 мкс.

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

Обозначение параметра Параметр Минимум Типовое значение Максимум Единица измерения
TL Линейность температурной зависимости напряжения датчика   ±1 ±2 ºC
Avg_Slope Средняя чувствительность 4.0 4.3 4.6 мВ/ºC
V25 Напряжение при температуре 25ºC 1.32 1.41 1.50 В
tSTART Время включения 4   10 мкс
TS_temp* Время выборки для ADC     17.1 мкс

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

Видим, что датчик имеет высоколинейную температурную характеристику. Но шибка измерения абсолютной величины температуры может достигать ±22.5ºC! Немного лучше обстоит дело с измерением изменений температуры, в этом случае ошибка не превышает 10%.

Для измерения температуры, выполняем следующую последовательность действий:
1. Установкой бита TSVREFE в регистре ADC_CR2 включаем датчик температуры, после чего ждём не менее 10 мкс (время, необходимое для включения датчика).
2. Выбираем канал ADCx_IN16.
3. Задаём время выборки 17.1 мкс.
4. Запускаем процесс преобразования установкой бита ADON или с помощью внешнего сигнала запуска.
5. Дождавшись завершения преобразования, считываем результат и определяем напряжение на выходе датчика температуры VSENSE.
6. Вычисляем температуру по формуле Temperature(°C) = ((V25-VSENSE)/Avg_Slope)+25. Параметры берём из таблицы параметров (см. выше).

Примечания.
1. В формуле (пункт 6) единица измерения Avg_Slope должна соответствовать единице измерения VSENSE, т.е., если напряжение датчика выражено в вольтах, то Avg_Slope необходимо перевести в В/°C; если хотим Avg_Slope задать в мВ/°C, то напряжение датчика следует перевести м милливольты.
2. После включения датчика температуры, требуется некоторое время для установки верного значения его выходного напряжения. Для включения ADC также требуется некоторое время. Для минимизации задержки, связанной с инициализацией периферии микроконтроллера, можно установить биты ADON и TSVREFE одновременно.
3. Как было сказано ранее, точность встроенного в микроконтроллеры STM32F100xx датчика, при измерении абсолютных значений температуры, крайне низкая. Например, в области комнатных температур можно получить результат от 0°C до 50°C.

Прерывания от ADC

С помощью битов EOCIE, JEOCIE, AWDIE регистра ADC_CR1 можно разрешить генерацию прерывания в случае, если происходит установка флагов EOC, JEOC, AWD (регистр ADC_SR) соответственно, т.е. в случае завершения преобразования в регулярной группе, в инжектируемой группе или при срабатывании сторожевой схемы. Для сброса флага, вызвавшего прерывание, следует записать в него 0. Флаг EOC также сбрасывается при чтении из регистра ADC_DR.

Обработчик прерываний от аналого-цифрового устройства имеет имя ADC1_IRQHandler.

extern "C" void ADC1_IRQHandler()
{
    // Выявляем причину прерывания, сбрасываем флаги.
    // .....
}

Для того, чтобы обработчик прерываний получал управление, в коде потребуется выполнить действия:

    // Задаём приоритет (в этом примере - минимальный).
    NVIC_SetPriority(ADC1_IRQn, (1<<__NVIC_PRIO_BITS)-1);
    
    // Разрешаем прерывания от ADC.
    NVIC_EnableIRQ(ADC1_IRQn);
    
    // Включаем тактовый сигнал ADC, включаем ADC, выполняем калибровку.
    // .....
    
    // Разрешаем генерацию прерываний при установке интересующих флагов.
    // Здесь: разрешаем генерацию прерывания при установке флага EOC.
    ADC1->CR1|=ADC_CR1_EOCIE;

Регистры ADC

Справочник по регистрам ADC микроконтроллера выделен в отдельный документ: "ADC. Описание регистров".

author: hamper; date: 2016-10-10
  @Mail.ru