Utiliser les PIC 16F et 18F/Interruption timer0 en langage C
Interruption timer0 sur les PIC 16F
modifierLe timer 0 et son interruption
modifierLa documentation du Timer0 du PIC® 16F84 a été présentée dans le TD précédent. Nous pensons utile de reproduire sa documentation avec la figure déjà présentée :
Nous passons donc à la description de son interruption associée.
Mettre en route le timer0 est une chose, mais déclencher une interruption en est une autre. Il nous faut maintenant documenter ce mécanisme.
Pour réaliser l'interruption, il faut réaliser un front montant dans l'ellipse rouge : on en déduit immédiatement les bits à mettre à 1 dans INTCON, à savoir T0IE et GIE.
T0IF est un drapeau (flag en anglais) un peu particulier. Comme tous les autres drapeaux ayant un nom se terminant par F, c’est le matériel qui le met à 1, mais le logiciel (c'est-à-dire vous, le programmeur) qui le met à 0.
Le programme qui gère l'interruption sera en adresse 0x004, mais ce sera transparent en langage C.
Les interruptions en C
modifierLa gestion des interruptions en C est fortement dépendante des compilateurs, comme le montre le tableau ci-dessous :
MikroC | Hitech C |
// interruption haute priorite seulement
void interrupt() {
// traitement interruption
// positionnement du FLAG
}
void main() {
// traitement
while(1);
}
|
#include <pic1684.h>
void interrupt it_gene(void);
main(){
// traitement
while(1);
}
void interrupt it_gene(void) {
// traitement interruption
// positionnement du FLAG
}
|
Avec le compilateur mikroC le nom de l'interruption est fixé.
L'écriture d'une interruption se fait normalement en trois étapes :
- spécifier que le sous-programme n’est pas un sous-programme normal, mais un sous-programme d'interruption,
- fixer l'adresse du sous-programme d'interruption
- initialiser le mécanisme d'interruption dans le programme principal.
Pour certains compilateurs (MikroC) les deux premières étapes se font simplement en donnant un nom prédéterminé au sous-programme d'interruption.
Exemple complet avec le Hitech C
modifierAvec le compilateur Hitech C les bits T0IE et GIE gardent leur noms.
//******** Hitech C **************
#include <pic1684.h>
void interrupt it_gene(void);
main(){
// initialisation du timer
OPTION = 0x07; // prescaler 256 , entrée sur quartz
TMR0 = 0x00;
// autorisation des interruptions
TOIE = 1;
GIE = 1;
while(1); // on reste ici jusqu'à ce qu'une âme charitable éteigne le courant
}
void interrupt it_gene(void) {
// traitement interruption
// positionnement du FLAG :
TOIF = 0; // c’est reparti pour un tour
}
Exemple d'application
modifierUne application typique sera traitée en exercice. Il s'agit de gérer deux afficheurs sept segments multiplexés : on envoie l’affichage des unités et on change ensuite pour afficher les dizaines. La sélection des afficheurs est justement gérée par une interruption.
Faites ces exercices : Interruption timer 0 en langage C. |
Le cas particulier du compilateur C18 sur PIC 18FXXXX
modifierDans la série des PIC 18F la gestion des interruptions est un peu plus sophistiquée. Il y a maintenant deux niveaux de priorité pour les interruptions.
Les interruptions du PIC 18F
modifierPartie logicielle
modifierLa partie MicroC n'a pas changée car ce compilateur peut cibler les deux séries 16F et 18F.
MikroC | C18 |
// interruption haute priorite seulement
void interrupt() {
// traitement interruption
// positionnement du FLAG
}
void main() {
// traitement
while(1);
}
|
#include<p18f452.h>
#pragma config WDT = OFF
#pragma config DEBUG=ON
void it_prioritaire(void) ;
#pragma code address_it=0x08
//0x18 pour basse priorité
void int_toto(void) {
_asm GOTO it_prioritaire _endasm
}
#pragma code
#pragma interrupt it_prioritaire
void it_prioritaire(void) {
// traitement interruption
// positionnement du FLAG
}
main(){
// traitement
while(1);
}
|
Exemple complet
modifierVoici un exemple complet en C18 :
//******** C18 *********************
#include<p18f452.h>
#pragma config WDT = OFF
#pragma config DEBUG=ON
void it_prioritaire(void) ;
#pragma code address_it=0x08 //0x18 pour basse priorité
void int_toto(void) {
_asm GOTO it_prioritaire _endasm
}
#pragma code
#pragma interrupt it_prioritaire
void it_prioritaire(void) {
if (INTCONbits.TMR0IF) {
// traitement interruption
PORTBbits.RB0 = !PORTBbits.RB0;
//TMR0H = 0xFF;
TMR0L = 0xF0;
// positionnement du FLAG
INTCONbits.TMR0IF = 0;
}
}
void main(void){
// Initialisation
TRISB = 0xFE;
PORTBbits.RB0 = 0;
INTCONbits.TMR0IF = 0;
INTCONbits.TMR0IE = 1;
INTCONbits.GIEH = 1;
T0CON = 0xCF;
//TMR0H = 0xFF;
TMR0L = 0xF0;
//INTCON2bits.TMR0IP=1; // inutile ?
// traitement
while(1);
}