0% found this document useful (0 votes)
49 views35 pages

9 TimerCounter v2

1. Calculate the timer value for a 5 ms delay using a 10 MHz clock: 5 ms / 0.1 us per clock = 50,000 clocks. Subtract from 256 to get 206. 2. Load 206 into TCNT0 and start the timer in normal mode with an internal clock source. 3. Toggle PORTB.3 when the overflow flag is set and restart the timer to generate the 10 ms square wave.

Uploaded by

Ulises Rosa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views35 pages

9 TimerCounter v2

1. Calculate the timer value for a 5 ms delay using a 10 MHz clock: 5 ms / 0.1 us per clock = 50,000 clocks. Subtract from 256 to get 206. 2. Load 206 into TCNT0 and start the timer in normal mode with an internal clock source. 3. Toggle PORTB.3 when the overflow flag is set and restart the timer to generate the 10 ms square wave.

Uploaded by

Ulises Rosa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd

Timer/counter

Sepehr Naimi

www.NicerLand.com
A counter register

2
A simple design (counting people)
First design

Sensor

3
A simple design (counting people)
Second design

Sensor

4
A simple design (making delay)

5
A generic timer/counter
 Delay generating
 Counting
 Wave-form generating
 Capturing

6
Timers in AVR
 1 to 6 timers
 3 timers in ATmega328
 8-bit and 16-bit timers
 two 8-bit timers and one 16-bit timer in ATmega328

7
Timer in AVR
 TCNTn (Timer/Counter register)

 TOVn (Timer Overflow flag)

 TCCRn (Timer Counter control register)

 OCRn (output compare register) TCCRn


 OCFn (output compare match flag)
TCNTn OCRn

TOVn
=
Comment:
All of the timer registers are
byte-addressable registers OCFn

8
Timer 0 (an 8-bit timer)
Timer 0
TCCR0A TCCR0B

OCR0A TCNT0 OCR0B

TOV0

= =

OCF0A OCF0B

10
Timer Clock
Mode Selector
(WGM) (CS)

CS02
WGM02CS01 Comment
CS00 WGM00
WGM01 Comment
00 00 0 0Normal
No clock source (Timer/Counter stopped)
00 00 1 1Phaseclkcorrect
(No Prescaling)
PWM
00 11 0 0CTCclk / 8 Timer on Compare Match)
(Clear
00 11 1 1Fast clk
PWM / 64
11 00 0 0Reserved
clk / 256
11 00 1 1Phaseclkcorrect
/ 1024 PWM
11 11 0 0Reserved
External clock source on T0 pin. Clock on falling edge
11 11 1 1Fast External
PWM clock source on T0 pin. Clock on rising edge

11
Normal mode
TCNT0

0xFF
TOV TOV TOV
0 time

FF
FE TOV0: 0
1

2
1
0 TOV0 = 1
12
Example 1: Write a program that waits 14 machine
cycles in Normal mode.
14 = $0E
$100
-$0E
$F2
$F2

0 0 TCCR0A = 0x00;
TCCR0B = 0x03;
0 0 0 1
Timer Mode (WGM)
WGM02 WGM01 WGM00 Comment
0 0 0 Normal
0 0 1 Phase correct PWM
0 1 0 CTC
0 1 1 Fast PWM
1 0 0 Reserved
1 0 1 Phase correct PWM
1 1 0 Reserved
1 1 1 Fast PWM
13
Example 1: Write a program that waits 14 machine
cycles in Normal mode.
$100
-$0E
$F2
LDI R16,(1<<5) ;R16=0x20
DDRB = 1<<5;
SBI DDRB,5 ;PB5 as an output
LDI R17,0 PORTB &= ~(1<<5); //PB5=0
OUT PORTB,R17 while (1)
BEGIN: LDI R20,0xF2
OUT TCNT0,R20 Question:
;load timer0 How to calculate the{delay generated
LDI R20,0x0
OUT TCCR0A,R20
by the timer? TCNT0 = 0xF2;

LDI R20,0x01 TCCR0A = 0x00;

Answer:
OUT TCCR0B,R20 ;Normal mode, inter. clk TCCR0B = 0x01;
AGAIN: SBIS TIFR0,TOV0 ;if TOV0 is set skip next
RJMP AGAIN 1) Calculate how much a machinewhile((TIFR0&(1<<TOV0))==0)
clock lasts.
LDI R20,0x0 T= 1/f {}
OUT TCCR0B,R20 ;stop Timer0
LDI R20,(1<<TOV0) Calculate
2) how many machine clocks it waits.
TCCR0B = 0;
;R20 = 0x01
OUT TIFR0,R20 3);clear
DelayTOV0 * number of machineTIFR0
= Tflag = (1<<TOV0);
cycles
PORTB ^= (1<<5);
EOR R17,R16 ;toggle D5 of R17
}
OUT PORTB,R17 ;toggle PB5
RJMP BEGIN

14
In example 1 calculate the delay.
XTAL = 10 MHz.

Solution 1 (inaccurate):
LDI R16,0x20
1) Calculating T: SBI DDRB,5 ;PB5 as an output
LDI R17,0
T = 1/f = 1/10M = 0.1µs OUT PORTB,R17
2) Calculating num of BEGIN: LDI R20,0xF2
OUT TCNT0,R20 ;load timer0
machine cycles: LDI R20,0x0
$100 OUT TCCR0A,R20
LDI R20,0x01
-$F2 OUT TCCR0B,R20 ;Normal mode, inter. clk
AGAIN: SBIS TIFR0,TOV0 ;if TOV0 is set skip next
$0E = 14 RJMP AGAIN
3) Calculating delay LDI R20,0x0
OUT TCCR0B,R20 ;stop Timer0
14 * 0.1µs = 1.4 0µs LDI R20,(1<<TOV0) ;R20 = 0x01
OUT TIFR0,R20 ;clear TOV0 flag

EOR R17,R16 ;toggle D5 of R17


OUT PORTB,R17 ;toggle PB5
RJMP BEGIN
15
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
LDI R16,0x20
SBI DDRB,5
LDI R17,0
OUT PORTB,R17
BEGIN: LDI R20,0xF2 1
OUT TCNT0,R20 1
LDI R20,0x00 1
OUT TCCR0A,R20 1
LDI R20,0x01 1
OUT TCCR0B,R20 1
AGAIN: SBIS TIFR0,TOV0 1/2
RJMP AGAIN 2
LDI R20,0x0 1
OUT TCCR0B,R20 1
LDI R20,0x01 1
OUT TIFR0,R20 1
EOR R17,R16 1
OUT PORTB,R17 1
RJMP BEGIN 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

16
Finding values to be loaded into the timer
1. Calculate the period of clock source.
 Period = 1 / Frequency
 E.g. For XTAL = 16 MHz  T = 1/16MHz
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

17
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.
LDI R16,(1<<5) ;R16=0x20 DDRB = 1<<3;
SBI DDRB,5 ;PB5 as an output
PORTB &= ~ (1<<3);
LDI R17,0
OUT PORTB,R17 while (1)
BEGIN: LDI R20,206 {
OUT TCNT0,R20 ;load timer0
LDI R20,0x0 TCNT0 = 206;
OUT TCCR0A,R20 TCCR0A = 0x00;
LDI R20,0x01
TCCR0B = 0x01;
OUT TCCR0B,R20 ;Normal mode, int. clk
AGAIN: SBIS TIFR0,TOV0 ;if TOV0 set skip next while((TIFR0&0x01) == 0)
RJMP AGAIN {}
LDI R20,0x0
OUT TCCR0B,R20 ;stop Timer0 TCCR0B = 0;
LDI R20,(1<<TOV0) ;R20 = 0x01 TIFR0 = 1<<TOV0;
OUT TIFR0,R20 ;clear TOV0 flag
PORTB = PORTB ^ (1<<3);
EOR R17,R16 ;toggle D5 of R17 }
OUT PORTB,R17 ;toggle PB5
RJMP BEGIN

18
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.
LDI R16,(1<<5) ;R16=0x20
SBI DDRB,5 ;PB5 as an output
DDRB = 1 << 3;
LDI R17,0
OUT PORTB,R17 PORTB &= ~(1<<3);
BEGIN: LDI R20,0 while (1)
OUT TCNT0,R20 ;load timer0
LDI R20,0x0 {
OUT TCCR0A,R20 TCNT0 = 0x00;
LDI R20,0x01
OUT TCCR0B,R20 ;Normal mode, int. clk TCCR0A = 0x00;
AGAIN: SBIS TIFR0,TOV0 ;if TOV0 set skip next TCCR0B = 0x01;
RJMP AGAIN
LDI R20,0x0 Solution
while((TIFR0&(1<<TOV0))==0)
OUT TCCR0B,R20 ;stop1)Timer0
Calculating T: {}
LDI R20,(1<<TOV0) ;R20 = 0x01
OUT TIFR0,R20 T =TOV0
;clear 1/f =flag
1/10MHz = 0.1µs TCCR0B = 0;
TIFR0 = 0x01;
EOR R17,R16 ;toggle2)
D5 Calculating
of R17 delay
OUT PORTB,R17 ;toggle PB5256 * 0.1µs PORTB = PORTB^(1<<3);
= 25.6µs
RJMP BEGIN }

19
Generating Large Delays
 Using loop
 Prescaler
 Bigger counters

20
Prescaler and generating a large time delay

21
CTC (Clear Timer on Compare match) mode
TCNT0
0xFF
OCR0

OCF0 OCF0 OCF0


0 time

OCR0 0
xx TOV0:

2 0
1
OCF0:
1
TOV0 = no change
0
OCF0 = 1
22
CTC mode (Cont.)
1 0

0
Timer Mode (WGM)
WGM02 WGM01 WGM00 Comment
0 0 0 Normal
0 0 1 Phase correct PWM
0 1 0 CTC
0 1 1 Fast PWM
1 0 0 Reserved
1 0 1 Phase correct PWM
1 1 0 Reserved
1 1 1 Fast PWM

23
Rewrite example 2 using CTC
Example 4: Rewrite example 2 using CTC
(Assuming XTAL = 10MHz, write a program to generate a square wave with a period of 10 ms.)

 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 OCR0A= 49.
LDI R16,(1<<3) ;R16 = 0x08 DDRB |= 1<<3;
SBI DDRB,3 ;PB3 as an output
while (1)
LDI R17,0
OUT PORTB,R17 {
LDI R20,49 OCR0A = 49;
OUT OCR0A,R20 ;load OCR0A
BEGIN: LDI R20,(1<<WGM01) ;TCCR0A=0x02 TCCR0A = (1<<WGM01); //CTC
OUT TCCR0A,R20 ;CTC mode, int. clk TCCR0B = 1; //N = 1
LDI R20,1 ; TCCR0B = 1
while((TIFR0&(1<<OCF0A))==0)
OUT TCCR0B,R20 ; N = 1
AGAIN: SBIS TIFR0,OCF0A ;if OCF0 is set skip next { }
RJMP AGAIN TCCR0B = 0; //stop timer0
LDI R20,0x0
OUT TCCR0B,R20 ;stop Timer0 TIFR0 = 1<<OCF0A;
LDI R20,1<<OCF0A PORTB ^= 1<<3; //toggle PB3
OUT TIFR0,R20 ;clear OCF0A flag
EOR R17,R16 ;toggle D3 of R17 }
OUT PORTB,R17 ;toggle PB3
RJMP BEGIN
24
Timer2 vs. Timer0
 Timer0
Timer2
TCCR0A TCCR0B TCCR2A TCCR2B

OCR0A TCNT0 OCR0B OCR2A TCNT2 OCR2B

TOV0 TOV2

= = = =

OCF0A OCF0B OCF2A OCF2B

25
The difference between Timer0 and Timer2
 Timer0  Timer2

CS02 CS01 CS00 Comment CS22 CS21 CS20 Comment


0 0 0 Timer/Counter stopped 0 0 0 Timer/Counter stopped
0 0 1 clk (No Prescaling) 0 0 1 clk (No Prescaling)
0 1 0 clk / 8 0 1 0 clk / 8
0 1 1 clk / 64 0 1 1 clk / 32
1 0 0 clk / 256 1 0 0 clk / 64
1 0 1 clk / 1024 1 0 1 clk / 128
1 1 0 External clock (falling edge) 1 1 0 clk / 256
1 1 1 External clock (rising edge) 1 1 1 clk / 1024

26
Timer 1
TCCR1A TCCR1B TCCR1C

OCR1AH OCR1AL TCNT1H TCNT1L OCR1BH OCR1BL

TOV1

= =

OCF1A OCF1B

27
Clock Selector (CS)

CS12 CS11 CS10 Comment


0 0 0 No clock source (Timer/Counter stopped)
0 0 1 clk (No Prescaling)
0 1 0 clk / 8
0 1 1 clk / 64
1 0 0 clk / 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

28
Assuming XTAL = 10 MHz write a program that toggles
PB5 once per millisecond, using Normal mode.
XTALOUT = 10 MHz  1/10
LDI R16,HIGH(RAMEND)
SPH,R16 MHz = 0.1 µs
;init stack pointer

Num.OUT of machine cycles = 1 ms / 0.1 µs = 10,000


LDI R16,LOW(RAMEND)
SPL,R16
TCNT1
BEGIN:SBI = PORTB,5
SBI DDRB,5
65,536;PB5 – 10,000
;PB5 = 1 = 55,536 = $D8F0
as an output

RCALL DELAY_1ms
CBI PORTB,5 ;PB5 = 0
RCALL DELAY_1ms
RJMP BEGIN TCNT1H TCNT1L
DELAY_1ms:
LDI R20,0xD8
LDI R20,HIGH(-10000)
STS TCNT1H,R20 ;TEMP = 0xD8
STS TCNT1H,R20
LDI R20,0xF0
LDI R20, ,LOW(-10000)
STS TCNT1L,R20 ;TCNT1L = 0xF0, TCNT1H = TEMP
STS TCNT1L,R20 ;Timer1 overflows after 10000 machine cycles
LDI R20,0x0
STS TCCR1A,R20 ;WGM11:10=00
LDI R20,0x1
STS TCCR1B,R20 ;WGM13:12=00,CS=CLK
AGAIN:SBIS TIFR1,TOV1 ;if TOV1 is set skip next instruction
RJMP AGAIN
LDI R20,1<<TOV1
OUT TIFR1,R20 ;clear TOV1 flag
LDI R19,0
STS TCCR1B,R19 ;stop timer
STS TCCR1A,R19 ;
RET

29
TEMP register

LDI
LDS R20,0xF3
R20,TCNT1L
TCNT1H
a = TCNT1L;
= 0xF3;
STS
LDS TCNT1H,R20
R21,TCNT1H
TCNT1L
b = TCNT1H;
= 0x53;
LDI R20,0x53
STS TCNT1L,R20

30
Assuming XTAL = 10 MHz, write a program that toggles
PB5 once per millisecond, using CTC mode.
LDI R16,HIGH(RAMEND) #include <avr/io.h>
OUT SPH,R16
LDI R16,LOW(RAMEND) void delay1ms();
OUT SPL,R16
int main(){
SBI DDRB,5 ;PB5 as an output
BEGIN:SBI PORTB,5 ;PB5 = 1 DDRB |= 1<<5;
RCALL DELAY_1ms
while (1) {
CBI PORTB,5 ;PB5 = 0
RCALL DELAY_1ms delay1ms();
RJMP BEGIN
PORTB ^= (1<<5); //toggle PB5
DELAY_1ms:
LDI R20,0x00 }
STS TCNT1H,R20 ;TEMP = 0
}
STS TCNT1L,R20 ;TCNT1L = 0, TCNT1H = TEMP
void delay1ms()
LDI R20,0x27
STS OCR1AH,R20 ;TEMP = 0x27 {
LDI R20,0x0F
STS OCR1AL,R20 ;OCR1AL = 0x0F, OCR1AH = TEMP TCNT1 = 0;

LDI R20,0x00
OCR1A = 10000-1;
STS TCCR1A,R20 ;WGM11:10=00 TCCR1A = 0; //WGM=0100 (CTC)
LDI R20,0x09
STS TCCR1B,R20 ;WGM13:12=01,CS=CLK TCCR1B = 0x09; //N = 1
AGAIN:
SBIS TIFR1,OCF1A ;if OCF1A is set skip next instruction while((TIFR1&(1<<OCF1A))==0)
RJMP AGAIN
LDI R19,0
{ } //wait until OCF1A is set
STS TCCR1B,R19 ;stop timer TCCR1B = 0; //stop timer1
STS TCCR1A,R19 ;
LDI R20,1<<OCF1A TIFR1 = 1<<OCF1A;//clear flag
OUT TIFR1,R20 ;clear OCF1A flag
RET }

31
Counting
Counting

T0

7
33
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.
#include <avr/io.h>
CBI DDRD,4 ;make T0 (PD4) input int main()
LDI R20,0xFF {
OUT DDRC,R20 ;make PORTC output
DDRC = 0xFF;
LDI R20,0x00
OUT TCCR0A,R20 TCCR0A = 0; //WGM=0000 (Normal)
LDI R20,0x06 TCCR0B = 0x06; //CS=6 (Count on fall)
OUT TCCR0B,R20 ;counter, falling edge while (1)
AGAIN:
IN R20,TCNT0 {
OUT PORTC,R20 ;PORTC = TCNT0 PORTC = TCNT0; //read TCNT0
RJMP AGAIN ;keep doing it }
}

34
Assuming that clock pulses are fed into pin T1. Write a program for Counter1 in CTC
mode to make PORTC.0 high every 100 pulses.
CBI DDRD,5 ;make T1 (PD5) input #include <avr/io.h>
SBI DDRC,0 ;PC0 as an output
int main()
LDI R20,0x00 {
OUT TCCR1A,R20 DDRD &= ~(1<<5);
LDI R20,0x0E ;CS=6 (falling edge counter)
DDRC |= 1<<0;
OUT TCCR1B,R20 ;CTC
AGAIN: TCCR1A = 0; //WGM=0100 (CTC)
LDI R20,0 TCCR1B = 0x0E; //CS=6 (Count on fall)
OUT OCR1AH,R20 ;TEMP = 0
OCR1A = 99;
LDI R20,99
OUT OCR1AL,R20 ;ORC1L = R20, OCR1H = TEMP while (1)
L1: {
SBRS TIFR1,OCF1A
RJMP L1 ;keep doing it while((TIFR1&(1<<OCF1A)) == 0);
LDI R20,1<<OCF1A ;clear OCF1A flag TIFR1 = (1<<OCF1A);
OUT TIFR1, R20 PORTC |= (1<<0); //PC0 = 1

SBI PORTC,0 ;PC0 = 1 PORTC &= ~(1<<0); //PC0 = 0


CBI PORTC,0 ;PC0 = 0 }
RJMP AGAIN ;keep doing it }

35

You might also like