Hallo

Die Library der bee ist durch ihre vielen Einzeldateien für Anfänger nicht einfach zu durchschauen. Was den Einstieg zudem erschwert ist die Verwendung von Makros (in iodefs.h definiert) für den Zugriff auf die Kontrollerregister. Um die von der Lib belegten Timer zu finden bleibt letzlich nur der beschwerliche Weg jeweils die Init-Funktionen die Teildateien zu untersuchen. Dann wird man in motpwm.c fündig: Hier wird in motpwm_init() der Timer 1 zur PWM-Ansteuerung der Motoren parametriert.

Ein Timer/Counter besteht aus einem Zählregister TCNTx, einem Vergleichsregister OCRx und einem Kontrollregister TCCRx (x steht hierbei für die Nummer des Timers)

Das Zählregister wird mit dem Timertakt von der Hardware unabhängig vom Programm weitergezählt. Neben anderen Möglichkeiten kann man den Timertakt auch aus dem Kontrollertakt erzeugen, Mithilfe des im Kontrollregister einstellbaren Prescaler (=Vorteiler) kann man den Timertakt verlangsamen.

Bei bestimmten "Ereignissen" kann der Timer eine Interruptanforderung erzeugen. Diese wird vom Kontroller erkannt und bearbeitet, wenn der entsprechende Interrupt im TIMSK-Register (TIMer interrupt maSKe) aktiviert ist und die Interrupts generell erlaubt sind (sei()).

Ein mögliches Ereigniss ist der Überlauf des Zählregisters. Wenn dies auftritt, wird ein Overflow-Interrupt signalisiert und die zugehörige Interruptserviceroutine ISR(TIMERx_OVF_vect) ausgeführt. Ein weiteres Ereigniss ist eine Übereinstimmung des Zählregisters mit dem Inhalt des Vergleichsregisters. Dieses Ereigniss erzeugt einen Match-Compare-Interrupt ISR(TIMERx_COMP_vect) (treffender Vergleich)

Die Timer kennen verschiedene Modi. Beim normalen Mode wird das Zählregister stur durchgezählt. Beim CTC-Mode wird nur bis zum Wert im Vergleichsregister gezählt, dann ein Comp-Interrupt ausgelöst und das Zählregister wieder auf null gesetzt. In der Fast-PWM-Betriebsart wird ebenfalls aufwärts gezählt, allerdings können hier bei 16-bit-Countern die Anzahl der Bits des Zählregisters verändert werden. Letztlich gibt es noch den Phase-Correct-PWM-Mode. Dieser zählt aufwärts bis zum Maxwert des Zählregisters und zählt dann rückwärts (!) wieder auf null. Bei null wird dann ein Overflow ausgelöst, Comp tritt bei Gleichheit mit dem Vergleichsregister in beiden Zählrichtungen auf!

Jetzt wagen wir uns mal an die Praxis. Grundkenntnisse in C sollten vorhanden sein, Zugriff auf Register des Kontrollers sollte beherrscht werden, das Datenblatt sollte bereit liegen und der Schaltplan der bee könnte auch hilfreich sein. Die gestellte Aufgabe: Eine Led im Sekundentakt blinken lassen. Ich wähle LED3 an Port B3. Da Timer1 schon belegt ist, verwenden wir Timer0.

Bevor wir nun losprogrammieren müssen wir etwas rechnen. Die bee läuft mit 15MHz Kontrollertakt. Wenn wir den Takt mit 1024 vorteilen kommen wir auf knapp 15000 Zähltakte pro Sekunde, bei 256 Zählschritten bis zum Überlauf ergibt das ca. 57 ISR-Aufrufe pro Sekunde:

Code:
// LED3 ansteuern mit Timer 0                                          14.3.2010 mic

#include <nibobee/iodefs.h>
#include <avr/interrupt.h>

int main(void)
{
   TCCR0 = (1<<CS02) | (1<<CS00); 		// Normal Mode, kein OC0-Pin, prescaler /1024
   TIMSK |= (1<<TOIE0); 					// Timer0 Overflow-Interrupt erlauben
   
	enable_interrupts();
   
   DDRB |= (1<<PB3); 						// LED an einem Ausgang
   PORTB &= ~(1<<PB3); 						// LED aus
   
	while(1)
	{
	   // nix zu tun
   }

}
ISR(TIMER0_OVF_vect)
{
	static uint8_t count=0;

	count++;
	if(count == 57) PORTB |= (1<<PB3); 	// LED an
	if(count > 2*57)
	{
		PORTB &= ~(1<<PB3); 					// LED aus
		count=0;
	}
}
Der eigentliche Trick ist natürlich eine günstige Kombination aus Prescaler und Betriebsart des Timers zu finden. Das Beispiel dient nur zum Einstieg...

Gruß

mic