Blue Pill - GPIOs - PINs - IRQs

Table des matières

TL;DR

Mise en place d'une interruption externe.

Le matériel

En plus du montage précédent: Ce bouton va permettre de basculer en mode "EMERGENCY" où seule la LED "ORANGE" clignote.

Interruption externe

Pour faire simple, il est possible de générer une interruption quand une PIN, configurée en entrée, change d'état. Appuyer sur le bouton va faire passer la PIN de l'état bas à haut (rising), relâcher le bouton fera passer la PIN de l'état haut à bas (falling). Les instructions pour mettre en place une interruption externe se trouvent page 208 paragraphe 10.2.4 Functional description du manuel de référence (RM0008):
  1. activer les lignes d'interruption dans le registrer IMR (Interrupt Mask Register) du composant EXTI (EXTernal Interrupt)
  2. activer les déclencheurs des lignes dans les registres FTSR (Falling Trigger Selection Register) et/ou RTSR (Rising ...)
  3. définir les gestionnaires d'interruption correspondant aux lignes d'interruption
Par soucis de simplicité, le montage précédent est modifié comme suit: et config.h devient:
...
#define SWITCH_GPIO  GPIOA
#define SWITCH_PIN   7
...
#define BUTTON_GPIO  GPIOA
#define BUTTON_PIN   0
...

Le montage modifié.

Quelques petites choses à savoir avant d'envoyer le code: L'extrait du config.h:
     1	#define BUTTON_EXTICR_IDX  (BUTTON_PIN / 4)
     2	#define BUTTON_EXTICR_VAL  AFIO_EXTICR1_EXTI0_PA  // 1 == 1 + (BUTTON_PIN / 4), 0 == BUTTON_PIN, A == BUTTON GPIO
     3	#define BUTTON_EXTI_PR     EXTI_PR_PR0            // 0 == BUTTON_PIN
     4	#define BUTTON_FTSR        EXTI_FTSR_TR0          // F == Falling, 0 == BUTTON_PIN
     5	#define BUTTON_HANDLER     EXTI0_IRQHandler       // cf STM32-base-master/startup/STM32F1xx/STM32F103xB.s
     6	#define BUTTON_IMR         EXTI_IMR_MR0           // 0 == BUTTON_PIN
     7	#define BUTTON_IRQn        EXTI0_IRQn             // 0 == BUTTON_PIN
     8	
     9	#define APB2_EN  RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN // GPIOA + AFIO
  1. index du registre de configuration du composant EXTI
  2. valeur à utiliser dans le registre de configuration
  3. valeur à utiliser pour acquitter l'interruption
  4. l'interruption se déclenche quand la PIN passe de l'état haut à l'état bas (Falling) donc quand on relâche le bouton
  5. nom du gestionnaire d'interruption
  6. ligne d'interruption à prendre en compte
  7. numéro d'interruption
et pour finir on active aussi le composant AFIO. Extraits du programme principal:
...
enum STATES { INIT = 0, RED, ORANGE, GREEN, EMERGENCY };
...
    gpio_pin_init(BUTTON_GPIO, BUTTON_PIN, I_PU_PD);
...
    __disable_irq();
    AFIO->EXTICR[BUTTON_EXTICR_IDX] = BUTTON_EXTICR_VAL;
    EXTI->IMR  |= BUTTON_IMR;
    EXTI->FTSR |= BUTTON_FTSR;
    NVIC_EnableIRQ(BUTTON_IRQn);
    __enable_irq();
...
        else if (state == EMERGENCY) {
            SWITCH_GPIO->ODR ^= 1 << SWITCH_PIN; // toogle state
        }
...
void
BUTTON_HANDLER(void) {
    EXTI->PR |= BUTTON_EXTI_PR; // Reset irq

    if (state == EMERGENCY) {
        state             = RED;
        SWITCH_GPIO->BSRR = 1 << SWITCH_PIN; // PIN high SWITCH on
        ORANGE_GPIO->BSRR = 1 << ORANGE_PIN; // PIN high ORANGE off
        RED_GPIO->BRR     = 1 << RED_PIN;    // PIN low RED on
    }
    else {
        if (state == RED) {
            RED_GPIO->BSRR = 1 << RED_PIN; // PIN high RED off
        }
        else if (state == GREEN) {
            GREEN_GPIO->BSRR = 1 << GREEN_PIN; // PIN high GREEN off
        }
        state            = EMERGENCY;
        ORANGE_GPIO->BRR = 1 << ORANGE_PIN; // PIN low ORANGE on
    }
    systick_irqs = 0;
}
  1. nouvel état "EMERGENCY"
  2. la PIN du bouton est en Input Pull Up / Pull Down
  3. mise en place de l'interruption
  4. nouvel état à prendre en compte
  5. gestionnaire d'interruption

Même si ici cela ne s'impose pas, la mise en place de l'interruption est encadrée par les fonctions __disable_irq et __enable_irq afin qu'une éventuelle autre interruption ne vienne pas interrompre le code.

Le code complet: https://gitlab.com/dsx/blue-pill/-/tree/master/stm32f103c8t6/00_gpios_ext_irq