24448

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

Дата последнего изменения: 23.03.2020 14:25:19

В данной статье рассмотрен простой пример работы с блоком аналого-цифрового преобразователя на МК 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, формируемую в блоке «Сигналов тактовой частоты».

Стоит отметить, что согласно спецификации на микроконтроллеры серии 1986ВЕ9х, частота тактирования(частота следования тактовых импульсов) АЦП не может превышать 14 МГц.

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

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

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

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

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

 Рисунок 1 - Структурная схема АЦП

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

H_Level = 0x900;

L_Level = 0x800;

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

 Рисунок 2 - Фрагмент платы 1986ВЕ91 с подстроечным резистором и перемычкой XP6

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

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

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

В МК 1986ВЕ1Т, 1986ВЕ3Т, 1986ВЕ4У по одному АЦП, однако регистр ADC2_CFG тоже присутствует. В этом регистре (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.

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

Рассмотрим конфигурацию АЦП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 в зависимости от изменения сопротивления подстроечного резистора, чтобы отловить момент выхода за объявленные границы (рисунок 3).

 Рисунок 3 - Регистры АЦП в режиме "отладки"


Расчет и измерение времени преобразования АЦП описано в статье "Расчет времени преобразования АЦП и время заряда внутренней емкости"

 Последовательное преобразование нескольких каналов

 В данном режиме работы есть определенное условие, которое надо обязательно соблюдать. Необходимо обеспечить выставление бит каналов, в регистре ADC1_CHSEL, участвующих в преобразовании до конфигурирования самого блока АЦП, то есть до записи в регистр ADCx_CFG.

Пример работы:

#define Amount_Conv 10

uint32_t status[Amount_Conv], data[Amount_Conv], counter = 0;
volatile uint32_t a=0;

int main (void)
{
MDR_RST_CLK->PER_CLOCK=0xFFFFFFFF;
MDR_PORTD->ANALOG=0xFFFF;
MDR_PORTD->PWR=0xFFFFFFFF;
MDR_PORTD->OE=0xFFFF;

MDR_ADC->ADC1_CHSEL=(1<<2) | (1 <<3);
MDR_ADC->ADC1_CFG |= (1<<3) | (1<<9) | (3<<12) | (7<<25);
MDR_ADC->ADC1_CFG |= 0x1;

while( counter < Amount_Conv )
  {
    while( ( MDR_ADC->ADC1_STATUS & (1<<2) ) == 0){}         
    status[counter] = MDR_ADC->ADC1_STATUS;
    data[counter] = MDR_ADC->ADC1_RESULT;                        
    counter++;
  }
while(1);
}

Сохранить статью в PDF

Файлы для скачивания

Документация

Программное обеспечение

Standard Peripherals Library + software pack для Keil MDK 5
Standard Peripherals Library + software pack для Keil MDK 5
ОФИЦИАЛЬНАЯ СБОРКА
Standard Peripherals Library – библиотека для микроконтроллеров.

Теги

Была ли статья полезной?