Table of Contents

Hardwareverzögerung

Notwendiges Wissen: [HW] Controller module, [AVR] Counters/Timers, [LIB] Pins, [LIB] Delay, [LIB] Timers, [PRT] Software delay

Theorie

Neben der Softwareverzögerung gibt es auch Timer, um Unterbrechungen zu erzeugen. Timer sind Hardwarekomponenten, die mit einer bestimmten Frequenz hoch oder runter zählen. Die Taktfrequenz des Timers kann über die Frequenz des Mikrocontrollers oder einen externen Taktgeber erzeugt werden. Allgemein kann die Taktfrequenz mit einem Multiplikator dividiert werden um eine geringere Frequenz zu erreichen. Hierzu wird ein Vorteiler verwendet. Wichtig ist jedoch, dass die festgelegte Taktfrequenz des Timers linear zu der Zeit ist. Die Zeit kann durch Multiplikation der Periode der Taktfrequent des Timers mit dem Wert des Timers berechnet werden.

Durch Veränderung des AVR Timers hervorgerufene Ereignisse.

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 timer_start dargestellt. F_CPU, eine Konstante in der Makrosprache, gibt die Taktfrequenz in Hz an. Diese sollte 25,6 betragen, da nur ganze Zahlen berücksichtigt werden, liegt der Startwert bei 26. Leider entsteht hier eine gewisse Ungenauigkeit, welche aber sehr gering ist (- 1,7µs).

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.

//
// 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 ("nop");
		}			
	}
 
	// Ü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.

//
// Beispielprogramm für eine Hardwareverzögerung mit dem HomeLab.
// Das Programm lässt eine LED immer nach ~1 Sekunde blinken.
//
#include <homelab/pin.h>
#include <homelab/delay.h>
 
//
// 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);
	}
}
de/examples/timer/hardware_delay.txt · Last modified: 2020/07/20 09:00 by 127.0.0.1
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0