Ingo Electronics


    HOME                                                           Stellaris LM4F120 LaunchPad


  Stellaris LM4F120 LaunchPad.   Išorinių  impulsų skaičiavimo režimas.                                                    Input Edge Count Timer Mode  

Taimeris šiame režime dirba nuo išorinio impulsų šaltinio, pajungto prie atitinkamo taimerio CCP išvado.

Šiame režime taimerio moduliai TIMER_A  ir  TIMER_B gali dirbti tik atskirai, t.y galima pasirinkti arba TIMER_A  arba TIMER_B, tai nurodoma funkcijoje  TimerConfigure įvedant parametrą  TIMER_CFG_SPLIT_PAIR

Maksimalus dažnis, kuris gali būti paduodamas į CCP įėjimą yra ¼ mikrokontrolerio taktinio dažnio.

Taimeris dirbantis Edge Count Mode režimu, yra sukonfiguruotas kaip 24 arba 48 bitų, UP arba DOWN skaitiklis, panaudojant papildomą registrą, vadinamą prescaler.

Taimerio prescaler reikšmė šiame režime yra pridedama kaip aukščiausių (MSB)  8bitų plėtinys iki 24bitų (16bitų modulis) arba  aukščiausių (MSB)  16bitų plėtinys (32bitų modulis) , kaip kad buvo pavaizduota ankstesnėje temoje. Link

Edge Count  režime, taimeris gali dirbti UP (didindamas savo reikšmę)  arba DOWN(mažindamas savo reikšmę)   režimais.

Norint kad skaitliukas suktusi didindamas savo reikšmę (UP), TimerConfigure funkcijoje, rašome parametrą TIMER_CFG_A_CAP_COUNT_UP

Norint kad skaitliukas suktusi žemyn (DOWN), TimerConfigure funkcijoje, rašome parametrą TIMER_CFG_A_CAP_COUNT

Esant režimui UP taimerio skaitiklis pradeda dirbti nuo nulinės reikšmės, o esant režimui DOWN – skaitiklis pradeda dirbti nuo nuo įvestos pradinės starto reikšmės.

Dirbant režimu DOWN, būtina įvesti taimerio starto pradines reikšmes naudojant funkcijas,  TimerLoadSet ir TimerPrescaleSet (16bitų modulis) arba TimerLoadSet64 ir TimerPrescaleSet (32bitų modulis)

Dirbant režimu UP taimerio pradinės starto reikšmės įvesti nereikia, nes skaitiklis, kaip jau buvo minėta, pradeda dirbti nuo nulinės reikšmės.

Taimeriui pasiekus reikšmę, kuri įvedama  funkcijomis  TimerMatchSet ir TimerPrescaleMatchSet, arba pasiekus nulinę vertę jeigu taimeris dirba DOWN režimu, suveikia programinių pertraukimų rodyklė, (parametras TIMER_CAPA_MATCH arba TIMER_CAPB_MATCH), ši rodyklė savo ruožtu paleidžia  pertraukimų funkciją, jeigu ji yra numatyta programos kode.

Suveikus pertraukimų rodyklei, taimeris yra stabdomas, ir vėl tuo pačiu režimu gali būti įjungiamas tik pakartotinai panaudojus funkciją TimerEnable , tuomet taimeris vėl restartuoja pagal anksčiau nustatytus parametrus, jeigu jie prieš tai nebuvo pakeisti.

Šiame režime yra veikiantis, t.y galimas, tik vienas pertraukimų tipas, jau anksčiau minėtas (parametras TIMER_CAPA_MATCH arba TIMER_CAPB_MATCH).

Dirbant Edge Count Mode režimu, teimerio skaitiklis gali būti sukamas nuo trijų tipų signalo fronto reikšmių: kylančio fronto, besileidžiančio fronto, arba nuo abiejų frontų (rising edge, falling edge, or both).

Taimerio skaitiklio ribinė (maksimali) reikšmė, įskaitant prescaler reikšmę, dirbant UP režimu yra  0xFFFFFF (16bitų modulis) arba 0xFFFFFFFFFFFF (32bitų modulis)

Taimerio skaitiklio ribinė (minimali) reikšmė, dirbant DOWN režimu, abiejų tipų moduliuose yra 0x00

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

Žemiau  Edge Count  Mode režimo konfiguravimas  aprašytas paimant konkretų taimerį.

Pasirenkam TIMER0  TIMER_A, pagal mikrokontrolerio LM4F120H5QR pdf aprašymą surandame, kad šio modulio CCP išvadas gali būti prijungtas prie PB6 arba prie PF0. Pasirenkame išvadą PB6.

//kadangi pasirinkome PB6, įjungiame PORTB taktavimą
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

//konfiguruojam, t.y prijungiam PB6 prie TIMER0  TIMER_A modulio
GPIOPinConfigure(GPIO_PB6_T0CCP0);
GPIOPinTypeTimer
(GPIO_PORTB_BASE, GPIO_PIN_6);

//įjungiame taktavimą TIMER0 moduliui
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

//konfiguruojame taimerį dirbti Edge Count  Mode režime
//galimi parametrai TIMER_CFG_B_CAP_COUNT_UP , TIMER_CFG_B_CAP_COUNT

TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_COUNT_UP );

//nustatome, kad taimeris reaguotų į kylantį signalo frontą
//galimi parametrai TIMER_EVENT_POS_EDGE,
TIMER_EVENT_NEG_EDGE, TIMER_EVENT_BOTH_EDGES               
TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);

//  jeigu reikalinga, įrašome prescalerio reikšmę (dirbant  DOWN režimu)
// TimerPrescaleSet(TIMER0_BASE,TIMER_A,0x00);

//  jeigu reikalinga, nurodome taimerio reiksme (dirbant  DOWN režimu)
// TimerLoadSet(TIMER0_BASE, TIMER_A, 200);

//  jeigu reikalinga, įvedame prescalerio sutapimo reikšmę
// TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A,0x00);

// jeigu reikalinga, įvedame taimerio  sutapimo reikšmę
TimerMatchSet(TIMER0_BASE, TIMER_A, 100);

// leidžiame TIMER0  TIMER_A modulio pertraukimus
IntEnable(INT_TIMER0A);

//nustatome pertraukimų tipą
TimerIntEnable(TIMER0_BASE, TIMER_CAPA_MATCH);

//leidžiame mikrovaldikliui reaguoti į pertraukimų rodykles
IntMasterEnable();

//įjungiame TIMER0  TIMER_A modulį
TimerEnable(TIMER0_BASE, TIMER_A);

 

Taimerio konfiguravimas baigtas. Galime pasirašyti funkciją, kurią vėliau naudoti kaip šabloną taimerio režimo Edge Count Mode konfiguravimui:

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

void init_edge_timing_mode ( ) {

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB6_T0CCP0);
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6);

SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_COUNT_UP );
TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);

//TimerPrescaleSet(TIMER0_BASE,TIMER_A,0x00);

//TimerLoadSet(TIMER0_BASE, TIMER_A, 200);

//TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A,0x00);

TimerMatchSet(TIMER0_BASE, TIMER_A, 100);

IntEnable(INT_TIMER0A);
TimerIntEnable(TIMER0_BASE, TIMER_CAPA_MATCH);
IntMasterEnable();

TimerEnable(TIMER0_BASE, TIMER_A);
}

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

Žemiau yra parodytas pats paprasčiausias koks tik begali būti taimerio konfiguravimas Edge Count režimui kodas.

Yra pasirinktas TIMER0 TIMER_A modulis, kurio CCP pinas yra PB6 .

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

//#includes
-------------
-------------

unsigned long timer_value;

void main(void) {     

           //80Mhz

       SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL| SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);     

            //Nustatome PB6 dirbti kaip TIMER0 TIMER_A CCP

            SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

            GPIOPinConfigure(GPIO_PB6_T0CCP0);

            GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6);

            SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

//Konfiguruojame TIMER0 moduli
//Nurodome kad tai bus atskiri TIMER_A ir TIMER_B moduliai (TIMER_CFG_SPLIT_PAIR),naudojame

//moduli TIMER_A ir nustatome kad jis dirbs Edge Count rezimu (TIMER_CFG_A_CAP_COUNT_UP)

            TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_COUNT_UP);

            //nurodome kad taimeris bus valdomas ieinanciu impulsu priekiniais frontais

            TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);

                              //ijungiame taimeri

            TimerEnable(TIMER0_BASE, TIMER_A);
while(1)
{
     

       timer_value = TimerValueGet(TIMER0_BASE,TIMER_A);            

}

} //end main

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

Kaip matome, viršuje esančiame kode, nėra TimerMatchSet ir TimerPrescaleMatchSet funkcijų ir nėra naudojami pertraukimai, todėl TIMER_A skaitliukas sukasi pastoviai, padidindamas savo 16 bitų registro reikšmę su kiekvienu paduodamo signalo periodu.

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

Sekantis žemiau pateiktas programos kodas, skirtas taimerio Edge Count darbo režimo pavaizdavimui.

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

Šiame pavyzdyje įeinanti signalas yra paimamas nuo PD0  išvado, kuris Stellaris LaunchPad plokštėje, per 0om rezistorių, yra sujungtas su šiame pavyzdyje naudojamu taimerio CCP išvadu PB6

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

Taip pat galima bandyti paduoti realų signalą nuo išorinio impulsų šaltinio, redaguojant programos kodą esantį while cikle .

Šio projekto failai parsisiuntimui: Link


#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_gpio.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(..);


#define SW1  GPIO_PIN_4

 unsigned long Period;
unsigned int PF3_state;
unsigned int PD0_state;
unsigned long timer_value;
char buf[];

void UARTSend(char *string);

//pertraukimu funkcija
void Timer0IntHandler(void)
{
// Clear the timer interrupt
TimerIntClear(TIMER0_BASE, TIMER_CAPA_MATCH);

PF3_state = ~PF3_state&0x08;

GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3,PF3_state);

TimerEnable(TIMER0_BASE, TIMER_A);

}

void main(void) {   

       //80Mhz

       SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL| SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

       //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

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

               //PF3 as output (Green LED)

              SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

              GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);

              GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0x00);

              //configure SW1

              GPIOPadConfigSet(GPIO_PORTF_BASE, SW1, GPIO_STRENGTH_8MA,GPIO_PIN_TYPE_STD_WPU);

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

              //PD0 as output

               SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

              GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0);

              GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0x00);

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

              //konfiguruojam TIMER0 CCP

            SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

            GPIOPinConfigure(GPIO_PB6_T0CCP0);

            GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6);

            SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

 //Nurodome kad tai bus atskiri TIMER_A  ir  TIMER_B moduliai (TIMER_CFG_SPLIT_PAIR), panaudojame

//moduli TIMER_A ir nustatome kad jis dirbs Edge Count rezimu (TIMER_CFG_A_CAP_COUNT)

            TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_COUNT);

            //nurodome kad taimeris bus valdomas ieinanciu impulsu priekiniais frontais

            TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);

            //write the prescale value

            //TimerPrescaleSet(TIMER0_BASE, TIMER_A, 1);

            //nurodome taimerio starto reiksme

           TimerLoadSet(TIMER0_BASE, TIMER_A, 120);

            //Load the prescaler match value

            //TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A,0x00);

 //ivedame taimerio reiksme kuomet turi suveikti pertraukimu funkcija

            TimerMatchSet(TIMER0_BASE, TIMER_A, 100);

    //Configure TimerA interrupt

       IntEnable(INT_TIMER0A);

       //nurodome pertraukimu tipa

       TimerIntEnable(TIMER0_BASE, TIMER_CAPA_MATCH);

       IntMasterEnable();

    //ijungiame taimeri

       TimerEnable(TIMER0_BASE, TIMER_A);

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

Period = 300000;

PF3_state = 0x08;

PD0_state=0x01;

while(1){

                    //Press SW1

                    if( !GPIOPinRead(GPIO_PORTF_BASE, SW1))

                    {

                      SysCtlDelay(500000);

                      Period -=1000;

                      if(Period==0){Period=300000;}

                    }

 timer_value = TimerValueGet(TIMER0_BASE,TIMER_A);

                           ltoa(timer_value, buf);

                                  UARTSend(buf);                               

                                  UARTSend("\n");

       SysCtlDelay(Period);

       PD0_state = ~PD0_state&0x01;

       GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0,PD0_state);

}

}

//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
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]);

                }

 }

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