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