esprit ingénieur

Introduction aux Microcontrôleurs et Interruptions

SA
StudyAI
AI-generated study notes
· Published Updated

From the architecture de microcontrolleur curriculum

TL;DR

Un microcontrôleur est un petit ordinateur autonome intégré qui contrôle des fonctions spécifiques. Les interruptions sont des signaux qui permettent au microcontrôleur de suspendre sa tâche actuelle pour gérer un événement urgent. Comprendre les interruptions est crucial pour concevoir des systèmes réactifs et efficaces.

1. The Mental Model

Imaginez que votre microcontrôleur est un cuisinier très occupé qui suit une recette (votre programme principal). Une interruption, c'est comme une minuterie de four qui sonne : le cuisinier arrête ce qu'il fait, vérifie le four, puis reprend sa recette exactement où il l'a laissée.

2. The Core Material

Un microcontrôleur (MCU) est un système sur puce qui contient un processeur, de la mémoire (RAM, ROM) et des périphériques d'entrée/sortie (GPIO, ADC, UART, etc.). Il est conçu pour exécuter des tâches spécifiques dans des systèmes embarqués, contrairement à un microprocesseur qui nécessite des composants externes pour fonctionner.

Le programme principal d'un microcontrôleur s'exécute généralement en boucle infinie (la fameuse while(1) ou for(;;)). Cependant, certains événements ne peuvent pas attendre que la boucle les vérifie. C'est là que les interruptions interviennent.

Une interruption est un signal matériel ou logiciel qui indique au processeur qu'un événement urgent s'est produit et qu'il doit s'arrêter temporairement pour le traiter. Lorsque le processeur reçoit une interruption :
1. Il suspend l'exécution de son programme actuel.
2. Il sauvegarde le contexte actuel (registres, compteur ordinal).
3. Il saute à une routine spécifique appelée Routine de Service d'Interruption (ISR - Interrupt Service Routine) ou gestionnaire d'interruption.
4. L'ISR exécute le code nécessaire pour traiter l'événement.
5. Une fois l'ISR terminée, le processeur restaure le contexte sauvegardé.
6. Il reprend l'exécution du programme principal exactement là où il l'avait laissé.

Il existe différents types d'interruptions :
* Interruptions externes : Déclenchées par des broches GPIO (par exemple, un bouton pressé).
* Interruptions de minuterie : Déclenchées par un débordement de minuterie/compteur.
* Interruptions de communication : Déclenchées par l'arrivée de données sur un port série (UART), SPI, I2C.
* Interruptions logicielles : Déclenchées par des instructions spécifiques dans le code.

Pour utiliser une interruption, tu dois :
1. Configurer la source d'interruption : Par exemple, quelle broche GPIO, quel mode (front montant/descendant) pour une interruption externe.
2. Activer l'interruption : Globalement (pour le processeur) et localement (pour le périphérique concerné).
3. Écrire l'ISR : Le code qui sera exécuté lorsque l'interruption se produit. Il doit être le plus court et rapide possible.
4. Effacer le drapeau d'interruption : Indiquer au périphérique que l'interruption a été traitée afin qu'il puisse générer de nouvelles interruptions.

graph TD
    A["Programme Principal (boucle infinie)"] --> B{Événement d'interruption ?}
    B -->|Non| A
    B -->|Oui| C["Sauvegarde du Contexte"]
    C --> D["Saut vers l'ISR"]
    D --> E["Exécution de la Routine de Service d'Interruption (ISR)"]
    E --> F["Effacement du drapeau d'interruption"]
    F --> G["Restauration du Contexte"]
    G --> A

Exemples de configurations (pseudo-code pour un STM32)

A dual screen setup showcasing programming code and image editing software.
Photo by Pixabay on Pexels

// Configuration d'une interruption sur une broche GPIO
void setup_external_interrupt() {
    // 1. Activer l'horloge du port GPIO et du périphérique SYSCFG
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;

    // 2. Configurer la broche PA0 comme entrée
    GPIOA->MODER &= ~(GPIO_MODER_MODER0); // Input mode

    // 3. Configurer l'interruption externe (EXTI) pour PA0
    // Lier EXTI0 à PA0
    SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR1_EXTI0_Msk;
    SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PA;

    // Configurer le déclenchement sur front montant pour EXTI0
    EXTI->RTSR |= EXTI_RTSR_RT0; // Rising edge trigger
    EXTI->FTSR &= ~EXTI_FTSR_FT0; // Disable falling edge

    // 4. Activer l'interruption EXTI0
    EXTI->IMR |= EXTI_IMR_IM0; // Unmask EXTI line 0

    // 5. Configurer et activer l'interruption dans le contrôleur d'interruption (NVIC)
    NVIC_SetPriority(EXTI0_IRQn, 0); // Priorité (la plus haute ici)
    NVIC_EnableIRQ(EXTI0_IRQn);      // Activer l'interruption EXTI0
}

// La Routine de Service d'Interruption (ISR)
void EXTI0_IRQHandler(void) {
    if ((EXTI->PR & EXTI_PR_PR0) != 0) { // Vérifier si l'interruption EXTI0 s'est produite
        // Votre code de gestion d'événement ici
        // Par exemple, basculer une LED
        GPIOA->ODR ^= GPIO_ODR_ODR5; // Supposons LED sur PA5

        // EFFACER le drapeau d'interruption !
        EXTI->PR |= EXTI_PR_PR0; // Écrire 1 pour effacer le bit du drapeau
    }
}

3. Worked Example

Imaginez que vous voulez allumer une LED sur la broche PA5 d'un microcontrôleur STM32F4 quand vous appuyez sur un bouton connecté à la broche PA0. Sans interruption, votre programme principal devrait constamment vérifier l'état de la broche PA0. Avec une interruption, la LED réagit instantanément, peu importe ce que fait le programme principal.

#include "stm32f4xx.h" // Inclure les en-têtes nécessaires pour le microcontrôleur

// Fonction pour configurer l'horloge et les GPIOs
void SystemClock_Config(void);
void GPIO_Init(void);
void EXTI0_Config(void);

int main(void) {
    SystemClock_Config(); // Initialisation de l'horloge système
    GPIO_Init();          // Initialisation des GPIOs (PA0 pour bouton, PA5 pour LED)
    EXTI0_Config();       // Configuration de l'interruption sur PA0

    while (1) {
        // Le programme principal peut faire autre chose ici
        // Par exemple, clignoter une autre LED ou effectuer des calculs
        // La réactivité du bouton n'est pas affectée par cette boucle
    }
}

// Configuration basique de l'horloge (pour l'exemple, pas nécessairement optimisée)
void SystemClock_Config(void) {
    // Activer l'oscillateur interne HSI
    RCC->CR |= RCC_CR_HSION;
    while (!(RCC->CR & RCC_CR_HSIRDY));

    // Configurer HSI comme source d'horloge système
    RCC->CFGR &= ~RCC_CFGR_SW;
    RCC->CFGR |= RCC_CFGR_SW_HSI;
    while (!((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSI));
}

// Initialisation des GPIOs
void GPIO_Init(void) {
    // Activer l'horloge du port GPIOA
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

    // Configurer PA0 comme entrée (bouton)
    GPIOA->MODER &= ~(GPIO_MODER_MODER0); // 00: Input mode

    // Configurer PA5 comme sortie (LED)
    GPIOA->MODER &= ~(GPIO_MODER_MODER5); // Clear bits 11:10
    GPIOA->MODER |= GPIO_MODER_MODER5_0;  // 01: General purpose output mode
    GPIOA->OTYPER &= ~GPIO_OTYPER_OT_5;   // Push-pull
    GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEEDR5; // Low speed
    GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR5;   // No pull-up/pull-down
}

// Configuration de l'interruption sur EXTI0 (PA0)
void EXTI0_Config(void) {
    // Activer l'horloge de SYSCFG
    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;

    // Lier EXTI0 à PA0
    SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR1_EXTI0_Msk; // Clear bits 3:0
    SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PA;   // Select PA0 for EXTI0

    // Configurer le déclenchement sur front montant pour EXTI0
    EXTI->RTSR |= EXTI_RTSR_RT0; // Activer le déclenchement sur front montant
    EXTI->FTSR &= ~EXTI_FTSR_FT0; // Désactiver le déclenchement sur front descendant

    // Activer l'interruption EXTI0 (démasquer la ligne d'interruption)
    EXTI->IMR |= EXTI_IMR_IM0;

    // Configurer et activer l'interruption dans le contrôleur d'interruption vectorisée (NVIC)
    NVIC_SetPriority(EXTI0_IRQn, 0); // Définir la priorité de l'interruption (0 étant la plus haute)
    NVIC_EnableIRQ(EXTI0_IRQn);      // Activer l'interruption EXTI0 dans le NVIC
}

// Routine de Service d'Interruption pour EXTI0
void EXTI0_IRQHandler(void) {
    // Vérifier si l'interruption EXTI0 est la source
    if ((EXTI->PR & EXTI_PR_PR0) != 0) {
        // Basculer l'état de la LED sur PA5
        GPIOA->ODR ^= GPIO_ODR_ODR5;

        // Effacer le drapeau de l'interruption pour EXTI0
        // C'est CRUCIAL, sinon l'ISR sera appelée en boucle
        EXTI->PR |= EXTI_PR_PR0; // Écrire un '1' pour effacer le bit
    }
}

4. Key Takeaways

  • Un microcontrôleur est un ordinateur complet sur une seule puce, optimisé pour des tâches embarquées.
  • Les interruptions permettent de réagir immédiatement à des événements externes ou internes sans bloquer le programme principal.
  • Chaque interruption a une Routine de Service d'Interruption (ISR) dédiée qui exécute le code de gestion.
  • Les ISRs doivent être aussi courtes et rapides que possible pour minimiser le temps d'interruption et ne pas bloquer les autres tâches.
  • Après avoir traité une interruption, tu dois toujours effacer son drapeau pour permettre de nouvelles interruptions du même type.

Common Mistakes to Avoid

Flat lay of a spiral notebook and eraser on a pastel pink background with crossed out words.
Photo by KATRIN BOLOVTSOVA on Pexels

  • Oublier d'effacer le drapeau d'interruption : Cela entraîne des appels répétitifs et infinis de l'ISR.
  • Faire trop de travail dans l'ISR : Les ISRs doivent être courtes. Les tâches longues devraient être signalées au programme principal (par exemple via un drapeau ou une file d'attente) pour être traitées hors de l'ISR.
  • Ne pas gérer les priorités d'interruption : Si plusieurs interruptions peuvent se produire en même temps, celles de haute priorité pourraient être bloquées par des ISRs de basse priorité.
  • Accéder à des variables partagées sans protection : Si l'ISR et le programme principal accèdent à la même variable, cela peut entraîner des problèmes si elle n'est pas déclarée volatile ou protégée par des mécanismes d'exclusion mutuelle.

5. Now Try It

Connecte une LED et un bouton à ton microcontrôleur (par exemple, un STM32 Nucleo ou Arduino si tu as une couche d'abstraction). Configure l'interruption sur la broche du bouton pour qu'à chaque pression, la LED change d'état (s'allume si éteinte, s'éteint si allumée). Utilise le code d'exemple comme point de départ, mais assure-toi de vérifier les registres exacts et les bits pour ton modèle de MCU spécifique. Si tu utilises un Arduino, utilise la fonction attachInterrupt(). Le succès, c'est que la LED réagit instantanément à chaque pression, peu importe ce que fait le programme principal (même si le while(1) est vide).

Frequently asked about Introduction aux Microcontrôleurs et Interruptions

Un microcontrôleur est un petit ordinateur autonome intégré qui contrôle des fonctions spécifiques. Les interruptions sont des signaux qui permettent au microcontrôleur de suspendre sa tâche actuelle pour gérer un événement urgent. Read the full notes above for the details.

Introduction aux Microcontrôleurs et Interruptions is a core topic in architecture de microcontrolleur. Most exam papers test it via a mix of definitions, worked examples, and applied problems. The notes above cover the high-yield sub-topics, common pitfalls, and the kind of questions examiners typically set.

Yes — every note in the StudyAI Campus Hub is free to read in full, right here on this page, with no account needed. If you clone the plan into your own dashboard, the free plan shows a preview of each note there; Basic and above unlock the full notes in your dashboard, along with practice quizzes, flashcards and offline study. You can always come back here to read the complete note for free.

Study this next


Get the full architecture de microcontrolleur curriculum

Clone the complete plan to your dashboard for unlimited AI-generated notes, practice quizzes, and a personalised revision schedule.

Save this course free