АЦП STM32W108

Микроконтроллеры STM32W108 имеют один встроенный 12-разрядный Σ-Δ АЦП с дифференциальным входом и встроенный источник опорного напряжения (ИОН) с номинальным напряжением 1,2 В.

У микроконтроллеров с 48 выводами имеется вывод VREF (PB0) для подключения внешнего ИОН. Этот же вывод может использоваться, как выход внутреннего ИОН. У микроконтроллеров с 40 выводами такие возможности отсутствуют.

Напряжение внешнего ИОН должно лежать в диапазоне от 1,1 В до 1,3 В.

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

АЦП может тактироваться двумя частотам: 1 МГц и 6 МГц. При этом можно выбрать количество периодов тактирования, за которое должно быть выполнено преобразование.

Все возможные режимы дискретизации АЦП:

Период дискретизации, мкс Частота дискретизации, кГц
Частота тактирования АЦП, МГц 1 6 1 6
Количество периодов для преобразования 32 32,0 5,333 31,2500000000 187,500000000
64 64,0 10,667 15,6250000000 93,750000000
128 128,0 21,333 7,8125000000 46,875000000
256 256,0 42,667 3,9062500000 23,437500000
512 512,0 85,333 1,9531250000 11,718750000
1024 1024,0 170,667 0,9765625000 5,859375000
2048 2048,0 341,333 0,4882812500 2,929687500
4096 4096,0 682,667 0,2441406250 1,464843750

При этом надо учитывать, что, чем меньше время преобразования, тем меньше разрешающая способность АЦП.

Единственный способ получения данных после преобразования — через DMA.

Буфер для DMA определяется двумя регистрами:

  • ADC_DMABEG — начальный адрес буфера, указатель на 16-битную знаковую переменную или массив из этих переменных;
  • ADC_DMASIZE — размер буфера, количество элементов в вышеназванном массиве или половина длины буффера в байтах.

Определить буфер можно так:

#define ADC_DMA_BUFFER_SIZE (10)
int16s ADC_DMA_buffer[ADC_DMA_BUFFER_SIZE];
ADC_DMABEG = (int32u)ADC_DMA_buffer;
ADC_DMASIZE = ADC_DMA_BUFFER_SIZE;

или так (для представления буффера одной переменной):

int16s ADC_DMA_buffer;
ADC_DMABEG = (int32u)&ADC_DMA_buffer;
ADC_DMASIZE = 1;

О ходе преобразования можно судить по флагам в регистре INT_ADCFLAG. Какое-либо событие устанавливает бит соответствующего флага в логическую 1. Флаги сбрасываются программно. Чтобы сбросить флаг в регистре INT_ADCFLAG, надо записать в соответствующий бит логическую 1. После этого из бита читается логический 0.

Пример работы с АЦП:

#include PLATFORM_HEADER
#include <hal/hal.h>
#include <simplemac/include/phy-library.h>

// Выделить буфер в который АЦП будет складывать данные
#define ADC_DMA_BUFFER_SIZE (1)
int16s ADC_DMA_buffer[ADC_DMA_BUFFER_SIZE];

int main()
{
  // Инициализировать микроконтроллер
  halCommonStartXtal();
  halInternalSetRegTrim(FALSE);
  halCommonCalibratePads();
  halCommonSwitchToXtal();
  halInternalCalibrateFastRc();
  halInternalStartSystemTimer();
  GPIO_DBGCFG &= ~GPIO_EXTREGEN; // Освободить PA7 от REG_EN

  // Настроить выводы МК к которым подключаются аналоговые цепи
  halGpioConfig(PORTB_PIN(7), GPIOCFG_ANALOG);
  halGpioConfig(PORTC_PIN(1), GPIOCFG_ANALOG);

  // Объяснить АЦП, где буфер и какого он размера
  ADC_DMABEG = (int32u)ADC_DMA_buffer;
  ADC_DMASIZE = ADC_DMA_BUFFER_SIZE;
  ADC_DMACFG = 0x3;

  // Настроить АЦП:
  //   частота тактирования: 6 МГц,
  //   частота дискретизации: 5,859375 кГц (1024 тактов на преобразование),
  //   входной канал: дифференциальный, ADC3 - положит., ADC2 - отриц.
  ADC_CFG = 0;
  ADC_CFG =     (ADC_MUX_ADC3           << ADC_MUXP_BIT)
              | (ADC_MUX_ADC2           << ADC_MUXN_BIT)
              | (ADC_SAMPLE_CLOCKS_1024 << ADC_PERIOD_BIT)
              | ADC_ENABLE; // запустить преобразование

  // Непрерывное преобразование и обработка дынных
  while(1)
  {
    double voltage;
    
    INT_ADCFLAG = 0xFFFF; // Сбросить флаги АЦп
    while (!(INT_ADCFLAG & INT_ADCULDFULL)); // Ждать завершения преобразования
    
    // Измеренное напряжение на входе АЦП
    voltage = 1.2 * ADC_DMA_buffer[0] / 0x3FFF;
    
    // Здесь должен быть код обработки данных.
    // Время обработки должно быть короче периода дискретизации,
    // чтобы не пропустить новые данные.
  }

  return 0;
}

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

Реклама

Автор

Дмитрий Бравиков

Инженер. Электронщик. Программист.

АЦП STM32W108: 15 комментариев

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

      1. Спасибо! Эти исходники помогли мне разобраться с запуском. Планируется ли продолжение статей про ацп? Очень интересует тема создания выборки нескольких каналов в один опрос и прерывания от ацп.

        1. Продолжение пока не планируется.

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

          О прерываниях в этих контроллерах пока ничего не знаю.

  2. Перед инициализацией DMA очень логично сбрасывать DMA при помощи ADC_DMACFG=ADC_DMARST; Это необходимо для запуска DMA после выхода микроконтроллера из спячки. Если этого не сделать, то DMA начинает беситься и писать куда угодно.
    И еще про спячку и DMA. Не могу понять почему после выхода из сна устанавливается 3ий бит (значение 4) в регистре INT_ADCCFG. На всякий случай советую переинициализировать и его. Для вышеприведенного примера значение этого регистра должно быть 0.
    Таким образом перед строкой 25 примера нужно вставить строки:
    INT_ADCCFG=0;
    ADC_DMACFG=ADC_DMARST;
    Тогда все будет нормально работать даже если перед использованием АЦП с DMA микроконтроллер находился в спячке.

    Как описать прерывания пока не разобрался.

  3. Добрый вечер, Дмитрий!

    Скажите, пожалуйста, какие средства Вы используете для программирования/отладки STM32W108. ST-Link V2 и ST Link Utility? Если да, какой интерфейс: JTAG или SWD?

    У меня собраны две платы на базе сборок SPZB32W (STM32W108 в составе) — по каким-то причинам не могу их «увидеть» st-link’ом: постоянно вылетает ошибка «internal command error»

      1. Добрый день, Дмитрий!

        Спасибо за Ваш ответ. Я попробовал подключиться к плате через STVP и ST-Link V2, входящий в состав STM32F4Discovery. Отмечу, что STVP без проблем опознаёт «штатный» STM32F407. К сожалению, STM32W108 не распознаётся. В связи с этим хочу спросить Вас, что представляет собой обвязка Вашего SPZB-модуля? Каким образом Вы подключаете сборку к программатору (я понимаю, там максимум 6 пинов и особо мудрить негде — но уже не знаю, куда копать =) )

        Если сообщите адрес электронной почты — я вышлю Вам свою принципиальную схему.

        Спасибо Вам!

        1. Я подаю общее питание 3.3 В на сборку и программатор. Подключаю программатор к выводам SWDIO и SWCLK сборки. В STVP выбираю STM32W108. И все.

          Возможно, когда вы подаете питание на сборку в ней начинает работать какая-то программа, которая перенастраивает выводы SWDIO и SWCLK. В результате программатор не может связаться со сборкой. Попробуйте во время прошивки удерживать вывод nRESET сборки в логическом нуле. Или подключить этот вывод к выводу NRST ST-link’a, чтобы он сам сбрасывал сборку, когда надо.

          Еще проследите, чтобы у STM32F4Discovery были сняты перемычки с CN3 и вроде как разомкнут SB11, если используете вывод NRST.

          Если не разберетесь, присылайте схему: bravikov@gmail.com

  4. Спасибо за статью!!
    У меня была проблема с этим примером:
    В первой выборке с АЦП я всегда получал нули.
    Решение:
    Необходимо после строки 44 вставить:
    asm(«DMB»);

    Толко вот я незнаю что означает команда «DMB».

  5. Скажите, пожалуйста, что означают эти цифры в конце обозначения микроконтроллера:

    Enabled protocol stack:
    “Blank” = Development sample platform (1)
    1. This P/N is under specific ordering conditions. Please refer to your nearest ST sales office.
    3 = RF4CE stack
    4 = IEEE 802.15.4 media access control

    Например, STM32W108C8U64TR — для этого МК цифра 4 означает, что в нем включен стек IEEE 802.15.4 .
    Я не понимаю что означает включен стек? Как я понимаю, стек — это набор библиотек, подключенных к проекту, но почему об этом пишут в обозначении МК.

    Спасибо!

    1. Для использования стека требуется лицензия, МК с соответствующим обозначением имеют эту лицензию. Стеки идут в бинарниках и, видимо, имеют проверку на наличие лицензии в МК.

      1. Это вы где-то прочитали или логически пришли к такому выводу? А стек simplicity можно использовать на любом МК?

        1. Логически. Но цена МК зависит от модификации стека.
          simple mac работает на всех, мы использовали разные модификации МК в наших продуктах, но у нас свой протокол.

          1. А что за устройство? Можете показать что получилось?

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

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s