STM32 АЦП.

STM32 АЦП.

Давайте рассмотрим какими особенностями обладает АЦП в STM32.
  • Разрядность 12 бит
  • Опорное напряжение от 2.4 до 3.6 Вольта
  • Скорость оцифровки до 1MSPS
  • 18 каналов(16 внешних и 2 внутренних – опорное напряжение и температурный датчик)
  • Прерывание по окончании регулярных и инжектированных преобразований
  • Прерывание от оконного компаратора(Analog watchdog)
  • Отправка данных по DMA для регулярных преобразований
  • Одиночное и непрерывное преобразование
  • Режим сканирования каналов по заданному списку
  • Самокалибровка
  • Выравнивание результата по выбранному краю
  • Время преобразования –12.5 цикла, время захвата – программируемое

STM32 АЦП.

Режим регулярных преобразований.
В этом режиме задаётся группа от 1 до 16 каналов, обработка которых производится последовательно, а результат помещается в один-единственный 12-разрядный регистр, подразумевается, что данные будут сохраняться с помощью DMA. Ещё раз хотелось бы подчеркнуть, что нельзя просто выбрать один канал, надо задать группу, а в ней выбрать количество каналов. Преобразования могут быть циклическими и периодическими, запускаться по таймеру или внешнему прерыванию.
 
Режим инжектированных преобразований.
В последовательность инжектированных преобразований может входить до 4 каналов, они имеют собственные регистры для сохранения результата. Сразу после запуска инжектированных преобразований, приостанавливается оцифровка регулярных, затем по окончании инжектированных, возобновляется оцифровка регулярных. В регистры компенсации можно записать число, которое будет автоматически вычитаться из результата преобразования, если в результате вычитания получается отрицательное число, регистр инжектированного преобразования дополняется знаком.
 
Оконный компаратор.
В специальных регистрах ADC_HTR и ADC_LTR мы задаём верхнее и нижнее значение результата преобразования, при выходе за которые устанавливается флаг AWD.
 
Для работы с АЦП в STM32 выделен 1 регистр статуса — SR и два регистра настройки CR1, CR2.
 
SR(Status Register)
 
AWD(Analog watchdog flag) — флаг оконного компаратора, устанавливается в 1, когда результат преобразования пересёк ADC_HTR и ADC_LTR.
 
EOC (End of conversion) – флаг окончания группового преобразования, устанавливается в 1 по окончании регулярного или инжектированного преобразования.
 
JEOC(Injected channel end of conversion) — флаг окончания инжетированного преобразования, устанавливается в 1 по окончании инжектированого преобразования.
 
JSTRT(Injected channel Start flag) — флаг запуска инжектированного преобразования, устанавливается в 1 при старте инжектированного преобразования.
 
STRT(Regular channel Start flag) — флаг запуска регулярного преобразования, устанавливается в 1 при старте регулярного преобразования.
Описанные выше флаги выставляются аппаратно, а сбрасывать их надо программно!!!
 

ADC_CR1(ADC control register 1)
 
AWDCH[4:0] (Analog watchdog channel select bits) — выбор канала для оконного компаратора, при условии, что битAWDSGL=1.
00000: Канал № 0.
00001: Канал №1.
………
10001: Канал №17.
 
EOCIE(Interrupt enable for EOC) — разрешение прерывания по окончании преобразования, 1 — разрешить, 0 — запретить.
 
AWDIE(Analog watchdog interrupt enable) — разрешение прерывания по сигналу оконного компаратора, 1 — разрешить, 0 — запретить.
 
JEOCIE(Interrupt enable for injected channels) — разрешение прерывания по окончании инжектированного преобразования, 1 — разрешить, 0 — запретить.
 
SCAN(Scan mode) — разрешить сканирование каналов по списку указанному в регистрах ADC_SQRx, 1 — разрешить, 0 — запретить.
 
AWDSGL(Enable the watchdog on a single channel in scan mode) — задаёт режим  сканирования оконного компаратора, 0 — все каналы, 1 — только канал указанный в AWDCH[4:0].
 
JAUTO(Automatic Injected Group conversion) — непрерывное преобразование инжектированных каналов, 1 — разрешить, 0 — запретить.
 
DISCEN(Discontinuous mode on regular channels) — дискретный(прерывистый) режим преобразования регулярных каналов, 1 — разрешить, 0 — запретить.
 
JDISCEN(Discontinuous mode on injected channels) — дискретный(прерывистый) режим преобразования инжектированных каналов, 1 — разрешить, 0 — запретить.
 
DISCNUM[2:0](Discontinuous mode channel count) — количество каналов регулярного преобразования.
000: 1 канал
001: 2 канала
…..
111: 8 каналов
 
DUALMOD[3:0](Dual mode selection) — определяет режим совместной работы двух АЦП.
 
JAWDEN(Analog watchdog enable on injected channels) — подключение оконного компаратора к инжектированным каналам, 1 — разрешить, 0 — запретить.
 
AWDEN(Analog watchdog enable on regular channels) — подключение оконного компаратора к регулярным каналам, 1 — разрешить, 0 — запретить.
 
 
ADC_CR2(ADC control register 2)
 
ADON(A/D converter ON / OFF) — управление АЦП, 1 — разрешает работу АЦП, 0 — прерывает преобразование/калибровку и переводит АЦП в режим пониженного энергопотребления.
 
CONT(Continuous conversion) — режим преобразования, 0 — однократный, 1 — непрерывный.
 
CAL(A/D Calibration) — запуск калибровки, 1 — запустить калибровку, 0 — устанавливается аппаратно по завершении калибровки. Производить до включения АЦП, каждый раз после подачи питания.
 
RSTCAL(Reset calibration) — сброс значений калибровки, 1 — сбросить, 0 — устанавливается по завершении сброса.
 
DMA(Direct memory access mode) — разрешает работу DMA, 1 – разрешает, 0 — запрещает.
 
ALIGN(Data alignment) — выравнивание данных, 1 — по правому краю, 0 — по левому. Здесь хорошо будет посмотреть на картинку, так как при инжектированных преобразованиях появляется ещё и знак, на картинке ячейки со знаком обозначены как SEXT.
 
STM32 АЦП.

 
JEXTSEL[2:0](External event select for injected group) – выбор внешнего источника запуска инжектированных каналов.
STM32 АЦП.

 
JEXTTRIG(External trigger conversion mode for injected channels) — разрешение запуска инжектированного преобразования внешним сигналом, 1 — разрешить, 0 — запретить.
 
EXTSEL[2:0](External event select for regular group) — выбор внешнего источника запуска регулярных каналов.
STM32 АЦП.

 
EXTTRIG(External trigger conversion mode for regular channels) — разрешение запуска регулярного преобразования внешним сигналом, 1 — разрешить, 0 — запретить.
 
JSWSTART(Start conversion of injected channels) — запуск преобразования инжектированных каналов, 1 — запустить преобразование, сбрасывается после запуска преобразования аппаратно. Также для запуска в JEXTSEL[2:0] источником запуска должен быть выбран JSWSTART.
 
SWSTART(Start conversion of regular channels) — запуск преобразования регулярных каналов, 1 — запустить преобразование, сбрасывается после запуска преобразования аппаратно. Также для запуска в EXTSEL[2:0] источником запуска должен быть выбран SWSTART.
 
TSVREFE(Temperature sensor and VREFINT enable) — включает измерение температуры и ИОН, 1 — включить, 0 — выключить. Есть только в ADC1.
 
 
SMPR[2:1](Channel x Sample time selection).
В этих регистрах задаётся количество тактов между выборками, отдельно для каждого канала.
В SMPR1 с 10 по 17-й канал.
 
STM32 АЦП.

В SMPR2 с 0 по 9-й канал.
STM32 АЦП.

Длительность преобразования составляет 12.5 цикла, для того чтобы найти период выборок надо к длительности преобразования прибавить значение SMPx[2:0].
STM32 АЦП.

Т = время между выборки + 12.5 цикла
Получается минимальный период выборок равен
Т = 12.5 + 1.5 = 14 тактов
Максимальная частота, с которой может тактироваться АЦП составляет 14MHz, таким образом, минимальный период выборок равен 1uS.
 
JOFRx(x=1..4)
Компенсационные регистры инжектированных каналов, в эти регистры можно записать значение, которое по окончании преобразования будет вычитаться из результата.
 
HTR и LTR
Верхний и нижний предел оконного компаратора.
 
SQRх[3:1] – этот регистр можно условно разделить на две части: биты L[3:0] и биты SQx[4:0].
STM32 АЦП.

STM32 АЦП.

STM32 АЦП.

Номер секции SQx определяет номер в группе регулярных преобразований, а число записанное в секцию определяет номер канала.
Узнать какому выводу соответствует канал можно из даташита в разделе Pinouts and pin description.
STM32 АЦП.

А битами L[3:0] в регистре SQR1 задаётся длина регулярной последовательности
0000: 1 преобразование
0001: 2 преобразования
….......
1111: 16 преобразований

Например
L = 0010
SQ1=00000, SQ2=00100, SQ3=00010
Означает что длина последовательности равна 3 и выполняться она будет в следующем порядке 1-й , 5-й , 3-й канал.
 
JSQR — в этих регистрах задаётся длина инжектированной последовательности и порядок преобразований. Битами JL[1:0] задаётся длина  последовательности
00: 1 преобразование
01: 2 преобразования
10: 3 преобразования
11: 4 преобразования

Номер секции JSQx определяет номер в группе инжектированных преобразований, а число записанное в секцию определяет номер канала.
Узнать какому выводу соответствует канал можно из даташита в разделе Pinouts and pin description.
Если количество преобразований меньше 4, например 3, то порядок преобразования для записи
ADC_JSQR[21:0] = 10 00011 00011 00111 00010
Будет 7-й,3-й,3-й, а не 2-й,7-й,3-й.

JDR(x = 1...4)
Регистры данных инжектированных преобразований.
 
DR
Регистр данных регулярных преобразований.

Ниже пример кода для запуска АЦП.

#include "stm32f10x.h"            

unsigned temp;

void ADC1_2_IRQHandler(void)
{
       if(ADC1->SR & ADC_SR_EOC)
	{
	     //записываем результат в переменную 
             temp =ADC1->DR;
	}
        //сбрасываем все флаги в регистре статуса
	ADC1->SR=0;
}
int main(void)
{
	//разрешаем тактирование порта А
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
        //настраиваем вывод для работы АЦП в режим аналогового входа
	GPIOA->CRL &= ~GPIO_CRL_CNF1;
	//так как тактовая частота АЦП не должна превышать 14MHz
	RCC->CFGR |= RCC_CFGR_ADCPRE_DIV8;
	//разрешаем тактирование АЦП
	RCC->APB2ENR |= RCC_APB2ENR_ADC1EN ;
        //в комментах подсказали, что в 17 ревизии указано, что перед калибровкоц АЦП надо включить
        ADC1->CR2 = | ADC_CR2_ADON;
        //запускаем калибровку и ждем пока завершится,  в симуляторе это не работает, в железе делать обязательно
       /* ADC1->CR2 |= ADC_CR2_CAL; 
         while (ADC1->CR2 & ADC_CR2_CAL)*/
	//разрешаем прерывание от АЦП
	NVIC->ISER[0] |= NVIC_ISER_SETENA_18;
	//для первого канала между выборками 7.5 цикла
	ADC1->SMPR2 = ADC_SMPR2_SMP1_0; 
	//разрешаем прерывания по окончанию преобразования
	ADC1->CR1 = ADC_CR1_EOCIE;
	//разрешаем запуск от SWSTAR, разрешаем работу АЦП, разрешаем запуск внешним сигналам, непрерывное преобразования
	ADC1->CR2 = ADC_CR2_EXTSEL | ADC_CR2_EXTTRIG | ADC_CR2_CONT ;
	//длина последовательности равна 1, первый канал
	ADC1->SQR1 = 0x00000000;
	ADC1->SQR2 = 0x00000000;
	ADC1->SQR3 = 0x00000001;
	//запускаем АЦП
	ADC1->CR2 |= ADC_CR2_SWSTART;
	while(1)
	{
		/*остановить проект, в командную строку записать include sine.ini
		     затем записать ADC1_IN1_Sine ()*/
	}
}


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

Для начала создаём текстовый документ, записываем в него следующий код и сохраняем его с названием sine.ini

SIGNAL void ADC1_IN1_Sine (void)  {
  float volts;        // peak-to-peak voltage
  float frequency;    // output frequency in Hz
  float offset;       // voltage offset
  float duration;     // duration in Seconds
  float val;
  long  i, end;
   
  volts     = 1.5;
  offset    = 1.5;
  frequency = 50;
  duration  = 0.01;

  printf ("Sine Wave Signal on AD Channel 1.\n");

  end = (duration * 1000000000);
  for (i = 0 ; i < end; i++)  {
    val = __sin (2 * 3.1415926 * frequency * (((float) STATES) / STCLK));
    ADC1_IN1 = (val * volts) + offset;
    swatch (0.00001);                // in 10 uSec steps
  }
}
DEFINE BUTTON "ADC1_IN1 Sin","ADC1_IN1_Sine()"

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