Utiliser les PIC 16F et 18F/Interruption timer0 en langage C

Début de la boite de navigation du chapitre
Interruption timer0 en langage C
Icône de la faculté
Chapitre no 9
Leçon : Utiliser les PIC 16F et 18F
Chap. préc. :Le Timer0 des 16FXXX et le langage C
Chap. suiv. :Le mode comparaison du module CCP (Capture Compare PWM)

Exercices :

Interruption timer0 en langage C
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Utiliser les PIC 16F et 18F : Interruption timer0 en langage C
Utiliser les PIC 16F et 18F/Interruption timer0 en langage C
 », n'a pu être restituée correctement ci-dessus.

Interruption timer0 sur les PIC 16F

modifier

Le timer 0 et son interruption

modifier

La 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 :

 
Le timer 0 du 16F84

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.

 
L'interruption du timer 0 dans le 16F84

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.


Le programme qui gère l'interruption sera en adresse 0x004, mais ce sera transparent en langage C.

Les interruptions en C

modifier

La 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

modifier

Avec 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

modifier

Une 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.

 
Comment utiliser deux afficheurs multiplexés


  Faites ces exercices : Interruption timer 0 en langage C.



Le cas particulier du compilateur C18 sur PIC 18FXXXX

modifier

Dans 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

modifier

Partie logicielle

modifier

La 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

modifier

Voici 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);
}