The Timer1 of the AVR ATMEGA328 microcontroller is a 16 bits timer/counter that is much more versatile and complex then the 8-bits TIMER0. Timer1 contains one 16-bit input capture register and two 16-bit output compare registers. The input capture register is used for measuring pulse widths or capturing times, while output compare registers are used for producing frequencies or pulses from the timer/counter to an output pin on the microcontroller. TIMER0 is usually started, stopped, and reset, while TIMER1 is usually left running.

TIMER1 Registers

Timer/counter prescaler and mode selector

TIMER1 is still a binary up-counter whose count speed or timing intervals depend on the clock signal applied to its input. Timer/counter control register 1 (TCCR1), is actually composed of two registers, TCCR1A and TCCR1B. TCCR1A controls the compare modes and the pulse width modulation modes of TIMER1. TCCR1B controls the prescaler and input multiplexer and the input capture modes. TCCR1A and TCCR1B are 8 bits registers.


Input capture mode

The input capture mode is used to capture external events and give them a timestamp that can be used to measure frequency, duty cycle or period times. 

To measure an event with Timer 1, the time is captured or held at the beginning of the event, the time is also captured at the end of the event, and the two are subtracted to find the time that it took for the event to occur. These tasks are managed by the input capture register (ICR1). ICR1 is a 16-bit register (ICR1H and ICR1L) that will capture the actual reading of Timer 1 when the microcontroller receives a certain signal. The signal that causes a capture to occur can be either a rising or a falling edge applied to the input capture pin (ICP) of the microcontroller. Since there is only one capture register available to TIMER1, the captured contents must be read out as soon as they are captured to prevent the next capture from overwriting and destroying the previous reading. In order to accomplish this, an interrupt is provided that occurs whenever new data is captured into ICR1. Each time the capture interrupt occurs, the program must determine whether the interrupt signals the beginning or the ending of an event that is being timed so that it can treat the data in ICR1 appropriately.

The program example below demonstrate the use of the input capture mode. The goal of this hardware and software is to measure the period of a square wave applied to the input capture pin (ICP) of the microcontroller and to output the result, in milliseconds on an LCD display connected to PORTD. For this project the ATMEGA328 board is used connected to a LCD display.

 

// program name: TIMER1_icp
// date: 30.08.2015
// author: www.avrprojects.net
// target device: atmega328
// hardware: ATMEGA326 board input capture pin
// software: WinAVR-20100110 compiler
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <util/lcd.h>
unsigned cha rov_counter,counter;/*counter for timer 1 overflow*/
unsigned int starting_edge,ending_edge;/*storage for times*/
unsigned int clocks;/*storage for actual clock counts in the pulse*/ ISR(TIMER1_OVF_vect)
{
ov_counter++; /*increment counter when overflow occurs*/
} ISR(TIMER1_CAPT_vect)
{ending_edge=256*ICR1H+ICR1L;//get end time for period
clocks=(unsignedlong)ending_edge+((unsignedlong)ov_counter*65536)-(unsignedlong)starting_edge;//clear overflow counter for this measurement ov_counter=0;//save end time to use as starting edge starting_edge=ending_edge;} intmain(void)
{LCDini();
DDRD=0xFF;/*set Port D for output*/
TCCR1A=0x00;/*disable all waveform functions*/
TCCR1B=0b10000101;/*Timer 1 input to clock/1024, enable input capture*/
TIMSK=0x24;/*unmask timer1 overflow and capture interrupts*/
sei();
LCDtxt("TIMER1 icp"); while(1) { LCDgoto(0,1); LCDint(clocks/16);// divide clocks by 16 gives milliseconds LCDtxt(" mS "); }
}

Output Compare Mode

The output compare mode is used by the microcontroller to produce output signals. The outputs may be square or asymmetrical waves, and they may be varying in frequency or symmetry. In the output compare mode the program loads a value in the output compare register (OCR1xH and OCR1xL)This value is compared to the value in the timer/counter register (TCNT1H and TCNT1L) , and when the two values match an interrupt occurs. This interrupt triggers the processor to execute a piece of program.The output compare mode can also automatically set, clear, or toggle a specific output port pin.

The output compare modes for TIMER1 are controlled by timer counter control register TCCR1A.

COM1A0 & COM1A1 Control the compare mode function for compare resister A
COM1B0 & COM1B1 Control the compare mode function for compare resister B

Control Bit Definitions TCCR1A
COM1x1 COM1x0 Function (x = A or B)
0 0 no output
0 1 Compare match toggles the OC1x line
1 0 Compare match clears the OC1x line to 0
1 1 Compare match sets the OC1x line to 1

As shown in the table, the compare mode control bits determine what action will be taken when a match occurs between the output compare register (OCR1xH and OCR1xL) and the timer register (TCNT1H and TCNT1L) . The associated output pin (OC1x) can be left alone, toggled, set, or cleared. The match also generates an interrupt. The purpose of the program code of the interrupt service routine is to reset or reload the compare register for the next match that must occur.

In this example we want to generate a square wave of 10kHz. Below you can see the schematic.

 So we need to calculate the value for the reload of the output compare register OCR1xH and OCR1xL.

One half of the square wave is 50µs.

The clock interval is 16Mhz / 8 = 2000kHz = 0,5µs

50µs / 0,5µs = 100 clock pulses per match point, we can program this in the Interrupt Service Routine. Below is the complete code.

// program name: TIMER1_OCM
// date: 04.09.2015
// author: www.avrprojects.net
// target device: atmega328
// harware: ATMEGA326 board output compare mode
// software: WinAVR-20100110 compiler
#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <util/lcd.h>
/* Timer 1 output compare A interrupt service routine*/
ISR(TIMER1_COMPA_vect)
{
OCR1A = OCR1A + 100;
} int main (void)
{
DDRB=0b00000010;/* set OC1A bit for output */
TCCR1A=0x40; /* enable output compare mode to toggle OC1A pin on match */
TCCR1B=0x02; /*set prescaler to Clock/8*/
TIMSK=0x10; /* unmask output compare match interrupt for register A */
sei(); /* enable global interupt */ while(1) { ;/* do nothing*/ }
}

In this picture you see the result of the code meusured on the Output Compare Pin.

output compare mode


 Pulse Width Modulation Mode

In the Pulse Width Modulation (PWM) mode the duty cycle of a square wave can be varied. This will vary the avarage DC voltage of the waveform. When the waveforn is filtered by an RC circuit, this will create a Digital to Analog Convertor (DAC). For example a LED brightness or a DC motor can be controlled by the PWM waveform.

TIMER 1 provides a built-in method to create a pulse width modulator. The TIMER 1 function can be changed to PWM mode. During PWM operation it counts from zero up to a top value and then it counts down.back to zero. The top value is determined by the resolution which can de set as 8-bit, 9-bit and 10-bit resolution by the Waveform Generation Mode (WGM) select bits in the TCCR1A register. It will also effect the frequency of the PWM waveform. See the table below how the select the resolution in the TCCR1A register.

PWM select bits PWM resolution Timer Top Value
 WGM11   WGM10   
0 0  PWM disabled
0 1  8-bit  255
1 0  9-bit 511
1 1  10-bit 1023

 

The PWM frequency for the output can be calculated by the following equation:

fPWM = fsystem clock /prescaler (1 * top count). 

In the example code we set the prescaler to 8, as the system clock is 16Mhz this will result in a PWM frequency of:

16Mhz / 8 * ( 1 + 255) = 7,813 kHz 

The output of the PWM channnel is OC1A(PORTB1).is connected to a LED. See the schematic below.

 

In the program code the duty cycle is set to 50%

// program name: TIMER1_PWM
// date: 08.09.2015
// author: www.avrprojects.net
// target device: atmega328
// harware: ATMEGA326 board PWM mode
// software: WinAVR-20100110 compiler
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <util/lcd.h>
int main(void)
{
DDRB=0x02;//set OC1A as output PORTB1 pin15 TCCR1A=0b10010001;//compare A for non-inv. PWM and 8 bit resolution TCCR1B=0b00000010;//set clock / 8 prescaler while(1) { OCR1A = 128; // duty cylce of 50% _delay_ms(100); }
}