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

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

В Примере 9.6 показано, как организуется программная задержка с помощью таймера MTIM. Переменная timer1 уменьшается на 1 каждую миллисекунду. В основном цикле программы идет ожидание, пока эта переменная не станет равной нулю. Записав предварительно значение 50 в переменную timer1, можно организовать задержку в 50мс.

Пример 9.6. Использование таймера MTIM

//ПримериспользованиямодуляMTIM
//ДемонстрационнаяплатаDEMO9S08QG8
//КатодсветодиодаLED1подключенклинииPTB6
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#include"hcs08.h"/*Этонашфайлсобъявлениями!*/
#defineLED1PTBD_PTBD6
unsignedinttimer1;
//ПодпрограммапрерываниямодуляMTIM(выполняетсякаждуюмиллисекунду)
voidinterruptVectorNumber_Vmtimmtim_isr(void)
{
MTIMSC_TOF=0;//СбросфлагаTOF
if(timer1)timer1--;//Еслиtimer1больше0,тоуменьшаемегона1
//Сюдадобавляютсядополнительныетаймеры...
}
voidmain(void)
{
//НастройкарегистраSOPT1,включениелинииBKGD
SOPT1=bBKGDPE;
//МодульICSработаетначастоте8МГц(BUSCLK=4МГц)
PTBDD=0xFF;//НастройкалинийпортаPTBнавывод
PTBD=0xFF;//УстановитьлинииPTBв1
//НастройкамодуляMTIM:разрешениепрерываний,тактированиеMTIM=BUSCLK/32
//Периодсброса=125
//Ttof=4МГц/(32*125)=1000
MTIMSC=bTOIE;
MTIMCLK=MTIM_DIV32;
MTIMMOD=124;//ПериодсчетаMTIM=124+1=125
EnableInterrupts;//Глобальноеразрешениепрерываний
while(1)
{
LED1=0;//ВключитьLED1
timer1=100;//Установитьtimer1(100мс)
while(timer1);//Подождать,покаработаеттаймер
LED1=1;//ВыключитьLED1
timer1=200;//Установитьtimer1(200мс)
while(timer1);//Подождать,покаработаеттаймер
}
}

Такой способ можно использовать в применении к любому из описанных выше модулей. Все, что необходимо сделать, — это добавить строку if (timerx) timerx--; то количество раз, которое вам необходимо (timerx — имя для таймера в вашем проекте). Учтите, что на изменение значения переменной уходит некоторое время, причем выбранный тип переменной timerx имеет большое значение. В листингах ниже показан генерируемый ассемблерный код при использовании 8-битной переменной типа char и 16-битной типа int.

LDAtimerx;3или4такта
BEQ*+6;3такта
LDHXtimerx;3такта
DEC,X;4такта

LDHXtimerx;4или5тактов
BEQ*+123;3такта
LDHX#ttimerx;3такта
TST1,X;4такта
BNE*+;3такта
DEC,X;4такта
DECl,x;5тактов


При использовании 8-битной переменной ее уменьшение занимает 13...14 периодов тактового сигнала ЦП, если она не равна 0,, а если равна 0, то всего 6...7 тактов (текст слева). Для 16-битной переменной ее уменьшение занимает 26...27 периодов тактового сигнала ЦП, если она не равна 0, а если равна 0, то всего 7...8 тактов (текст справа).

Если переменные timerx записаны в страницу прямого доступа памяти, то время выполнения этого фрагмента кода уменьшается на 1 период тактового импульса благодаря использованию прямого способа адресации функции LDA или LDHX.

Использовать переменные типа long не рекомендуется, поскольку генерируется более сложный и медленный ассемблерный код!

В следующем примере рассмотрено использование конечных автоматов для управления миганием двух светодиодов с разной частотой. Использование конечных автоматов — хороший способ управления состоянием светодиодов, зуммеров и дисплеев, особенно если возможны несколько их режимов работы (включен, выключен, быстрое мигание, медленное мигание и т.д.).

Пример 9.7. Использование конечных автоматов для управления несколькими объектами

//ПримериспользованиямодуляMTIMнадемонстрационнойплатеDEMO9S08QG8
//Конечныйавтомат
//КатодсветодиодаLED1подключенклинииPTB6
//КатодсветодиодаLED2подключенклинииPTB7
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#include"hcs08.h"//Этонашфайлсобъявлениями!
#defineLED1PTBD_PTBD6
#defineLED2PTBD_PTBD7
#defineLED1_TON200//СветодиодLED1включенвтечение200мс
#defineLED1_TOFF220//СветодиодLED1выключенвтечение220мс
#defineLED2_TON220//СветодиодLED2включенвтечение220ис
#defineLED2_TOFF220//СветодиодLED2выключенвтечение220мс
unsignedinttimer1,timer2;
enumeled_fsm
{
LED_ON,LED_OFF,LED_DELAY
};
//ПодпрограммапрерываниямодуляMTIM(выполняетсякаждуюмс)
voidinterruptVectorNumber_Vmtimmtim_isr(void)
{
MTIMSC_TOF=0;//СброситьфлагTOF
if(timer1)timer1--;//Еслиtimer1больше0,тоуменьшаемего
if(timer2)timer2--;//Еслиtimer2больше0,тоуменьшаемего
}
voidled1_state_machine(void)
{
staticenumeled_fsmled_state,next_state;
switch(led_state)
{
caseLED_ON:
LED1=0;//ВключитьсветодиодLED1
timer1=LED1_TON;//Установитьtimer1(задержка)
led_state=LED_DELAY;//Текущеесостояниеавтоматаledstate–задержка
next_state=LED_OFF;//Следующеесостояниеавтомата–выключено
break;
caseLED_OFF:
LED1=1;//ВыключитьсветодиодLED1
timer1=LED1_TOFF;//Установитьtimer1(задержка)
led_state=LED_DELAY;//Текущеесостояниеавтоматеledstate–задержка
next_state=LED_ON;//Следующеесостояниеавтомата–включено
break;
caseLED_DELAY://Задержка
//Изменитьсостояниесветодиода,когдаtimer1становитсяравным0
if(!timer1)led_state=next_state;
break;
}
}
voidled2_state_machine(void)
{
staticenumeled_fsmled_state,next_state;
switch(led_state)
{
caseLED_ON:
LED2=0;//ВключитьLED2
timer2=LED2_TON;//Установитьtimer2(задержка)
led_state=LED_DELAY;//Текущеесостояниеавтоматаledstate–задержка
next_state=LED_OFF;//Следующеесостояниеавтомата–выключено
break;
caseLED_OFF:
LED2=1;//ВыключитьсветодиодLED2
timer2=LED2_TOFF;//Установитьtimer2(задержка)
led_state=LED_DELAY;//Текущеесостояниеавтоматаledstate–задержка
next_state=LED_ON;//Следующеесостояниеавтомата–включено
break;
caseLED_DELAY://Задержка
//Еслиtimer2=1,изменитьсостояниеавтомата
if(!timer2)led_state=next_state;
break;
}
}
voidmcu_init(void)
{
//НастройкарегистраSOPT1,разрешитьвыводBKGDдляотладки
SOPT1=bBKGDPE;
PTBDD=0xFF;//PTB–навывод
PTBD=0xFF;//ВсевыходыPTBв1
//КонфигурироватьMTIM:разрешитьпрерывания,MTIMclock=BUSCLK/32,modulo=125
//Ttof=4МГц/(32*125)=1000
MTIMSC=bTOIE;
MTIMCLK=MTIM_DIV32;
MTIMMOD=124;//MTIMmodulo=124+1=125
EnableInterrupts;//Разрешитьпрерывания
}
voidmain(void)
{
mcu_init();
while(1)
{
led1_state_machine();
led2_state_machine();
}
}

9.4. Модуль процессора событий TPM

Модуль процессора событий TPM — многофункциональный таймер общего назначения, способный генерировать периодические прерывания МК, точно измерять период и длительность импульсов внешних сигналов, генерировать импульсы различной длительности сразу по нескольким выходам МК, формировать ШИМ-сигналы.

Модуль TPM состоит из 16-битного счетчика временной базы с программно настраиваемым коэффициентом счета и нескольких полностью независимых универсальных каналов захвата/сравнения/ШИМ. Разные модели МК HCS08 оснащены процессорами событий, которые имеют от 2 до 8 универсальных каналов.

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