Week 9
Week 9
16-bit
1. Timer/Counter 2. Timer/Counter
0
1
3. Timer/Counter 4. Timer/Counter
2
3
5. Timer/Counter
4
Counter:
Basic steps for Counter Register in counting an event:
Connect External Event Source to the associated Clock Pin of counter register
When event occurs externally, the contents of counter register is incremented
Timers:
Basic steps for Counter Register in generating time delays:
Connect the Oscillator (Internal Oscillator) to the Clock Pin of the Counter
When the oscillator ticks, the content of the counter register is incremented
the content of the counter register represents, how many ticks have occurred
Since Crystal Frequency is known, calculate the tick period.
Multiply tick period with the content of the counter register
Mode of Operation-1 (Normal Mode)
Mode of Operation-2 (CTC Mode)
Load the counter register
Clear the counter register
Wait until the counter register overflows
Wait until the counter reaches a number
And the flag is SET
And the flag is SET
Example:
Example:
Consider Oscillator Frequency = 1 MHz with 8-bit register.
Then, content of counter register increment 1/1MHz = 1s.
So, if we want a time delay of 3s:
Load the counter register with 0xFD
Wait until flag is set after 3 ticks b/c of overflow
Flag should be cleared by the software (programmer)
With First Tick, content of register increment to 0xFE, Second
Tick: 0xFF, Third Tick: Overflow (0x00) and flag is SET
Programming of Timers:
Every timer needs a Clock Pulse to Tick. Clock Source can be internal or External.
Internal Clock Source
= Timers
External Clock Source on AVR pins = Counter
[Do by yourself]
Timer/Counter2, Timer/Counter3, Timer/Counter4, Timer/Counter5
8-bit Timer/Counter0
8-bit Registers
TCCRnx, TCNTn,
OCRnx, TIFRn,
TIMSKn
Write a program to toggle all the bits of PORTK continuously with some delay. Use Timer0,
Normal mode, and no prescaler option to generate delay.
#include <avr/io.h>
void fordelay()
{
TCNT0 = 0x20;
// load TCNT0
TCCR0A = 0x00;
// Timer0
TCCR0B = 0x01;
// Normal Mode, No prescaler
while((TIFR0 & 0x1) == 0); // wait for TOV0 to roll over
TCCR0B = 0x00;
// stop the clock source
TIFR0 = 0x1;
// clear TOV0
}
int main (void)
{
DDRK = 0xFF;
// OUTPUT
while(1)
{
PORTK = 0xFF;
fordelay();
PORTK = 0x00;
fordelay();
}
return
0;
}
The Timer/Counter Register gives direct access, both for read and write operations, to the Timer/Counter unit 8-bit counter. Writing
to the TCNT0 Register blocks (removes) the Compare Match on the following timer clock. Modifying the counter (TCNT0) while
the counter is running, introduces a risk of missing a Compare Match between TCNT0 and the OCR0x Registers.
The Output Compare Register A contains an 8-bit value that is continuously compared with the counter value (TCNT0). A match
can be used to generate an Output Compare interrupt, or to generate a waveform output on the OC0A pin.
The Output Compare Register B contains an 8-bit value that is continuously compared with the counter value (TCNT0). A match
can be used to generate an Output Compare interrupt, or to generate a waveform output on the OC0B pin.
Calculate the amount of delay generated by the timer. Assume crystal frequency 16MHz.
Counter Delay = Number of Counts (Ticks) * Period of each Clock
void fordelay()
{
TCNT0 = 0xF2;
// load TCNT0
TCCR0A = 0x00;
// Timer0, Normal Mode
TCCR0B = 0x01;
// No prescaler
while((TIFR0 & 0x1) == 0); // wait for TOV0 to roll over
TCCR0B = 0x00;
// stop the clock source
TIFR0 = 0x1;
// clear TOV0
}
Write a program to toggle all the bits of PORTK continuously with some delay. Use Timer0,
Normal mode, and no prescaler option to generate delay.
#include <avr/io.h>
void fordelay()
{
TCNT0 = 0x20;
// load TCNT0
TCCR0A = 0x00;
// Timer0, Normal Mode
TCCR0B = 0x01;
// No prescaler
while((TIFR0 & 0x1) == 0); // wait for TOV0 to roll over
TCCR0B = 0x00;
// stop the clock source
TIFR0 = 0x1;
// clear TOV0
}
int main (void)
{
DDRK = 0xFF;
// OUTPUT
while(1)
{
PORTK = 0xFF;
fordelay();
PORTK = 0x00;
fordelay();
}
return
0;
}
F = 16MHz
T = 1/16MHz = 62.5ns
Value (Ticks) = ( 0xFF - XX + 1 )
Delay = ( 0xFF - XX + 1 ) * 62.5ns
Value = 0xFF 0x20 + 1 = 0xE0 (224)
Delay = 224 * 62.5ns = 14s
Write a program to toggle bit 4 of PORTK continuously every 70s. Use Timer0, Normal mode,
and 1:8 prescaler to generate the delay. Assume XTAL = 16MHz.
F = 16MHz
F/F(Prescaler) = 16MHz / 8 = 2MHz
T = 1/2MHz = 500ns
Clocks = Required Time / T
Clocks = 70s / 500ns = 140 => 0x8C
Value = 0xFF 0x8C + 1 = 0x74
#include <avr/io.h>
void fordelay()
{
TCNT0 = 0x74;
// load TCNT0
TCCR0A = 0x00;
// Timer0, Normal Mode
TCCR0B = 0x02;
// No prescaler
while((TIFR0 & (1<<TOV0)) == 0); // wait for TOV0 to roll over
TCCR0B = 0x00;
// stop the clock source
TIFR0 = 0x1<<TOV0;
// clear TOV0
}
int main (void)
{
DDRK = 0xFF;
// OUTPUT
while(1)
{
PORTK |= (1<<4);
fordelay();
PORTK &= ~(1<<4);
fordelay();
}
return
0;
}
Assume XTAL = 16MHz. Write a program to generate a square wave of 64KHz on bit 3 of
PORTK continuously.
Look at the following steps:
1.
2.
3.
4.
5.
Generate Maximum Time Delay and Minimum Time Delay. Assume XTAL = 16MHz.
Assume XTAL = 16MHz. Write a program to generate a square wave of 16KHz on bit 3 of
PORTK continuously.
(Hint : Use Prescaler)
Write a program to generate a square wave of 125Hz on bit 3 of PORTK continuously
Assume XTAL = 16MHz. Write a program to generate a delay of 1ms to toggle bit 4 of PORTK
continuously. Use Timer0, CTC mode, and with prescaler = 64.
T = 64 * 62.5ns = 4s
Clocks = 1ms / 4s = 250
Value = 250 1 = 249 (0xF9)
void fordelay()
{
TCNT0 = 0x00;
// load TCNT0
OCR0A = 0xF9;
// load OCR0A
TCCR0A = 0x01;
// Timer0, CRC Mode
TCCR0B = 0x01;
// No prescaler
while((TIFR0 & (1<<OCF0A)) == 0);//wait for OCF0A to roll over
TCCR0B = 0x00;
// stop the clock source
TIFR0 = (1<< OCF0A);
// clear OCF0A
}
Write a program to generate a delay of 750s
If TCNT0 = 95 and OCR0A = 89. Find the delay when bit 3 of PORTK get high, and also find,
for how much time it stay high.
16-bit Timer/Counter1
16-bit Registers
TCNTn, OCRnx
ICRn(to calculate frequency, duty-cycle, etc.)
8-bit Registers
TCCRnx, TIFRn, TIMSKn
(n = 0-5, x = A or B)
The two Timer/Counter I/O locations (TCNTnH and TCNTnL, combined TCNTn) give direct access, both for read and for write
operations, to the Timer/Counter unit 16-bit counter.
The Output Compare Registers contain a 16-bit value that is continuously compared with the counter value (TCNTn).
The Input Capture is updated with the counter (TCNTn) value each time an event occurs on the ICPn pin.
Assume XTAL = 16MHz. Write a program to generate a delay of 25.6ms to toggle bit 4 of PORTK
continuously. Use Timer1, Normal mode, and with prescaler = ???
#include <avr/io.h>
void fordelay()
{
TCNT1H = 0xC8;
TCNT1L = 0x00;
TCCR1A = 0x00;
// load TCNT0
TCCR1B = 0x02;
// Timer0, Normal Mode
TCCR1C = 0x00;
// No prescaler
while((TIFR1 & 0x1) == 0);
// wait for TOV0 to roll over
TCCR1B = 0x00;
// stop the clock source
TIFR1 = 0x1;
// clear TOV0
}
int main (void)
{
DDRK = 0xFF; // OUTPUT
while(1)
{
PORTK = 0xFF;
fordelay();
PORTK = 0x00;
fordelay();
}
return
0;
}
Prescaler
No
Prescaler
(1/8)
(1/64)
(1/256)
(1/1024)
Frequenc Time
y
Period
16MHz 6.25E-08
0.000000
5
250000 0.000004
62500 0.000016
15625 0.000064
2000000
Clocks
Value
(hex)
40960
64000
0
51200
C800
6400
1600
400
1900
640
190
Assume XTAL = 16MHz. Write a program to generate a delay of 1s to toggle bit 4 of PORTK
continuously. Use Timer1, Normal mode, and with prescaler = ???
#include <avr/io.h>
void fordelay()
{
TCNT1H = 0xF4;
TCNT1L = 0x24;
TCCR1A = 0x00;
// load TCNT0
TCCR1B = 0x04;
// Timer0, Normal Mode
TCCR1C = 0x00;
// No prescaler
while((TIFR1 & 0x1) == 0);
// wait for TOV0 to roll over
TCCR1B = 0x00;
// stop the clock source
TIFR1 = 0x1;
// clear TOV0
}
int main (void)
{
DDRK = 0xFF; // OUTPUT
while(1)
{
PORTK |= (1<<4);
fordelay();
PORTK &= ~(1<<4);
fordelay();
}
return
0;
}
Prescaler
Frequenc
y
Time
Period
No
Prescaler
16MHz
6.25E-08
(1/8)
2000000
(1/64)
Clocks
Value
(hex)
16000
F42400
000
0.000000 20000
1E8480
5
00
250000 0.000004
25000
0
3D090
(1/256)
62500
0.000016 62500
F424
(1/1024)
15625
0.000064 15625
3D09
Counters
AVR timer can also be used to count, detect, and measure the time of events happening outside
the AVR. When used as counter, it is a pulse outside the AVR that increments the TCNTn register.
CS bits (Clock Selector) in TCCR0B register decide the source of the clock for the timer/counter0.
If CS02:00 is set as 6 or 7, the timer is used as counter and gets pulses from a source outside the
AVR chip. For timer/counter1, CS bits (Clock Selector) in TCCR1B register decide the source of
the clock. If CS12:10 is set as 6 or 7, the timer is used as counter and gets pulses from a source
outside the AVR chip. For timer/counter0 external clock input pin is T0 (PD7/pin-50),and
for timer/counter1external clock input is T1 (PD6/pin-49).
Timer/Counter0 (As counter):
Find the value for TCCR0A and TCCR0B if we want to program Timer/Counter0 as Normal mode
counter. Use external clock for the clock source and increment on the positive edge.
TCCR0A = 0x00 and
Assume that a button input is fed into pin T0, and display the counter on PORTK.
#include<avr/io.h>
int main (void)
{
PORTD = 0x80; //activate pull-up of
DDRK = 0xFF;
TCCR0A = 0x00;
TCCR0B = 0x07;
while(1)
{
do
{
PORTK = TCNT0;
}while((TIFR0 & (0x1 << TOV0)) == 0); //wait for TOV0 to roll over
TIFR0 = 0x1 << TOV0;
}
return 0;
}
Assume that a 1Hz clock pulse is fed into pin T0, use the TOV0 flag to extend Timer/Counter0 to
a 16-bit counter and display the counter on PORTF and PORTK.
#include<avr/io.h>
int main (void)
{
PORTD = 0x80; //activate pull-up of
DDRF = 0xFF;
DDRK = 0xFF;
TCCR0A = 0x00;
TCCR0B = 0x07;
while(1)
{
do
{
PORTF = TCNT0;
}while((TIFR0 & (0x1 << TOV0)) == 0); //wait for TOV0 to roll over
TIFR0 = 0x1 << TOV0;
PORTK++;
}
return 0;
}
Assume that a 50Hz clock pulse is fed into pin T5, write a program for counter5 in rising edge
mode to count the pulses and display the TCNT5H and TCNT5L registers on PORTF and PORTK.
#include<avr/io.h>
int main (void)
{
PORTL = 0x04; //activate pull-up of
DDRF = 0xFF;
DDRK = 0xFF;
TCCR5A = 0x00;
TCCR5B = 0x07;
TCCR5C = 0x00;
while(1)
{
do
{
PORTF = TCNT5L;
PORTK = TCNT5H;
}while((TIFR5 & (0x1 << TOV5)) == 0); //wait for TOV5 to roll over
TIFR5 = 0x1 << TOV5;
}
return 0;
}