====== Exercice 1 (TP4) ====== ===== Organigrammes ===== ==== Fonction principale ==== {{:fr:supervisors:solutions:didalab:ex1_tp4_organigramme1.png?600|}} ==== Fonction d'interruption ==== {{:fr:supervisors:solutions:didalab:ex1_tp4_organigramme2.png|}} ===== Programme ===== /************************************************************************************************ * TPs sur EID210 / Réseau CAN - VMD (Véhicule Multiplexé Didactique) ************************************************************************************************* * APPLICATION: Commande Essuie-glace ************************************************************************************************* * TP Exercice n°1: Séquence commande moteur E.G. *------------------------------------------------------------------------------------------------ * CAHIER DES CHARGES : * ********************* * On souhaite que l'état du moteur dépende de la position du commodo * - Si Position 1 Moteur en marche à faible vitesse * - Si Position 2 Moteur en marche à grande vitesse * - Si Position 3 Moteur en marche à vitesse ajustable par l'entrée analogique * - Si Position 4 Moteur en marche périodique avec dans l'état marche une vitesse ajustable *---------------------------------------------------------------------------------------------- * NOM du FICHIER : TP_Exercice 1.C * ***************** *************************************************************************************************/ // Fichiers à inclure //******************** #include #include "Structures_Donnees.h" #include "cpu_reg.h" #include "eid210_reg.h" #include "Can_vmd.h" #include "Aton_can.h" // Variables globales //--------------------- union byte_bits Indicateurs; #define I_Affiche Indicateurs.bit.b0 #define I_Fin_Tempo Indicateurs.bit.b1 #define I_Active_Tempo Indicateurs.bit.b2 #define I_Etat_Moteur Indicateurs.bit.b3 unsigned int Compteur_Passage_Irq; // Fonction d'interruption "Base de Temps" //======================================== void irq_bt() // Fonction exécutée toute les 10 mS {if(I_Active_Tempo) // Si mode intermittent actif {Compteur_Passage_Irq++; if(Compteur_Passage_Irq==400) // 4 Secondes se sont écoulées {Compteur_Passage_Irq=0; I_Fin_Tempo=1; } } } // Fin de la fonction d'interruption //========================== // FONCTION PRINCIPALE //========================== main() {// Définition de variables locales int Compteur_Passage; unsigned char Commodo_EG_Mem; unsigned int Cptr_TimeOut; unsigned char AN0H; // Pour mémoriser les 8 biits de poids forts du résultat de conversion A->N unsigned char Val_Vitesse,Val_Vitesse_Mem; Trame Trame_Recue; Trame T_IRM_Commodo_EG; // Trame pour interroger Module 8E sur Commodo Essuie Glace // IRM -> Information Request Message -> Trame interrogative Trame T_IM_Commodo_EG; // Trame pour commander le Module 8E sur Commodo Essuie Glace // IM -> Information Message -> Trame de commande Trame T_IM_Asservissement; // Trame pour commander le module "Asservissement" // IM -> Information Message -> Trame de commande // Initialisations //***************** /* Initialisation DU SJA1000 de la carte PC104 */ Init_Aton_CAN(); // Pour initialiser les liaisons en entrées noeud "Commodo_EG" T_IM_Commodo_EG.trame_info.registre=0x00; T_IM_Commodo_EG.trame_info.champ.extend=1; // On travaille en mode étendu T_IM_Commodo_EG.trame_info.champ.dlc=0x03; // Il y aura 3 données de 8 bits (3 octets envoyés) T_IM_Commodo_EG.ident.extend.identificateur.ident=Ident_T_IM_Commodo_EG; T_IM_Commodo_EG.data[0]=0x1F; // première donnée -> "Adresse" du registre concernée //(GPDDR donne la direction des I/O) adresse = 1Fh page 16 T_IM_Commodo_EG.data[1]=0x7F; // deuxième donnée -> "Masque" //-> Tous les bits concernés sauf GP0 (voir doc page 16) T_IM_Commodo_EG.data[2]=0x7F; // troisième donnée -> "Valeur" -> Tous les bits en entrée // Envoi trame pour définir de la direction des entrées sorties Ecrire_Trame(T_IM_Commodo_EG); // Envoyer trame sur réseau CAN Cptr_TimeOut=0; do{Cptr_TimeOut++;}while((Lire_Trame(&Trame_Recue)==0)&&(Cptr_TimeOut<2000)); if(Cptr_TimeOut==2000) { clsscr(); gotoxy(2,12); printf(" Pas de reponse a la trame de commande en initialisation \n"); printf(" Couper et/ou remettre alimentation 12 V \n"); do{}while(Lire_Trame(&Trame_Recue)==0); // On attend les trames "On Bus" for(Cptr_TimeOut=0;Cptr_TimeOut<200000;Cptr_TimeOut++); Ecrire_Trame(T_IM_Commodo_EG); // Renvoyer trame IM sur réseau CAN Cptr_TimeOut=0; do{Cptr_TimeOut++;}while((Lire_Trame(&Trame_Recue)==0)&&(Cptr_TimeOut<2000)); if(Cptr_TimeOut==2000) { gotoxy(2,12); printf(" Pas de reponse a la trame de commande en initialisation \n"); printf(" Modifier le programme et recommencer \n"); do{}while(1); // On reste bloqué, on ne continue pas } } // Pour activer les conversions Ana -> Num T_IM_Commodo_EG.data[0]=0x2A; // Adresse du registre ADCON0 T_IM_Commodo_EG.data[1]=0xF0; // Masque -> bits 7..4 concernés T_IM_Commodo_EG.data[2]=0x80; // Valeur -> ADON=1 et "prescaler rate"=1:32 Ecrire_Trame(T_IM_Commodo_EG); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour définir le mode de conversion T_IM_Commodo_EG.data[0]=0x2B; // Adresse du registre ADCON1 T_IM_Commodo_EG.data[1]=0xFF; // Masque -> tous les bits sont concernés T_IM_Commodo_EG.data[2]=0x0C; // Valeur -> voir doc MCP25050 page 36 Ecrire_Trame(T_IM_Commodo_EG); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour initialiser le module "Asservissement" // Trame de type "IM" (trame de commande): Données d'identification pour le noeud "Asservissement" T_IM_Asservissement.trame_info.registre=0x00; T_IM_Asservissement.trame_info.champ.extend=1; T_IM_Asservissement.trame_info.champ.dlc=0x03; T_IM_Asservissement.trame_info.champ.rtr=0; T_IM_Asservissement.ident.extend.identificateur.ident=Ident_T_IM_Asservissement; // Pour définir des Entrées/Sorties T_IM_Asservissement.data[0]=0x1F; // Adresse du registre GPDDR (direction de E/S) T_IM_Asservissement.data[1]=0xEF; // Masque -> Bit 7 non concerné T_IM_Asservissement.data[2]=0xE3; // Valeur -> 1 si Entrée et 0 si Sortie // GP7=fs Entrée; GP6=fcg Entree; GP5=fcd Entrée; GP4=ValidIP Sortie; // GP3=PWM2 Sortie; GP2=PWM1 Sortie; GP1=AN1 Entrée; GP0=AN0 Entrée; Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre trame réponse (acquitement) // Pour mettre à 0 les sorties T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x1C; // Masque -> sorties GP4,3,2 sont consernées T_IM_Asservissement.data[2]=0x00; // Valeur -> les 3 sorties sont forcée à 0 (ValidIP=0) Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse (acquitement) // Pour définir sortie GP2 en PWM1 T_IM_Asservissement.data[0]=0x21; // Adresse du registre T1CON T_IM_Asservissement.data[1]=0xB3; // Masque -> seuls bit 7;5;4;1;0 consernés T_IM_Asservissement.data[2]=0x80; // Valeur -> TMR1ON=1; Prescaler1=1 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse (acquitement) // Pour définir fréquence signal sortie PWM1 T_IM_Asservissement.data[0]=0x23; // Adresse du registre PR1 T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=0xFF; // Valeur -> PR1=255 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse (acquitement) // Pour trame interrogative envoyée au commodo Essuie-Glace -> 'IRM' (Information Request Message) // Définir données d'identification T_IRM_Commodo_EG.trame_info.registre=0x00; T_IRM_Commodo_EG.trame_info.champ.extend=1; T_IRM_Commodo_EG.trame_info.champ.dlc=0x08; // On attend 8 octets en réponse T_IRM_Commodo_EG.trame_info.champ.rtr=1; T_IRM_Commodo_EG.ident.extend.identificateur.ident=Ident_T_IRM8_Commodo_EG; // Voir définitions dans fichier CAN_VMD.h // Une première acquisition pour initialiser les grandeurs mise en mémoire Ecrire_Trame(T_IRM_Commodo_EG); // On envoi une première trame interrogative pour initialiser la mémoire do{}while(Lire_Trame(&Trame_Recue)==0); Commodo_EG.valeur=Trame_Recue.data[1]&0xF0; Commodo_EG_Mem=Commodo_EG.valeur; // On met en mémoire l'état actuel pour comparaison ultéérieure Val_Vitesse=Trame_Recue.data[2]; // On récupére les MSB de la conversion A->N voie AN0 Val_Vitesse_Mem=Val_Vitesse; // On met en mémoire la valeur pour comparaison ultérieure // Pour les indicateurs binaires Indicateurs.valeur=0; //Tous les indicateurs sont positionnés à 0 // Les initialisations se sont bien passée // On peut afficher le titre du TP clsscr(); gotoxy(1,2); printf(" *************************************************************\n"); printf(" TPs sur Reseau CAN Application: Commande Essui-glace \n"); printf(" ------------------------------------------------------------\n"); printf(" TP exercie n°1 Sequence de commande moteur E.G. \n"); printf(" La vitesse moteur depend de la position commodo \n"); printf(" Pos1: Petite vitesse Pos2: Grande Vitesse \n"); printf(" Pos3: Vitesse Ajustable Pos4: Fonctionnement périodique \n"); printf(" **************************************************************\n"); // Pour initialiser la base de temps et temporisations SetVect(96,&irq_bt); // mise en place de l'autovecteur PITR = 0x0048; // Une interruption toutes les 10 millisecondes PICR = 0x0760; // 96 = 60H // Boucle principale //******************* do { Ecrire_Trame(T_IRM_Commodo_EG); // On envoi trame interrogative au noeud commodo Essuie-Glace // On attend la réponse do{}while(Lire_Trame(&Trame_Recue)==0); // La fonction renvoie 1 dans ce cas if (Trame_Recue.ident.extend.identificateur.ident==Ident_T_IRM8_Commodo_EG) { Commodo_EG.valeur=Trame_Recue.data[1]&0xF0; // On récupére les états des entrées binaires if(Commodo_EG.valeur!=Commodo_EG_Mem) {// S'il y a eu changement d'une des entrées binaires, on commande le moteur if(Commodo_EG.bit.GP4==0) // On test GP4 (BP1) du commodo EG { // BP1 est actionné (GP4=0) I_Active_Tempo=0; gotoxy(2,12); printf(" Action sur BP1 (GP4) \n" ); T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> seule la sortie ValidIP sera consernée T_IM_Asservissement.data[2]=0x10; // ValidIP =1 donc moteur en marche Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour modifier le rapport cyclique PWM1 -> c'est le module de la commande T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=40; // Valeur ->PWM1DC Vitesse lente Ecrire_Trame(T_IM_Asservissement); // Le moteur ne peut tourner car ValidIP=0 do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse } //else { if(Commodo_EG.bit.GP5==0) // On test GP5 (BP2) du commodo EG { // BP2 est actionné (GP5=0) I_Active_Tempo=0; gotoxy(2,12); printf(" Action sur BP2 (GP5) \n" ); T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> seule la sortie ValidIP sera consernée T_IM_Asservissement.data[2]=0x10; // ValidIP =1 donc moteur en marche Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour modifier le rapport cyclique PWM1 -> c'est le module de la commande T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=70; // Valeur ->PWM1DC Vitesse rapide Ecrire_Trame(T_IM_Asservissement); // Le moteur ne peut tourner car ValidIP=0 do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse } //else { if(Commodo_EG.bit.GP6==0) // On test GP6 (BP3) du commodo EG { // BP3 est actionné (GP6=0) I_Active_Tempo=0; gotoxy(2,12); printf(" Action sur BP3 (GP6)\n" ); T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> seule la sortie ValidIP sera consernée T_IM_Asservissement.data[2]=0x10; // ValidIP =1 donc moteur en marche Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour modifier le rapport cyclique PWM1 -> c'est le module de la commande T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=Val_Vitesse; // Valeur ->PWM1DC Vitesse réglable Ecrire_Trame(T_IM_Asservissement); // Le moteur ne peut tourner car ValidIP=0 do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse } //else { if(Commodo_EG.bit.GP7==0) // On test GP6 (BP3) du commodo EG { // BP3 est actionné (GP6=0) I_Active_Tempo=1; gotoxy(2,12); printf(" action sur BP4 (GP7)\n" ); T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> seule la sortie ValidIP sera consernée T_IM_Asservissement.data[2]=0x10; // ValidIP =1 donc moteur en marche Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour modifier le rapport cyclique PWM1 -> c'est le module de la commande T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=Val_Vitesse; // Valeur ->PWM1DC Vitesse réglable Ecrire_Trame(T_IM_Asservissement); // Le moteur ne peut tourner car ValidIP=0 do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse } //else { // ni BP1 ni BP2 ni BP3 ni BP4 actionné -> On arrete donc le moteur if(Commodo_EG.valeur==0xF0) {I_Active_Tempo=0; T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> seule la sortie ValidIP sera consernée T_IM_Asservissement.data[2]=0x00; // ValidIP =0 donc moteur à l'arret Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse gotoxy(2,12); printf(" Moteur a l'arret \n"); } gotoxy(2,14); printf(" Valeur entrees binaires = %2.2x \n",Commodo_EG.valeur); // On affiche sa valeur }// Fin si changement d'une des entrées binaires // Pour l'entrée analogique Val_Vitesse=Trame_Recue.data[2]; // On récupére les MSB de la conversion A->N voie AN0 if(Val_Vitesse!=Val_Vitesse_Mem) { gotoxy(2,16); printf(" Valeur entree analogique = %3d \n",Val_Vitesse); // On affiche sa valeur if((Commodo_EG.bit.GP6==0)||(Commodo_EG.bit.GP7==0)) {// Pour modifier le rapport cyclique PWM1 -> c'est le module de la commande T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=Val_Vitesse; // Valeur ->PWM1DC Ecrire_Trame(T_IM_Asservissement); // Le moteur ne peut tourner car ValidIP=0 do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse } } // Mise en mémoire des valeurs acquises Commodo_EG_Mem = Commodo_EG.valeur; // On met en mémoire l'état des entrées binaires Val_Vitesse_Mem=Val_Vitesse; // On met en mémoire le résultat de conversion A->N } // Fin si identificateur correct // Pour mode périodique if(I_Active_Tempo==1) {if(I_Fin_Tempo==1) {I_Fin_Tempo=0; if(I_Etat_Moteur==1) {I_Etat_Moteur=0; T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> seule la sortie ValidIP sera consernée T_IM_Asservissement.data[2]=0x00; // ValidIP =0 donc moteur à l'arret Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse } else {I_Etat_Moteur=1; T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> seule la sortie ValidIP sera consernée T_IM_Asservissement.data[2]=0x10; // ValidIP =1 donc moteur en marche Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse } } } }while(1);// FIN de la boucle principale }// FIN fonction principale