/********************************************************** Projet : tp3_s.prj Fichier(s) : TP_3S.c Objet : Utilisation d'un Timer/Counter Départ Rallye et Chronométrage Auteur : Hensinger Benoît / Cuenot Gaël Binome : 3 Groupe : RLI 1 Date création : 23/11/2001 **********************************************************/ // Fichiers à inclure : #include #include #include #include // Equivalences : #define ARRET 0 #define MARCHE 1 #define CHRONO 0 // Fonctions externes : // Fonctions locales (Prototypes) : void tempo(unsigned int); // Fonction temporisation logicelle void car(void); // Fonction compte à rebours void tempo_hard(unsigned int t); //Fonction tempo materielle void IRQ_P10_Depart(void) interrupt 10 using 0; // Fonction d'IRQ sur P1.0 (BP Départ) void IRQ_P11_Reset(void)interrupt 11 using 0; // Fonction d'IRQ sur P1.1 (BP Reset chrono) void IRQ_P14_Arret(void) interrupt 9 using 0; // Fonction d'IRQ sur P1.4 (BP Arret chrono) void IRQ_T2_P15_Fodep(void) interrupt 5 using 1; // Fonction d'IRQ sur T2 et P1.5 (BP faux départ) // Definitions particulières (zone SFR ou RAM externe) : at 0xCA sfr16 CRCHL; // Registre timer -> adresse 0xCA at 0xCC sfr16 THL2; // valeur timer -> adresse 0xCC // Variables Globales : bit mode; // mode dans lequel on est bit depart; // etat du depart bit chrono; // etat du chrono unsigned char cpt; // valeur finale du timer unsigned char free_cpt; // valeur courante du timer unsigned char ms; // variable utilisee pour afficher les milisecondes unsigned char sec; // variable utilisee pour afficher les secondes unsigned char car_state; // etape du compte à rebours // ================ ZONE PROGRAMME ============================== /******************************************************** Nom : main() Objet : Phase d'initialisation et gestion des modes de fonctionnement Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void main () { clrscr(); // Efface tout sur le LCD printf("--> TP3_S <-- \n"); // Affiche "TP3_S" (1ère ligne LCD) P4=0; // reset port P4 P5=0; // reset port P5 // Initialisation de P1.0 (Départ) I3FR=0; // FD sur P1.0 IEX3=0; // reset flag P1.0 EX3=1; // autorisation IRQ sur P1.0 // Initialisation de P1.1 (Reset) IEX4=0; // reset flag P1.1 EX4=0; // interdiction IRQ sur P1.1 // Initialisation de P1.4 (Arret) I2FR=0; // FD sur P1.4 IEX2=0; // reset flag P1.4 EX2=0; // interdiction IRQ sur P1.4 // Initialisation de P1.5 (faux départ) EXF2=0; // reset flag de P1.5 ET2=1; // autorisation IRQ P1.5 et T2 EXEN2=0; // interdiction IRQ sur P1.5 ms=0; // reset de la variable des milisecondes sec=0; // reset de la variable des secondes depart=ARRET; mode=1; chrono=ARRET; car_state=0; // Compte à rebours --> 1ere etape // initialisation du timer T2 CRCHL=-10000/1; // valeur Timer T2 (base de tps de 10ms) THL2=CRCHL; // init Timer T2PS=0; // FTimer = Fquartz/12 T2R0=0; // mode 0 auto-reload T2R1=1; // mode 0 auto-reload T2I0=1; // mode Timer T2I1=0; // mode Timer TF2=0; // Reset flag de T2 //priorité la plus élevée sur P1.5 et T2 IP0= (IP0 & 0xD1)|0x00; IP1= (IP1 & 0xD1)|0x20; EAL=1; // autorisation globale IRQ while(1) // boucle infinie { if(depart==MARCHE) // Test si le bp de depart a ete actionne { if(mode==1) // Test si on est dans 1 phase de compte a rebour { car(); // appel a car (ss prog de compte a rebour) } else { if(chrono==MARCHE) // Test si le chrono est en train de fonctionner { EX2=1; EX4=0; } } } else { P4=0x04; // Feux rouges sur la voie princ allumes printf("\n\n Attente depart "); // Affichage "Attente depart" (2ème ligne LCD) } } } // end main /******************************************************** Nom : IRQ_P10_Depart Objet : Depart du compte a rebour Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void IRQ_P10_Depart(void) interrupt 10 using 0 { tempo(100); // Anti rebond IEX3=0; // reset flag P1.0 depart=MARCHE; // Demarrage du compte a rebour ET2=1; // Autorisation des IRQ sur T2 } // end IRQ_P10_Depart /******************************************************** Nom : car Objet : compte à rebours du depart Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void car(void) { car_state=0; // Etape initiale du compte a rebour while(car_state<=3) // tant que le compte a rebour n'a pas atteint le dernier etat { EX3=0; // inhibition de P1.0 (interdiction IRQ) EX4=0; // Inhibition de P1.1 (interdiction par IRQ) EXEN2=1; // Autorisations des IRQ de P1.5 switch(car_state) // Differentes etapes du compte a rebours { case 0: P4=0x04; car_state=1; printf("\n\n | 3 | "); tempo_hard(100); break; case 1: P4=0x04; car_state=2; printf("\n\n | 2 | "); tempo_hard(100); break; case 2: P4=0x02; car_state=3; printf("\n\n | 1 | "); tempo_hard(100); break; case 3: P4=0x01; car_state=500; printf("\n\n !! GO !! "); chrono=MARCHE; // Compte a rebours terminé mode=CHRONO; // Passage en mode chrono EXEN2=0; // Inhibition de P1.5 (interdiction IRQ) EX2=1; // Autorisation des IRQ de P1.4 break; default: break; } } } // end car /******************************************************** Nom : IRQ_T2_P15_Fodep Objet : Fonction faux depart Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void IRQ_T2_P15_Fodep(void) interrupt 5 using 1 { if(TF2==1) // Si une IRQ a ete provoquee par T2 { TF2=0; // Reset du flag de T2 if(mode==1) // Si on est en mode compte a rebours free_cpt++; else { if(chrono==MARCHE) // et qu'on est en mode chronomètre { ms++; // Incremente les milisecondes printf("\n\nTemps: %u \" %u ",sec,ms); // Affichage du temps (2e ligne LCD) if(ms==100) { sec++; // Incremente les secondes ms=0; // Reset des millisecondes } } } } else { tempo(100); // Anti rebond EXF2=0; // reset flag P1.5 EXEN2=0; // Inhibition de P1.5 car_state=500; depart=ARRET; // Stop du compte a rebour EX3=1; // Autorisation des IRQ de P1.0 } } // Fin de IRQ_T2_P15_Fodep /******************************************************** Nom : IRQ_P14_Arret Objet : Arret du chronomètre Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void IRQ_P14_Arret(void) interrupt 9 using 0 { tempo(100); // Anti rebonds IEX2=0; // Reset flag P1.4 EX2=0; // Inhibition de P1.4 chrono=ARRET; // Stop le chrono EX4=1; // Autorisation IRQ sur P1.1 } // end IRQ_P14_Arret /******************************************************** Nom : IRQ_P11_Reset Objet : Reset du chrono Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void IRQ_P11_Reset(void) interrupt 11 using 0 { tempo(100); // Anti rebonds IEX4=0; // Reset flag P1.1 ms=0; // RAZ des milisecondes sec=0; // RAZ des secondes depart=ARRET; // Stop le chrono mode=1; // Retour en mode compte a rebours chrono=ARRET; // Stop le chrono EX3=1; // Autorisation des IRQ venant de P1.0 (Bp Départ) ET2=0; // Autorisation des IRQ venant de T2 } // end IRQ_P11_Reset /******************************************************** Nom : tempo_hard Objet : base de temps materielle de 1 ms Paramètres : - d'appel : durée de la tempo en ms - de retour : aucun *********************************************************/ void tempo_hard(unsigned int t) { cpt=free_cpt+t; while(free_cpt != cpt); } // end tempo_hard /******************************************************** Nom : tempo Objet : base de temps logicielle de 1 ms Paramètres : - d'appel : durée de la tempo en ms - de retour : aucun *********************************************************/ void tempo(unsigned int t) { int ttempo; while (t != 0) { for (ttempo = 1;ttempo < 493;ttempo++); t--; // décrémentation de la variable de contrôle } } // end tempo