Inhaltsverzeichnis:

AVR-Mikrocontroller. LEDs blinken mit Timer. Timer-Unterbrechungen. Timer-CTC-Modus - Gunook
AVR-Mikrocontroller. LEDs blinken mit Timer. Timer-Unterbrechungen. Timer-CTC-Modus - Gunook

Video: AVR-Mikrocontroller. LEDs blinken mit Timer. Timer-Unterbrechungen. Timer-CTC-Modus - Gunook

Video: AVR-Mikrocontroller. LEDs blinken mit Timer. Timer-Unterbrechungen. Timer-CTC-Modus - Gunook
Video: Timer & PWM [06 | AVR - Mikrocontroller C] by Fusel 2024, Juli
Anonim
Image
Image

Hallo alle zusammen!

Timer ist ein wichtiges Konzept im Bereich der Elektronik. Jedes elektronische Bauteil arbeitet auf Zeitbasis. Diese Zeitbasis hilft, die gesamte Arbeit synchron zu halten. Alle Mikrocontroller arbeiten mit einer vordefinierten Taktfrequenz, sie haben alle die Möglichkeit, Timer einzurichten. AVR rühmt sich, einen Timer zu haben, der sehr genau, präzise und zuverlässig ist. Es bietet viele Funktionen darin, was es zu einem riesigen Thema macht. Das Beste daran ist, dass der Timer völlig unabhängig von der CPU ist. Somit läuft er parallel zur CPU und es gibt keinen CPU-Eingriff, was den Timer recht genau macht. In diesem Abschnitt erkläre ich die grundlegenden Konzepte von AVR-Timern. Ich schreibe ein einfaches Programm in C-Code, um LED-Blinker mit Timern zu steuern.

Schritt 1: Beschreibung

Problemstellung 1: Lassen Sie uns alle 50 Ms die erste LED (grün) blinken
Problemstellung 1: Lassen Sie uns alle 50 Ms die erste LED (grün) blinken

In ATMega328 gibt es drei Arten von Timern:

Timer/Counter0 (TC0) - ist ein Allzweck-8-Bit-Timer/Counter-Modul mit zwei unabhängigen OutputCompare-Einheiten und PWM-Unterstützung;

Timer/Counter1 (TC1) - Die 16-Bit-Timer/Counter-Einheit ermöglicht genaues Timing der Programmausführung (Ereignisverwaltung), Wave-Generierung und Signal-Timing-Messung;

Timer/Counter2 (TC2) – ist ein Allzweck-Kanal-8-Bit-Timer/Counter-Modul mit PWM und asynchronem Betrieb;

Schritt 2: Problembeschreibung 1: Lassen Sie uns alle 50 Ms die erste LED (grün) blinken

Problemstellung 1: Lassen Sie uns alle 50 Ms die erste LED (grün) blinken
Problemstellung 1: Lassen Sie uns alle 50 Ms die erste LED (grün) blinken
Problemstellung 1: Lassen Sie uns alle 50 Ms die erste LED (grün) blinken
Problemstellung 1: Lassen Sie uns alle 50 Ms die erste LED (grün) blinken

Methodik:

– Verwenden eines Timer0-Vorskalierers, um ein elektrisches Hochfrequenzsignal durch ganzzahlige Division auf eine niedrigere Frequenz zu reduzieren;

- Verwenden eines Interrupts jedes Mal, wenn der Timer0 überläuft;

Timer0 (8 Bit) zählt von 0 bis 255 danach, sie laufen über, dieser Wert ändert sich bei jedem Takt.

F_CPU=16MHz: Taktzeit = 1000ms / 16000000Hz = 0,0000625ms

Timer-Zählung = (erforderliche Verzögerung / Taktzeitperiode)-1 = (50 ms / 0,0000625 ms) = 799999

Die Uhr hat bereits 799999 mal getickt, was eine Verzögerung von nur 50 ms ergibt!

Wir können eine Technik der Frequenzteilung verwenden, die als Vorskalierung bezeichnet wird, um die Timer-Zählung zu verringern. Der AVR bietet uns die folgenden Prescaler-Werte zur Auswahl: 8, 64, 256 und 1024. In der Tabelle sind die Ergebnisse der Verwendung verschiedener Prescaler zusammengefasst.

Der Zählerwert sollte immer eine ganze Zahl sein. Wählen wir einen Prescaler 256!

In den meisten Mikrocontrollern gibt es etwas namens Interrupt. Dieser Interrupt kann immer dann ausgelöst werden, wenn bestimmte Bedingungen erfüllt sind. Wenn nun ein Interrupt ausgelöst wird, stoppt der AVR und speichert seine Ausführung der Hauptroutine, kümmert sich um den Interrupt-Aufruf (durch Ausführen einer speziellen Routine, die als Interrupt Service Routine, ISR bezeichnet wird) und kehrt, sobald er damit fertig ist, zum Hauptroutine und fährt mit der Ausführung fort.

Da die erforderliche Verzögerung (50 ms) größer ist als die maximal mögliche Verzögerung: 4 096 ms = 1000 ms / 62500 Hz * 256, läuft der Timer offensichtlich über. Und immer wenn der Timer überläuft, wird ein Interrupt ausgelöst.

Wie oft soll der Interrupt ausgelöst werden?

50ms / 4.096ms = 3125 / 256 = 12.207 Wenn der Timer 12 mal übergelaufen ist, wären 12 * 4.096ms = 49.152ms vergangen. In der 13. Iteration benötigen wir eine Verzögerung von 50 ms – 49,152 ms = 0,848 ms.

Bei einer Frequenz von 62500 Hz (Prescaler = 256) dauert jeder Tick 0,016 ms. Um eine Verzögerung von 0,848 ms zu erreichen, wären also 0,848 ms / 0,016 ms = 53 Ticks erforderlich. Daher lassen wir in der 13. Iteration den Timer nur bis 53 zählen und setzen ihn dann zurück.

Timer0/Counter initialisieren (siehe Bild):

TCCR0B |= (1 << CS02) // Timer mit Prescaler einrichten = 256 TCNT0 = 0 // Zähler initialisieren TIMSK0 |= (1 << TOIE0) // Überlauf-Interrupt aktivieren sei() // Globale Interrupts aktivieren tot_overflow = 0 // Überlaufzählervariable initialisieren

Schritt 3: Problembeschreibung 2: Lassen Sie uns alle 1s die zweite LED (blau) blinken

Problemstellung 2: Lassen Sie uns alle 1s die zweite LED (blau) blinken
Problemstellung 2: Lassen Sie uns alle 1s die zweite LED (blau) blinken
Problemstellung 2: Lassen Sie uns alle 1s die zweite LED (blau) blinken
Problemstellung 2: Lassen Sie uns alle 1s die zweite LED (blau) blinken
Problemstellung 2: Lassen Sie uns alle 1s die zweite LED (blau) blinken
Problemstellung 2: Lassen Sie uns alle 1s die zweite LED (blau) blinken

Methodik:

– Verwenden eines Timer1-Vorskalierers, um ein elektrisches Hochfrequenzsignal durch ganzzahlige Division auf eine niedrigere Frequenz zu reduzieren;

- Verwenden des Clear Timers im Vergleichsmodus (CTC);

- Verwendung von Interrupts im CTC-Modus;

Timer1 (16 Bit) zählt von 0 bis 65534 danach, sie laufen über. Dieser Wert ändert sich bei jedem Taktimpuls.

F_CPU=16MHz: Taktzeitperiode = 1000ms / 16000000Hz = 0,0000625msTimerzähler = (Erforderliche Verzögerung / Taktzeitperiode)-1 = (1000ms / 0,0000625ms) = 15999999

Die Uhr hat bereits 15999999 mal tickt, um eine Verzögerung von 1s zu ergeben!

Wir können eine Technik der Frequenzteilung verwenden, die als Vorskalierung bezeichnet wird, um die Timer-Zählung zu verringern. Der AVR bietet uns die folgenden Prescaler-Werte zur Auswahl: 8, 64, 256 und 1024. In der Tabelle sind die Ergebnisse der Verwendung verschiedener Prescaler zusammengefasst. Der Zählerwert sollte immer eine ganze Zahl sein. Wählen wir einen Prescaler 256!

Im Clear Timer on Compare(CTC)-Modus werden die Register OCR1A oder ICR1 verwendet, um die Zählerauflösung zu manipulieren. Im CTC-Modus wird der Zähler auf Null zurückgesetzt, wenn der Zählerwert (TCNT1) entweder mit OCR1A oder ICR1 übereinstimmt. Der OCR1A bzw. ICR1 definiert den Spitzenwert des Zählers und damit auch dessen Auflösung. Dieser Modus ermöglicht eine bessere Kontrolle der Ausgangsfrequenz der Vergleichsübereinstimmung. Außerdem vereinfacht er die Zählung externer Ereignisse. Wir müssen dem AVR mitteilen, dass er den Timer1/Counter zurücksetzen soll, sobald sein Wert den Wert 62500 erreicht, also eine Verzögerung von 1s erreicht.

Timer1/Counter initialisieren (siehe Bild):

TCCR1B |= (1 << WGM12)|(1 << CS12) // Timer mit Prescaler = 256 und CTC-Modus einrichten TCNT1 = 0 // Zähler initialisieren TIMSK1 |= (1 << OCIE1A) // Vergleichsinterrupt aktivieren OCR1A = 62500 // Vergleichswert initialisieren

Schritt 4: Problembeschreibung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken

Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken
Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken
Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken
Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken
Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken
Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken
Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken
Problemstellung 3: Lassen Sie uns alle 16 ms die dritte LED (rot) blinken

Methodik:

– Verwenden eines Timer2-Vorskalierers, um ein elektrisches Hochfrequenzsignal durch ganzzahlige Division auf eine niedrigere Frequenz zu reduzieren;

- Verwenden des Clear Timers im Vergleichsmodus (CTC);

- Verwenden des Hardware-CTC-Modus ohne Unterbrechungen;

Timer2 (8 Bit) zählt von 0 bis 255 danach, sie laufen über. Dieser Wert ändert sich bei jedem Taktimpuls.

F_CPU=16MHz: Taktzeit = 1000ms / 16000000Hz = 0,0000625ms

Timer-Zählung = (Erforderliche Verzögerung / Taktzeitperiode)-1 = (16 ms / 0,0000625 ms) = 255999

Die Uhr hat bereits 255999 Mal getickt, was eine Verzögerung von 16ms ergibt!

In der Tabelle sind die Ergebnisse der Verwendung verschiedener Vorteiler zusammengefasst. Der Zählerwert sollte immer eine ganze Zahl sein. Wählen wir einen Prescaler 1024!

Im CTC-Modus wird der Zähler auf Null zurückgesetzt, wenn der Zählerwert (TCNT2) entweder mit OCR2A oder ICR2 übereinstimmt. Pin PB3 ist auch der Output Compare Pin von TIMER2 - OC2A (siehe Diagramm).

Timer/Counter2 Control Register A – TCCR2A Bit 7:6 – COM2A1:0 – Compare Output Mode for Compare Unit A. Da wir die LED umschalten müssen, wählen wir die Option: Toggle OC2A on Compare Match Immer wenn eine Vergleichsübereinstimmung auftritt, Der OC2A-Pin wird automatisch umgeschaltet. Keine Notwendigkeit, irgendein Flag-Bit zu überprüfen, keine Notwendigkeit, sich um irgendwelche Interrupts zu kümmern.

Timer2/Zähler initialisieren

TCCR2A |= (1 << COM2A0)|(1 << WGM21) // Timer OC2A Pin im Toggle-Modus und CTC-Modus einrichten TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20) // Timer mit Prescaler einrichten = 1024 TCNT2 = 0 // Zähler initialisieren OCR2A = 250 // Vergleichswert initialisieren

Schritt 5: Schreiben von Code für ein Programm in C. Hochladen der HEX-Datei in den Mikrocontroller-Flash-Speicher

Schreiben von Code für ein Programm in C. Hochladen einer HEX-Datei in den Mikrocontroller-Flash-Speicher
Schreiben von Code für ein Programm in C. Hochladen einer HEX-Datei in den Mikrocontroller-Flash-Speicher
Schreiben von Code für ein Programm in C. Hochladen einer HEX-Datei in den Mikrocontroller-Flash-Speicher
Schreiben von Code für ein Programm in C. Hochladen einer HEX-Datei in den Mikrocontroller-Flash-Speicher

Schreiben und Erstellen der AVR-Mikrocontroller-Anwendung in C-Code mit der integrierten Entwicklungsplattform - Atmel Studio.

F_CPU definiert die Taktfrequenz in Hertz und ist in Programmen üblich, die die avr-libc-Bibliothek verwenden. In diesem Fall wird es von den Verzögerungsroutinen verwendet, um zu bestimmen, wie Zeitverzögerungen berechnet werden.

#ifndef F_CPU

#define F_CPU 16000000UL // Angabe der Quarzfrequenz des Controllers (16 MHz AVR ATMega328P) #endif

#include // Header, um die Datenflusskontrolle über Pins zu ermöglichen. Definiert Pins, Ports usw.

Die erste Include-Datei ist Teil von avr-libc und wird in so ziemlich jedem AVR-Projekt verwendet, an dem Sie arbeiten. io.h ermittelt die von Ihnen verwendete CPU (weshalb Sie den Teil beim Kompilieren angeben) und fügt wiederum den entsprechenden IO-Definitionsheader für den von uns verwendeten Chip hinzu. Es definiert einfach die Konstanten für alle Ihre Pins, Ports, Sonderregister usw.

#include // Header zum Aktivieren von Interrupt

flüchtig uint8_t tot_overflow; // globale Variable zum Zählen der Überläufe

Methodik der Problembeschreibung: Zuerst blinkende (grüne) LED alle 50 ms

– Verwenden eines Timer0-Vorskalierers, um ein elektrisches Hochfrequenzsignal durch ganzzahlige Division auf eine niedrigere Frequenz zu reduzieren;

- Verwenden eines Interrupts jedes Mal, wenn der Timer0 überläuft;

void timer0_init() // initialisiere timer0, interrupt und variable

{TCCR0B |= (1 << CS02); // Timer mit Prescaler einrichten = 256 TCNT0 = 0; // Zähler initialisieren TIMSK0 |= (1 << TOIE0); // Überlauf-Unterbrechung aktivieren sei(); // globale Interrupts aktivieren tot_overflow = 0; // Überlaufzählervariable initialisieren }

Methodik der Problembeschreibung: Blinken der zweiten LED (blau) alle 1s

– Verwenden eines Timer1-Vorskalierers, um ein elektrisches Hochfrequenzsignal durch ganzzahlige Division auf eine niedrigere Frequenz zu reduzieren;

- Verwenden von Clear Timer im Vergleichsmodus (CTC);

- Verwendung von Interrupts im CTC-Modus;

Void Timer1_init () // Timer1, Interrupt und Variable initialisieren { TCCR1B |= (1 << WGM12)|(1 << CS12); // Timer mit Prescaler = 256 und CTC-Modus einrichten TCNT1 = 0; // Zähler initialisieren OCR1A = 62500; // Vergleichswert initialisieren TIMSK1 |= (1 << OCIE1A); // Vergleichsinterrupt aktivieren}

Methodik der Problembeschreibung: Dritte LED (rot) alle 16 ms blinken lassen

- Verwenden eines Timer2-Vorskalierers, um ein elektrisches Hochfrequenzsignal durch ganzzahlige Division auf eine niedrigere Frequenz zu reduzieren;

- Verwenden des Clear Timers im Vergleichsmodus (CTC);

- Verwenden des Hardware-CTC-Modus ohne Unterbrechungen;

void timer2_init() // initialisiere timer2{ TCCR2A |= (1 << COM2A0)|(1 << WGM21); // Timer OC2A Pin im Toggle-Modus und CTC-Modus einrichten TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20); // Timer mit Prescaler einrichten = 1024 TCNT2 = 0; // Zähler initialisieren OCR2A = 250; // Vergleichswert initialisieren }

TIMER0-Überlauf-Interrupt-Service-Routine, die immer aufgerufen wird, wenn TCNT0 überläuft:

ESR(TIMER0_OVF_vect)

{tot_overflow++; // Verfolgen Sie die Anzahl der Überläufe }

Dieser ISR wird immer dann ausgelöst, wenn eine Übereinstimmung auftritt, daher wird hier selbst umgeschaltet:

ISR (TIMER1_COMPA_vect){ PORTC ^= (1 << 1); // hier umschalten}

int main(void)

{ DDRB |= (1 << 0); // Verbinden Sie 1 (grün) mit Pin PB0 DDRC |= (1 << 1); // Verbinden Sie 2 (blau) mit Pin PC1 DDRB |= (1 << 3); // Verbinden Sie 3 (rot) mit Pin PB3 (OC2A) timer0_init (); // initialisiere timer0 timer1_init(); // initialisiere timer1 timer2_init(); // initialisiere timer2 while(1) // Schleife für immer {

Wenn der Timer0 12 mal übergelaufen ist, wären 12 * 4.096ms = 49.152ms vergangen. In der 13. Iteration benötigen wir eine Verzögerung von 50 ms – 49,152 ms = 0,848 ms. Daher lassen wir in der 13. Iteration den Timer nur bis 53 zählen und setzen ihn dann zurück.

if (tot_overflow >= 12) // prüfen ob nein. von Überläufen = 12 HINWEIS: '>=' wird verwendet

{ if (TCNT0 >= 53) // Überprüfen Sie, ob der Timer-Zähler 53 erreicht { PORTB ^= (1 << 0); // schaltet die LED um TCNT0 = 0; // Zähler zurücksetzen tot_overflow = 0; // Überlaufzähler zurücksetzen } } } }

Hochladen der HEX-Datei in den Flash-Speicher des Mikrocontrollers:

Geben Sie im DOS-Eingabeaufforderungsfenster den Befehl ein:

avrdude –c [Name des Programmierers] –p m328p –u –U flash:w:[Name deiner Hex-Datei]In meinem Fall ist es: avrdude –c ISPProgv1 –p m328p –u –U flash:w:Timers.hex

Dieser Befehl schreibt eine Hex-Datei in den Speicher des Mikrocontrollers. Sehen Sie sich das Video mit einer detaillierten Beschreibung des Brennens des Mikrocontroller-Flash-Speichers an:

Microcontroller-Flash-Speicher brennt…

Okay! Nun arbeitet der Mikrocontroller gemäß den Anweisungen unseres Programms. Schauen wir es uns an!

Schritt 6: Herstellen des Stromkreises

Herstellen des Stromkreises
Herstellen des Stromkreises
Herstellen des Stromkreises
Herstellen des Stromkreises
Herstellen des Stromkreises
Herstellen des Stromkreises

Komponenten gemäß Schaltplan anschließen.

Empfohlen: