« Utiliser les PIC 16F et 18F/Exercices/Interruption timer0 en langage C » : différence entre les versions

m
Robot : remplacement de texte automatisé (-(<|</)source([ \t>]) +\1syntaxhighlight\2)
m (Robot : Remplacement de texte automatisé (-resp\. +respectivement))
m (Robot : remplacement de texte automatisé (-(<|</)source([ \t>]) +\1syntaxhighlight\2))
 
 
Un [[w:PIC_16F84_de_Microchip|PIC16F84]] est enfoui dans un [[w:FPGA|FPGA]]. Sa seule particularité est de fonctionner à {{Unité|50|{{abréviation|Mhz|mégahertz}}}} contre 10 (respectivement {{Unité|20|{{abréviation|Mhz|mégahertz}}}}) de fréquence maximale d'horloge pour les PIC 16F84 (respectivement 16F84A). Il exécute le programme suivant (écrit avec le compilateur Hitech C) :
<sourcesyntaxhighlight lang="c">
//#include <pic1684.h>
#include <htc.h> //A changer si autre compilateur
T0IF = 0; // acquittement interruption
}
</syntaxhighlight>
</source>
Remarquez comment est écrit une interruption avec ce compilateur.
 
 
5°) Le programme suivant est donné comme exemple du compilateur MikroC et tourne dans un PIC 16F84 qui a un quartz de {{Unité|4|{{abréviation|Mhz|mégahertz}}}}.
<sourcesyntaxhighlight lang="c">
unsigned cnt;
void interrupt() {
} while(1);
}
</syntaxhighlight>
</source>
Quelle est la fréquence de clignotement des LEDs reliées au '''PORTB''' ?
 
{{Solution|contenu=
1°) Pas grand chose de changé :
<sourcesyntaxhighlight lang="c">
void interrupt decalage(void) {
nb++;
}
}
</syntaxhighlight>
</source>
2°) Je l'ai réalisé dans un {{Abréviation|FPGA|Field Programmable Gate Array|en}} et à vue de nez la fréquence est entre 5 et {{Unité|10|{{abréviation|Hz|hertz}}}}.
 
 
Comme la division se fait par 16 qui est une puissance de deux, on peut utiliser un masque pour faire ce calcul bien plus rapidement :
<sourcesyntaxhighlight lang="c">
// langage C
if (!(nb & 0x0F)) // idem à if (!(nb % 16)) mais plus rapide
</syntaxhighlight>
</source>
4°) Décalage tout simple d'une LED vers les poids forts.
 
 
6°)
<sourcesyntaxhighlight lang="c">
#include <pic1684.h>
//#include <htc.h> serait-il mieux ?
T0IF = 0; // acquittement interruption
}
</syntaxhighlight>
</source>
}}
 
2°) réaliser une fonction responsable du transcodage :
<sourcesyntaxhighlight lang="c">
unsigned char Display(unsigned char no) {
unsigned char Pattern;
unsigned char SEGMENT[] = {0x3F,....
</syntaxhighlight>
</source>
3°) Réaliser le programme main() responsable de l'initialisation de l'interruption qui doit avoir lieu toutes les 10ms (avec un quartz de {{Unité|4|{{abréviation|Mhz|mégahertz}}}}) et qui compte de 00 à 99 toutes les secondes environ (avec un "Delay_ms(1000);")
 
* etc etc
Soit en final :
<sourcesyntaxhighlight lang="c">
unsigned char SEGMENT[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
</syntaxhighlight>
</source>
2°)
<sourcesyntaxhighlight lang="c">
unsigned char Display(unsigned char no) {
unsigned char Pattern;
return Pattern;
}
</syntaxhighlight>
</source>
ou encore
<sourcesyntaxhighlight lang="c">
unsigned char Display(unsigned char no) {
//unsigned char Pattern;
return SEGMENT[no];
}
</syntaxhighlight>
</source>
3°) Pour bien faire, le comptage doit se faire en BCD. Cela peut se faire avec :
<sourcesyntaxhighlight lang="c">
nb++;
// gérer le problème des unités
// gérer le problème des dizaines
if ((((nb &0xF0) > 0x90) nb = 0;
</syntaxhighlight>
</source>
Les compilateurs C compilent cela certainement de manière peu optimisée. Il faut savoir qu’il existe un bit "half carry" dans le registre '''Status''' qui permet certainement d'optimiser, mais nous laissons tomber ce genre de détail.
 
Pour la période de l'interruption, on part de la fréquence quartz divisée par 4 soit : {{Unité|1|{{abréviation|Mhz|mégahertz}}}} qu’il faut diviser par {{formatnum:10000}} pour avoir une période d'overflow de 10 ms. Le timer gère une division par 256 qu'on peut ramener à 250 en l'initialisant à 6 mais il nous reste à réaliser une division par 40 qui n’est pas une puissance de 2. On va prendre une division par 64 et 10000 / 64 = 156,25 donc notre timer0 sera initialisé à 256-156 = 100.
<sourcesyntaxhighlight lang="c">
//****** Mikro C ********
unsigned char nb,mux;
}
}
</syntaxhighlight>
</source>
4°)
<sourcesyntaxhighlight lang="c">
void interrupt(void) {
TMR0 = 100;
INTCON.T0IF = 0; // clear TMR0IF
}
</syntaxhighlight>
</source>
Cette façon de faire (division par 10 et reste de la division par 10) est utile si nb n’est pas en BCD, or nous avons présenté dans le main une incrémentation qui veille à laisser nb en BCD ! On peut donc renplacer cette interruption par :
<sourcesyntaxhighlight lang="c">
void interrupt(void) {
TMR0 = 100;
}
ce qui est bien plus efficace pour un code d'interruption.
</syntaxhighlight>
</source>
}}
 
143 371

modifications