Programming ATmega328P in CTC Mode: An Overview

The ATmega328P microcontroller is a popular choice for many electronics projects, due to its ease of use and versatility. One of its useful modes of operation is the Clear Timer on Compare (CTC) mode. In this mode, the microcontroller can generate a specific frequency of square wave signals by comparing the counter value to a predetermined value. This mode is particularly useful for applications that require precise timing, such as waveform generation, PWM, and event counting. In this AVR Timer tutorial, we will explore how to program the ATmega328P microcontroller in CTC mode.

Prerequisites

Before we begin programming the ATmega328P in CTC mode, there are a few things you will need:

  • A programmer such as an Arduino board or an AVR ISP programmer
  • A breadboard
  • Wires
  • A ATmega328P microcontroller
  • An Integrated Development Environment (IDE) such as ATMEL studio

The atmel studio tutorial explains step by step how to program atmega328p.

How CTC mode works

Clear Timer on Compare (CTC) mode is one mode of operation for the timers in microcontrollers. It can be used to create counter that counts a specific value and when it reaches the count value (or compare value) we can direct the MCU to do a specific task. For example and a common usage is to generate square wave signals of a specific frequency by comparing the timer's counter value to a predetermined value, also known as the compare value or count value.

When the timer is in CTC mode, it increments its counter value until it reaches the compare value. When the counter value reaches the compare value, the timer resets to zero and sets an output compare match flag. This flag can trigger an interrupt, or it can be used to toggle an output pin, generating a square wave signal.

The frequency of the square wave signals generated in CTC mode is determined by the compare value, the clock speed of the microcontroller, and the timer prescaler value. The compare value is calculated based on the desired frequency of the square wave signals and the clock speed of the microcontroller. The formula for calculating the compare value is:

 \[C=\frac{F_{clk}}{2 N F_{w}}-1\]

 where, Fclk is the microcontroller CPU clock frequency, N is the pre-scalar value and Fw is the output wave frequency or the frequency at which compare happens.

The output wave frequency Fw in the above case is the frequency at which you want the MCU to do tasks like sampling of signals, generate signal at that frequency etc. 

The following shows the ATmega328p CTC pins for Timer0, Timer 1 and Timer 2 location.

CTC Mode Programming Overview

The code for programming the ATmega328P in CTC mode involves setting up the timer and calculating the compare value. 

First, we need to set the waveform generation mode to CTC by using the following line of code:

TCCR1B |= (1 << WGM12);

 Then we need to calculate the compare value based on the desired frequency of the square wave signals and the clock speed of the microcontroller. The formula for calculating the compare value is as follows:

compareValue = (clockSpeed / (2 * N * desiredFrequency)) - 1;

where, N is the pre-scalar 

Once calculated we need to set the compare value by using the following line of code:

OCR1A = compareValue;

Finally, we can either poll the output compare flag or we can enable the output compare match interrupt.

If we are using polling method to monitor the compare match then we need to use the following lines of codes:

while((TIFR0 &  (1<<OCF0A)) == 0);	//check OCF0A flag
	TIFR0 = (1<<OCF0A);	//clear OCF0A flag

Or if we are using the compare match interrupt then we have to use the following line of code:

TIMSK1 |= (1 << OCIE1A);

ATmega328P in CTC Mode Program Example

Below are polling and interrupt program examples of using Timer 1 of ATmega328P microcontroller in CTC mode.

Polling Method

The following is a sample program that toggles a LED connected to PB5 pin with a frequency of 5KHz using ATmega328p Timer1 in CTC (Clear Timer on Compare) mode and by polling the compare overflow flag.

#include <avr/io.h>

#ifndef F_CPU
#define F_CPU 8000000UL // 8 MHz clock speed
#endif

#define FREQ 5000UL // 5 KHz LED toggle frequency

int main(void)
{
  //set PB5 pin for LED as output
  DDRB |= (1<<PB5);
  // Set up Timer1 in CTC mode
  TCCR1A = 0; // Normal port operation, OC1A/OC1B disconnected
  TCCR1B = (1 << WGM12) | (1 << CS10); // CTC mode, no prescaler
  OCR1A = (F_CPU / 2 / FREQ) - 1; // Compare match value
  TCNT1 = 0; // Initialize timer value
  
  while (1)
  {
    // Check for Timer1 compare match
    if (TIFR1 & (1 << OCF1A))
    {
      // Clear compare match flag
      TIFR1 = (1 << OCF1A);
      
      // Toggle output pin
      PORTB ^= (1 << PB5);
    }
  }
  
  return 0;
}    

In the above CTC mode code, the frequency of the LED toggle is defined by the FREQ macro. The F_CPU macro defines the clock speed of the ATmega328p microcontroller. The TCCR1A and TCCR1B registers are configured to set Timer1 in CTC mode with no prescaler. The compare match value for Timer1 is calculated using the formula OCR1A = (F_CPU / 2 / FREQ) - 1.

In the main loop, the program polls the OCF1A flag in the TIFR1 register to check for a Timer1 compare match. If a compare match occurs, the program clears the flag and toggles the output pin connected to PB5 where a LED is connected.

Note that in the program the output pin PB5 has been set as an output using the statement DDRB=(1<<PB5). The following shows LED connected to PB5 pin of ATmega328P and blinking at 5KHz using the CTC mode program code above.

CTC mode  blinking LED

Interrupt Method

Here is a sample code to generate a 5kHz square wave signal using ATmega328p Timer 1 in CTC mode with interrupt:

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

#ifndef F_CPU
#define F_CPU 8000000UL // 8 MHz clock speed
#endif

#define FREQ 5000UL // 5 KHz LED toggle frequency

int main(void)
{
  //set PB5 pin for LED as output
  DDRB |= (1<<PB5);
  // Set up Timer1 in CTC mode
  TCCR1A = 0; // Normal port operation, OC1A/OC1B disconnected
  TCCR1B = (1 << WGM12) | (1 << CS10); // CTC mode, no prescaler
  OCR1A = (F_CPU / 2 / FREQ) - 1; // Compare match value
  TCNT1 = 0; // Initialize timer value
  TIMSK1 |= (1<<OCIE1A);  // Enable timer compare interrupt
  sei();                   // Enable global interrupt
  
  while (1){
    //do nothing
  }
  
  return 0;
}


ISR(TIMER1_COMPA_vect)    // Timer 1 compare match interrupt service routine
{
  PORTB ^= (1<<PB5);      // Toggle PB1 to generate wave
}


Testing and Debugging 

After you have written the code and uploaded it to the ATmega328P, it's important to test and debug it to make sure it's working correctly. Some common problems that can arise when programming the ATmega328P in CTC mode include incorrect wiring, incorrect clock speed, and incorrect compare value. If you experience any issues, you can use a logic analyzer or oscilloscope to visualize the signals generated by the microcontroller. This can help you identify and troubleshoot any problems.

In summary, CTC mode allows the microcontroller to generate precise frequency square wave signals by comparing the timer's counter value to a predetermined value, resetting the counter value when the compare value is reached, and setting an output compare match flag to trigger an interrupt or toggle an output pin. 

References:

- CTC mode Atmega328

- Arduino CTC mode Programming with Examples

Post a Comment

Previous Post Next Post