Réagissez instantanément aux événements avec les interruptions matérielles
Une interruption est un mécanisme matériel qui permet au microcontrôleur de suspendre temporairement l'exécution du programme principal pour traiter un événement urgent (appui sur un bouton, fin de conversion ADC, débordement d'un timer, etc.).
Sans interruption, le processeur devrait constamment vérifier (« polling ») si un événement s'est produit, ce qui gaspille des cycles. Avec les interruptions, le PIC peut vaquer à ses occupations et réagir instantanément quand un événement se produit.
Le PIC16F683 utilise un vecteur d'interruption unique à l'adresse 0x004. Toutes les interruptions passent par la même routine (ISR — Interrupt Service Routine), et c'est au programmeur de vérifier les flags pour déterminer la source.
| Source | Flag | Enable | Description |
|---|---|---|---|
| INT (RA2) | INTF | INTE | Interruption externe sur broche RA2 |
| Timer0 | T0IF | T0IE | Débordement du Timer0 |
| Timer1 | TMR1IF | TMR1IE | Débordement du Timer1 |
| PORTB Change | RAIF | RAIE | Changement d'état sur PORTA |
| ADC | ADIF | ADIE | Fin de conversion analogique |
| Comparateur | C1IF/C2IF | C1IE/C2IE | Changement de sortie comparateur |
| EEPROM | EEIF | EEIE | Fin d'écriture EEPROM |
Pour activer une interruption, trois conditions doivent être remplies :
// Activer l'interruption Timer0 INTCONbits.T0IE = 1; // Enable Timer0 interrupt INTCONbits.T0IF = 0; // Clear flag INTCONbits.GIE = 1; // Global interrupt ON // Activer l'interruption Timer1 (périphérique) PIE1bits.TMR1IE = 1; // Enable Timer1 interrupt PIR1bits.TMR1IF = 0; // Clear flag INTCONbits.PEIE = 1; // Peripheral interrupt ON INTCONbits.GIE = 1; // Global interrupt ON
#include <xc.h> #define _XTAL_FREQ 4000000 volatile unsigned char compteur = 0; // Routine d'interruption (ISR) void __interrupt() isr(void) { if(INTCONbits.T0IF) { INTCONbits.T0IF = 0; // TOUJOURS reset le flag ! TMR0 = 6; // Recharger pour ~1ms compteur++; if(compteur >= 250) { // ~250ms écoulées compteur = 0; PORTA ^= 0b00000001; // Toggle LED } } } void main(void) { OSCCON = 0b01100000; ANSEL = 0; TRISA = 0b11111110; PORTA = 0; // Config Timer0 OPTION_REG = 0b00000010; // Prescaler 1:8 TMR0 = 6; // Activer interruptions INTCONbits.T0IE = 1; INTCONbits.T0IF = 0; INTCONbits.GIE = 1; // Boucle principale : le processeur est libre ! while(1) { // Peut faire d'autres tâches ici NOP(); } }
void __interrupt() isr(void) { if(INTCONbits.INTF) { INTCONbits.INTF = 0; PORTA ^= 0b00000010; // Toggle LED sur RA1 __delay_ms(50); // Anti-rebond simple } } void main(void) { ANSEL = 0; TRISA = 0b11111100; // RA0-RA1 sortie, RA2 entrée (INT) PORTA = 0; OPTION_REGbits.INTEDG = 0; // Front descendant INTCONbits.INTE = 1; // Enable INT INTCONbits.INTF = 0; INTCONbits.GIE = 1; while(1) { NOP(); } }