xmega_tutorial.jpg

Bewertung:  / 4
SchwachSuper 
  • xmega_block_diagram3D

Bei den Xmega Controllern sind jedem I/O-Port mehrere Timer/Counter-Module zugeordnet. Diese können verwendet werden um einen Interrupt auszulösen oder um die Ausgänge der I/O-Pins anzusteuern. Der Name des jeweiligen TC-Moduls setzt sich aus dem I/O-Port, an dem er angeschlossen ist und der Zahl der verfügbaren Timer/Counter Module zusammen (TCxn). TC ist die Abkürzung für Timer/Counter, das X zeigt den Port an den angeschlossenen Port und n ist die T/C-Nummer innerhalb des PORTx (zB. ist TCD0 Timer/Counter 0 an PORTD). Timer sind jeweils an PORTC, PORTD, PORTE und PORTF verfügbar dieser Portx an dem Controller verfügbar ist.

  • xmega_timer_pins
Jeweils der Timer0 an jedem Port verfügt über 4 compare or capture channels. Der Timer1 verfügt über 2 compare or capture channels. Die Abbildung (rechts) zeigt wie die einzelnen Output Compare-Channels der verschiedenen Timer an dem jeweiligem I/O-Port angeschlossen sind. Generell sind die Ausgänge von Timer0 mit den Pins 0-3 innerhalb eines Portx verbunden, während die Ausgänge von Timer1 mit den Pins 4 und 5 verbunden sind.

 

  • xmega_timer_diagram

Features

  • True 16 bit operation
  • Double buffered timer period setting
  • 4 (2) compare or capture channels per timer
    - 4 channels on each Timer 0
    - 2 channels on each Timer 1
    - Double buffered
  • 2 bit operation with 32 bit input capture by timer cascading
  • Event counter
  • Timer overflow and error interrupts (and events)
  • Input capture interrupts (and events)

Das folgende Beispiel zeigt eine Möglichkeit wie man einen Timer verwendet, um ein Event in bestimmten Zeitintervallen auszulösen. Dafür wird der Timer so konfiguriert, dass er im Takt von 1Khz, also jede Milisekunde einen Interrupt auslöst. In dem Beispiel wird der Timer C0 verwendet.  Um den am Timereingang anliegenden Systemtakt von 32Mhz in einen Takt von 1Khz zu skalieren wird dieser mit Hilfe des Prescalers durch 1024 geteilt. Dieser Teiler muss mit der entsprechenden Codierung in das "Control A Register” des verwendeten Timers geschrieben werden. Die Codierung kann man dem Datenblatt oder der folgenden Tabelle entnehmen.

CLKSEL[3:0]
0000
0001
0010
0011
0100
0101
0110
0111
1nnn

Group Configuration
OFF
DIV1
DIV2
DIV4
DIV8
DIV64
DIV256
DIV1024
EVCHn

Description
None (i.e, timer/counter in OFF state)
Prescaler: Clk
Prescaler: Clk/2
Prescaler: Clk/4
Prescaler: Clk/8
Prescaler: Clk/64
Prescaler: Clk/256
Prescaler: Clk/1024
Event channel n, n= [0,...,7]

Mit der Wahl des entsprechenden Prescalers wurde der Timer gleichzeitig aktiviert. Jetzt  muss nur noch der Topwert für den Timer berechnet und in das Periodenregister geschrieben werden. Bei einem CPU-Takt von 32Mhz, einem Prescaler von 1024 und einem gewünschten Eventintervall von 1Khz kann man den Wert wie folgt berechnen: Topwert = 65535 – (CPU_Takt/ Eventintervall/ Prescaler). Danach wird der Betriebsmodi des Timers durch das “Control B Register” ausgewählt. Für einen normalen Event-Timer wählt man den Modus "Normal Mode". Momentan zählt der Timer schon im Hintergrund und würde bei jedem Überlauf, beim Erreichen des Periodenregister ein Event auslösen. Diesem Event muss aber erst noch eine Priorität zugeordnet werden, damit es verarbeitet wird. Dazu wird im “Interrupt Enable Register A” die entsprechende Codierung eingetragen. Für das Beispiel wird die höchste Priorität verwendet.

Der Timer ist jetzt komplett konfiguriert, so dass nur noch die Eventroutine "ISR(TCC0_OVF_vect)" für den Timer geschrieben werden muss. Diese Routine wird jede Millisekunde aufgerufen und dekrementiert unsere Timervariable. Wenn die Variable Null wird, wird die LED in der Main-Schleife getoggelt und die Variable wieder auf 500ms gesetzt. Fertig!

Tutorial Xmega - Timer/ Counter
//################# Variablen
volatile int timer_blink = 500; // timer für echtzeit ausführung
 
//######################################################## initialisierung
void initialisierung(void)
{ 
 cli(); // Interrupts deaktivieren
 //################# Timer0 - 1Khz
 TCC0.CTRLA = TC_CLKSEL_DIV1024_gc; // Presacler 1024
 TCC0.CTRLB = 0x00; // select Modus: Normal
 TCC0.PER = 32; // Zähler Top-Wert 1000 Hz 
 TCC0.CNT = 0x00; // Zähler zurücksetzen
 TCC0.INTCTRLA = 0b00000011; // Interrupt Highlevel
 
 //################# Interrupts High-,Medium- und Lowlevel freigeben
 PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm; 
 sei(); // Interrupts aktivieren
}
//######################################################## Int TimerC0 1Khz 
ISR(TCC0_OVF_vect) 
{
 timer_blink--; if (timer_blink <0) {timer_blink= 0;} // Echtzeitablauf
}
//######################################################## Main
int main (void) 
{ 
 initialisierung();
 while(1) 
 { 
 //#################### while start 
 if (timer_blink <= 0) 
 { 
 /* zB. toggle Pin --> LED*/
 timer_blink=500;
 }
 //#################### while end
 } 
}

Hinweis:
Das Tutorial wird nach und nach von mir ergänzt. Wenn ihr Fehler in dem Tutorial findet, würde ich mich freuen wenn ihr mir diese mitteilt, damit ich diese korrigieren kann. Wenn jemand eigene Tips, Informationen oder Code-Schnipsel hat kann er mir diese gern zusenden, damit ich sie anschließend in das Tutorial einbinden kann.

Links

 
Atmel Appnote
Xmega Timer
AVR1306: Using the XMEGA Timer/Counter (pdf)
AVR1306: Using the XMEGA Timer/Counter (Software)
Kommentar hinzufügen

Neuste Beiträge

30/08/2016
Es gibt nun endlich ein Update für die Tinyg CNC Controller Hardware und der dazu gehörenden PC Software...
03/09/2015
In den letzten Monaten habe ich lange das CAD Programm und meinen kleinen Ultimaker 3D Drucker gequält....
15/05/2015
Zuerst wurde eine kleine Katze am Computer konstruiert. Der erste Druck mit 0,3mm Schichtstärke war...
06/05/2015
Da beim Ultimaker keine Beleuchtung des Arbeitstisches vorgesehen ist, muss ich mir hier selber eine...