Skip to content

Commit c07b9fa

Browse files
committed
Extended version of L15
1 parent 1ea031d commit c07b9fa

3 files changed

Lines changed: 103 additions & 13 deletions

File tree

15_TimerUndInterrupts.md

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ int main(){
287287
### Einführungsbeispiele
288288

289289
**Externe Interrupts**
290+
290291
Wenden wir das Konzept mal auf einen konkreten Einsatzfall an und lesen die externen Interrupts in einer Schaltung. Dabei sollen Aktivitäten an einem externen Interruptsensiblen Pin überwacht werden.
291292

292293
> **Aufgabe:** Ermitteln Sie mit die PORT zugehörigkeit und die ID der Externen Interrupt PINs `ÌNT0` und `ÌNT1`. Welche Arduino Pin ID gehört dazu?
@@ -303,8 +304,8 @@ ISR(INT0_vect) {
303304

304305
int main (void) {
305306
DDRB |= (1 << PB5);
306-
DDRD &= ~(1 << DDD2);
307-
PORTD |= (1 << PORTD2);
307+
DDRD &= ~(1 << DDD2); // Pin als Eingang
308+
PORTD |= (1 << PORTD2); // Pullup-Konfiguration
308309
EIMSK |= ( 1 << INT0);
309310
EICRA |= ( 1 << ISC01);
310311
sei();
@@ -315,30 +316,40 @@ int main (void) {
315316
316317
**Analog Digitalwandler**
317318
318-
```c
319-
#define F_CPU 16000000UL
319+
Das folgende Beispiel nutzt den Analog-Digital-Wandler in einem teilautonomen Betrieb. Innerhalb der Interrupt-Routine wird das Ergebnis ausgewertet und jeweils eine neue Wandlung aktiviert.
320+
321+
Als Demonstrator dient ein Spannungsteiler über einen lichtabhängigen Widerstand.
320322
323+
```c
321324
#include <avr/io.h>
322325
#include <avr/interrupt.h>
323326
324327
// Interrupt subroutine for ADC conversion complete interrupt
325328
ISR(ADC_vect) {
326-
if(ADCW >= 900)
329+
//Serial.println(ADCW);
330+
if(ADCW >= 600)
327331
PORTB |= (1 << PB5);
328332
else
329333
PORTB &=~(1 << PB5);
330334
ADCSRA |= (1<<ADSC);
331335
}
332336
333-
int main(void) {
337+
int main(void){
338+
Serial.begin(9600);
334339
DDRB |= (1 << PB5);
335340
ADMUX = (1<<REFS0);
336-
ADCSRA |= (1<<ADEN)|(1<<ADIE);
341+
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1<<ADPS0) | (1<<ADEN)|(1<<ADIE);
337342
sei(); // Set the I-bit in SREG
338343
ADCSRA |= (1<<ADSC); // Start the first conversion
339344
340-
while (1);
341-
return 0; // This line will never be executed
345+
int i = 0;
346+
while (1) {
347+
Serial.print("Ich rechne fleißig ... ");
348+
Serial.println(i++);
349+
_delay_ms(50);
350+
}
351+
352+
return 0;
342353
}
343354
```
344355

@@ -568,14 +579,40 @@ Folgende Fragen müssen wir die Nutzung des Timers beantwortet werden:
568579

569580
#### Timer Modi
570581

582+
Timer-Modi bestimmen das Verhalten des Zählers und der angeschlossenen Ausgänge / Interrupts. Neben dem als Normal-Mode bezeichneten Mechanismus existieren weitere Konfigurationen, die unterschiedliche Anwendungsfelder bedienen.
583+
584+
**Clear to Compare Mode (CTC)**
585+
571586
![Bild](./images/15_Timer/CTC_mode.png)<!-- style="width: 75%; max-width: 1000px" -->[^4]
572587

588+
Die Periode über eine `OCnA` Ausgang ergibt sich entsprechend zu
589+
590+
$$
591+
f_{OCnA} = \frac{f_{clk_i/o}}{2 \cdot N \ cdot (1 + OCRnA)}
592+
$$
593+
594+
Der Counter läuft zwei mal durch die Werte bis zum Vergleichsregister `OCRnA`. Die Frequenz kann durch das Setzen eine Prescalers korrigiert werden.
595+
596+
**Fast PWM**
597+
573598
![Bild](./images/15_Timer/FastPWM.png)<!-- style="width: 75%; max-width: 1000px" -->[^4]
574599

600+
Die Periode des Signals an `OCRnA` wechselt während eines Hochzählens des Counters. Damit kann eine größere Frequenz bei gleicher Auflösung des Timers verglichen mit CTC erreicht werden.
601+
602+
$$
603+
f_{OCnA} = \frac{f_{clk_i/o}}{N \ cdot (1 + TOP)}
604+
$$
605+
606+
**Phase Correct PWM**
607+
575608
![Bild](./images/15_Timer/PhaseCorrectPWM.png)<!-- style="width: 75%; max-width: 1000px" -->[^4]
576609

577610
[^4]: Firma Microchip, megaAVR® Data Sheet, Seite 141, [Link](http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf)
578611

612+
$$
613+
f_{OCnA} = \frac{f_{clk_i/o}}{2 \cdot N \ cdot TOP)}
614+
$$
615+
579616
#### Timer-Funktionalität (Normal-Mode)
580617

581618
Für die Umsetzung eines einfachen Timers, der wie im Nachfolgenden Beispiel jede
@@ -634,6 +671,8 @@ Wir verknüpfen unseren Timer im Comparemodus mit einem entsprechenden Ausgang u
634671
635672
> **Frage:** Welchen physischen Pin des Controllers können wir mit unserem Timer 1 ansteuern?
636673
674+
**Normal Mode Konfiguration**
675+
637676
<div>
638677
<wokwi-led color="green" pin="9" port="B" label="B1"></wokwi-led>
639678
<span id="simulation-time"></span>
@@ -654,11 +693,36 @@ int main(void)
654693
655694
while (1) _delay_ms(500);
656695
}
657-
658-
659696
```
660697
@AVR8js.sketch
661698

699+
**Fast PWW Konfiguration**
700+
701+
```cpp avrlibc.cpp
702+
#ifndef F_CPU
703+
#define F_CPU 16000000UL // 16 MHz clock speed
704+
#endif
705+
706+
int main(void){
707+
DDRB |= (1<<PORTB1); //Define OCR1A as Output
708+
TCCR1A |= (1<<COM1A1) | (1<<WGM10); //Set Timer Register
709+
TCCR1B |= (1<<WGM12) | (1<<CS11);
710+
OCR1A = 0;
711+
int timer;
712+
while(1) {
713+
while(timer < 255){ //Fade from low to high
714+
timer++;
715+
OCR1A = timer;
716+
_delay_ms(50);
717+
}
718+
while(timer > 1){ //Fade from high to low
719+
timer--;
720+
OCR1A = timer;
721+
_delay_ms(50);
722+
}
723+
}
724+
}
725+
```
662726
663727
#### Capture Mode
664728

exampleCode/15_Timer/CaptureMode/CaptureMode.ino

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ int main(void)
1212
PORTB = 0xFF;
1313

1414
TCCR1A = 0; // Normal Mode
15-
16-
TCCR1B = 0;
1715
// 1024 als Prescale-Wert Rising edge
1816
TCCR1B = (1 << CS12) | (1 <<CS10) | (1 << ICES1);
1917
TIFR1 = (1<<ICF1);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef F_CPU
2+
#define F_CPU 16000000UL // 16 MHz clock speed
3+
#endif
4+
5+
int main(void){
6+
Serial.begin(9600);
7+
DDRB |= (1<<PORTB1); //Define OCR1A as Output
8+
TCCR1A |= (1<<COM1A1) | (1<<WGM10); //Set Timer Register
9+
TCCR1B |= (1<<WGM12) | (1<<CS11);
10+
OCR1A = 0;
11+
int timer;
12+
while(1) {
13+
while(timer < 255){ //Fade from low to high
14+
timer++;
15+
OCR1A = timer;
16+
_delay_ms(20);
17+
Serial.print("Auf ");
18+
Serial.println(timer);
19+
}
20+
while(timer > 1){ //Fade from high to low
21+
timer--;
22+
OCR1A = timer;
23+
_delay_ms(20);
24+
Serial.print("Ab ");
25+
Serial.println(timer);
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)