This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| de:examples:timer:hardware_delay [2010/11/10 02:00] – Wember | de:examples:timer:hardware_delay [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Hardwareverzögerung ====== | ||
| + | |||
| + | // | ||
| + | |||
| + | ===== Theorie ===== | ||
| + | |||
| + | Neben der Softwareverzögerung gibt es auch Timer, um Unterbrechungen zu erzeugen. Timer sind Hardwarekomponenten, | ||
| + | |||
| + | [{{ : | ||
| + | |||
| + | AVR Taktgeber können so eingestellt werden, dass sie bei Überlauf des Timers oder bei Vergleichstreffern informieren. Ein Überlauf tritt auf, wenn der Timer seinen maximalen Wert erreicht hat und der Zyklus wieder bei 0 anfängt. Nach Erreichen eines vorgegebenen Wertes beginnt der Timer bei jedem Anstieg seines Wertes diesen mit einem vom Benutzer vorgegebenen Wert zu vergleichen. Daraufhin werden die Bits des AVR-Statusindexes automatisch high gesetzt. | ||
| + | |||
| + | Um eine Verzögerung mit einem Timer zu generieren, muss man nur den Timer setzen und darauf warten, dass das Statusbit high wird. Im Unterschied zur Softwareverzögerung ist die Arbeit des Timers nicht vom Compiler abhängig, wodurch er zuverlässiger ist. Gleichzeitig ist die Diversität (bzw. Komplexität) der Einstellungen des AVR Timers hoch. Je nach Taktsignal des Mikrocontrollers kann es sein, dass es nicht exakt mit der gewünschten Verzögerungsperiode dividiert und die Verzögerung so ungenau wird. | ||
| + | |||
| + | ===== Übung ===== | ||
| + | |||
| + | Der Programmcode unterhalb stellt eine vereinfachte Timer-basierte Verzögerungsfunktion dar. Das Zählen funktioniert genauso wie bei einer Softwareverzögerungsfunktion. Es wird eine gewünschte Verzögerung von 1 ms mit dem Timer 0 eines 8-Bit ATmega128 erzeugt. Die zuvor errechnete Taktfrequenz liegt bei 14,7456 MHz und das Timersignal muss mindestens 64 Mal dividiert werden, so dass der Timer seinen Überlauf nicht in einer Millisekunde erreicht. | ||
| + | Der Wert den der Timer haben muss, so dass der Überlauf nach 1 ms stattfindet wird mit durch die Variable // | ||
| + | Leider entsteht hier eine gewisse Ungenauigkeit, | ||
| + | |||
| + | In dem Zyklus wird der Timer initialisiert und die Überlauf-Flagge genullt (in dem eine 1 hineingeschrieben wird). Dann wird abgewartet bis der Timer vom Startwert bis 256 gezählt hat, also zum Überlauf. In dem Moment wird die Flagge hoch gesetzt und eine Verzögerung von einer 1 ms hat stattgefunden. Am Ende der Funktion wird der Timer gestoppt. | ||
| + | |||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // Hardwareverzögerung in Millisekunden. | ||
| + | // | ||
| + | void hw_delay_ms(unsigned short count) | ||
| + | { | ||
| + | // Berechnung des Startwertes des Timers. | ||
| + | register unsigned char timer_start = 256 - F_CPU / 1000 / 64; | ||
| + | |||
| + | // Start des Timers. | ||
| + | timer0_init_normal(TIMER0_PRESCALE_64); | ||
| + | |||
| + | // Zählen der Verzögerungsvariable auf 0. | ||
| + | while (count-- > 0) | ||
| + | { | ||
| + | // Initialisierung des Timers. | ||
| + | timer0_set_value(timer_start); | ||
| + | |||
| + | // Überlauf-Flagge auf Null setzen. | ||
| + | timer0_overflow_flag_clear(); | ||
| + | |||
| + | // Warten auf den Überlauf. | ||
| + | while (!timer0_overflow_flag_is_set()) | ||
| + | { | ||
| + | asm volatile (" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Überlauf-Flagge auf Null setzen. | ||
| + | timer0_overflow_flag_clear(); | ||
| + | |||
| + | // Timer anhalten. | ||
| + | timer0_stop(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Das folgende Programm ist ähnlich wie das für die Softwareverzögerung. In der kürzeren 100 ms langen halb-Periode wird die LED eingeschaltet und in der längeren 900 ms halb-Periode ausgeschaltet. Das Resultat: die LED blinkt jede Sekunde. Leider beträgt die Periode in diesem Beispiel ebenfalls nicht exakt eine Sekunde, da die Ausführung anderer Funktionen des Programms ebenfalls Zeit verbraucht. Für ein exaktes Timing, muss ein 16-Bit Timer mit Interrupts genutzt werden. | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // Beispielprogramm für eine Hardwareverzögerung mit dem HomeLab. | ||
| + | // Das Programm lässt eine LED immer nach ~1 Sekunde blinken. | ||
| + | // | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | // | ||
| + | // Festlegung des Pins der Test-LED. | ||
| + | // | ||
| + | pin debug_led = PIN(B, 7); | ||
| + | |||
| + | // | ||
| + | // Hauptprogramm. | ||
| + | // | ||
| + | int main(void) | ||
| + | { | ||
| + | // LED Pin als Output setzen. | ||
| + | pin_setup_output(debug_led); | ||
| + | |||
| + | // Endlosschleife. | ||
| + | while (true) | ||
| + | { | ||
| + | // Aufleuchten der LED. | ||
| + | pin_clear(debug_led); | ||
| + | |||
| + | // Hardwareverzögerung von 100 ms. | ||
| + | hw_delay_ms(100); | ||
| + | |||
| + | // Ausschalten der LED. | ||
| + | pin_set(debug_led); | ||
| + | |||
| + | // Hardwareverzögerung von 900 ms. | ||
| + | hw_delay_ms(900); | ||
| + | } | ||
| + | } | ||
| + | </ | ||