Timers and Counters

Timer/counter
Chapter 12
A counter register
UP
COUT
Counter Register
Load
A simple design (counting people)
First design
Sensor
UP
COUT
Counter Register
Load
4
Comparator
=
A simple design (counting people)
Second design
Sensor
UP
COUT
Counter Register
8
$FC
Load
A simple design (making delay)
UP
COUT
Counter Register
8
$FC
Load
A generic timer/counter
•
•
•
•
Delay generating
Counting
Wave-form generating
Capturing
Oscillator
External
source
0
COUT
1
Counter/Timer
Flag
Counter register
Timers in AVR
• 1 to 6 timers
– 3 timers in ATmega32
• 8-bit and 16-bit timers
– two 8-bit timers and one 16-bit timer in ATmega32
Timer in AVR
Oscillator

TCNTn

TOVn

TCCRn

OCRn
(output compare register)

OCFn
(output compare match flag)
(Timer/Counter register)
Counter register
External
source
(Timer Overflow flag)
Counter/Timer
Flag
(Timer Counter control register)
TCCRn
TCNTn
TOVn
Comment:
All of the timer registers are
byte-addressable I/O registers
=
OCRn
OCFn
Timer 0 (an 8-bit timer)
Timer 0
TCCR0
TCNT0
TOV0
OCF2
TOV2
ICF1
OCF1A
OCF1B
TOV1
OCF0
TOV0
=
TIFR
OCR0
OCF0
FOC0
WGM00
COM01
COM00
WGM01
CS02
CS01
TCCR0
CS00
Clock Mode
Timer
Selector
(WGM)
(CS)
CS02 CS01 CS00 Comment
0
0
0
0
0
0
1
1
1
1
1
1
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
No clock source (Timer/Counter stopped)
clk (No Prescaling)PSR10
Normal
clk / 8
CTC (Clear Timer on Compare Match)
Clear
clk / 64
clkIO
10-bit T/C Prescaler
PWM, phase correct
clk / 256
Fast PWM
clk / 1024
External clock source on T0 pin. Clock on falling edge
External clock source on T0 pin.
Clock on rising edge
0
CS00
CS01
CS02
0
1
2
3
4
clk/1024
clk/256
clk/64
0
1
0
1
clk/8
WGM00 WGM01 Comment
5
Timer/Counter0 clock
source
6
7
T0
Where does PSR10 come from?
Normal mode
TCNT0
0xFF
0
TOV
FF
FE
2
1
0
TOV0 = 1
TOV0:
0
1
TOV
TOV
time
Example 1: Write a program that waits 14 machine
cycles in Normal mode.
14 = $0E
UP
COUT
Load
Counter Register
$100
8
-$0E
$F2
$F2
FOC0
WGM00
0
COM01
COM00
WGM01
CS02
CS01
0
0
0
TCCR0
CS00
1
PSR10
0
CS00
CS01
CS02
0
1
2
3
4
clk/1024
Normal
CTC
PWM, phase correct
Fast PWM
clk/256
0
1
0
1
10-bit T/C Prescaler
clk/64
0
0
1
1
Clear
clkIO
clk/8
WGM00 WGM01 Comment
5
Timer/Counter0 clock
source
T0
6
7
Example 1: write a program that waits 14 machine
cycles in Normal mode.
$100
FOC0
WGM00
COM01
COM00
WGM01
CS02
CS01
CS00
TCCR0
-$0E
OCF2
TOV2
ICF1
OCF1A
OCF1B
TOV1
OCF0
TOV0
TIFR
$F2
.INCLUDE "M32DEF.INC"
BEGIN:
AGAIN:
LDI
SBI
LDI
OUT
LDI
OUT
LDI
OUT
IN
SBRS
RJMP
LDI
OUT
LDI
OUT
EOR
OUT
RJMP
R16,0x20
DDRB = 1<<5;
DDRB,5
;PB5 as an output
PORTB &= ~(1<<5); //PB5=0
R17,0
PORTB,R17
while (1)
R20,0xF2
{
TCNT0,R20
;load timer0
R20,0x01
TCNT0 = 0xF2;
TCCR0,R20 ;Timer0,Normal mode,int clk
Question:
How to calculate
the= delay
TCCR0
0x01; generated
R20,TIFR
;read TIFR
R20,0 ;if TOV0by
isthe
settimer?
skip next inst. while((TIFR&(1<<TOV0))==0);
AGAIN
TCCR0 = 0;
R20,0x0
TCCR0,R20
;stop Timer0
Answer:
TIFR = (1<<TOV0);
R20,(1<<TOV0)
;R20 = 0x01
1) Calculate
how much a PORTB
machine
clock lasts.
= PORTB^(1<<5);
TIFR,R20
;clear TOV0 flag
T= 1/f
}
R17,R16
;toggle
D5
of
R17
2) Calculate how many machine clocks it waits.
PORTB,R17
;toggle PB5
3)
Delay
= T * number of machine cycles
BEGIN
In example 1 calculate the delay. Imagine XTAL = 10 MHz.
Solution 1 (inaccurate):
.INCLUDE "M32DEF.INC"
1) Calculating T:
T = 1/f = 1/10M = 0.1µs
2) Calculating num of
machine cycles:
$100
-$F2
$0E = 14
3) Calculating delay
14 * 0.1µs = 1.4 0µs
BEGIN:
AGAIN:
LDI
SBI
LDI
OUT
LDI
OUT
LDI
OUT
IN
SBRS
RJMP
LDI
OUT
LDI
OUT
R16,0x20
DDRB,5
;PB5 as an output
R17,0
PORTB,R17
R20,0xF2
TCNT0,R20
;load timer0
R20,0x01
TCCR0,R20 ;Timer0,Normal mode,int clk
R20,TIFR
;read TIFR
R20,0 ;if TOV0 is set skip next inst.
AGAIN
R20,0x0
TCCR0,R20
;stop Timer0
R20,0x01
TIFR,R20
;clear TOV0 flag
EOR
OUT
RJMP
R17,R16
PORTB,R17
BEGIN
;toggle D5 of R17
;toggle PB5
Accurate calculating
Other than timer, executing the instructions consumes time; so if we
want to calculate the accurate delay a program causes we should add
the delay caused by instructions to the delay caused by the timer
BEGIN:
AGAIN:
LDI
SBI
LDI
OUT
LDI
OUT
LDI
OUT
IN
SBRS
RJMP
LDI
OUT
LDI
OUT
EOR
OUT
RJMP
R16,0x20
DDRB,5
R17,0
PORTB,R17
R20,0xF2
TCNT0,R20
R20,0x01
TCCR0,R20
R20,TIFR
R20,0
AGAIN
R20,0x0
TCCR0,R20
R20,0x01
TIFR,R20
R17,R16
PORTB,R17
BEGIN
1
1
1
1
1
1/2
2
1
1
1
1
1
1
2
18
Delay caused by timer = 14 * 0.1µs = 1.4 µs
Delay caused by instructions = 18 * 0.1µs = 1.8
Total delay = 3.2 µs  wave period = 2*3.2 µs = 6.4 µs  wave frequency = 156.25 KHz
Finding values to be loaded into the timer
1. Calculate the period of clock source.
– Period = 1 / Frequency
•
E.g. For XTAL = 8 MHz  T = 1/8MHz
2. Divide the desired time delay by period of
clock.
3. Perform 256 - n, where n is the decimal value
we got in Step 2.
4. Set TCNT0 = 256 - n
•
Example 2: Assuming that XTAL = 10 MHz, write a program to generate a
square wave with a period of 10 ms on pin PORTB.3.
For a square wave with T = 10 µs we must have a time delay of 5 µs. Because XTAL = 10
MHz, the counter counts up every 0.1 µs. This means that we need 5 µs / 0.1 µs = 50
clocks. 256 - 50 = 206.
.INCLUDE "M32DEF.INC"
DDRB = 1<<3;
BEGIN:
AGAIN:
LDI
SBI
LDI
OUT
LDI
OUT
LDI
OUT
IN
SBRS
RJMP
LDI
OUT
LDI
OUT
EOR
OUT
RJMP
R16,0x08
DDRB,3
;PB3 as an output
R17,0
PORTB,R17
R20,206
TCNT0,R20
;load timer0
R20,0x01
TCCR0,R20 ;Timer0,Normal mode,int clk
R20,TIFR
;read TIFR
R20,TOV0 ;if TOV0 is set skip next
AGAIN
R20,0x0
TCCR0,R20
;stop Timer0
R20,0x01
TIFR,R20
;clear TOV0 flag
R17,R16
;toggle D3 of R17
PORTB,R17
;toggle PB3
BEGIN
PORTB &= ~ (1<<3);
while (1)
{
TCNT0 = 206;
TCCR0 = 0x01;
while((TIFR&0x01) == 0);
TCCR0 = 0;
TIFR = 1<<TOV0;
PORTB = PORTB ^ (1<<3);
}
Example 3: Modify TCNT0 in Example 2 to get the largest time delay possible with no prescaler.
Find the delay in µs. In your calculation, do not include the overhead due to instructions.
• To get the largest delay we make TCNT0 zero. This will count up
from 00 to 0xFF and then roll over to zero.
.INCLUDE "M32DEF.INC"
BEGIN:
AGAIN:
LDI
SBI
LDI
OUT
LDI
OUT
LDI
OUT
IN
SBRS
RJMP
LDI
OUT
LDI
OUT
EOR
OUT
RJMP
R16,1<<3
DDRB,3
;PB3 as an output
R17,0
PORTB,R17
R20,0x0
TCNT0,R20
;load Timer0
R20,0x01
TCCR0,R20 ;Timer0,Normal mode,int clk
R20,TIFR
;read TIFR
R20,TOV0 ;if TOV0 is set skip next
Solution
AGAIN
R20,0x0
T:
TCCR0,R201) Calculating
;stop Timer0
R20,0x01
1/10MHz
= 0.1µs
TIFR,R20 T = 1/f = ;clear
TOV0
flag
R17,R16
;toggle D3 of R17
2)
Calculating
PORTB,R17
;toggle delay
PB3
BEGIN
256 * 0.1µs = 25.6µs
DDRB = 1 << 3;
PORTB &= ~(1<<3);
while (1)
{
TCNT0 = 0x0;
TCCR0 = 0x01;
while((TIFR&(1<<TOV0))==0);
TCCR0 = 0;
TIFR = 0x01;
PORTB = PORTB^(1<<3);
}
Generating Large Delays
• Using loop
• Prescaler
• Bigger counters
Prescaler and generating a large time delay
PSR10
0
CS00
CS01
CS02
0
1
2
3
4
clk/1024
clk/256
clk/8
10-bit T/C Prescaler
clk/64
Clear
clkIO
5
Timer/Counter0 clock
source
T0
6
7
CTC (Clear Timer on Compare match) mode
TCNT0
0xFF
OCR0
0
OCR0
xx
2
1
0
TOV0 = no change
OCF0 = 1
OCF0
TOV0:
0
OCF0:
0
1
OCF0
OCF0
time
Example 4: Rewrite example 2 using CTC
Rewrite example 2 using CTC
•
FOC0
WGM00
COM01
COM00
WGM01
CS02
CS01
CS00
TCCR0
OCF2
TOV2
ICF1
OCF1A
OCF1B
TOV1
OCF0
TOV0
TIFR
For a square wave with T = 10 µs we must have a time delay of 5 µs. Because XTAL = 10
MHz, the counter counts up every 0.1 µs. This means that we need 5 µs / 0.1 µs = 50
clocks. Therefore, we have OCR0= 49.
.INCLUDE "M32DEF.INC"
LDI
R16,0x08
SBI
DDRB,3
;PB3 as an output
LDI
R17,0
OUT
PORTB,R17
LDI
R20,49
OUT
OCR0,R20 ;load timer0
BEGIN:
LDI
R20,0x09
OUT
TCCR0,R20 ;Timer0,CTC mode,int clk
AGAIN:
IN
R20,TIFR
;read TIFR
SBRS
R20,OCF0 ;if OCF0 is set skip next
RJMP
AGAIN
LDI
R20,0x0
OUT
TCCR0,R20
;stop Timer0
LDI
R20,0x02
OUT
TIFR,R20
;clear TOV0 flag
EOR
R17,R16
;toggle D3 of R17
OUT
PORTB,R17
;toggle PB3
RJMP
BEGIN
DDRB |= 1<<3;
PORTB &= ~(1<<3);
while (1)
{
OCR0 = 49;
TCCR0 = 0x09;
while((TIFR&(1<<OCF0))==0);
TCCR0 = 0; //stop timer0
TIFR = 0x02;
PORTB.3 = ~PORTB.3;
}
Timer2
• Timer0
TOV0
• Timer2
TCCR0
TCCR2
TCNT0
TCNT2
=
TOV2
OCF0
OCR0
OCF2
TOV2
=
OCF2
OCR2
ICF1
OCF1A
OCF1B
TOV1
OCF0
TOV0
TIFR
The difference between Timer0 and Timer2
• Timer0
• Timer2
CS02 CS01 CS00 Comment
0
0
0
0
1
1
1
1
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
Timer/Counter stopped
clk (No Prescaling)
clk / 8
clk / 64
clk / 256
clk / 1024
External clock (falling edge)
External clock (rising edge)
CS22 CS21 CS20 Comment
0
0
0
0
1
1
1
1
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
Timer/Counter stopped
clk (No Prescaling)
clk / 8
clk / 32
clk / 64
clk / 128
clk / 256
clk / 1024
Timer 1
OCR1BH
OCR1BL
=
TCCR1A
TCNT1H TCNT1L
TCCR1B
TOV1
OCF2
TOV2
ICF1
OCF1A
OCF1B
TOV1
OCF0
TOV0
OCF1B
=
OCF1A
TIFR
OCR1AH
OCR1AL
COM1A1
COM1A0
COM1B1
COM1B0
FOC1A
FOC1B
WGM11
WGM10
TCCR1A
ICNC1
ICES1
-
WGM13
WGM12
CS12
CS11
CS10
TCCR1B
Clock Selector (CS)
CS12 CS11 CS10 Comment
CS10
CS11
CS12
0
1
2
3
4
clk/1024
No clock source (Timer/Counter stopped)
PSR10
clk (No Prescaling)
Clear
clk / 8
clkIO
10-bit T/C Prescaler
clk / 64
clk / 256
clk / 1024
T1
External clock source on T0 pin. Clock on falling edge
External clock source on0T0 pin. Clock on rising edge
clk/256
0
1
0
1
0
1
0
1
clk/64
0
0
1
1
0
0
1
1
clk/8
0
0
0
0
1
1
1
1
5
Timer/Counter1 clock
source
6
7
Assuming XTAL = 10 MHz write a program that toggles
PB5 once per millisecond, using Normal mode.
.INCLUDE "M32DEF.INC"
XTAL
MHz  1/10;init
MHz
= 0.1
µs
LDI = 10
R16,HIGH(RAMEND)
stack
pointer
OUT
SPH,R16
Num.
machine cycles = 1 ms / 0.1 µs = 10,000
LDI ofR16,LOW(RAMEND)
OUT
SPL,R16
TCNT1
=
65,536 – 10,000
SBI
DDRB,5
;PB5=as55,536
an output= $D8F0
BEGIN:SBI
RCALL
CBI
RCALL
RJMP
PORTB,5
DELAY_1ms
PORTB,5
DELAY_1ms
BEGIN
DELAY_1ms:
LDI
R20,0xD8
R20,HIGH(-10000)
OUT
TCNT1H,R20
LDI
R20,0xF0
R20,
,LOW(-10000)
OUT
TCNT1L,R20
LDI
R20,0x0
OUT
TCCR1A,R20
LDI
R20,0x1
OUT
TCCR1B,R20
AGAIN:IN R20,TIFR
SBRS R20,TOV1
RJMP AGAIN
LDI
R20,1<<TOV1
OUT
TIFR,R20
LDI
R19,0
OUT
TCCR1B,R19
OUT
TCCR1A,R19
RET
;PB5 = 1
;PB5 = 0
TCNT1H
TCNT1L
;TEMP = 0xD8
;TCNT1L overflows
= 0xF0, TCNT1H
TEMP machine cycles
;Timer1
after =10000
;WGM11:10=00
;WGM13:12=00,CS=CLK
;read TIFR
;if OCF1A is set skip next instruction
;clear TOV1 flag
;stop timer
;
TEMP register
Data bus (8-bit)
TEMP (8-bit)
OCR1xH (8-bit)
OCR1xL (8-bit)
OCR1x (16-bit Register)
OCR1xH buf.
OCR1xL buf.
TCNT1H (8-bit)
TCNT1L (8-bit)
TCNT1 (16-bit Counter)
Note: OCR1x is OCR1A or OCR1B
OCR1x buffer (16-bit Register)
LDI
R20,0xF3
IN R20,TCNT1L
OUT
TCNT1H,R20
IN R21,TCNT1H
LDI
R20,0x53
OUT
TCNT1L,R20
a = TCNT1L;
TCNT1H
= 0xF3;
b = TCNT1H;
TCNT1L
= 0x53;
Assuming XTAL = 10 MHz write a program that toggles
PB5 once per millisecond, using CTC mode.
.INCLUDE "M32DEF.INC"
LDI
R16,HIGH(RAMEND)
OUT
SPH,R16
LDI
R16,LOW(RAMEND)
OUT
SPL,R16
SBI
DDRB,5
BEGIN:SBI
PORTB,5
RCALL
DELAY_1ms
CBI
PORTB,5
RCALL
DELAY_1ms
RJMP
BEGIN
DELAY_1ms:
LDI
OUT
OUT
LDI
OUT
LDI
OUT
LDI
OUT
LDI
OUT
AGAIN:
IN
SBRS
RJMP
LDI
OUT
LDI
OUT
OUT
RET
R20,0x00
TCNT1H,R20
TCNT1L,R20
R20,0x27
OCR1AH,R20
R20,0x0F
OCR1AL,R20
R20,0x3
TCCR1A,R20
R20,0x19
TCCR1B,R20
R20,TIFR
R20,OCF1A
AGAIN
R20,1<<OCF1A
TIFR,R20
R19,0
TCCR1B,R19
TCCR1A,R19
;PB5 as an output
;PB5 = 1
;PB5 = 0
;TEMP = 0
;TCNT1L = 0, TCNT1H = TEMP
;TEMP = 0x27
;OCR1AL = 0x0F, OCR1AH = TEMP
;WGM11:10=11
;WGM13:12=11,CS=CLK
;read TIFR
;if OCF1A is set skip next instruction
;clear OCF1A flag
;stop timer
;
Counting
Counting
0
CS00
CS01
CS02
0
1
2
3
4
clk/1024
clk/8
10-bit T/C Prescaler
clk/256
Clear
clkIO
clk/64
PSR10
5
7
6
7
T0
Timer/Counter0 clock
source
6
T0
Example Assuming that clock pulses are fed into pin T0, write a program for counter 0
in normal mode to count the pulses on falling edge and display the state of the TCNT0
count on PORTC.
PSR10
;counter, falling edge
0
CS00
CS01
CS02
;PORTC = TCNT0
1
2
3
4
5
Timer/Counter0 clock
source
;keep doing it
WGM01
;keepCS02
doingCS01
it
0
clk/1024
;make PORTC output
clk/256
;make T0 (PB0) input
10-bit T/C Prescaler
clk/64
Clear
clkIO
clk/8
.INCLUDE "M32DEF.INC"
CBI DDRB,0
LDI R20,0xFF
OUT DDRC,R20
LDI R20,0x06
OUT TCCR0,R20
AGAIN:
IN
R20,TCNT0
OUT PORTC,R20
IN
R16,TIFR
SBRS R16,TOV0
RJMP AGAIN
LDI R16,1<<TOV0
OUT TIFR, R16
FOC0RJMP
WGM00
COM01 COM00
AGAIN
CS00
TCCR0
T0
6
7
Assuming that clock pulses are fed into pin T1. Write a program for counter 1 in CTC
mode to make PORTC.0 high every 100 pulses.
.INCLUDE "M32DEF.INC"
CBI
DDRB,1
;make T1 (PB1) input
SBI
DDRC,0
;PC0 as an output
R20,0x0
TCCR1A,R20
R20,0x0E
TCCR1B,R20
;CTC, counter, falling edge
LDI
OUT
LDI
OUT
AGAIN:
LDI
OUT
LDI
OUT
L1: IN
SBRS
RJMP
LDI
OUT
SBI
CBI
RJMP
R20,0
OCR1AH,R20
R20,99
OCR1AL,R20
R20,TIFR
R20,OCF1A
L1
R20,1<<OCF1A
TIFR, R20
PORTC,0
PORTC,0
AGAIN
;TEMP = 0
;ORC1L = R20, OCR1H = TEMP
;keep doing it
;clear OCF1A flag
;PC0 = 1
;PC0 = 0
;keep doing it