Il faudrait connaitre l'ordre de gandeur de la duree de cette impulsion : plutot de l'ordre de la microseconde, de la milliseconde, ou au-dela ? Quand au code, ca depend du compilateur C que tu utilises, c'est lequel ? Certains compilateurs ont des macros qui rendent l'init des interruptions tres facile a ecrire, mais qui cachent les details d'initialisation des registres, et ce code n'est pas portable d'un compilo a l'autre et pas bon pour apprendre.
Je ne connais pas le 16F628 mais le principe reste le meme pour les uC. Tu valides l'interruption d'overflow d'un timer ininterruptible, dans cette interruption tu incrementes juste une variable qui indiquera le nombre d'overflows eventuels que le timer a fait. Le prediviseur de ce timer est a choisir en fonction de la duree de l'impulsion que tu vas mesurer : plus l'impulsion sera courte, plus le diviseur sera petit pour garder un increment faible, et inversement.
Tu valides une interruption qui se declenche lors d'un changement d'etat sur l'entree du PIC qui recoit l'impulsion : quand cette impulsion se declenche sur le front montant, tu mets a zero le compteur du timer ainsi que la variable associee.
Lors de la seconde interruption (front descendant) tu lis la valeur du timer (et de la variable) qui te donnent la duree de l'impulsion avec une precision de l'ordre de celle de ton quartz multipliee par les pre-diviseurs.
Le code pour la mesure (a traduire pour ton PIC) avec un timer 16 bits :
//-------------------------------------------------------
// definition de l'entree qui recoit le signal #define ENTREE BIT_RB0 // exemple avec RB zero
// constantes #define FQUARTZ 20000000 // frequence du quartz (ex: 20 MHz) #define DIVISEUR 16 // pre-diviseur du timer (exemple)
// variables globales unsigned long uTimer=0, uOverflow=0; // compteurs timer float fValeur = 0.0; // valeur du timer unsigned char flag=0; // flag de fin de mesure
// interruption du timer --------------------------------- void interrupt timer(void) { ++uOverflow; // increment du compteur d'overflows }
// interruption de changement d'etat --------------------- void interrupt change(void) { // etat logique de l'entree a cet instant if ( ENTREE ) // front montant { TIMER = 0; // reset du compteur du timer start_timer(); // demarrage de l'interruption du timer } else // front descendant { uTimer = TIMER; // lecture de la valeur actuelle du timer stop_timer(0); // arret de l'interruption du timer flag = 1; // mesure terminee } }
// programme de fond -----------------------------------
void main(void) {
// inits preset_timer(DIVISEUR); // initialise les pre-diviseurs du timer
while ( 1 ) // boucle principale { // inits uTimer = uOverflow = 0; // remise a zero des compteurs flag = 0; // reset du flag de fin de mesure
// mesure while( ENTREE ) ; // attend la fin de l'etat "un" sur l'entree start_change(); // demarrage de l'interruption de changement d'etat while( !flag ) ; // attend la fin de la mesure stop_change(); // arret de l'interruption de changement d'etat
// affichage fValeur = (float)uTimer + (float)uOverflow * 65536.0; // valeur de comptage fValeur *= (DIVISEUR / FQUARTZ); // conversion en secondes (ou ms, ou us) print( "%f\n", fValeur ); // affichage de la valeur delay( ? ); // attente eventuelle pour l'affichage }
}