10.2.6. Примеры использования модуля ADC

(Руководство разработчика по микроконтроллерам семейства HCS08)

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

Светодиод LED1 горит, когда напряжение на входе больше, чем

.

Светодиод LED2 горит, когда напряжение на входе больше, чем

.

Пример 10.4. Использование модуля ADC

//ПримериспользованиямодуляADC
//ДемонстрационнаяплатаDEMO9S08QG8
//СветодиодLED1подключенклинииPTB6
//СветодиодLED2подключенклинииPTB7
//RV1подключенклинииPTA0
//RZподключенклинииPTA1
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#include"hcs08.h"/*Этонашфайлсобъявлениями!*/
#defineLED1PTBD_PTBD6
#defineLED2PTBD_PTBD7
unsignedintresult;
voidmain(void)
{
SOPT1=bBKGDPE;//НастройкарегистраSOPT1,включениелинииBKGD
ICSSC=NV_FTRIM;//НастройказначенияFTRIM
ICSTRM=NV_ICSTRM;//НастройказначенияTRIM
ICSC2=0;//ICSOUT=DCOOUT/1
ADCCFG=bADLSMP|ADC_10BITS;//Увеличенноевремязарядавходнойемкости
//Разрешение10бит
APCTL1=BIT_0;//ADP0ваналоговомрежиме
ADCSC1=bADCO|ADCH0;//Канал0модуляADCврежиме
//многократногопреобразования
PTBDD=BIT_6|BIT_7;//НастройкалинийPTB6иPTB7навывод
while(1)
{
if(ADCSC1_COCO)//Еслипреобразованиезакончено
{
result=ADCR;//Считываемрезультат(сбрасываемфлагCOCO)
if(result>512)LED1=0;elseLED1=1;
if(result>768)LED2=0;elseLED2=1;
}
}
}

Вы можете следить за результатом преобразования с помощью программы отладчика, используя режим периодического обновления. Более подробно это описывается в подразделе 3.6.1.

Давайте посчитаем частоту преобразования сигнала в описанном выше примере. Предположим, что частота BUSCLK, которая тактирует модуль ADC, равна 8МГц (ADICLK= 00). Это означает, что период тактового сигнала модуля ADC равен 125нс.

Из Табл.10.5 следует, что время первого преобразования равно 43ADCK + 5BUSCLK = 48BUSCLK = 6мкс. Следующее преобразование займет 5мкс (40 периодов BUSCLK). Это означает, что можно достичь скорости преобразования 200000 преобразований в секунду, или 200kSPS.

Учтите, что если установлен режим медленного преобразования, то частота BUSCLK должна быть в 8 раз выше частоты тактирования модуля ADC, чтобы гарантированно получить необходимое время преобразования. Для этого в предыдущем примере в качестве источника тактирования модуля ADC необходимо использовать сигнал BUSCLK/2 и настроить внутренний делитель частоты на режим деления на 8. А именно — изменить настройку регистра ADCCFG следующим образом:

ADCCFG=bADLSMP|ADC_10BITS|ADC_BUSCLK_DIV2|ADIV_8;

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

В следующем примере показано, как использовать модуль ADC в режиме генерации прерывания для выполнения задачи, решенной в Примере 10.4.

Пример 10.5. Использование модуля ADC с генерацией прерываний

//ПримериспользованиямодуляADCсгенерациейпрерываний
//ДемонстрационнаяплатаDEMO9S08QG8
//СветодиодLED1подключенклинииPTB6,
//светодиодLED2подключенклинииPTB7
//RV1подключенклинииPTA0,RZподключенклинииPTA1
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#include"hcs08.h"/*Этонашфайлсобъявлениями!*/
#defineLED1PTBD_PTBD6
#defineLED2PTBD_PTBD7
unsignedintresult;
//ПодпрограммапрерываниямодуляADC(чтениерезультатапреобразования)
voidinterruptVectorNumber_Vadcadc_isr(void)
{
result=ADCR;//Читаемрезультат(сбрасываемфлагпрерывания)
}
voidmain(void)
{
SOPT1=bBKGDPE;//НастройкарегистраSOPT1,включениелинииBKGD
ICSSC=NV_FTRIM;//НастройказначенияFTRIM
ICSTRM=NV_ICSTRM;//НастройказначенияTRIM
ICSC2=0;//ICSOUT=DCOOUT/1(16МГц)
//Увеличенноевремязарядавходнойемкости,разрешение10бит
//ADICLK=11b,ADCK=BUSCLK/2
ADCCFG=bADLSMP|ADC_10BITS|ADC_BUSCLK_DIV2|ADIV_8;
APCTL1=BIT_0;//ADP0ваналоговомрежиме
ADCSC1=bAIEN|bADCO|ADCH0;//Канал0модуляADCврежимемногократного
//преобразованиясгенерациейпрерываний
PTBDD=BIT_6|BIT_7;//НастройкаPTB6иPTB7навывод
EnableInterrupts;//Разрешениепрерываний(CCR:I=0)
while(1)
{
if(result>512)LED1=0;elseLED1=1;
if(result>768)LED2=0;elseLED2=1;
}
}

В Примере 10.6 показано применение модуля ADC для реализации последовательных измерений. В этом примере канал 0 и канал 1 проверяются последовательно. По окончанию каждого преобразования вызывается подпрограмма прерывания, в которой считывается результирующее значение после преобразования и назначается номер канала для следующего преобразования.

В примере считываются сигналы, определяемые потенциометром RV1, который подключен к линии PTA0/ADP0, и датчиком освещенности RZ1, который подключен к линии PTA1/ADP1.

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

  • светодиод LED загорается, если напряжение, установленное потенциометром RV1, больше чем 1.65В (результат преобразования больше 512), иначе светодиод не горит;
  • светодиод LED2 включается, если напряжение на световом датчике RZ1 больше, чем напряжение, установленное потенциометром RV1.

Программа примера была отлажена на демонстрационной плате DEMO9S08QG8.

Пример 10.6. Использование модуля ADC для измерения по двум каналам

//ПримериспользованиямодуляADCврежимепоследовательногопреобразования
//ДемонстрационнаяплатаDEMO9S08QG8
//СветодиодLED1подключенклинииPTB6
//СветодиодLED2подключенклинииPTB7
//RV1подключенклинииPTA0,RZподключенклинииPTA1
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#include"hcs08.h"/*Этонашфайлсобъявлениями!*/
#defineLED1PTBD_PTBD6
#defineLED2PTBD_PTBD7
unsignedinttrimpot,sensor;
//ПодпрограммапрерываниямодуляADC(сохраняетсязначениепреобразованного
//напряжениядатчикаосвещенностиилипотенциометра)
voidinterruptVectorNumber_Vadcadc_isr(void)
{
if(ADCSC1&0x1F)
{
sensor=ADCR;//Читаемрезультатпреобразованиянапряженияканала1
ADCSC1=bAIEN|ADCH0;//Следующийканал—0
}
else
{
trimpot=ADCR;//Читаемрезультатпреобразованиянапряженияканала0
ADCSC1=bAIEN|ADCH1;//Следующийканал—1
}
}
voidmain(void)
{
SOPT1=bBKGDPE;//НастройкарегистраSOPT1,включениелинииBKGD
ICSSC=NV_FTRIM;//НастройказначенияFTRIM
ICSTRM=NV_ICSTRM;//НастройказначенияTRIM
ICSC2=0;//ICSOUT=DCOOUT/1(16МГц)
//Увеличенноевремязарядавходнойемкости,разрешение10бит
//ADICLK=11b,ADCK=BUSCLK/2
ADCCFG=bADLSMP|ADC_10BITS|ADC_BUSCLK_DIV2|ADIV_8;
APCTL1=BIT_0|BIT_1;//КаналыADP0иADP1ваналоговомрежиме
//Включениеканала0сгенерациейпрерывания
ADCSC1=bAIEN|ADCH0;
PTBDD=BIT_6|BIT_7;//НастройкалинийPTB6иPTB7навывод
EnableInterrupts;//Разрешениепрерываний(CCR:I=0)
while(1)
{
if(trimpot>512)LED1=0;elseLED1=1;
if(sensor>trimpot)LED2=0;elseLED2=1;
}
}

В Примере 10.7 показано, как использовать модуль ADC в режиме цифрового сравнения, т.е. с использованием встроенного цифрового компаратора. Модуль ADC читает состояние светового датчика и, если световой датчик находится в темноте, то загорается светодиод LED1.

Также в примере показаны принципы работы модуля ADC в режиме останова Stop3 с тактированием модуля ADC асинхронным генератором (ADACK).

Пример 10.7. Использование цифрового компаратора модуля ADC

//ПримериспользованияцифровогокомпараторамодуляADCирежимаостанова
//ДемонстрационнаяплатаDEMO9S08QG8
//СветодиодLED1подключенклинииPTB6,
//светодиодLED2подключенклинииPTB7
//RV1подключенклинииPTA0
//RZподключенклинииPTA1
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#include"hcs08.h"/*Этонашфайлсобъявлениями!*/
#defineLED1PTBD_PTBD6
unsignedintsensor;
//ADCISR
voidinterruptVectorNumber_Vadcadc_isr(void)
{
sensor=ADCR;
if(ADCSC2_ACFGT)//Есликомпараторработаетпологике«больше»
{
LED1=0;//ВключитьсветодиодLED1
ADCSC2_ACFGT=0;//Переключитькомпараторнаработупологике«меньше»
}
else//Есликомпараторработаетпологике«меньше»
{
LED1=1;//ВыключитьсветодиодLED1
ADCSC2_ACFGT=1;//Переключитькомпараторнаработупологике«больше»
}
ADCSC1_ADCH=1;//НачатьпреобразованиемодуляADC
}
voidmain(void)
{
//НастройкарегистраSOPT1:включитьлиниюBKGDиразрешитькомандуSTOP
SOPT1=bSTOPE|bBKGDPE;
ICSSC=NV_FTRIM;//НастройказначенияFTRIM
ICSTRM=NV_ICSTRM;//НастройказначенияTRIM
ICSC2=0;//ICSOUT=DCOOUT/1
SPMSC2=0;//ВыборрежимаостановаStop3
//Увеличенноевремязарядавходнойемкости,разрешение10бит
//ADICLK=11b,ADCK=ADACK
ADCCFG=bADLSMP|ADC_10BITS|ADC_INTCLK|ADIV_8;
ADCCV=900;//ЗначениедлясравнениякомпаратораADC
ADCSC2=bACFE|bACFGT;//Включениекомпараторапологике«большеилиравно»
APCTL1=BIT_1;//ЛинияADP1ваналоговомрежиме
//Многократноепреобразованиеканала1модуляADCсгенерациейпрерывания
ADCSC1=bAIEN|bADCO|ADCH1;
PTBDD=BIT_6;//НастройкалинииPTB6навывод
LED1=1;//ВыключитьсветодиодLED1
EnableInterrupts;//Разрешениепрерываний(CCR:I=0)
while(1)
{
STOP;//ПереходврежимостановаStop3
}
}

Модуль ADC может быть использован в необычных целях, например для генерации периодических прерываний!

В Примере 10.8 показано, как реализовать подобную задачу, используя только внутренние ресурсы модуля ADC: датчик температуры, источник опорного напряжения VREFH или VREFL). Но без внешних подключений!

Учтите, что при использовании режима медленного преобразования (ADLSMF = 1) и тактирования от частоты BUSCLK/16 каждое преобразование занимает 80мкс (кроме первого) при частоте BUSCLK = 8МГц. Если использовать режим быстрого преобразования, то время преобразования будет составлять 40мкс. Хотя можно настроить модуль ADC на более быстрое преобразование, это может привести к очень большому количеству прерываний за секунду и помешать обработке прерываний от других модулей.

Пример 10.8. Использование модуля ADC в качестве таймера

//ПримертаймеранаосновемодуляADC
//ДемонстрационнаяплатаDEMO9S08QG8
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#include"hcs08.h"/*Этонашфайлсобъявлениями!*/
#defineLED1PTBD_PTBD6
unsignedinttimeout;
//ПодпрограммапрерываниймодуляADC
voidinterruptVectorNumber_Vadcadc_isr(void)
{
chartemp;
temp=ADCRL;//ЧтениерегистраADCRдлясбросафлагапрерывания
if(timeout)timeout--;
}
//Функциязадержки
voidadc_delay(unsignedintdelay)
{
timeout=delay;
while(timeout);
}
voidmain(void)
{
//НастройкарегистраSOPT1:включитьлиниюBKGD
SOPT1=bBKGDPE;
ICSSC=NV_FTRIM;//НастройказначенияFTRIM
ICSTRM=NV_ICSTRM;//НастройказначенияTRIM
ICSC2=0;//ICSOUT=DCOOUT/1
//Увеличенноевремязарядавходнойемкости,разрешение10бит
//ADICLK=11b,ADCK=BUSCLK
//ЧастотаADC=500кГц
ADCCFG=bADLSMP|ADC_10BITS|ADC_BUSCLK_DIV2|ADIV_8;
//МодульADCработаетврежимемногократногопреобразования,
//преобразованиеканала30(VREFL),разрешениепрерываний
//Однопреобразованиезанимает40периодовчастотыADCили80мкс
ADCSC1=bAIEN|bADCO|ADCH_REFH;
PTBDD=BIT_6;//НастройкалинииPTB6навывод
EnableInterrupts;//Разрешениепрерываний(CCR:I=0)
while(1)
{
LED1=0;//ВключитьсветодиодLED1
adc_delay(6250);//Задержка500мс
LED1=1;//ВыключитьсветодиодLED1
adc_delay(6250);//Задержка500мс
}
}


Электронные компоненты Freescale >>>
Подробнее о компании Freescale >>>