Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - Timer, Counter: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: AVR Embedded Tutorial - Timer, Counter

OldNewLine
1+# Timer / counter
2+
3+This is not about understanding all the AVR registers. This is only a practical example of how to implement timers/counters in FPC. You should understand that timers are simply counters.
4+
5+More details are available [here](https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR) (in German) or use your favourite search engine.
6+
7+## Example, control LEDs via timer
8+
9+This example shows how you can use the two timers of an ATtiny2313. Each timer controls an LED, which are at bits 0 and 1 of Port D. The LED on PD0 should flash a little faster.
10+
11+### Example code
12+
13+``` pascal
14+program Project1;
15+```
16+
17+#### Timer 0 interrupt
18+
19+``` pascal
20+procedure Timer0_Interrupt; public name 'TIMER0_COMPA_ISR'; interrupt;
21+ const
22+ t = 10; // LED should only switch every 10th pass
23+ z : integer = 0; // Counter for idle runs
24+ begin
25+ TCNT0 := 128; // Half speed 0 = slow (default)
26+ Inc(z);
27+
28+ if(z = t) then
29+ begin
30+ PORTD := PORTD or (1 shl 0); // Pin 0 LED on
31+ end;
32+
33+ if(z = t shl 1) then
34+ begin
35+ PORTD := PORTD and not (1 shl 0); // Pin 0 LED off
36+ z := 0;
37+ end;
38+ end;
39+```
40+
41+#### Timer 1 interrupt
42+
43+``` pascal
44+procedure Timer1_Interrupt; public name 'TIMER1_COMPA_ISR'; interrupt;
45+ const
46+ t = 500; // LED should only switch every 500th pass
47+ z : integer = 0; // Counter for idle runs
48+ begin
49+ Inc (z);
50+
51+ if(z = t) then
52+ begin
53+ PORTD := PORTD or (1 shl 1); // Pin 1 LED on
54+ end;
55+
56+ if(z = t shl 1) then
57+ begin
58+ PORTD := PORTD and not (1 shl 1); // Pin 1 LED off
59+ z : = 0;
60+ end;
61+ end;
62+```
63+
64+#### Initialize the timer
65+
66+``` pascal
67+ begin
68+ // Disable interrupts
69+ asm
70+ cli
71+ end;
72+
73+ // Set PD0 and PD1 to output
74+ DDRD := %00000011;
75+
76+ // Initialize timer0
77+ TCCR0A := 0; // Normal mode
78+ TCCR0B := %101; // CPU clock / 1024
79+ TIMSK := TIMSK or (1 shl OCIE0A); // Timer0 should trigger an interrupt
80+
81+ // Initialize timer1
82+ TCCR1A := 1; // CTC (Clear Timer on Compare match) mode
83+ TCCR1B := %010; // CPU clock / 8
84+ TIMSK := TIMSK or (1 shl OCIE1A); // Timer1 should trigger an interrupt
85+
86+ // Enable interrupts
87+ asm
88+ sei
89+ end;
90+
91+ // Main loop
92+ repeat
93+ // Do something
94+ until 1 = 2;
95+ end.
96+```
97+
98+## Timer clocked externally
99+
100+A timer can also be clocked externally. The following example demonstrates this with an Atmega328. The following pins are available on the AVR for external clocking:
101+
102+- **T0** clocks timer 0
103+- **T1** clocks timer 1
104+
105+Timer 2 cannot be clocked externally.
106+
107+### Clock example
108+
109+A quartz crystal/oscillator with 4.194304MHz is suitable for an exact clock. This can easily be divided into a power of two, so that you get a cycle of one second. Here timer 0 is clocked externally, for this you have to connect the oscillator to T0 (PD4).
110+
111+#### Timer interrupt
112+
113+Every 16,384th call of the interrupt is one second.
114+
115+``` pascal
116+procedure Timer0_Interrupt; public name 'TIMER0_OVF_ISR'; interrupt;
117+ const
118+ cl = 16384 shr 1; // 4194304/256/2
119+ counter : UInt16 = 0; // Counts until cl is reached
120+
121+ begin
122+ Inc(counter);
123+
124+ // Turn off the LED after half a second
125+ if count = cl then
126+ begin
127+ PORTB := PORTB and not (1 shl 5);
128+ end;
129+
130+ // 1 second is reached.
131+ if count > = cl shl 1 then
132+ begin
133+ PORTB := PORTB or (1 shl 5);
134+ count := 0; // Reset counter.
135+ end;
136+ end;
137+```
138+
139+#### Initialize the timer
140+
141+The important point is the value at TCCR0B which determines that the timer is clocked externally.
142+
143+``` pascal
144+ begin
145+ DDRB := 1 shl 5; // Set pin PD5 as an output
146+
147+ TCCR0A := %00; // Normal timer
148+ TCCR0B := %111; // Clock / external pin TO, rising edge.
149+ TIMSK0 := (1 shl TOIE0); // Activate timer 0 interrupt.
150+
151+ asm
152+ sei // enable interrupts
153+ end;
154+
155+ repeat
156+ // Here the time can be shown on a display
157+ until 1 = 2;
158+ end.
159+```
160+
161+#### Pitfalls
162+
163+The names of the procedures can differ, for example:
164+
165+``` pascal
166+ // ATtiny2313
167+ procedure Timer0_Interrupt; public name 'TIMER0_COMPA_ISR'; interrupt;
168+ // ATtiny44
169+ procedure Timer0_Interrupt; public name 'TIM0_COMPA_ISR'; interrupt;
170+```
171+
172+# See also
173+
174+- [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview
175+
176+---
177+*From the Free Pascal wiki, page "AVR Embedded Tutorial - Timer, Counter", as it stood on 2020-01-24 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
178+Category: AVR
179+Category: Arduino
180+Category: Embedded
181+Category: Tutorials

Back to history