Перейти к содержанию

Цифро-аналоговый преобразователь (ЦАП)

Цифро-аналоговый преобразователь (ЦАП) делает обратное АЦП: получает число и выдаёт напряжение, пропорциональное этому числу и опорному напряжению. Для N-разрядного ЦАП VOUT = VREF · D / 2^N; качество выхода определяют нелинейность, время установления и способность выхода работать на нагрузку.

Обновлено Редакция GAW

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

Коротко

Формула выходного напряжения

У N-разрядного ЦАП с кодом D выход равен

VOUT=VREF⋅D2NV_{OUT} = \frac{V_{REF} \cdot D}{2^N}

Так её записывают и Microchip для MCP4725 (VREF = VDD, деление на 4096, DS22039D, разд. 5.1), и ST для ЦАП STM32F0 (опора VDDA, RM0091, разд. 14.5.3). Код 0 даёт ноль, наибольший код 2N − 1 — опорное напряжение минус 1 LSB: у MCP4725 код FFFh соответствует VDD − 1 LSB (DS22039D, табл. 6-1).

ЦАПVREF1 LSB
8 бит5 В19,5 мВ
10 бит5 В4,88 мВ
12 бит (MCP4725)5 В1,22 мВ
12 бит (MCP4725)3 В0,73 мВ
12 бит (STM32)3,3 В0,81 мВ

Пример. Нужно 1,000 В от MCP4725 с питанием 5 В. Код D = 1,000 · 4096 / 5 = 819,2 → 819; на выходе 819 · 5 / 4096 = 0,9998 В. Ближе подойти нельзя: соседний код 820 даёт 1,0010 В. Погрешности самого ЦАП и неточность 5 В добавятся сверху.

Как устроен ЦАП

Матрица R-2R

Самая известная схема — резистивная матрица R-2R: два номинала резисторов, R и 2R, и переключатель на каждый разряд. Переключатель подключает «ногу» 2R своего разряда к опорному напряжению (бит равен 1) или к общему проводу (бит равен 0).

Четырёхразрядный ЦАП на резистивной матрице R-2RВдоль верхней шины резисторы R соединяют узлы четырёх разрядов, от левого края на общий провод — резистор 2R. Из каждого узла вниз идёт резистор 2R к переключателю разряда, который подключает его к опорному напряжению или к общему проводу. Узел старшего разряда справа подключён к повторителю на операционном усилителе.2RR2Rb0R2Rb1R2Rb22Rb3VREFпереключатель: VREF (1) или общий провод (0)+−VOUT

Секрет в том, что сопротивление цепочки, если смотреть из любого узла влево, равно 2R. Поэтому в каждом узле напряжение делится пополам: вклад старшего разряда — VREF/2, следующего — VREF/4 и так далее до младшего VREF/2N. Сумма вкладов единичных разрядов и есть VREF · D / 2N. Выходное сопротивление матрицы постоянное и равно R, поэтому её почти всегда нагружают повторителем на операционном усилителе.

Слабые места R-2R: точность старших разрядов зависит от согласованности резисторов, а на переходах, где меняются сразу все разряды (0111 → 1000), переключатели срабатывают не одновременно, и на выходе появляется кратковременный выброс (glitch).

Резистивная цепочка

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

Трёхразрядный ЦАП на резистивной цепочкеВосемь одинаковых резисторов соединены последовательно между опорным напряжением и общим проводом. Каждая точка соединения через свой ключ может быть подключена к общей шине, которая идёт на вход повторителя; код включает ровно один ключ.VREF111110101100011010001000+−VOUT

Каждый следующий код берёт напряжение с более высокого отвода, поэтому выход монотонен при любом разбросе резисторов: больший код никогда не даёт меньшего напряжения. Цена — 2N резисторов и ключей, но внутри микросхемы это не проблема. Так устроен, например, MCP4725: резистивная цепочка с прецизионным выходным усилителем (DS22039D, разд. 5).

ЦАП на ШИМ

Самый дешёвый «ЦАП» — ШИМ с RC-фильтром. Таймер выдаёт импульсы с заполнением D, фильтр нижних частот оставляет среднее значение VREF · D. Разрядность определяется разрешением таймера, а пульсации и время установления — частотой ШИМ и фильтром. Так получают аналоговое напряжение на Arduino Uno, у которого нет своего ЦАП. Номиналы фильтра и пульсации считает калькулятор ЦАП на ШИМ.

Параметры ЦАП

ПараметрЧто значитMCP4725 (DS22039D, табл. 1)
РазрядностьЧисло разрядов кода12 бит
DNLОтклонение шага от 1 LSB; при DNL > −1 LSB ЦАП монотонен±0,2 LSB тип., ±0,75 LSB макс.
INLОтклонение выхода от прямой±2 LSB тип., ±14,5 LSB макс.
СмещениеВыход при коде 00,02 % шкалы тип., 0,75 % макс.
Ошибка усиленияНаклон характеристики при коде FFFh без учёта смещения−0,1 % тип., ±2 % макс.
Время установленияСколько выход идёт к новому значению с точностью ½ LSB (код 400h → C00h)6 мкс тип.
Скорость нарастанияНаибольшая скорость изменения выхода0,55 В/мкс

INL и DNL у MCP4725 нормированы на кодах 100–4000, а не на всей шкале (примечание 1 к таблице). Смещение и ошибку усиления можно откалибровать по двум точкам, нелинейность — только таблицей поправок.

Выходной буфер

Выход ЦАП нужно рассматривать как источник с внутренним сопротивлением. У ЦАП STM32 есть встроенный буфер, который можно включить или выключить (RM0091, разд. 14.2). Без буфера выходное сопротивление большое, и нагрузка вместе с ним работает как делитель: по AN3126 (разд. 1.9), чтобы у STM32F4 без буфера падение было меньше 1 %, нагрузка должна быть больше 1,5 МОм. С включённым буфером выход совпадает с заданным; диапазон выходного напряжения буфера и его смещение указаны в даташите конкретной микросхемы.

У MCP4725 выход всегда буферизован усилителем rail-to-rail (DS22039D, разд. 5); ток короткого замыкания выхода — 15 мА тип., 24 мА макс. при 5 В.

ЦАП в STM32

У STM32F0 один 12-разрядный канал DAC_OUT1, у STM32F07x и F09x — второй канал DAC_OUT2, генераторы шума и треугольного сигнала (RM0091, разд. 14.2). Код можно записать с выравниванием вправо или влево, а обновлять выход по событию таймера и подавать данные через DMA — так ЦАП выдаёт сигнал без участия процессора.

Синус из таблицы. AN3126 показывает, как получить синусоиду: в памяти лежит таблица из ns отсчётов, DMA по событию таймера отправляет их в ЦАП по кругу. Частота сигнала

fsin⁡=fTRGOnsf_{\sin} = \frac{f_{TRGO}}{n_s}

где fTRGO — частота событий таймера. Пример из AN3126: при ns = 10 и событиях таймера 1 МГц на выходе 100 кГц. Отсчёты — значения (sin(2πx/ns) + 1) · 4096 / 2: 2048, 3251, 3995, 3996, 3253, 2051, 847, 101, 98, 839 (табл. 3). Чем больше отсчётов на период, тем ближе выход к синусоиде; таблицу под свои параметры строит генератор таблиц синуса.

Синус из десяти отсчётов ЦАП и его восстановление фильтромСтупенчатая кривая — выход ЦАП, который держит каждый из десяти кодов синуса до следующего отсчёта: от 2048 до 3996 и вниз до 98. Плавная кривая — тот же сигнал после фильтра нижних частот: синусоида, сдвинутая на полшага.020484095время: 10 отсчётов на период

ЦАП держит каждый код до следующего отсчёта, поэтому на выходе ступеньки. Их сглаживает восстанавливающий фильтр нижних частот после ЦАП — RC-цепочка или активный фильтр на ОУ с частотой среза выше частоты сигнала и заметно ниже частоты отсчётов; частоту RC-фильтра считает калькулятор RC-фильтра. Отфильтрованный сигнал отстаёт от ступенек примерно на половину шага.

Внешний ЦАП MCP4725 по I²C

MCP4725 — 12-разрядный ЦАП в корпусе SOT-23-6 с питанием 2,7–5,5 В, опорой служит само питание VDD. Адрес на шине I²C — 1100 A2 A1 A0: биты A2 и A1 задаются при заказе (по умолчанию 00), а A0 — уровнем на выводе A0, поэтому на одной шине без доработок работают два одинаковых ЦАП (адреса 0x60 и 0x61). Код можно записать и в EEPROM: тогда после включения питания ЦАП сразу выдаёт сохранённое напряжение. Запись в EEPROM занимает 25–50 мс (DS22039D).

Быстрая запись (Fast Mode) — два байта после адреса: 0 0 PD1 PD0 D11 D10 D9 D8, затем D7 … D0; выход обновляется по спаду ACK третьего байта (DS22039D, рис. 6-1).

#include <Wire.h>

const uint8_t MCP4725_ADDR = 0x60;  // A0 pin to GND

void dacWrite(uint16_t code) {
  Wire.beginTransmission(MCP4725_ADDR);
  Wire.write((code >> 8) & 0x0F);   // fast mode: C2 = C1 = 0, PD1 = PD0 = 0, D11..D8
  Wire.write(code & 0xFF);          // D7..D0
  Wire.endTransmission();
}

void setup() {
  Wire.begin();
  dacWrite(819);                    // 819 * 5 V / 4096 = 0.9998 V
}

void loop() {}

Типичные ошибки

  • Ожидание точного напряжения «по формуле». Формула идеальна; реальный выход отличается на смещение, ошибку усиления и нелинейность, а при опоре от питания — ещё и на неточность питания.
  • Нагрузка на небуферизованный выход. Без буфера даже мегаом заметно сажает выход; ставят встроенный буфер или повторитель на ОУ.
  • Деление на 2N − 1. Наибольший код даёт VREF − 1 LSB, а не VREF.
  • Нет восстанавливающего фильтра. Ступеньки и выбросы на переходах кодов попадают в нагрузку: звук «звенит», регулятор получает помеху.
  • Частая запись в EEPROM MCP4725. EEPROM нужна для значения при включении, а для обычной работы есть команда записи только в регистр ЦАП.

Частые вопросы

Есть ли ЦАП у Arduino Uno?

Нет: у ATmega328P нет цифро-аналогового преобразователя, а analogWrite() выдаёт ШИМ — прямоугольные импульсы с меняющимся заполнением. Чтобы получить постоянное напряжение, ШИМ пропускают через RC-фильтр (это ЦАП на ШИМ) или подключают внешний ЦАП, например MCP4725 по I²C.

Чем ЦАП на R-2R отличается от ЦАП на резистивной цепочке?

В матрице R-2R всего два номинала резисторов и 2N резисторов на N разрядов, но точность старших разрядов зависит от точности резисторов, и на переходах вроде 0111 → 1000 возможны выбросы. В резистивной цепочке 2^N одинаковых резисторов и ключ на каждый отвод: каждый следующий код берёт напряжение с более высокого отвода, поэтому выход монотонен при любом разбросе резисторов. Такую архитектуру использует, например, MCP4725.

Почему без буфера выход ЦАП «проседает» под нагрузкой?

У небуферизованного выхода большое выходное сопротивление: нагрузка вместе с ним образует делитель. По AN3126, чтобы у STM32F4 без буфера падение было меньше 1 %, сопротивление нагрузки должно быть больше 1,5 МОм. Встроенный буфер или внешний повторитель на ОУ снимают эту проблему; у буфера свой диапазон выхода, он указан в даташите.

Как выбрать разрядность ЦАП?

От нужного шага напряжения: 1 LSB = VREF / 2^N. Для 12-разрядного ЦАП с опорой 5 В шаг 1,22 мВ, с опорой 3,3 В — 0,81 мВ. При этом точность выхода ограничивают не только шаг, но и нелинейность, смещение и ошибка усиления: у MCP4725 INL до ±14,5 LSB, поэтому для точных установок выход калибруют.

Источники

  1. Microchip. MCP4725: 12-Bit Digital-to-Analog Converter with EEPROM Memory in SOT-23-6 (DS22039D) — архитектура резистивной цепочки с буфером, формула выхода, таблица 6-1, характеристики (INL, DNL, смещение, усиление, время установления), команды записи (рис. 6-1), адресация
  2. STMicroelectronics. RM0091: STM32F0x1/STM32F0x2/STM32F0x8 reference manual, Rev 10 — разд. 14.2 (возможности ЦАП), 14.5.3 (выходное напряжение)
  3. STMicroelectronics. AN3126: Audio and waveform generation using the DAC in STM32 products, Rev 5 — разд. 1.9 (выходной буфер), 2.1 (синус из таблицы, частота сигнала, табл. 3)

Нашли ошибку?