Table of Contents

Exercice 1 (TP4)

Organigrammes

Fonction principale

Fonction d'interruption

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 <stdio.h>
#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