0
0
Power-electronicsHow-ToBeginner · 4 min read

How to Configure Timer Mode in Embedded C: Simple Guide

To configure timer mode in embedded C, set the timer control registers to select the desired mode (e.g., normal, CTC, PWM) and configure the prescaler for timer speed. Use TCCRn registers to set mode bits and TCNTn to initialize the timer count.
📐

Syntax

Timer configuration involves setting control registers and prescalers. For example, in AVR microcontrollers, TCCRn controls timer mode, TCNTn sets the timer count, and TIMSK enables interrupts.

  • TCCRn: Timer/Counter Control Register to select mode and clock source.
  • TCNTn: Timer/Counter Register to set initial count value.
  • TIMSK: Timer Interrupt Mask Register to enable timer interrupts.
c
/* Example syntax for setting Timer1 to CTC mode with prescaler 64 */
TCCR1A = 0x00;           // Normal port operation, OC1A/OC1B disconnected
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC mode, prescaler 64
TCNT1 = 0;               // Initialize counter
OCR1A = 25000;           // Compare value for 1 second delay (assuming 16MHz clock)
TIMSK1 = (1 << OCIE1A);  // Enable Timer1 compare interrupt
💻

Example

This example configures Timer1 in CTC mode on an AVR microcontroller to toggle an LED every second using interrupts.

c
#include <avr/io.h>
#include <avr/interrupt.h>

void timer1_init() {
    TCCR1A = 0x00; // Normal port operation
    TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC mode, prescaler 64
    OCR1A = 25000; // Compare value for 1 second delay
    TCNT1 = 0; // Reset timer count
    TIMSK1 = (1 << OCIE1A); // Enable Timer1 compare interrupt
    sei(); // Enable global interrupts
}

ISR(TIMER1_COMPA_vect) {
    PORTB ^= (1 << PORTB5); // Toggle LED on pin PB5
}

int main(void) {
    DDRB |= (1 << DDB5); // Set PB5 as output
    timer1_init();
    while(1) {
        // Main loop does nothing, LED toggled by interrupt
    }
    return 0;
}
Output
LED connected to PB5 toggles ON and OFF every 1 second
⚠️

Common Pitfalls

  • Not setting the correct bits in TCCRn for the desired timer mode causes unexpected behavior.
  • Forgetting to enable global interrupts with sei() means interrupt service routines won't run.
  • Incorrect prescaler values lead to wrong timer speeds and delays.
  • Not initializing TCNTn can cause timer to start from an unknown count.
c
/* Wrong: Missing prescaler bits, timer won't start */
TCCR1B = (1 << WGM12); // CTC mode but no clock source set

/* Right: Include prescaler bits to start timer */
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC mode, prescaler 64
📊

Quick Reference

Register/BitPurposeExample Value
TCCRnSelect timer mode and clock prescalerTCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10)
TCNTnTimer counter initial valueTCNT1 = 0
OCRnAOutput compare register for CTC modeOCR1A = 25000
TIMSKEnable timer interruptsTIMSK1 = (1 << OCIE1A)
sei()Enable global interruptssei()

Key Takeaways

Set timer control registers (TCCRn) to select mode and prescaler correctly.
Initialize timer count (TCNTn) before starting the timer.
Enable interrupts and global interrupts if using timer interrupts.
Check prescaler values to get accurate timing delays.
Always verify timer mode bits to avoid unexpected behavior.