Инструменты пользователя

Инструменты сайта


prog:adc:example1986ve91t

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

В данной статье рассмотрен простой пример работы с блоком аналого-цифрового преобразователя на МК 1986ВЕ91Т в составе отладочной платы. Блок АЦП идентичен по своей структуре в следующих МК: 1986ВЕ1Т, 1986ВЕ3Т, 1986ВЕ4У, серия 1986ВЕ9х, 1901ВЦ1Т. Однако в каждом процессоре есть свои особенности. МК серии 1986ВЕ9х и 1901ВЦ1Т содержат два независимых АЦП до 16 каналов каждый, в то время как в МК 1986ВЕ1Т, 1986ВЕ3Т и 1986ВЕ4У по одному АЦП до 8 каналов. Пример проекта, рассмотренного в статье, доступен по ссылке.

Введение

Блок аналого-цифрового преобразователя представляет собой устройство, на вход которого подается аналоговый сигнал, а на выходе выдается цифровой код, пропорциональный поданному напряжению. АЦП является основой многих измерительных приборов, например, цифровых мультиметров, электронных весов, приборов для измерения температуры и давления и многих других…

АЦП может быть как отдельной микросхемой, например, как 5101НВ015, так и быть в составе микроконтроллера. МК1986ВЕ9х, 1986ВЕ1Т, 1986ВЕ3Т, 1986ВЕ4У содержат в себе интегрированный блок АЦП. Основные характеристики АЦП — это разрядность и время преобразования. Разрядность 12 бит, следовательно, АЦП может различать 212 = 4096 различных уровней подаваемого на вход напряжения. А время преобразования, в свою очередь, зависит от частоты, подаваемой на АЦП. По спецификации для осуществления преобразования требуется не менее 28 тактов синхронизации CLK, в качестве которой мы можем использовать как частоту процессора CPU_CLK, так и частоту ADC_CLK, формируемую в блоке «Сигналов тактовой частоты».

Стоит отметить, что согласно всё той же спецификации, частота тактирования АЦП не может превышать 14 МГц.

АЦП имеет следующие основные режимы работы:

-режим одиночного преобразования по одному каналу (с возможностью опроса бита окончания преобразования или с прерыванием по окончанию преобразования);

-режим многократного преобразования (по одному каналу/с автоматическим переключением нескольких каналов и возможностью использования прямого доступа к памяти).

Преобразование с контролем границ

Микроконтроллеры серии 1986ВЕ9х и 1901ВЦ1Т имеют в своём арсенале 2 независимых АЦП – ADC1, ADC2, которые входят в состав блока АЦП. Общая схема приведена на рисунке 1.

Рисунок 1.

Основной идеей данного примера является использование контроля уровня входного сигнала. В начале примера мы задали следующие переменные

H_Level = 0x900;

L_Level = 0x800;

которые являются нашими границами и за которыми МК будет следить. Изменять на входе напряжение будем с помощью подстроечного резистора, который согласно описанию платы, подключен к 7 каналу АЦП. Для этого необходимо установить перемычку на разъём XP6 в положение “TRIM”.

Таким образом, в случае нарушения данных границ (то есть выхода за границы интервала от 0x800 до 0x900) МК возведёт флаг Flg REG AWOIFEN в регистре ADCx_STATUS.

Настройка АЦП

Как мы отмечали ранее, в микроконтроллерах серии 1986ВЕ9x и 1901ВЦ1Т есть два независимых АЦП. И поэтому в спецификации есть два регистра настроек ADC1_CFG и ADC2_CFG.

В МК 1986ВЕ1Т, 1986ВЕ3Т, 1986ВЕ4У по одному АЦП, однако регистр ADC2_CFG тоже присутствует, в котором описан только 17 бит ADC1_OP "Выбор источника для формирования внутренней рабочей точки".

Настройка АЦП в 1986ВЕ9x происходит с использованием двух структур: ADC_StructInit и ADCx_StructInit. Это обусловлено это тем, что первая структура ADC_StructInit содержит «общие настройки», которые применимы для самого контроллера блока ADC. А уже структура ADCx_StructInit содержит в себе настройку конкретного АЦП1 или АЦП2. Рассмотрим каждую по отдельности.

Первую структуру ADC_StructInit мы оставим без изменений:

#if defined( USE_MDR1986VE9x ) || defined (USE_MDR1901VC1T)
  ADC_InitStruct->ADC_SynchronousMode     = ADC_SyncMode_Independent; // параметр отвечает за синхронный/независимый запуск двух АЦП (только для 1986ВЕ9х и 1901ВЦ1Т)
#endif

  ADC_InitStruct->ADC_StartDelay        	= 0; //позволяет задать задержку между запусками АЦП1 и АЦП2
  ADC_InitStruct->ADC_TempSensor        	= ADC_TEMP_SENSOR_Disable; //запрет работы температурного датчика и источника опорного напряжения (бит TS_EN)
  ADC_InitStruct->ADC_TempSensorAmplifier   = ADC_TEMP_SENSOR_AMPLIFIER_Disable; //запрет работы выходного усилителя (бит TS_BUF)
  ADC_InitStruct->ADC_TempSensorConversion  = ADC_TEMP_SENSOR_CONVERSION_Disable; //запрет выбора датчика температуры (бит SEL_TS)
  ADC_InitStruct->ADC_IntVRefConversion     = ADC_VREF_CONVERSION_Disable; //запрет выбора источника опорного напряжения для оцифровки (бит SEL_VREF для 1986ВЕ9x значение 1.23 В)
  ADC_InitStruct->ADC_IntVRefTrimming     	= 0; //задавая значения от 0 до 7, можно в небольших пределах подстроить 

#if defined ( USE_MDR1986VE3 ) || defined ( USE_MDR1986VE1T )
  ADC_InitStruct->ADC_IntVRefAmplifier    	= ADC_INT_VREF_AMPLIFIER_Disable; //запрет выбора источника опорного напряжения для оцифровки ( бит SEL_VREF_BUF в регистре  ADC1_TRIM данный регистр реализован только в 1986ВЕ1Т и 1986ВЕ3Т со второй ревизии)
#endif

Здесь стоит отметить следующий момент: параметр ADC_IntVRefConversion разрешает и запрещает выбор источника опорного напряжения бит SEL_VREF регистра ADC1_CFG. Затем с помощью параметра ADC_IntVRefTrimming можно выполнить подстройку значений от 0 до 7 - биты 24..21 TR того же регистра ADC1_CFG. В микроконтроллерах 1986ВЕ1Т и 1986ВЕ3Т разрешение выбора данного датчика, а также подстройка значений, выполняется в отдельном регистре ADC1_TRIM.

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

Теперь переходим к конфигурации АЦП1.

  sADCx.ADC_ClockSource      = ADC_CLOCK_SOURCE_CPU; //выбор источника тактирования, частота ядра
  sADCx.ADC_SamplingMode     = ADC_SAMPLING_MODE_CICLIC_CONV; //режим многократного преобразования
  sADCx.ADC_ChannelSwitching = ADC_CH_SWITCHING_Disable; // автоматическое переключение каналов
  sADCx.ADC_ChannelNumber    = ADC_CH_ADC7; //выбор номера канала
  sADCx.ADC_Channels         = 0; //количество используемых каналов, если включен перебор ADC_CH_SWITCHING_Enable
  sADCx.ADC_LevelControl     = ADC_LEVEL_CONTROL_Enable; // контроль уровня входного сигнала
  sADCx.ADC_LowLevel         = L_Level;//нижний уровень контроля
  sADCx.ADC_HighLevel        = H_Level; // верхний уровень
  sADCx.ADC_VRefSource       = ADC_VREF_SOURCE_INTERNAL; //выбор внутреннего источника опорного напряжения
  sADCx.ADC_IntVRefSource    = ADC_INT_VREF_SOURCE_INEXACT; //вид источника для датчика опорного напряжения
  sADCx.ADC_Prescaler        = ADC_CLK_div_32768; //выбор делителя тактовой частоты
  sADCx.ADC_DelayGo          = 0xF; //значение задержки перед началом следующего преобразования

Прерывания по завершению преобразования

После инициализации АЦП с помощью функции ADC1_ITConfig разрешим прерывания по завершению преобразования. Затем функцией ADC1_Cmd (ENABLE) разрешаем работу АЦП. Как только АЦП выполнит преобразование, произойдет переход в функцию обработчика прерываний, в котором мы сначала выполняем проверку установки флага выхода за границы. Если значение на входе АЦП не попадает в обозначенные границы, загорается диод VD5, затем мы считываем значение регистра ADC1_RESULT и накладываем маску, поскольку биты данного регистра содержат также номер канала, и сравниваем результат. Если мы превысили верхнее значение границы, то вместе с VD5 горит диод VD6, а если нижнее, то VD5 горит вместе с VD7. При попадании значения на входе АЦП в нужный интервал все диоды погаснут. В конце обработчика выполняем очистку флагов.

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

void ADC_IRQHandler(void)
{
  if(ADC1_GetFlagStatus(ADCx_IT_OUT_OF_RANGE) == SET)
  {
    /* Turns LED1 On */
    PORT_SetBits(MDR_PORTD, PORT_Pin_10);
  }
  else
  {
    /* Turns LED1 Off */
    PORT_ResetBits(MDR_PORTD, PORT_Pin_10);
  }
  tmp = MDR_ADC->ADC1_RESULT & 0x0FFF;
  if(tmp > H_Level)
  {
    /* Turns LED2 On */
    PORT_SetBits(MDR_PORTD, PORT_Pin_11);
  }
  else
  {
    /* Turns LED2 Off */
    PORT_ResetBits(MDR_PORTD, PORT_Pin_11);
  }
  if (tmp < L_Level) 
  {
    PORT_SetBits(MDR_PORTD, PORT_Pin_12);
  }
  else
  {
    PORT_ResetBits(MDR_PORTD, PORT_Pin_12);
  }
		
  /* Clear ADC1 OUT_OF_RANGE interrupt bit */
 
  MDR_ADC->ADC1_STATUS = (ADCx_IT_END_OF_CONVERSION | ADCx_IT_OUT_OF_RANGE)<<2;
}

В режиме отладки можно посмотреть, как происходят изменения значения в регистре ADC1_RESULT в зависимости от изменения сопротивления подстроечного резистора, чтобы отловить момент выхода за объявленные границы.

Расчёт и измерение времени преобразования АЦП

Для всех указанных в данной статье МК общее время преобразования АЦП складывается:

28*CLK + (DelayGO+1)*CPU_CLK, где CLK и CPU_CLK - периоды частоты CLK и CPU_CLK.

28 тактов частоты CLK требуется на выполнение самого преобразования, количество тактов DelayGO+1 частоты CPU_CLK используется для задержки перед преобразованием в циклическом режиме для заряда внутренней емкости АЦП.

В качестве источника синхросигнала CLK может быть выбрана частота либо CPU_CLK, либо ADC_CLK. Настройка частоты ADC_CLK производится в блоке управления тактовыми частотами RST_CLK. Частота CPU_CLK для тактирования контроллера АЦП может быть настроена с помощью отдельного для АЦП делителя, коэффициент деления задаётся битами Cfg REG DIVCLK [3:0], регистр ADCx_CFG. В этом случае частота CLK = CPU_CLK = HCLK / (2^DIVCLK). В данном случае частота CPU_CLK - это частота тактирования блока АЦП после делителя DIVCLK.

Дополнительная задержка перед началом преобразования всегда определяется в тактах частоты CPU_CLK, которая также поступает через делитель и равна HCLK / (2^DIVCLK).

Таким образом, при выборе источника синхросигнала CLK = CPU_CLK, установке DelayGO = 7, частоте тактирования МК 80 МГц и делителе DIVCLK = 6, общее время преобразования будет равняться:

28*CLK + (DelayGO+1)*CPU_CLK = 28*CPU_CLK + 8*CPU_CLK = 36*CPU_CLK,

CPU_CLK = HCLK / (2^DIVCLK) = 80 МГц / 64 = 1.25 МГц,

период CPU_CLK = 1/1.25 = 0.8 мкс,

общее время преобразования = 36*0.8 мкс = 28.8 мкс.

Однако в МК серии 1986ВЕ9x необходимо учитывать ошибку 0016 errata "Некорректное вычисление дополнительной задержки начала преобразования контроллера АЦП вариант 2", из-за которой дополнительная задержка, задаваемая битами DelayGO, вычисляется некорректно. На практике, к сожалению, расчёт дополнительной задержки зависит от многих факторов и поэтому рассчитать теоретически данную задержку не получится, её можно измерить только экспериментально.

prog/adc/example1986ve91t.txt · Последние изменения: 2018/11/12 10:56 — katya