Ingo Electronics


    HOME                                                           Stellaris LM4F120 LaunchPad

  Stellaris LM4F120 LaunchPad. Periodinis (nenutrūkstamas) ir vieno kadro taimerio darbo režimas.  One-Shot/Periodic Timer Mode

Taimeris Periodic režime gali dirbti tiek mažindamas, tiek didindamas savo reikšmę, (angl. up, down) režimai.

Kai tik taimeris įjungiamas funcijos xxxxxxxx pagalba, taimerio skaitiklis pradeda dirbti į viršų didindamas savo reikšmę nuo 0x00 reikšmės, arba mažindamas savo reikšmę dirbdamas down režimu nuo prieš tai nustatytos starto reikšmės kurios įvedamos su funkcijomis TimerLoadSet ir TimerPrescaleSet (16bitų modulis) arba TimerLoadSet64 ir TimerPrescaleSet (32bitų modulis)

Su funkcija TimerControlWaitOnTrigger taimerio skaitiklį galima nustatyti, taip kad jis nepradeda suktis kol negauna signalo iš žemiau esančio modulio. Tai negalioja tik TIMER0 A moduliui moduliui. Tokiu būdu  taimerių modulius, galima sujungti į taip vadinamą grandinę (angl. Daisy Chain), tai gali būti naudojama ilgesniams laiko išlaikymams.

Kai taimerio skaitiklis dirbdamas režimu down pasiekia 0x00 reikšmę, jis restartuoja nuo reikšmės, kuri buvo įvesta su funkcijomis TimerLoadSet ir TimerPrescaleSet (16bitų modulis) arba TimerLoadSet64 ir TimerPrescaleSet (32bitų modulis)

Kai taimerio skaitiklis dirbdamas režimu up pasiekia reikšmę kuri buvo įvesta su prieš tai išvardintomis funkcijomis, taimeris restartuoja nuo reikšmės 0x00. angl. terminas šiais atvejais, kai skaitiklis restartuoja pasiekęs ribines reikšmes: timeout event.

Vieno kadro (one-shot) režimu dirbančio taimerio konfigūravimas nieko nesiskiria nuo Periodic režimo, išskyrus tai, kad taimeris pasiekęs timeout event taimeris automatiškai yra stabdomas, ir vėl gali būti paleidžiamas tik panaudojus funkciją  TimerEnable

Periodiniu, nepertraukiamu (Periodic) režimu dirbantis taimeris vis restartuodamas, sukasi pastoviai.

Taimerio einamąją reikšmę (neįskaitant Prescale reikšmės)  bet kuriuo momentu galime nuskaityti panaudoję funkcijas: TimerValueGet (16bitų modulis) arba TimerValueGet64 (32bitų modulis).

Jeigu norime nuskaityti taimerio reikšmę kur jau yra pridėta ir  Prescale reikšmė (tik režimui up),Turėtume naudoti žemiau pateiktą kodą
(pvz. TIMER0 A moduliui)  :

timer_value = HWREG(TIMER0_BASE + TIMER_O_TAV);

 
Prescale yra naudojamas tik kai taimerio moduliai A ir B konfiguruojami kaip du atskiri viens nuo kito nepriklausomi moduliai.

Konfiguruojant režimui down , Prescale dirba kaip įprastas 8(16)bitų dažnio daliklis.

Dirbant režimu up,  Prescale reikšmė (8bitai) yra pridedama kaip aukščiausių (MSB)  8bitų plėtinys iki 24bitų (16bitų modulis) arba  aukščiausių (MSB)  16bitų plėtinys (32bitų modulis) ,ko pasekoje gauname 24 arba 48 bitų modulius, kaip kad buvo pavaizduota ankstesnėje temoje. 

Nuskaitant taimerio einamąją reikšmę, reikia įvertinti, kad šią reikšmę mikrovaldiklis duoda jau pridėjęs Prescale reikšmę, išskyrus jeigu taimerio modulis sukonfiguruotas dirbti Periodic/One-Shot down režimui.  

Taimerio modulis gali generuoti pertraukimų rodykles kurios įjungiamos su funkcija  IntEnable

Yra galimi du pertraukimų tipai: kai taimeris pasiekia timeout event t.y restartuodamas, ir kai taimeris pasiekia sutapimo reikšmę, kuri buvo įvesta su funkcijomis TimerMatchSet ir TimerPrescaleMatchSet (16bitų modulis) arba TimerMatchSet ir TimerPrescaleMatchSet (32bitų modulis)

Pertraukimų tipas nustatomas panaudojant funkciją TimerIntEnable

Suveikus bet kuriai pertraukimų rodyklei, ji yra fiksuojama, ištrinama programiniu būdu naudojant funkciją TimerIntClear
Pertraukimų rodyklių būsena gali būti  nuskaitoma su funkcija
TimerIntStatus

Pertraukimai gali būti bet kuriuo momentu išjungiami panaudojus funkciją TimerIntDisable

Kaip papildoma opcija, įvykus timeout event pertraukimui, taimeris gali pasiūsti valdymo signalą į ADC modulį , tai nustatoma su funkcija TimerControlTrigger

Jeigu programa keičia reikšmes įvestas funkcijose TimerLoadSet ir TimerPrescaleSet (16bitų modulis) arba TimerLoadSet64 ir TimerPrescaleSet (32bitų modulis) tuo metu kai taimerio skaitiklis sukasi žemyn (down), taimerio skaitiklis iškart pereina prie naujų, reikšmių, t.y nebaigęs pradėto periodo, kitaip sakant skaitiklis iškart peršoka prie naujos pradinės starto reikšmės ir pradeda naują periodą.
Norint, kad taimerio skaitiklis, tokiu atveju, pabaigtų pradėtą periodą reikalingą nustatyti bitą
 ILD.  
Tai padaroma į programą įvedus sekančią eilutę (pvz. TIMER0 A moduliui)  :

HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TAILD);

 

Jeigu programa keičia reikšmes įvestas funkcijose TimerMatchSet ir TimerPrescaleMatchSet (16bitų modulis) arba TimerMatchSet ir TimerPrescaleMatchSet (32bitų modulis) tuo metu kai taimerio skaitiklis sukasi aukštyn, arba žemyn (up or down), taimerio skaitiklis iškart pereina prie naujų, reikšmių, t.y nebaigęs pradėto periodo, kitaip sakant skaitiklis iškart peršoka prie naujos pradinės starto reikšmės ir pradeda naują periodą.
Šiuo atveju, norint, kad taimerio skaitiklis, pabaigtų pradėtą periodą reikalingą nustatyti bitą
 MRSU
Tai padaroma į programą įvedus sekančią eilutę (pvz. TIMER0 A moduliui)  :

HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TAMRSU);

//********************************************************************************************

Žemiau yra parodyta kaip konfiguruojamas taimeris darbui One-Shot/Periodic režimui

Šiam pavyzdžiui paimtas TIMER0 A modulis, įvedami parametrai gali būti ir kitokie, priklausomai kaip modulis šiam režimui konfiguruojamas:

//************************************************************************************************************************************************************************************

            //periferiniui taimerio moduliui įjungiame taktavimą

       SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

 // Pagrindinė taimerio konfiguravimo funkcija,galima naudoti žemiau parodytas reikšmes

//TIMER_CFG_SPLIT_PAIR |TIMER_CFG_A_PERIODIC , TIMER_CFG_A_PERIODIC_UP , TIMER_CFG_A_ONE_SHOT , TIMER_CFG_A_ONE_SHOT_UP

//TIMER_CFG_SPLIT_PAIR |TIMER_CFG_B_PERIODIC , TIMER_CFG_B_PERIODIC_UP , TIMER_CFG_B_ONE_SHOT , TIMER_CFG_B_ONE_SHOT_UP

//TIMER_CFG_PERIODIC , TIMER_CFG_PERIODIC_UP , TIMER_CFG_ONE_SHOT , TIMER_CFG_ONE_SHOT_UP

       TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);

 //jeigu reikalinga, įrašome prescalerio reikšmę (dirbant  DOWN režimu)

       TimerPrescaleSet(TIMER0_BASE, TIMER_A,0xFF);

 // jeigu reikalinga, nurodome taimerio reikšmę (dirbant  DOWN režimu)

       TimerLoadSet(TIMER0_BASE, TIMER_A, 0xFFFF);

 // jeigu reikalinga, įvedame prescalerio sutapimo reikšmę

       TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A,125);

 // jeigu reikalinga, įvedame taimerio skaitiklio  sutapimo reikšmę

       TimerMatchSet(TIMER0_BASE, TIMER_A,30000);


       //Enable/disable the ADC trigger output.

       //TimerControlTrigger(TIMER0_BASE, TIMER_A,true);

       // jeigu keli moduliai jungiami į grandinę

       //TimerControlWaitOnTrigger(TIMER0_BASE, TIMER_A, true);

 //papildomi, tačiau nebūtini konfiguravimo bitai

       //HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);

       //HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TASNAPS);

 

//leižiame modulio pertraukimus

       IntEnable(INT_TIMER0A);

 //nustatome pertraukimų tipą (parodyti keli varijantai)

       //TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

       //TimerIntEnable(TIMER0_BASE, TIMER_TIMA_MATCH);

       TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMA_MATCH);

//leidžiame mikrovaldikliui reaguoti į pertraukimų rodykles

       IntMasterEnable();

 //įjungiame taimerį

       TimerEnable(TIMER0_BASE, TIMER_A);

 
Taimerio konfiguravimas baigtas. Galime pasirašyti  funkciją, be didelių komentarų kurią vėliau naudoti kaip šabloną taimerio režimo One-Shot/Periodic konfiguravimui:

//************************************************************************************************************************************************************************************

void init_timer_periodic ( ) {

       SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

 

       TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);

 

       TimerPrescaleSet(TIMER0_BASE, TIMER_A,0xFF);

       TimerLoadSet(TIMER0_BASE, TIMER_A, 0xFFFF);

 

       TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A,125);

       TimerMatchSet(TIMER0_BASE, TIMER_A,30000);

 

       //Enable/disable the ADC trigger output.

       //TimerControlTrigger(TIMER0_BASE, TIMER_A,true);

 

       // jeigu keli moduliai jungiami į grandinę

       //TimerControlWaitOnTrigger(TIMER0_BASE, TIMER_A, true);

 

                          //papildomi, tačiau nebūtini konfiguravimo bitai

       //HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);

       //HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TASNAPS);

 

       IntEnable(INT_TIMER0A);

       TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMA_MATCH);

       IntMasterEnable();

 

       TimerEnable(TIMER0_BASE, TIMER_A);

}

//************************************************************************************************************************************************************************************

//taimerio + prescaler'io reiksmė periodic (up mode)

timer_value = HWREG(TIMER0_BASE + TIMER_O_TAV);  xV registras

 

//vien tik taimerio reikšmė

timer_value =TimerValueGet(TIMER0_BASE,TIMER_A); // xR registras

//************************************************************************************************************************************************************************************

Žemiau pateiktas programos kodas, skirtas taimerio Periodic darbo režimo susipažinimui ir nagrinėjimui.

Gaunamų reikšmių pavaizdavimui ir debuginimui šiame pavyzdyje panaudotas raudonas šviesos diodas ir UART terminalas.

Pavyzdys skirtas tik susipažinti su nagrinėjamu taimerio darbo režimu, kuriame galima  keisti skaitines parametrų reikšmes  ir taimerio konfiguravimą pagal galimus šiam režimui nustatymus.

Šio projekto failai parsisiuntimui: Link

//************************************************************************************************************************************************************************************
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_timer.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"
#include "driverlib/uart.h"
#include "driverlib/string.h"
#include "driverlib/stdlib.h"//for ltoa(..);

 
unsigned int state;
unsigned long timer_value;
char buf[];

void UARTSend(char *string);

 

void Timer0IntHandler(void)

{

// Clear the timer interrupt

//TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

//TimerIntClear(TIMER0_BASE, TIMER_TIMA_MATCH);

unsigned long status = TimerIntStatus(TIMER0_BASE, true);

TimerIntClear(TIMER0_BASE, status);

if (status & TIMER_TIMA_MATCH)

{

 state = ~state&0x08;

 GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3,state);

}

if (status & TIMER_TIMA_TIMEOUT)

{

 state = ~state&0x08;

 GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3,state);

}

}

 

 

void main(void) {    

       SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL| SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

       SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

       GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);

       GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0x00);

       //''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

                  //UART initialization

                  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

                  // Unlock PD7

                  HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;

                  HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |=  GPIO_PIN_7;

                  HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;

                  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);

                  // Set GPIO PD6 RX  and PD7 TX as UART pins.

                  GPIOPinConfigure(GPIO_PD6_U2RX);

                  GPIOPinConfigure(GPIO_PD7_U2TX);

                  GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7);

              // Configure the UART for 115,200, 8-N-1 operation.

       UARTConfigSetExpClk(UART2_BASE, SysCtlClockGet(), 115200,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE));

                   UARTFIFODisable(UART2_BASE);

                  //End UART initialization

       //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

       SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

//TIMER_CFG_SPLIT_PAIR |TIMER_CFG_A_PERIODIC , TIMER_CFG_A_PERIODIC_UP , TIMER_CFG_A_ONE_SHOT , TIMER_CFG_A_ONE_SHOT_UP

//TIMER_CFG_PERIODIC , TIMER_CFG_PERIODIC_UP , TIMER_CFG_ONE_SHOT , TIMER_CFG_ONE_SHOT_UP

       TimerConfigure(TIMER0_BASE,TIMER_CFG_SPLIT_PAIR |  TIMER_CFG_A_PERIODIC);


       TimerPrescaleSet(TIMER0_BASE, TIMER_A,0xFF);

       TimerLoadSet(TIMER0_BASE, TIMER_A, 0xFFFF);

 

       TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A,125);

       TimerMatchSet(TIMER0_BASE, TIMER_A,30000);

 

       //Enable/disable the ADC trigger output.

       //TimerControlTrigger(TIMER0_BASE, TIMER_A,true);

       //WOT bit

       //TimerControlWaitOnTrigger(TIMER0_BASE, TIMER_A, true);

       //HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);

       //HWREG(TIMER0_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TASNAPS);

 

       IntEnable(INT_TIMER0A);

       //TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

       //TimerIntEnable(TIMER0_BASE, TIMER_TIMA_MATCH);

       TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMA_MATCH);

       IntMasterEnable();

       TimerEnable(TIMER0_BASE, TIMER_A);

 

//''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

state = 0x08;

while(1){

       //timer_value =      TimerValueGet(TIMER0_BASE,TIMER_A);

       timer_value = HWREG(TIMER0_BASE + TIMER_O_TAV);

       ltoa(timer_value, buf);

                                  UARTSend(buf);

                                  UARTSend("\n");

       SysCtlDelay(2666666);

}

}

//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

void

UARTSend(char *string)

{

 

       unsigned long Idx;

       unsigned long string_lenght;

       string_lenght =      strlen(string);

 

 

        for(Idx = 0; Idx<string_lenght; Idx++)

                {

               UARTCharPut(UART2_BASE, string[Idx]);

                }

 

}

 

//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

.//************************************************************************************************************************************************************************************