Avr Timer Programming in Assembly and C: BY:-Pratik Gohel Asst. Professor Government Engineering College
Avr Timer Programming in Assembly and C: BY:-Pratik Gohel Asst. Professor Government Engineering College
Avr Timer Programming in Assembly and C: BY:-Pratik Gohel Asst. Professor Government Engineering College
PROGRAMMING
IN ASSEMBLY AND C
BY:- Pratik Gohel
Asst. professor
Government Engineering College
Introduction
• Many applications need to count an event or generate time delays.
• When we want to count an event, we connect the external event
source to the clock pin of the counter register.
• Then, when an event occurs externally, the content of the counter is
incremented; in this way, the content of the counter represents how
many times an event has occurred.
• When we want to generate time delays, we connect the oscillator to
the clock pin of the counter.
• So, when the oscillator ticks, the content of the counter is
incremented.
• one way to generate a time delay is to clear the counter at the start
time and wait until the counter reaches a certain number.
• For example, consider a microcontroller with an oscillator with
frequency of 1 MHz.
• the content of the counter register increments once per microsecond.
• If we want a time delay of 100 microseconds, we should clear the
counter and wait until it becomes equal to 100.
• there is a flag for each of the counters. The flag is set when the
counter overflows, and it is cleared by software.
• The second method to generate a time delay is to load the counter
register and wait until the counter overflows and the flag is set.
• For example, in a microcontroller with a frequency of 1 MHz, with an
8-bit counter register, if we want a time delay of 3 microseconds, we
can load the counter register with $FD and wait until the flag is set
after 3 ticks.
• After the first tick, the content of the register increments to $FE; after
the second tick, it becomes $FF; and after the third tick, it overflows
(the content of the register becomes $00) and the flag is set.
• In ATmega32, there are three timers: Timer0, Timer1, and Timer2.
• Timer0 and Timer2 are 8-bit, while Timer1 is 16-bit.
• we cover Timer0 and Timer2 as 8-bit timers, and Timer1 as a 16-bit timer.
• Every timer needs a clock pulse to tick. The clock source can be internal or
external.
• If we use the internal clock source, then the frequency of the crystal oscillator is
fed into the timer.
• Therefore, it is used for time delay generation and consequently is called a timer.
• By choosing the external clock option, we feed pulses through one of the AYR's
pins. This is called a counter.
Basic Registers of Timers
• In AVR, for each of the timers, there is a TCNTn (timer/founter)
register. That means in ATmega32 we have TCNT0, TCNT1, and
TCNT2.
• The TCNTn register is a counter. Upon reset, the TCNTn contains
zero. It counts up with each pulse.
• The contents of the timers/counters can be accessed using the
TCNTn. You can load a value into the TCNTn register or read its
value.
• Each timer has a TOVn (Timer Overflow) flag, as well. When a
timer overflows, its TOVn flag will be set.
• Each timer also has the TCCRn (timer/counter Control register)
register for setting modes of operation.
• For example, you can specify Timer0 to work as a timer or a
counter by loading proper values into the TCCR0.
• Each timer also has an OCRn (Output Compare Register) register.
The content of the OCRn is compared with the content of the
TCNTn. When they are equal the OCFn (Output Compare Flag)
flag will be set.
• The timer registers are located in the I/O register memory. Therefore,
you can read or write from timer registers using IN and OUT
instructions, like the other I/O registers.
• the following instructions load TCNT0 with 25:
LDI R20,25 ;R20 = 25
OUT TCNT0,R20 ;TCNT0 = R20
or "IN R19, TCNT2" copies TCNT2 to R19.
The internal structure of the ATmega32 timers
is shown in Figure
Timer 1
Timer 2
Timer0 Programming
• TCNTO is 8-bit as shown in Figure:
COM01:00
• D5 D4 Compare Output Mode:
These bits control the waveform generator
CS02:00
D2 D1 D0 Timer0 clock selector
0 0 0 No clock source (Timer/Counter stopped)
0 0 1 Clk (No Prescaling)
0 1 0 Clk I 8
0 1 1 Clk I 64
1 0 0 Clk I 256
1 0 1 Clk/ 1024
1 1 0 External clock source on T0 pin. Clock on falling edge.
1 1 1 External clock source on T0 pin. Clock on rising edge.
• the delay length depends primarily on two factors: (a) the crystal
frequency, and (b) the prescaler factor.
• A third factor in the delay size is the C compiler because various C
compilers generate different hex code sizes, and the amount of overhead
due to the instructions varies by compiler.
• Example to calculate delay: Use Timer0, Normal mode, and 1:8 prescaler
to create 70 μs delay. Assume XTAL = 8 MHz.
• XTAL = 8MHz T machine cycle = 1/8 MHz
• Prescaler = 1:8 Tclock = 8 x 1/8 MHz= 1 μs
• 70 μs/1 μs = 70 clocks 1 + 0xFF – 70 = 0xBA= 186
Write a C program to toggle only the PORTB.4 bit continuously every 70 μs.
Use Timer0, Normal mode, and 1:8 prescaler to create the delay. Assume XTAL
= 8 MHz.
#include <avr/io.h>
void T0Delay ( );
int main ( )
{
DDRB = 0xFF; //PORTB output port
while (1)
{
T0Delay ( ); //Timer0, Normal mode
PORTB = PORTB ~ 0x10; //toggle PORTB.4
}
}
void T0Delay ( )
{
TCNT0 = 186; //load TCNT0
TCCR0 = 0x02; //Timer0, Normal mode, 1:8 prescaler
while ((TIFR&(1<<TOV0))==0); //wait for TOV0 to roll over
TCCR0 = 0; //turn off Timer0
TIFR = 0x1; //clear TOV0
}
Write a C program to toggle only the PORTB.4 bit continuously every 2 ms.
Use Timer1, Normal mode, and no prescaler to create the delay. Assume
XTAL = 8 MHz.
• XTAL = 8MHz T machine cycle = 1/8 MHz
• Prescaler = 1:1 Tclock = 1 x 1/8 MHz= 0.125 μs
• 2ms/0.125 μs = 16000 clocks 0X3E80 Clocks
• 1+ 0xFFFF - 0x3E80 = OxC180
Solution
#include <avr/io.h>
void T1Delay ( );
int main ( )
{
DDRB = 0xFF; //PORTB output port Cont….
while (1)
{
PORTB = PORTB ^ (1<<PB4); //toggle PB4
T1Decay ( ); //delay size unknown
}}
void T1Delay ( )
{
TCNT1H =0xC1; //TEMP 0xC1
TCNT1L = 0x80;
TCCR1A =0x00; //Normal mode
TCCR1B = 0x01; //Normal mode, no prescaler
while ((TIFR&(0x1<<TOV1))==0); //wait for TOV1 to roll over
TCCR1B = 0;
TIFR = 0x1<<TOV1; //clear TOV1
}
C programming of Timers 0 and 1 as
counters
• Timers can be used as counters if we provide pulses from outside the
chip instead of using the frequency of the crystal oscillator as the
clock source.
• By feeding pulses to the T0 (PB0) and T1 (PB1) pins, we use Timer0
and Timer 1 as Counter 0 and Counter 1, respectively.
• Let how Timers 0 and l are programmed as counters using C language.
Assuming that a l Hz clock pulse is fed into pin T0, use the TOV0 flag to
extend Timer0 to a 16-bit counter and display the counter on PORTC and
PORTD.
#include <avr/io.h>
int main ( )
{
PORTB = 0x01; //activate pull-up of PB0
DDRC = 0xFF; //PORTC as output
DDRD = 0xFF; //PORTD as output
TCCR0 = 0x06; //output clock source
TCNT0 = 0x00;
while (1)
{
• Do
•{
• PORTC = TCNT0;
• } while((TIFR&(0x1<<TOV0))==0) ; //wait for TOV0 to roll over
• TIFR = 0x1<<TOV0; //TIFR = 0x0<<TOV0;
• PORTD ++; //increment PORTD
•}
•}
Assume that a 1-Hz external clock is being fed into pin T1 (PB1). Write
a C program for Counter1 in rising edge mode to count the pulses and
display the TCNT1H and TCNT1L registers on PORTD and PORTC,
respectively.
#include <avr/io.h>
int main ( )
{
PORTB = 0x01; //activate pull-up of PB0
DDRC = 0xFF; //PORTC as output
DDRD = 0xFF; //PORTD as output
. INCLUDE "M32DEF.INC“
LDI R20,HIGH(RAMEND)
OUT SPH,R20
LDI R20,LOW(RAMEND)
OUT SPL,R20
LDI R16, 0x20
SBI DDRB,5 ;PB5 as an output
LDI R17, 0
OUT PORTB, R17
BEGIN:RCALL DELAY
EOR R17 ,R16 ;toggle DS of R17
OUT PORTB, R17 ;toggle PB5
RJMP BEGIN
DELAY:LDI R20,0x3E
OUT TCNT0,R20 ;load timer0
LDI R20,0x01
OUT TCCR0,R20 ;Timer0, Normal mode, int clk, no prescaler
AGAIN:IN R20,TIFR ;read TIFR
SBRS R20,TOV0 ;if TOV0 is set skip next instruction
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0,R20 ;stop Timer0
LDI R20, (1<<TOV0) ;R20 = 0x01
OUT TIFR,R20 ;clear TOV0 flag
RET
Assuming XTAL = 8 MHz, write a Assembly
program to generate 1 Hz frequency on PC4.
• With 1 Hz we have T = 1 I F = 1 I 1 Hz = 1 second, half of which is high
and half low. Thus we need a delay of 0.5 second duration.
• Since XTAL = 8 MHz, the different outputs of the prescaler are as
follows:
Program Continue……
AGAIN:
IN R20,TCNT1L ;R20 = TCNT1L, TEMP = TCNT1H
OUT PORTC, R20 ; PORTC = TCNT0
IN R20,TCNT1H ;R20 = TEMP
OUT PORTD,R20 ; PORTD = TCNT0
IN R16, TIFR
SBRS R16, TOV1
RJMP AGAIN; keep doing it
LDI R16, 1<<TOV1 ;clear TOV1 flag
OUT TIFR, R16
RJMP AGAIN; keep doing it
Assuming that clock pulses are fed into pin T1 (PB1) and a buzzer is
connected to pin PORTC.0, write a program for Counter I in CTC mode
to sound the buzzer every 100 pulses.
• To sound the buzzer every 100 pulses, we set the OCR1A value to 99
(63 in hex), and then the counter counts up until it reaches OCR1A.
Upon compare match, we can sound the buzzer by toggling the
PORTC.O pin.
.INCLUDE "M32DEF.INC"
CBI DDRB,1 ;make T1 (PB1) input
SBI DDRC,0 ;PC0 as an output
LDI R16,0x1
LDI R17,0
LDI R20,0x0
OUT TCCR1A,R20
LDI R20,0x0E
OUT TCCR1B,R20 ;CTC, counter, falling edge
Program Continue…..
AGAIN:
LDI R20,0
OUT OCR1AH,R20 ;TEMP = 0
LDI R20,99
OUT OCR1AL,R20 ;ORC1L = R20, OCR1H = TEMP
L1: IN R20,TIFR
SBRS R20,0CF1A
RJMP L1 ; keep doing it
LDI R20,1<<OCF1A ;clear OCF1A flag
OUT TIFR, R20
EOR R17,R16 ;toggle D0 of R17
OUT PORTC, R17 ; toggle PC1
RJMP AGAIN; keep doing it
Exercise
• Program Timer1 to generate a square wave of 3 kHz. Assume that
XTAL = 8 MHz.