1

TUTO XMEGA (ASF) : Timer en mode NORMAL

La derniere version de ce tuto est disponible sur le WIKI

Créer un nouveau projet ASF.

Importer les librairies qui sont nécessaires. Cliquer sur ASF → ASF Wizard. Chercher les librairies suivantes :

  • TC – Timer Counter (driver)
  • GPIO – Généra purpose Input/Output
  • Generic board support (elle integre des fonctions qui seront necessaire pour utiliser la librairie delay)
  • IOPORT – Généra purpose Input/Output (Librairie que nous avons vu dans la partie entrée/sorties.

Nous allons utiliser l’horloge par défaut de 2Mhz.
L’objectif de cette exemple sera de faire clignoter une LED toutes les secondes.

Dans le principe de fonctionnement, le timer est cadencé par une horloge. A chaque coup d’horloge, le compteur va s’incrémenter.

Nous utiliserons le Timer 0 qui est un timer de 16bits. Il a donc, au maximum, 65535 pas d’incrémentation.

Nous voulons que la LED s’allume toutes les secondes. Le timer doit donc déclencher un interruption toutes les 500ms.

Avec un horloge à 2Mhz cela nous fait un pas d’incrémentation toutes 0.5µs même si le compteur allait jusqu’à 65535 cela nous ferait 33ms de temps entre chaque interruption sachant que nous voulons environ 500ms.

Nous avons le choix entre les diviseurs suivants :

    TC_CLKSEL_DIV1_gc = (0x01<<0),  /* System Clock */
    TC_CLKSEL_DIV2_gc = (0x02<<0),  /* System Clock / 2 */
    TC_CLKSEL_DIV4_gc = (0x03<<0),  /* System Clock / 4 */
    TC_CLKSEL_DIV8_gc = (0x04<<0),  /* System Clock / 8 */
    TC_CLKSEL_DIV64_gc = (0x05<<0),  /* System Clock / 64 */
    TC_CLKSEL_DIV256_gc = (0x06<<0),  /* System Clock / 256 */
    TC_CLKSEL_DIV1024_gc = (0x07<<0),  /* System Clock / 1024 */

Nous allons donc diviser la fréquence par 64. Ce qui nous fera un pas d’incrémentation toutes les 32µs. Pour avoir un période de 500ms, il faudra que notre compteur compte jusqu’à 500 000 / 32 = 15625

#include <asf.h>
 
//Led
#define LED IOPORT_CREATE_PIN(PORTR, 1)
 
//Déclenchement toutes les 500ms
static void timer0_tick(void)
{
	ioport_toggle_pin_level(LED); //Inverse l'état de la LED
}
 
int main (void)
{
	//Initialisation du controleur d'interruptions
	pmic_init();	
	//Initialisation de l'horloge	
	sysclk_init();		
 
	//Initialisation des entrées/sorties
	ioport_set_pin_dir(LED, IOPORT_DIR_OUTPUT);
 
	//Initialisation du Timer 0
	tc_enable(&TCC0);	
	tc_set_overflow_interrupt_callback(&TCC0, timer0_tick); //Création d'un callback qui sera executé quand un overflow du timer sera déclenché.
	tc_set_wgm(&TCC0, TC_WG_NORMAL);		//Choix du mode du timer0, dans ce cas il comptera jusqu'à sa valeur "TOP" et retombera à 0
	tc_write_period(&TCC0, 15625);			//Définition de la valeur "TOP"	
	tc_set_overflow_interrupt_level(&TCC0, TC_INT_LVL_LO);	//Activation de l'interruption du timer 
	cpu_irq_enable();										//Activation de l'interruption globale					
	tc_write_clock_source(&TCC0, TC_CLKSEL_DIV64_gc);		//Activation de l'horloge du timer 0
 
	board_init();
 
	while(1)
	{
 
	}
}

Explications :

pmic_init();

Initialise le controleur d’interruption. Sans ca, les interruptions du timer ne se déclencheront pas.

sysclk_init();

Initialise l’horloge système. Cf conf_clock.h (Horloge de 2Mhz sans prédivison)

tc_enable(&TCC0);

Active le timer0

tc_set_overflow_interrupt_callback(&TCC0, timer0_tick);

Définit que la fonction timer0_tick sera appelée à chaque interruption du timer 0. La fonction :

static void timer0_tick(void)
{
	ioport_toggle_pin_level(LED); //Inverse l'état de la LED
}

sera executée toutes les 500ms

tc_set_wgm(&TCC0, TC_WG_NORMAL);

Définit le mode de fonctionnement “Normal” du timer. Dans ce cas il comptera jusqu’à sa valeur “TOP”, déclenchera l’interruption overflow, repassera à 0 et ainsi de suite …

cpu_irq_enable();

Activation globale des interruptions

tc_write_clock_source(&TCC0, TC_CLKSEL_DIV64_gc);

On alimente le timer avec l’horloge système / 64

admin

One Comment

  1. Bravo pour ce tuto et son frère sur wikielectronique. Je n’ai rien vu d’équivalent ailleurs, surtout en mode ASF. Si j’était tombé sur votre site plus tôt j’aurais gagné du temps. Merci

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *