IT343 Lecture 05
IT343 Lecture 05
In AVR
Lecture 5
A generic timer/counter
Delay Generating - 1
Oscillator 0
◼ COUT
Counter register
External 1
source
Flag
Counter/Timer
• 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. As a result, the content of the counter register represents how
many ticks have occurred from the time we have cleared the counter. Since
the speed of the oscillator in a microcontroller is known, we can calculate the
tick period, and from the content of the counter register we will know how
much time has elapsed. So, one way to generate a time delay is to clear
(reset) the counter at the start time and wait until the counter reaches a
certain number.
• In the microcontrollers, 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.
3
A generic timer/counter (Cont..2)
Counting
Oscillator 0
◼ COUT
Counter register
External 1
source
Flag
Counter/Timer
• Many applications need to count an event. So, there are counter registers in
microcontrollers for this purpose. 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.
4
Timers in AVR
◼ 1 to 6 timers: referred to as Timers 0, 1, 2, 3, 4, and 5
◼ 3 timers (Timer0, Timer1, and Timer2) in ATmega328
5
Timer in AVR (Cont..1)
◼ Every timer needs a clock pulse to tick.
Oscillator
Counter register
External
source
Flag
Counter/Timer
6
Timer in AVR (Cont..2)
For each of the timers, there is basic:
◼ TCNTn (Timer/Counter register)
TOVn
=
Comment:
All of the timer registers are
byte-addressable registers OCFn
7
Timer in AVR (Cont..3)
◼ TCNTn (Timer/Counter) register
➢ Upon reset, it contains zero.
➢ It counts up with each pulse.
➢ The contents of the timers/counters can be accessed using it.
➢ Can load a value into it or read its value.
9
Timer 0 (an 8-bit timer)
Timer 0
◼ Timer0 is 8-bit in ATmega32; thus, TCNT0 is 8-bit as shown
12
Timer 0 (Cont..2)
◼ TCCR0 is an 8-bit register used for control of Timer0.
13
Timer 0 (Cont..3)
◼ Normal Mode
I. The content of the timer/counter TCNT0
2
1
0 TOV0 = 1
14
Timer 0 (Cont..4)
◼ TIFR (Timer/counter Interrupt Flag Register)
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 1: Write a program that waits 14 machine
cycles in Normal mode
$100
- - - - - OCF0B OCF0A TOV0 TIFR0
-$0E
$F2
DDRB = 1<<5; calculate the delay, if
PORTB &= ~(1<<5); //PB5=0 XTAL = 10 MHz.
while (1) Solution:
{
1) Calculating T:
TCNT0 = 0xF2;
T = 1/f = 1/10M = 0.1µs
TCCR0A = 0x00;
TCCR0B = 0x01; 2) Calculating num of
while((TIFR0&(1<<TOV0))==0) machine cycles:
{} $100
TCCR0B = 0; -$F2
TIFR0 = (1<<TOV0);
$0E = 14
PORTB ^= (1<<5);
} 3) Calculating delay
PORTB=PORTB ^ 0b00100000 14 * 0.1µs = 1.4 µs
18
Example 2: Assuming that XTAL = 10 MHz, write a program to generate a
square wave with a period of 10 µs on pin PORTB.3.
◼ For a square wave with T = 10 µs we must have
a time delay of 5 µs.
19
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.
20
21
Generating Large Delays
◼ Using loop
◼ Prescaler
◼ Bigger counters
22
Prescaler and generating a large time delay
PSR10
Clear
clkIO 10-bit T/C Prescaler
clk/8
clk/64
clk/256
clk/1024
T0
0
CS00 0 1 2 3 4 5 6 7
CS01
CS02
Timer/Counter0 clock
source
23
CTC (Clear Timer on Compare match) mode
TCNT0
0xFF
OCR0
OCR0 0
xx TOV0:
2 0
1
OCF0:
1
TOV0 = no change
0
OCF0 = 1
24
CTC mode (Cont.)
COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00 TCCR0A
1 0
FOC0A FOC0B - - WGM02 CS02 CS01 CS00 TCCR0B
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
25
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.)
26
The difference between Timer0 and Timer2
◼ Timer0 ◼ Timer2
27
Counting
Counting
PSR10
Clear
clkIO 10-bit T/C Prescaler
clk/8
clk/64
clk/256
clk/1024
T0
0
CS00 0 1 2 3 4 5 6 7
CS01
CS02 28 pin
(PCINT14/RESET) PC6 1 28 PC5 (ADC5/SCL/PCINT13)
(PCINT16/RXD) PD0 2 27 PC4 (ADC4/SDA/PCINT12)
Timer/Counter0 clock
(PCINT17/TXD) PD1 3 26 PC3 (ADC3/PCINT11)
source
(PCINT18/INT0) PD2 4 MEGA328 25 PC2 (ADC2/PCINT10)
(PCINT19/OC2B/INT1) PD3 5 24 PC1 (ADC1/PCINT9)
T0 PD4
(PCINT20/XCK/T0) 6 23 PC0 (ADC0/PCINT8)
VCC 7 22 GND
GND 8 21 AREF
(PCINT6/XTAL1/TOSC1) PB6 9 20 AVCC
6 (PCINT7/XTAL2/TOSC2) PB7 10 19 PB5 (SCK/PCINT5)
(PCINT21/OC0B) PD5 11 18 PB4 (MISO/PCINT4)
(PCINT22/OC0A/AIN0) PD6 12 17 PB3 (MOSI/OC2A/PCINT3)
(PCINT23/AIN1) PD7 13 16 PB2 (SS/OC1B/PCINT2)
7 (PCINT0/CLKO/ICP1) PB0 14 15 PB1 (OC1A/PCINT1)
29
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
LDI R20,0x00 DDRC = 0xFF;
OUT TCCR0A,R20 TCCR0A = 0; //WGM=0000 (Normal)
LDI R20,0x06
TCCR0B = 0x06; //CS=6 (Count on fall)
OUT TCCR0B,R20 ;counter, falling edge
AGAIN: while (1)
IN R20,TCNT0 {
OUT PORTC,R20 ;PORTC = TCNT0 PORTC = TCNT0; //read TCNT0
RJMP AGAIN ;keep doing it
}
}
PSR10
Clear
clkIO 10-bit T/C Prescaler
clk/8
clk/64
clk/256
clk/1024
CS00 0 1 2 3 4 5 6 7
CS01
CS02
Timer/Counter0 clock
source
30
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)
OUT TCCR1B,R20 ;CTC DDRC |= 1<<0;
AGAIN: TCCR1A = 0; //WGM=0100 (CTC)
LDI R20,0
TCCR1B = 0x0E; //CS=6 (Count on fall)
OUT OCR1AH,R20 ;TEMP = 0
LDI R20,99 OCR1A = 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
}
31
32
The End
QUESTIONS?
33