Nile University Embedded Real Time Systems
School of Engineering and Applied Sciences
Lecture 3
Timers in Embedded Real Time Systems
Benefits of Using Timers:
1. Precise Timing Control:
Accurate Delays: Timers allow for precise control over time delays without
relying on CPU-intensive software loops.
2. Periodic Tasks:
Regular Intervals: Timers can trigger interrupts at regular intervals, which is
useful for tasks that need to run periodically (e.g., sensor readings, updating
displays).
Real-Time Clock: Maintaining accurate real-time clocks or counters.
3. PWM Generation:
Pulse Width Modulation (PWM): Timers are crucial for generating PWM
signals used for motor control, LED dimming, and other applications requiring
varying duty cycles.
4. Input Capture:
Event Timing: Timers can capture the exact time of an external event, useful for
measuring pulse lengths, frequency, or intervals between events.
5. Reducing CPU Load:
Efficient Task Management: Offloading timing-related tasks to hardware timers
frees up the CPU to handle other processing tasks, improving overall system
performance.
6. Synchronizing and Scheduling Tasks:
Coordinated Operations: Timers help synchronize different parts of the system,
ensuring coordinated operation and avoiding timing conflicts.
7. Event Counting:
Counting Events: Timers can be configured to count external events.
Case study: Timers in AVR Micro controllers (Atmega32)
Timer modes such as Normal, CTC (Clear Timer on Compare Match), PWM (Pulse Width
Modulation), and others are generally available in most microcontrollers, including popular ones
like AVR (Atmel), PIC (Microchip), STM32 (STMicroelectronics), and others. These modes
provide essential timing and signal generation capabilities and are standard features found across
various microcontroller families, facilitating versatile applications in embedded systems and
electronics.
ECEN435 Dr. Noha Younis
ECEN435 Dr. Noha Younis
Timer0
Timer2
ECEN435 Dr. Noha Younis
*Note: on MAX” in the table refers to the overflow event (reaching TOP = 0xFF), but the flag
TOVn actually goes high in the cycle when the counter wraps to 0x00.
*Note: non-MWM modes are the normal and CTC modes
ECEN435 Dr. Noha Younis
ECEN435 Dr. Noha Younis
1- Normal Mode
The counter simply overruns when it passes its maximum
8- bit value (TOP = 0xFF) and then restarts from the
bottom (0x00).
Timer/Counter Overflow Flag (TOVn) will be set in the
same timer clock cycle as the TCNT0 becomes zero.
TOVn is used to trigger the ISR (Timern_OVF_vect)
TIMSK |= (1 << TOIE0); sei();
Calculating the initial TCNT of the normal mode to generate
a certain delay:
Timer tick delay= N/fcpu , where N is the desired prescaler
NoT(Delay) = No. of ticks for D delay = (Dxfcpu)/N NoT <= 2n
where : n is the number of timer bits (= 8 for Timers0 and 2 and 16 for Timer1)
TCNTn = (2n - NoT(Delay)) : 2n -1 ≥ TCNTn ≥ 0
ECEN435 Dr. Noha Younis
Example: Write a program to continually turn on a device connected
to atmega32 for 2 seconds then turn it off for 2 seconds the device is
connected to Portb0 of the microcontroller. The CPU frequency is
100KHz.
No. of ticks for D delay = (Dxfcpu)/N Should be <= 2n
Use Timer0 in normal mode:
NoT(2 sec) = (2x100000)/N
Start with the largest N ( 1024) as NoT Should be <= 256
NoT(2sec) = 200000/1024 = 195.3125 ~ 195 < 256 (OK)
TCNT0 (2sec) = 256 – NoT = 256 – 195 ~ 60
#include <avr/io.h>
#define F_CPU 100000UL // 100KHZ Clock frequency
#define LED_PIN PB0 // Pin for LED (adjust as needed)
void timer0(void)
{
TCNT0 = 60 ;
// Set prescaler to 1024
TCCR0 |= (1 << CS02) | (1 << CS00);
}
int main(void)
{
// Set LED_PIN as output
DDRB |= (1 << LED_PIN);
// Initialize Timer0
timer0();
ECEN435 Dr. Noha Younis
while (1)
{
if ((TIFR & (1 << TOV0))!=0) //TOV0 = 1 Overflow occurs
{
TCCR0 = 0 ; // stop timer0
TIFR |= (1 << TOV0); // clear TOV0 // Pooling
// Toggle LED
PORTB ^= (1 << LED_PIN);
timer0(); // rerun Timer0
//DO SOMETHING ELSE
return 0;
}
ECEN435 Dr. Noha Younis
Interrupt service routine for timers in GCC Compiler
ECEN435 Dr. Noha Younis
Repeat the previous example using interrupt:
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 100000UL // Clock frequency
#define LED_PIN PB0 // Pin for LED (adjust as needed)
void timer0(void)
{
TCNT0 = 60 ;
// Set prescaler to 1024
TCCR0 |= (1 << CS02) | (1 << CS00);
}
ISR(TIMER0_OVF_vect)
{
TCCR0 = 0 ;
TCNT0 = 60 ;
// Toggle LED
PORTB ^= (1 << LED_PIN);
TCCR0 |= (1 << CS02) | (1 << CS00); // START TIMER AGAIN
}
int main(void)
{
// Set LED_PIN as output
DDRB |= (1 << LED_PIN);
TIMSK |= (1 << TOIE0); // Enable TOV interrupt
// Enable global interrupts
sei();
timer0(); // start timer
while (1)
{
// Do other things :)!
}
return 0;}
ECEN435 Dr. Noha Younis
2- Clear Timer on Compare Match (CTC)
The Output Compare Register (OCRn) defines the top value for the
counter, hence also its resolution.
The counter TCNTn is cleared to zero and the flag OCFn is set after the
the counter value (TCNTn) matches the OCRn.
OCn either toggles, set or cleared when TCNTn = OCRn
OCn pin must be configured as an output pin to use it
On match: OCFn is used to trigger the ISR (Timern_COMP_vect) :
TIMSK |= (1 << OCIE2); sei();
ECEN435 Dr. Noha Younis
CTC MODE is suitable to generate a square wave of more flexible
frequency, where the new generated frequency follows the following
form:
CTC is also useful to enable/disable a device by sending high or low
signals on OCn after a defined delay:
Delay = N*(OCRn+1)/ fclk_I/O
Then:
OCRn =( (delay*fclk_I/O)/N) -1
For n-bit timers, CTC mode is suitable for:
1. Generating high frequencies with values ≥ fcpu / (2 x Nmax x 2n).
2. Generating short delays ≤ (Nmax x 2n) / fcpu.
ECEN435 Dr. Noha Younis
Example:
A 3D printer is controlled and monitored by an AVR ATmega32
microcontroller. The heating element in the 3D printer must turn on 5 seconds
after the system starts. This delay ensures that initial system checks and
calibrations are completed before the heating process begins. The heating
element is activated by sending a high signal to enable its power. Turn on an
active low led connected to PORTC6 to identify that the printer is ready after
the 5 second warming up. Use Timer2 of the ATmega32 in CTC mode, with a
clock frequency of 2 kHz to activate the heating element after the specified
delay.
Try pre-scaler 256:
OCR2 = (5x2000/256)-1 = 38.0625 ~ 38
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 2000UL
#define L_LED 6
void timer2_ctc_mode() {
// Clear the timer
TCNT2 = 0;
// Set CTC mode
TCCR2 |= (1 << WGM21);
TCCR2 &= ~(1 << WGM20);
// Set OCR2 value to 38
OCR2 = 38;
TIMSK |= (1 << OCIE2);
// Enable global interrupts
sei();
// clear OC2 on compare match
TCCR2 |= (1 << COM21) ;
TCCR2 |= (1 << CS22) | (1 << CS21);} // Pre-scaler = 256
ECEN435 Dr. Noha Younis
ISR(TIMER2_COMP_vect)
{ PORTC &=~(1<< L_LED) ;
TCCR2 = 0 ; // Stop Timer2 for not running again
int main(void) {
// Configure Timer2 in CTC mode
DDRC |= (1 << L_LED);
PORTC|= (1 << L_LED); // the LED is initially off
// Configure PD7 (OC2) as output
DDRD |= (1 << PD7); Must
//SET THE WARMING SIGNAL TO LAST HIGH FOR 5 SEC
PORTD |= (1 << PD7);
timer2_ctc_mode();
while (1) {
// Do other things :)!
}
return 0;
}
ECEN435 Dr. Noha Younis