Timers
Tous les microcontrôleurs sont équipés de dispositifs appelés "timers". Ce sont des compteurs / décompteurs qui offrent de nombreuses fonctionnalités :
- générer une interruption lorsqu'ils ont atteint une certaine valeur, ce qui permet d'effectuer des tâches à intervalles réguliers
- changer automatiquement l'état d'une une broche du microprocesseur, ce qui permet de générer facilement du PWM
- compter non pas les cycles d'horloges mais des événements externes
- déterminer automatiquement la largeur d'un créneau appliqué à une broche externe
- etc.
Les Cortex incluent tous un timer spécial appelé SysTick
. Ce timer est fait spécifiquement pour donner une base de temps aux OS multitâches, de façon à ce qu'ils puissent effectuer des changements de contexte à intervalles réguliers.
Les microcontrôleurs incluent d'autres timers en tant que périphériques externes, disponibles pour l'utilisateur (le SysTick
étant généralement réservé à l'OS). Le STM32L475VGT6 dispose de plusieurs timers (9 TIMx et 2 LPTIM).
Il y a quelques différences de fonctionnalités entre les différents timer, mais ils partagent les caractéristiques suivantes (voir le manuel de référence pour le détail):
- une résolution de 16 ou 32 bits
- mode PWM, comptage/décomptage, déclenchement de DMA, ou d’interruptions...
- peuvent être utilisés indépendamment ou chaînés si nécessaire
- peuvent être reliées aux IOs (en sortie ou en entrée pour la capture d’événements)
Mise en œuvre du TIM2
Le TIM2 est un "general-purpose timer" avec une résolution de 32 bits (voir page 1012 du manuel). Nous allons l'utiliser pour générer régulièrement des interruptions pour avoir une base de temps qui nous permettra de synchroniser certains événements (faire clignoter une led puis mettre à jour la matrice de leds)
L'horloge du timer
Le timer TIM2 est connecté sur le bus APB1 (voir figure 15 page 208).
Ce timer est sur le bus APB1. Comme l'horloge de ce bus (PCLK1
) est la même que l'horloge principale (SYSCLK
) (défini par le champ PPRE1 de RCC_CFGR page 227), le timer utilisera aussi cette horloge (voir 6.2.15 page 218).
Configuration du timer
Nous voudrions avoir le comportement suivant :
- mode compteur (upcounter)
- le compteur change chaque microseconde (fréquence de 1MHz)
- auto chargement (quand le compteur arrive à la valeur max, il repasse à 0 et recommence)
- génération d'un événement à chaque fois qu'il repasse à 0 (update event) qui servira comme source d'interruption
❎ Dans un fichier timer.c
écrivez la fonction void timer_init(int max_us)
qui effectue les initialisations suivantes:
- active l'horloge du timer TIM2 (chercher le bon
ENR
du RCC) - effacer d'éventuels flags dans le registre de statut (
TIMx_SR
) et mettre à zéro la valeur du compteur (TIMx_CNT
) - configurer le timer pour avoir le bon mode de fonctionnement, sans l'activer
- changer le prescaler du timer (
TIMx_PSC
) pour compter à la microseconde - modifier la valeur d'auto chargement (
TIMx_ARR
) en fonction du paramètre de la fonction - autoriser la génération d'une interruption sur l'événement de mise à jour du timer (
TIMx_DIER
) - autoriser l'interruption de TIM2 au niveau du NVIC (attention, il faudra avoir un nouveau handler comme décrit dans la suite)
- activer le timer
❎ Pour pouvoir tester que l'interruption est bien prise en compte, dans le même fichier, redéfinir le handler pour le TIM2 pour changer l'état de la led verte à chaque interruption.
❎ Dans le programme principal, appeler la fonction d'initialisation du timer pour que la led clignote toutes les secondes
Fonctionnement de la matrice sous IRQ
❎ Faites maintenant en sorte que l'affichage de la matrice soit géré par des interruptions du timer: affichage de l'image courante au moins 60 fois par seconde.
❎ L'affichage est-il régulier ? Toutes les lignes bénéficient-elles du même temps d'exposition ? Si ce n'est pas le cas, modifiez votre programme pour que le timer détermine la date d'affichage de chaque ligne plutôt que la date d'affichage de chaque image.
❎ N'oubliez pas de commiter avec le tag TIMERS
.