Timer A up mode and polling concept

In this post I’ve tried to use the Timer A peripheral of msp430 to give delay in up mode. This time I am writing about the mode rather than just initializing using grace. Timer A module of msp430 is a 16 bit counter/timer. It has various modes of operation. They are listed below:

Timer-modesWe’ll be using up mode for this activity. Up mode counts from 0 to TACCR0 as mentioned in the mode description. TACCR0 is a 16 bit register which is used for the mode. You can give any value from 0 to 0FFFFh.

Now we want 1 sec delay so we’ll be using the 32KHz crystal. That is why we’ll give the Timer A that input. For one second delay we need to count till 32768. That is why we must give 08000h as the word into the TACCR0 register.

TACTL

(This pic is taken from the data sheet of msp430x2xx)

Now we’ll see how to initialize the control register of Timer A. TACTL is a 16 bit register with controlling bits as shown in the image. TASSELx is used to select the clock. Since we need to use ACLK we have write 01 in TASSELx location. IDx is used to divide the frequency. Since I don’t want any division I’ll put 00 in IDx. MCx is used for selecting the mode. We want up mode so we need to put 01. TAIFG flag is used to check when 1 sec has passed. TAIFG flag should be reset first. Now when ever a roll over takes place i.e the counter reaches the maximum count in this case TACCR0 count we’ll get an interrupt. But since we haven’t enabled the interrupt by setting TAIE the program won’t go to the ISR instead will just set the TAIFG flag and make it one. Now its the duty of the programmer to manually clear this flag, since once set it’ll remain set till values are not explicitly changed.

Now I’ll tell you how exactly to send the bits that we discussed into the TACTL register. You can either use the hexadecimal command word or else use the msp430.h header file defined bits for this.

First we’ll see the good old hex word formation.

First 15-10 are unused bits do they are don’t care conditions, thus their being set or reset makes no difference to Timer A working. So I’ll make these bits reset by 000000b

TASSELx i.e bits 9 and 8. We want mode one so 01b

IDx i.e bits 7 and 6. We want no division so 00b

MCx i.e bits 5 and 4. We want up mode so 01b

Bit 3 unused => don’t care => we’ll use 0b

TACLR i.e bit 2 0b

TAIE i.e bit 1. We don’t want interrupt so 0b

TAIFG i.e bit 0 has to be reset so 0b

Now we’ll write all the binary values together 000000 01 00 01 0 0 0 0.

The hex value after conversion comes out to be 0110h. So this this the hex value that we need to write in the command word TATCL to initialize the timer A in the manner that we require for this task at hand.

Now we’ll see the better approach i.e using the header file constants.

Each and every bit field of the TACTL register is defined in the header file.

I’ll give one example to clear the usage.

#define MC_0 (00x10u) / Timer A mode control: 0 – Stop /
#define MC_1 (1
0x10u) /* Timer A mode control: 1 – Up to CCR0 /
#define MC_2 (2
0x10u) /* Timer A mode control: 2 – Continous up /
#define MC_3 (3
0x10u) /* Timer A mode control: 3 – Up/Down */

Now these above lines are copy pasted from the msp430g2553.h header file.  Now the ‘u’ in this 0x10u stands for unsigned and 0x implies that the value is in hexadecimal number. I’ll write the binary equivalent of these values.

0*0x10u = 000000 (all bits to left of 6th bit are reset)

1*0x10u = 010000 (all bits to left of 6th bit are reset)

2*0x10u = 100000 (all bits to left of 6th bit are reset)

3*0x10u = 110000 (all bits to left of 6th bit are reset)

Thus you can clearly see that when you or this predefined values with the command word only the bits desired for the mode are set. This is the case with all the other constants defined in the header file. One thing to notice is the nomenclature MC_1 and others. So the underscore number is the decimal equivalent of the mode bits given in binary. With background lets initialize this timer, shall we?

We want the ACLK so TASSEL_1, no division is needed so ID_0, up mode so MC_1, we don’t want timer interrupt to change the program flow so we won’t set that bit. That’s all there is to it.

In c language we’ll or this value with the timer command word register. I’ll be using timer 0 so TA0CTL is used.

TA0CTL |= TASSEL_1|ID_0|MC_1;

This takes care of the initialization of the timer A.

Now we’ll see what polling is. I’ll give to two examples. First example: Suppose my sister has gone to the market to get food materials and I’m in my room writing something. Now I know she’ll be coming and I need to open the door for her. There are two approaches I can adopt. First is I would check after every 5 mins(fixed interval) whether she has come or not. In this case I’ll have to check this many times depending upon when will the event of her coming back occurs. The other approach is that my door has a bell so might as well make constructive use of it by letting it do whats its supposed to do. I’ll keep on writing and when I hear the door bell I’ll complete the sentence that I am writing and then attend the door. Example two: Suppose I’m eating gol gappe (indian dish) and then the person who is serving me those can do two things. One is that he’ll keep one piece in my plate ask me then if i say yes he’ll put another and so on. Second is keep the gol gappes in my plate one after the other till I say my stomach is full no more. In both the examples the first case is nothing but polling. You check the status of something after regular intervals of time till you finally detect the occurrence of the event being polled. This is a normal procedure for checking the status of interrupt or maybe the position of a switch and so on. The second case is kind of interrupt. When you get an interrupt you know that the event has occurred and you do whatever is required to do. In technical language you execute the ISR. But then there is the context saving followed by context switching and then normal program resume. This was a little talk about polling. Hope you understand what polling is now.

We’ll be using polling to find out when overflow occurs. Overflow is when the counter reaches the maximum count and reloads the initial condition. In our case when the timer has counted 32k times and rolls over we’ll get exactly 1 sec delay. This overflow event is marked by the setting of the interrupt overflow flag. The setting is done by the processor as soon as the count reaches the CCR0 value.

timer_taifg

The TAIFG flag setting can be seen in the image shown above. This is directly pasted from the msp430 manual. Now we’ll come to know when the required delay has occurred. The next thing would be to reset the flag so that it can be set again on the next roll over. This is taken care in the program. And last but not the least, in order to do something after the overflow has occurred I’ll be showing 0 to 9 on a common cathode seven segment display increasing the value by 1 after each roll over and repeating the process. Again the main motive was to use timer A in up mode with our choice of delay.  Hope you understood what I tried to convey. Again thank you for reading this post. Your feedback will remain priceless like always.

P.S : If you have any doubt about how I got those hex values for ports for each and every number feel free to contact me.

Circuit Connection:

circuit connections

Program Code:

#include <msp430g2553.h>
void main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
TA0CCR0 = 0x8000;                           // load count for 1 sec delay
TA0CTL |= TASSEL_1|ID_0|MC_1|TACLR; // set timer A in up mode
P1OUT = 0x00;
P1DIR = 0xFF;                 // make all ports as output
for(;;)
{

P1OUT = 0x3F; // display 0
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x06; TA0CTL&=~(TAIFG); // display 1 and clear the interrupt flag
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x5B; TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x4F; TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x66; TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x6D; TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x7C; TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x07; TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x7F;TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}
P1OUT = 0x67;TA0CTL&=~(TAIFG);
while((TA0CTL&TAIFG)==0){}TA0CTL&=~(TAIFG);
}
}

Using Grace: