Monday 15 September 2014

Guide to Timer units and example programs:


In this post you will learn to work with timer and to trigger required interrupts.
                Every micro controller has at least 2 (maybe wrong..!) timer units - Timer0 and Timer1. The RX-63N processor in GR-Sakura has 4 Timers Timer 0 – Timer 3 (8 bit). Also Timer0 and Timer1 as well as Timer2 and Timer3 can be combined (cascaded) to provide two 16 bit timer units.
  
              Timer speed is based on the clock source provided to it. An 8 bit timer/counter counts from 0 to 255 (2^8), whereas a 16 bit timer/counter counts from 0 – 65535 (2^16). A clock source defines in what speed the timer counts (increment/decrement) these values.

For example,
                Consider an 8 bit timer with clock source as 20MHz. Then the timer will increment (from 0) for each 1/20000000 =  0.05u Sec. And thus the total time for the timer to count 255 is given by,
1/2000000 * 255 = 0.05u * 255 = 12.75u seconds

Similarly for a 16 bit timer,
1/2000000 * 65535 = 0.05u * 65535 = 3.27m seconds

                Since the timer units are within the microcontroller, you may think that whatever clock is given to microcontroller is available for the timer units. The microcontroller’s clock input is referred as Primary Clock (PCLK). Either you can use this clock or change the clock source to a timer unit. This is achieved with the TCCR (Timer Counter Control) Register as in Sakura’s case. The clock source can be PCLK, PCLK/2, PCLK/4, ……, PCLK/8192 (Refer datasheet).

We will see what is the use in dividing the clock source..,
                If you select the clock source to be PCLK/4, then clock will be 5 MHz (For PCLK = 20MHz) and the time to count for a 8 bit timer will be
1 / 5000000 * 255 = 51u sec
Thus you can increase the timing.

Ok.. The timer starts and finishes its counting.. what’s in there for us and what to do with that.?
1.       delay() functions can be replaced with such timers. Because delay() functions make the processor to do nothing and just simply wait. Whereas if you use a timer, you can perform other functions when the timer is counting (probably multitasking).
2.       Can be used to trigger certain on chip peripherals such as ADC, periodically using interrupts.

A timer either

1.       counts from 0-255 for 8 bit timer and 0-65535 for a 16 bit timer and Overflows

2.       a specific value can be written and the timer counts from that specific value

3.       a specific value can be written and the timer counts up to that specific value

8 bit Timer Overflow Interrupt:

         A simple timer program for GR-Sakura – The following code involves enabling Timer0 (8 bit). Once the timer overflows, it generates Timer0 Overflow Interrupt which increments the cnt variable. And once the value of cnt reaches 50, it changes the state of the on board LED.

Note:    GR-Sakura’s clock source (PCLK) is 48MHz.
--------------------------------------------------------------------------------------------------------------------------
#include <rxduino.h>
#include <iodefine_gcc63n.h>

#include"intvect.h"

void Excep_TMR0_OVI0 (void) __INTTERUPT_FUNC;
void init_tmr();

int cnt=0;
volatile int state=0;
 
int main ()
{
                pinMode (PIN_LED0, OUTPUT);

                init_tmr();

                while(1)
                {
                                if(cnt>50)
                                {
                                                cnt=0;

                                                state=!state;
                                                digitalWrite (PIN_LED0, state); 
                                }
                }
}

 
void init_tmr()
{

   MSTP(TMR0) = 0;  // Timer unit enable
   TMR0.TCCR.BIT.CKS = 0b110;   // Clock Select Bit (refer below image) – PCLK/8192

   TMR0.TCCR.BIT.CSS = 0b01;   //  Clock Source Select Bit (refer below image)
   TMR0.TCR.BIT.OVIE = 0b1;   // Timer 0 overflow interrupt enable bit

   IEN (TMR0, OVI0) = 1; // Timer 0 overflow interrupt Enable MACRO
   IPR (TMR0, OVI0) = 2; // Interrupt priority – Level 2

}

void Excep_TMR0_OVI0(void)
{
                cnt++;
}

--------------------------------------------------------------------------------------------------------------------------
                By executing the code, LED is turned On after 2.176 seconds (1/48000000 * 255 * 8192).



 Compare Match Interrupt Program:


                Other than starting from 0 and count to 255/65535, you can write a specific value to registers TCORA/TCORB, and when the timer reaches that value, it stops and clears the TCNT (Timer Counter) register.
--------------------------------------------------------------------------------------------------------------------------
 #include <rxduino.h>
#include <iodefine_gcc63n.h>

#include"intvect.h"


void Excep_TMR0_CMIA0 (void) __INTTERUPT_FUNC;
void init_tmr();

int cnt=0;
volatile int state=0;

int main ()
{
                pinMode (PIN_LED0, OUTPUT);

                init_tmr();
                while(1)

                {
                                if(cnt>50)

                                {
                                                cnt=0;

                                                state=!state;
                                                digitalWrite (PIN_LED0, state); 
                               }

                }
}

 
void init_tmr()
{

   MSTP(TMR0) = 0;  // Timer unit enable
   TMR0.TCCR.BIT.CKS = 0b110; 

   TMR0.TCCR.BIT.CSS = 0b01;
   TMR0.TCR.BIT.CCLR = 0b01; // Automatic clearing enabled

   TMR0.TCR.BIT.CMIEA = 0b1; // Compare match A interrupt enable
   TMR0.TCORA=118; // write the required value to TCORA register (in this case timer starts from 118 and ends at 255)

   IEN (TMR0, CMIA0) = 1; 
   IPR (TMR0, CMIA0) = 2;
}

void Excep_TMR0_CMIA0(void)
{
                cnt++;
}

 -------------------------------------------------------------------------------------------------------------------------
                Compare Match can be used to provide precision timings. For example, if you need an accurate 1 sec delay, then you can write the required value at which the timer starts so that a 1 sec delay is achieved. Need to do some math…!!!!!

Cascading two 8 bit timers to obtain a 16 bit Timer:


                Here two 8 bit timers namely Timer2 and Timer3 are cascaded to achieve a single 16 bit timer. The concept is that whenever the lower 8 bit timer overflows, then the upper 8 bit is incremented once.

 
In this code Timer2 is the upper register and Timer3 is the lower register.
--------------------------------------------------------------------------------------------------------------------------

#include <rxduino.h>
#include <iodefine_gcc63n.h>

#include <intvect.h>
 
void Excep_TMR2_CMIA2(void) __INTTERUPT_FUNC;

void init();
int k;

main()
{
               Serial.begin(9600);

                delay(7000);

                init();
                while(1)

                {
                                if(k>5)

                                {
                                                Serial.print(k);

                                                Serial.println(" Counted");
                                }

                }
}

 
void Excep_TMR2_CMIA2(void)
{
                 k++;
}

 
void init()
{
                MSTP(TMR2)=0;

                TMR3.TCCR.BYTE=0;
                TMR2.TCCR.BIT.CSS=0b11; // clock source is the a Timer3 overflow signal

                TMR23.TCNT=0;
                TMR2.TCR.BIT.CCLR=0b01; // cleared by Compare Match A

                TMR2.TCR.BIT.CMIEA=1;
                IEN(TMR2,CMIA2)=1;

                IPR(TMR2,CMIA2)=1;
                TMR23.TCORA=60000;  // change this value and notice the change in timings

                TMR3.TCCR.BIT.CSS=0b01;
                TMR3.TCCR.BIT.CKS=0b100;
}

--------------------------------------------------------------------------------------------------------------------------
Hope it helps somebody..!!!

No comments:

Post a Comment