Timers


DOCUMENTATION


1 - Qu’est ce qu’un timer ?

Un périphérique Timer est un Compteur, que l’on utilise en parallèle d’un processeur pour :

  • Effectuer une Temporisation
  • Générer un Signal PWM ( mode Waveform )
  • Compter des événements extérieurs ( mode Capture )

2 - Le périphérique Timer

L’élément principal du périphérique est le compteur TIMx_CNT.
Lorsque la valeur contenue dans TIMx_CNT est égale à celle se trouvant dans TIMx_ARR, l’unité de contrôle peut :

  • Arrêter le comptage ( STOP ON MATCH )
  • Relancer le comptage ( RESET ON MATCH )

Le Prescale Counter permet de prédiviser l’horloge à l’entrée du périphérique.

timer_simple.svg


3 - Exemple de Fonctionnement Périodique

Calcul de la Période TCNT T_{CNT} ( Période de remise à 0 du compteur principal )

chronogramme.svg

On connait la fréquence de l’horloge d’entre FCKPSC=84MHz F_{CKPSC} = 84MHz
Le Prescale Counter se remet à 0 tous les TPSC=3.TCKPSC=(PSC+1).TCKPSC T_{PSC}=3.T_{CKPSC} = ( PSC+1 ).T_{CKPSC}
Le compteur principal TIMx_CNT se remet à 0 tous les

TCNT=(ARR+1).(PSC+1).TCKPSC T_{CNT} = (ARR+1).(PSC+1).T_{CKPSC}

A.N.

TCNT=(3+1).(2+1).184.106 T_{CNT}= (3+1).(2+1).\frac{1}{84.10^6}
TCNT=1.43107s T_{CNT}= 1.43 10^{-7}s


4 - Programmation du périphérique Timer

Modèle de Programmation

registres_timer.svg

Nous allons considérer la structure TIM_HandleTypeDef suivante :

stm32f4xx_hal_tim.h
typedef struct
{
  TIM_TypeDef                 *Instance;     /*!< Register base address             */
  TIM_Base_InitTypeDef        Init;          /*!< TIM Time Base required parameters */
} TIM_HandleTypeDef;

TIM_TypeDef Permet d’accéder aux différents registres du TIMER :

stm32f411xe.h
typedef struct
{
  __IO uint32_t CR1;         /*!< TIM control register 1,              Address offset: 0x00 */
  __IO uint32_t CR2;         /*!< TIM control register 2,              Address offset: 0x04 */
  __IO uint32_t SMCR;        /*!< TIM slave mode control register,     Address offset: 0x08 */
  __IO uint32_t DIER;        /*!< TIM DMA/interrupt enable register,   Address offset: 0x0C */
  __IO uint32_t SR;          /*!< TIM status register,                 Address offset: 0x10 */
  __IO uint32_t EGR;         /*!< TIM event generation register,       Address offset: 0x14 */
  __IO uint32_t CCMR1;       /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
  __IO uint32_t CCMR2;       /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
  __IO uint32_t CCER;        /*!< TIM capture/compare enable register, Address offset: 0x20 */
  __IO uint32_t CNT;         /*!< TIM counter register,                Address offset: 0x24 */
  __IO uint32_t PSC;         /*!< TIM prescaler,                       Address offset: 0x28 */
  __IO uint32_t ARR;         /*!< TIM auto-reload register,            Address offset: 0x2C */
  __IO uint32_t RCR;         /*!< TIM repetition counter register,     Address offset: 0x30 */
  __IO uint32_t CCR1;        /*!< TIM capture/compare register 1,      Address offset: 0x34 */
  __IO uint32_t CCR2;        /*!< TIM capture/compare register 2,      Address offset: 0x38 */
  __IO uint32_t CCR3;        /*!< TIM capture/compare register 3,      Address offset: 0x3C */
  __IO uint32_t CCR4;        /*!< TIM capture/compare register 4,      Address offset: 0x40 */
  __IO uint32_t BDTR;        /*!< TIM break and dead-time register,    Address offset: 0x44 */
  __IO uint32_t DCR;         /*!< TIM DMA control register,            Address offset: 0x48 */
  __IO uint32_t DMAR;        /*!< TIM DMA address for full transfer,   Address offset: 0x4C */
  __IO uint32_t OR;          /*!< TIM option register,                 Address offset: 0x50 */
} TIM_TypeDef;

TIM_Base_InitTypeDef Permet de définir les différents éléments de configuration :

stm32f4xx_hal_tim.h
typedef struct
{
  uint32_t Prescaler;
  uint32_t CounterMode;
  uint32_t Period;
  uint32_t AutoReloadPreload;
} TIM_Base_InitTypeDef;

Fonction de Temporisation

Nous allons configurer le timer de telle sorte qu’il se réinitialise à 0 toutes les 1 seconde.

Initialisation

La fonction HAL_TIM_Base_Init() permet de définir les registres PSC et ARR, et le mode de fonctionnement.

stm32f4xx_hal_tim.c
int HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
{
	htim->Instance->SR &= ~0x1F; // clear pending interrupts
	htim->Instance->CR1 = (htim->Instance->CR1 & 0xFC00); // set mode
	htim->Instance->PSC = htim->Init.Prescaler; // set prescaler
	htim->Instance->ARR =htim->Init.Period; 	// set period
	
    return 0;
}

Dans la phase d’initialisation de la fonction main :

main.c
	uint32_t prescalerValue;
	prescalerValue = (uint32_t) SystemCoreClock;
	htim5.Instance = TIM5;
	htim5.Init.Period = 	// A COMPLETER;
	htim5.Init.Prescaler =  // A COMPLETER;
	HAL_TIM_Base_Init(&htim5);

La variable SystemCoreClock retourne une valeur de 84e6 Hz, correspondant à FCKPSC F_{CKPSC}

Etant donné que TCNT=(ARR+1).(PSC+1).TCKPSC T_{CNT} = (ARR+1).(PSC+1).T_{CKPSC}, que peut on mettre dans ARR et PSC pour que TCNT=1sT_{CNT} = 1s ?

ATTENTION : les registres ARR et PSC ont une taille de 16 bits.


5 - Travaux Pratiques

PROJET SOURCE

WORKSPACE_F411_HAL_STM32CUBE.zip

Temporisation

Q1. Compléter les fonctions suivantes :

  • HAL_TIM_Base_Start() : Remise à zéro du comptage et autorisation du comptage
  • HAL_TIM_Base_Stop() : Arrêt du comptage

Q2. Vérifier le bon fonctionnement du timer en faisant clignoter une led selon la valeur courante de comptage contenue dans CNT.

Q3. Proposer des valeurs pour PSC et ARR afin que le compteur principal s’incrémente toutes les 100µs, et que la fin de comptage ait lieu toutes les 500ms.

REMARQUE : Dès lors que le processeur est constamment occupé à surveiller le contenu d’un registre, nous avons ici en fonctionnement en scrutation.