Sei sulla pagina 1di 8

How Do I Use Two General Purpose Timers to Count at the

Same Time?
1. Our microcontroller actually has multiple general purpose timers that we can use in our programs.
The default timer that we used in the previous lessons is called Timer_A0. The second timer that
we can use is called Timer_A1.

The default Timer_A0 and alternative Timer_A1 are almost identical, so you already know
almost everything necessary to use both timers in your programs. The only differences between
the two are their register names. For example, here is a program that we used for Timer_A0.
For easy reference, we have indicated the Timer_A0 register names.

#include <msp430.h>

#define RED_LED 0x0001 // P1.0 is the Red LED


#define DEVELOPMENT 0x5A80 // Stop the watchdog timer
#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs
#define ACLK 0x0100 // Timer_A ACLK source
#define UP 0x0010 // Timer_A UP mode
#define TAIFG 0x0001 // Used to look at Timer A Interrupt FlaG

main()
{
WDTCTL = DEVELOPMENT; // Stop the watchdog timer
PM5CTL0 = ENABLE_PINS; // Enable inputs and outputs

TA0CCR0 = 5000; // We will count up from 0 to 5000


TA0CTL = ACLK | UP; // Use ACLK, for UP mode

P1DIR = RED_LED; // Set red LED as an output

while(1)
{
if(TA0CTL & TAIFG) // If timer has counted to 5000
{
P1OUT = P1OUT ^ RED_LED; // Then, toggle red P1.0 LED
TA0CTL = TA0CTL & (~TAIFG); // Count again
}
}
}

Copyright © 2012-2015 Page 1 of 8


Valparaiso University
2. Create a new CCS project called Timer_A1_Up. Copy the program below into the new main.c
file.

We have highlighted the changes below:

TA0CCR0 → TA1CCR0 Note, this is not TA1CCR1! This is a common mistake


TA0CTL → TA1CTL

Notice, the #define terms (ACLK, UP, and TAIFG) are not changed. This is because the ACLK,
UP, and TAIFG bits are located in the same position in both the TA0CTL and TA1CTL registers.

Save, Build, Debug, and run your program to verify that it works. The red LED should be
blinking on and off approximately 4 times per second.

When you are ready, click Terminate to return to the CCS Editor.

#include <msp430.h>

#define RED_LED 0x0001 // P1.0 is the Red LED


#define DEVELOPMENT 0x5A80 // Stop the watchdog timer
#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs
#define ACLK 0x0100 // Timer_A ACLK source
#define UP 0x0010 // Timer_A UP mode
#define TAIFG 0x0001 // Used to look at Timer A Interrupt FlaG

main()
{
WDTCTL = DEVELOPMENT; // Stop the watchdog timer
PM5CTL0 = ENABLE_PINS; // Enable inputs and outputs

TA1CCR0 = 5000; // We will count up from 0 to 5000


TA1CTL = ACLK | UP; // Use ACLK, for UP mode

P1DIR = RED_LED; // Set red LED as an output

while(1)
{
if(TA1CTL & TAIFG) // If timer has counted to 5000
{
P1OUT = P1OUT ^ RED_LED; // Then, toggle red P1.0 LED
TA1CTL = TA1CTL & (~TAIFG); // Count again
}
}
}

Copyright © 2012-2015 Page 2 of 8


Valparaiso University
3. Next, we want to look at using the two general purpose timers simultaneously. Create a new CCS
project Two_Timers_Simple and copy and paste the program below into the new main.c file.

Timer_A0 will count up from 0 to 33,000. This will take approximately:

(33,000)*(25µs) = 0.825 seconds

Timer_A1 will count up from 0 to 5,000. This will take approximately:

(5,000)*(25µs) = 0.125 seconds

#include <msp430.h>

#define RED_LED 0x0001 // P1.0 is the red LED


#define GREEN_LED 0x0080 // P9.7 is the green LED
#define DEVELOPMENT 0x5A80 // Stop the watchdog timer
#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs
#define ACLK 0x0100 // Timer_A ACLK source
#define UP 0x0010 // Timer_A UP mode
#define TAIFG 0x0001 // Used to look at Timer A Interrupt FlaG

main()
{
WDTCTL = DEVELOPMENT; // Stop the watchdog timer
PM5CTL0 = ENABLE_PINS; // Enable inputs and outputs

TA0CCR0 = 33000; // We will count up from 0 to 33000


TA0CTL = ACLK | UP; // Use ACLK, for UP mode

TA1CCR0 = 5000; // We will count up from 0 to 5000


TA1CTL = ACLK | UP; // Use ACLK, for UP mode

P1DIR = RED_LED; // Set red LED as an output


P9DIR = GREEN_LED; // Set green LED as an output

while(1)
{
if(TA0CTL & TAIFG) // If timer 0 has counted to 33000
{
P1OUT = P1OUT ^ RED_LED; // Then, toggle red P1.0 LED
TA0CTL = TA0CTL & (~TAIFG); // Count again
}

if(TA1CTL & TAIFG) // If timer 1 has counted to 5000


{
P9OUT = P9OUT ^ GREEN_LED; // Then, toggle green P9.7 LED
TA1CTL = TA1CTL & (~TAIFG); // Count again
}

}//end while(1)

}//end main()

Copyright © 2012-2015 Page 3 of 8


Valparaiso University
4. For a program like this, we figured it might be time to use a flowchart to explain how it works.
After stopping the watchdog and enabling the input and output pins, the program starts the two
timers counting. It then makes the red and green LED pins outputs.

Then, the program enters an infinite while(1) loop. In the loop, the program is continuously
checking to see if Timer 0 has counted to 33,000. If the answer is yes, the program toggles the
red P1.0 LED and clears the Timer 0 TAIFG flag in preparation for the next 33,000 count.

Next, the program checks to see if Timer 1 has counted to 5,000. If the answer is yes, the
program toggles the green P9.7 LED and clears the Timer 1 TAIFG flag in preparation for the
next 5,000 count. The program then returns to the top of the while(1) loop and checks the
status of the timers repeatedly.

Copyright © 2012-2015 Page 4 of 8


Valparaiso University
5. If you have not already done so, Save and Build your Two_Timers_Simple project. Debug
and run your program when you are ready. You should see the green LED blinking much faster
than the red LED.

6. Click Terminate to return to the CCS Editor when you are ready.

7. Using multiple timers like in the above program is relatively straightforward. However, if you
have to count higher than 65,535, it becomes a little more complicated.

A program is shown on the next page, and its corresponding flowchart is shown on the page after
that. However, for a short summary:

1) Every 10ms, Timer 0 causes the watchdog to be petted

2) After ten periods of 10ms elapses, Timer 0 causes the red LED to toggle

3) After 3 periods of 1s elapses, Timer 1 causes the green LED to toggle

What you will see is that this program has become quite complex rather quickly. There are a few
more bonus sections on timers that follow, but after that, we are going to introduce the concept of
functions in the C programming language. Functions will greatly simplify the development and
also the readability of our C programs.

Copyright © 2012-2015 Page 5 of 8


Valparaiso University
#include <msp430.h>

#define RED_LED 0x0001 // P1.0 is the red LED


#define GREEN_LED 0x0080 // P9.7 is the green LED
#define DEVELOPMENT 0x5A80 // Stop the watchdog timer
#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs
#define ACLK 0x0100 // Timer_A ACLK source
#define UP 0x0010 // Timer_A UP mode
#define TAIFG 0x0001 // Used to look at Timer A Interrupt FlaG
#define PET_WATCHDOG 0x5A08 // WDT password and pet

main()
{
unsigned char t0_count=0;
unsigned char t1_count=0;

PM5CTL0 = ENABLE_PINS; // Enable inputs and outputs

TA0CCR0 = 400; // Count up from 0 to 400 (~10ms)


TA0CTL = ACLK | UP; // Use ACLK, for UP mode
TA1CCR0 = 40000; // Count up from 0 to 40000 (~1s)
TA1CTL = ACLK | UP; // Use ACLK, for UP mode

P1DIR = RED_LED; // Set red LED as an output


P9DIR = GREEN_LED; // Set green LED as an output

while(1)
{

if(TA0CTL & TAIFG) // If timer 0 has counted ~10ms


{
WDTCTL = PET_WATCHDOG; // Pet the watchdog
TA0CTL = TA0CTL & (~TAIFG); // Count again
t0_count = t0_count + 1; // Increment 10ms counts

if(t0_count == 10) // If ~ 100ms has elapsed


{
t0_count = 0; // Reset 10ms counter
P1OUT = P1OUT ^ RED_LED; // Toggle red LED
}

}//end timer0 if

if(TA1CTL & TAIFG) // If timer 1 has counted to 5000


{
TA1CTL = TA1CTL & (~TAIFG); // Count again
t1_count = t1_count + 1; // Increment 1s counts

if(t1_count == 3) // If ~3s has elapsed


{
t1_count = 0; // Reset 1s counter
P9OUT = P9OUT ^ GREEN_LED;// Toggle green LED
}

}//end timer1 if
}//end while(1)
}//end main()

Copyright © 2012-2015 Page 6 of 8


Valparaiso University
Ena ble pins

Ti mer 0
Count up
for 10ms

Ti mer 1
Count up
for 1s

Ma ke outputs
P1.0 a nd P9.7

Ti mer 0 Yes Cl ea r Timer 0 Increment 10ms


rea ched Pet wa tchdog
TAIFG fl ag counter, t0_count
10ms ?

No
No 100ms
el apsed?

Yes
Cl ea r 10ms
counter

Toggl e red LED

No Ti mer 1 Yes Cl ea r Timer 1 Increment 3s


rea ched
TAIFG fl ag counter, t1_count
1s ?

No 3s
el apsed?

Yes
Cl ea r 3s
counter

Toggl e green
LED

Copyright © 2012-2015 Page 7 of 8


Valparaiso University
All tutorials and software examples included herewith are intended solely for
educational purposes. The material is provided in an “as is” condition. Any
express or implied warranties, including, but not limited to the implied warranties
of merchantability and fitness for particular purposes are disclaimed.

The software examples are self-contained low-level programs that typically


demonstrate a single peripheral function or device feature in a highly concise
manner. Therefore, the code may rely on the device's power-on default register
values and settings such as the clock configuration and care must be taken when
combining code from several examples to avoid potential side effects.
Additionally, the tutorials and software examples should not be considered for use
in life support devices or systems or mission critical devices or systems.

In no event shall the owner or contributors to the tutorials and software be liable
for any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services; loss of
use, data, or profits; or business interruption) however caused and on any theory
of liability, whether in contract, strict liability, or tort (including negligence or
otherwise) arising in any way out of the use of this software, even if advised of
the possibility of such damage.

Copyright © 2012-2015 Page 8 of 8


Valparaiso University