/********************************************************** Projet : tp3s.prj Fichier(s) : TP_3S.c Objet : Utilisation d'un Timer/Counter Départ Rallye et Chronométrage Auteur : Groupe : Date création : 21/11/2001 **********************************************************/ // Fichiers à inclure : #include // Commandes du moniteur de mise au point #include // déclaration des registres interne au µC 80C515(SFR) #include // Commandes de l'afficheur LCD #include // E/S standard (ex.: printf...) // Equivalences : #define ARRET 0 #define MARCHE 1 #define CHRONO 0 #define CReb 1 // Fonctions externes : // Fonctions locales (Prototypes) : void tempo(unsigned int); // Fonction temporisation pour anti-rebonds uniquement void cpt_rebours(void); // Fonction compte à rebours void tempo_1s(void); // Fonction tempo de 1s pour le compte à rebours 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_Fauxdep(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; // in_CRCHL : Registre timer (adresse 0xCA) at 0xCC sfr16 THL2; // in_THL2 : valeur timer (adresse 0xCC) // Variables Globales : bit mode; // variable utilisée pour définir le mode (compte à rebours ou chrono) bit chronometre; // variable utilisée pour définir l'état du chrono (Marche ou Arrêt) bit depart; // variable utilisée pour définir l'état du depart (Marche ou Arrêt) unsigned char cpt;// valeur finale timer unsigned char free_cpt; // valeur courante dans le timer unsigned char tps_ms; // variable utilisée pour afficher le nbre de milli secondes unsigned char tps_sec; // variable utilisée pour afficher le nbre de secondes unsigned char etat_cpte_reb; // variable utilisée pour définir l'étape du compte à rebours // ================ ZONE PROGRAMME ============================== /******************************************************** Nom : main() Objet : Initialisation + Gestion des différents mode de fonctionnement Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void main () { clrscr(); // efface affiche LCD printf(" TP3 Synthese "); // Affiche "TP3 Synthese" sur la 1ère ligne du LCD P4=0x04; // reset port P4 et allumage feux rouges VP P5=0; // reset port P5 I3FR=0; // FD sur P1.0 Bp Départ IEX3=0; // reset flag EX3=1; // autorisation IRQ sur P1.0 Bp Départ IEX4=0; // reset flag P1.1 Bp Reset EX4=0; // interdiction IRQ sur P1.1 Bp Reset (voir cahier des charges) I2FR=0; // FD sur P1.4 Bp Arret IEX2=0; // reset flag P1.4 Bp Arret EX2=0; // interdiction IRQ sur P1.4 Bp Arret (voir cahier des charges) EXF2=0; // reset flag (FD sur P1.5 Bp faux départ (IRQ la plus prioritaire)) ET2=1; // autorisation IRQ P1.5 et T2 (1/2) attention : double autorisation nécessaire EXEN2=0; // interdiction IRQ sur P1.5 (2/2) tps_ms=0; // reset du nbre de ms tps_sec=0; // reset du nbre de secondes depart=ARRET; // condition initiale mode=CReb; // condition initiale chronometre=ARRET; // condition initiale etat_cpte_reb=0; // on se place dans la 1ère étape du compte à rebours CRCHL=-10000/1; // valeur Timer T2 (base de tps de 10ms) THL2=CRCHL; // initialisation Timer T2PS=0; // fréquence Timer = Fquartz/12 T2R0=0; // mode 0 auto-reload T2 T2R1=1; // mode 0 auto-reload T2 T2I0=1; // mode Timer pour T2 T2I1=0; // mode Timer pour T2 TF2=0; // Reset flag Timer T2 IP0= (IP0 & 0xD1)|0x00; //priorité la plus élevée sur P1.5 (BP Faux départ) et T2 IP1= (IP1 & 0xD1)|0x20; EAL=1; // autorisation globale IRQ while(1) // boucle infinie { if(depart==MARCHE) // si on a appuyé dur le BP départ -> depart=MARCHE { if(mode==CReb) // et si on est en mode compte à rebours { cpt_rebours(); // on appelle le SP de gestion du compte à rebours } else // par contre si on est pas en compte à rebours on est donc en mode chrono { if(chronometre==MARCHE) // si le chrono est en cours { //printf("\n TP3_S CHRONO "); EX2=1; EX4=0; } // end if else // par contre si le chrono est arrêté { //EX2=0; // on interdit les IRQ venant de P1.4 (BP Arrêt) après le chronometrage //EX4=1; // on autorise les IRQ venant de P1.1 (BP Reset) après le chronometrage //printf("\n Temps: %ds %d0ms",tps_sec,tps_ms); } // end else } // end else } // end if else // par contre si depart=ARRET { P4=0x04; // on allume les Feux Rouges sur la VP printf("\n Attente depart \n"); // et on affiche "Attente depart" sur la 2ème ligne } // end else } // end while boucle infinie } // end main /******************************************************** 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 /******************************************************** Nom : IRQ_P10_Depart Objet : Depart du C. à R. Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void IRQ_P10_Depart(void) interrupt 10 using 0 { tempo(100); //Gestion des rebonds IEX3=0; // reset flag depart=MARCHE; // on lance le compte à rebours car on a appuyé sur départ ET2=1; // on autorise les IRQ sur T2 } // end IRQ_P10_Depart /******************************************************** Nom : cpt_rebours Objet : compte à rebours du depart Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void cpt_rebours(void) { etat_cpte_reb=0; // étape initiale du compte à rebours while(etat_cpte_reb<=3) // tant que on est pas à l'étape 4 du compte à rebours on exécute ceci { EX3=0; // on interdit les IRQ venant de P1.0 (Bp Départ) EX4=0; // on interdit les IRQ venant de P1.1 (BP Reset) EXEN2=1; // on autorise les IRQ venant de P1.5 (BP Faux départ) pendant le compte à rebours switch(etat_cpte_reb) // boucle cas parmis en fonction de l'étape demandée { case 0: P4=0x04; etat_cpte_reb=1; printf("\n Depart dans 3s \n"); tempo_1s(); break; case 1: P4=0x04; etat_cpte_reb=2; printf("\n Depart dans 2s \n"); tempo_1s(); break; case 2: P4=0x02; etat_cpte_reb=3; printf("\n Depart dans 1s \n"); tempo_1s(); break; case 3: P4=0x01; etat_cpte_reb=500; printf("\n !!! GO !!! \n"); chronometre=MARCHE; // le compte à rebours est terminé on lance le chrono mode=CHRONO; // le compte à rebours est terminé on lance le mode chrono EXEN2=0; // on interdit les IRQ venant de P1.5 (BP Faux départ) pendant le chrono EX2=1; // on autorise les IRQ venant de P1.4 (BP Arrêt) durant le chronometrage break; default: break; //EXEN2=0; // on interdit les IRQ venant de P1.5 (BP Faux départ) qd on est plus dans le Compte à rebours } // end switch case } // end while } // end cpt_rebours /******************************************************** Nom : tempo_1s Objet : temporisation de 1s pour le compte à rebours Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void tempo_1s(void) { cpt=free_cpt+100; // cpt est mis à 100x10ms=1s while(cpt!=free_cpt); // on attend que la tempo de 1s se termine } // end tempo_1s /******************************************************** Nom : IRQ_T2_P15_Fauxdep Objet : Gestion du Timer et des Faux Départs Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void IRQ_T2_P15_Fauxdep(void) interrupt 5 using 1 { if(TF2==1) // si l'IRQ a été provoquée par T2 { TF2=0; // on reset le flag T2 if(mode==CReb) // si on est en mode compte à rebours free_cpt++; // on incrémente le compteur libre else // par contre si on est pas en mode compte à rebours { if(chronometre==MARCHE) // et qu'on est en mode chronomètre { tps_ms=tps_ms+1; // on compte le temps ecoule en millisecondes printf("\nTemps: %ds %d0ms\n",tps_sec,tps_ms); // on affiche le temps écoulé en secondes et millisecondes if(tps_ms==100) // toutes les fois qu'on a 100X10ms=1s { tps_sec++; // on ajoute une seconde à la variable qui compte les secondes tps_ms=0; // on remet la variable qui compte les millisecondes à 0 } // end if } // end if } // end else } // end if else // par contre si l'interruption a été provoquée par un appui sur P1.5 (BP Faux départ) { tempo(100); //gestion des rebonds EXF2=0; // reset flag EXEN2=0; // on interdit les IRQ venant de P1.5 (BP Faux départ) pendant le chrono etat_cpte_reb=500; // on sort de la boucle switch case du SP cpt_rebours //mode=CReb; depart=ARRET; // on arrête le compte à rebours EX3=1; // on autorise les IRQ venant de P1.0 (Bp Départ) } // end else } // Fin d'IRQ_T2_P15_Fauxdep /******************************************************** 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); // Gestion des rebonds IEX2=0; // reset flag P1.4 Bp Arret EX2=0; // on interdit les IRQ venant de P1.4 (Bp Arrêt) chronometre=ARRET; // arrêt du chronomètre EX4=1; // autorisation IRQ sur P1.1 Bp Reset } // end IRQ_P14_Arret /******************************************************** Nom : IRQ_P11_Reset Objet : Reset du chronometre Paramètres : - d'appel : aucun - de retour : aucun *********************************************************/ void IRQ_P11_Reset(void) interrupt 11 using 0 { tempo(100); //Gestion des rebonds IEX4=0; // reset flag P1.1 Bp Reset tps_ms=0; // remise à 0 de la variable qui compte les msec tps_sec=0; // remise à 0 de la variable qui compte les secondes depart=ARRET; // on arrête le chrono mode=CReb; // et on le place en mode compte à rebours pour le prochain départ chronometre=ARRET; // on arrête le chrono EX3=1; // on autorise les IRQ venant de P1.0 (Bp Départ) ET2=0; // on interdit les IRQ venant de T2 } // end IRQ_P11_Reset