====== Exemple 1 (TP1) ======
===== Sujet =====
**Acquérir l'état du commodo d'essuie-glace
**
==== Objectifs ====
* Définir les trames de commande qui permettent d'initialiser un nœud CAN
* Définir, puis envoyer une trame interrogative à un module d'entrées, accessible à une adresse définie.
* Tester si une trame a été reçue
* Extraire d'une trame réponse les informations attendues
* Visualiser sur l'écran les trames reçues ainsi que les trames envoyées
* Visualiser sur l'écran les données attendues
==== Cahier des charges ====
A intervalles de temps réguliers, on interroge le module sur lequel est connecté le commodo Essuie-Glace afin de connaître son état.
* L'entrée analogique sera convertie
* Les trames reçues ou envoyées sur le bus CAN sont affichées
* La temporisation est de type //logiciel// (comptage du nombre de passages dans la boucle principale)
* Les différentes commandes imposées par la position de la manette commodo seront affichées individuellement
----
===== Eléments de solution =====
==== Analyse ====
Avant de pouvoir lire l'état des entrées du module 8 entrées (dont on donne le schéma structurel en [[annex4|annexe 4]]) sur lequel est relié le commodo essuie-glace, il faut préalablement configurer le CAN expender MCP25050
Cette configuration a pour but de définir en entrée les 8 bits du port (GP0 à GP7). Pour configurer un bit du port en entrée, il faut écrire un "1" sur le bit correspondant du registre GPDDR (Data Direction Register) (voir tableau Register 5-1 à la page 27 de la {{:fr:hardware:didalab:mcp2502x_5x.pdf|doc. technique}} du 25050)
Dans ce cas, la trame envoyée par le contrôleur CAN (Circuit SJA1000 sur carte CAN_PC104) sera vue par le récepteur (circuit MCP25050 sur module) comme une ''IM'' (Input message), avec la fonction ''Write register'' (voir {{:fr:hardware:didalab:mcp2502x_5x.pdf|doc. technique}} du MPC25025 page 22). On pourra ainsi modifier les différents registres du module Asservissement.
=== Configuration des liaisons en entrées ===
**Définition de la trame de commande (''IM'') qui sera envoyée pour configurer le module Commodo-EG**
* Définition de variables structurées sous le modèle ''Trame'' :
''Trame T_IM_Commodo_EG;''
* Définition des éléments d'identification de la variable structurée ''T_IM_ Commodo_EG''
T_IM_Commodo_EG.trame_info.registre=0x00; //On initialise tous les bits à 0
T_IM_Commodo_EG.trame_info.champ.extend=1; //On travaille en mode étendu
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 octets de données
T_IM_Commodo_EG.ident.extend.identificateur.ident=Ident_T_IM_Commodo_EG;
Rem : ''Ident_T_IM_Commodo_EG '' est défini dans le fichier ''[[annex2|CAN_VMD.h]]''
* Définition des paramètres associés à la trame de commande
Il faut initialiser le registre GPDDR (Data Direction Register) en écrivant un 1 si bit d'entrée et un 0 si bit de sortie ({{:fr:hardware:didalab:mcp2502x_5x.pdf|doc. technique}} MCP25050 p. 27).
T_IM_Commodo_EG.data[0]=0x1F; // Adresse du registre GPDDR en écriture (doc MCP25050 page 16)
T_IM_Commodo_EG.data[1]=0x7F; // Masque: bit 7 non concerné (doc MCP25050 page 16)
T_IM_Commodo_EG.data[2]=0x7F; // Valeur: à charger dans le registre adressé (Tous les bits du port sont des entrées)
Suite à ces définitions, il faudra :
* envoyer la trame par la fonction ''Ecrire_Trame(T_IM_Commodo_EG)''
* puis attendre la réponse de type ''Ack'' en utilisant la fonction ''Lire_Trame(&T_Recue)''
L'entrée GP0 étant une entrée analogique (AN0), il faudra mettre en œuvre la fonction de conversion analogique -> numérique.
=== Activation de la conversion Analogique -> Numérique ===
Définition des trois octets de données associées pour :
* activer et configurer la conversion Analogique vers Numérique
D'après la {{:fr:hardware:didalab:mcp2502x_5x.pdf|doc. technique}} du circuit MCP25050 (pages 34 à 37) :
Il faut initialiser le registre ADCON0,
T_IM_ Commodo_EG.data[0]=0x2A; // Adresse du registre ADCON0 en écriture ({{:fr:hardware:didalab:mcp2502x_5x.pdf|doc.}} MCP25050 p15) 0EH + décalage = 0EH + 1CH = 2AH
T_IM_ Commodo_EG.data[1]=0xF0; // Masque: Seul le bit 7 est concerné
T_IM_ Commodo_EG nt.data[2]=0x80; // Valeur: ADON=1 -> Activation convertisseur et prescaler rate = 1:32
Suite à ces définitions, il faudra :
* envoyer la trame par la fonction ''Ecrire_Trame(T_IM_Commodo_EG)''
* puis attendre la réponse de type ''Ack'' en utilisant la fonction ''Lire_Trame(&T_Recue)''
Il faut aussi initialiser le registre ADCON1 :
T_IM_ Commodo_EG.data[0]=0x2B; // Adresse du registre ADCON1 en écriture ({{:fr:hardware:didalab:mcp2502x_5x.pdf|doc.}} MCP25050 p. 15) 0FH + décalage = 0EH + 1CH = 2BH
T_IM_ Commodo_EG.data[1]=0xFF; // Masque: les 8 bits sont concernés
T_IM_ Commodo_EG.data[2]=0xO3; // Valeur: (doc MCP25050 p36)
b7=ADCS1=0; b6=ADCS0=0 → Fréquence Fosc/2
b5=VCFG1=0; b4=VCFG0=0 → Plage de tension en entrée 0/+5V
PCFG3:PCFG0=1100 → Conversion des entrées analogiques 1 et 0 (sur GP1 et GP0)
Suite à ces définitions, il faudra :
* envoyer la trame par la fonction ''Ecrire_Trame(T_IM_Commodo_EG)''
* puis attendre la réponse de type ''Ack'' en utilisant la fonction ''Lire_Trame(&T_Recue)''
=== Acquisition de l'état des entrées sur le module Commodo-EG ===
A intervalles de temps réguliers, on interroge le module 8 entrées sur lequel est connecté le commodo Essuie-Glace. Dans la réponse on attend également le résultat de conversion de l'entrée analogique.
** Définition de la trame interrogative qui sera envoyée **
Dans ce cas, la trame envoyée par le contrôleur CAN (Circuit SJA1000 sur carte CAN_PC104) sera vue par le récepteur (circuit MCP25050 sur module) comme un ''IRM'' (Information Request Message), avec la fonction "Read A/D Regs" (voir {{:fr:hardware:didalab:mcp2502x_5x.pdf|doc. technique}} du CAN Expander MPC25025 pages 22).
* Définition de variables structurées sous le modèle ''Trame'':
''Trame T_IRM_Commodo_EG;'' Trame destinée à l’interrogation du module 8 entrées sur lequel est connecté le commodo lumière
Rem : La variable structurée ''T_IRM_Commodo_EG'' comportera 5 octets utiles seulement, 1'octet pour ''trame_info'' et 4 octets pour l'identificateur en mode étendu (qui comprendra l'adresse du registre concerné par la lecture.
* Accès et définition des différents éléments de la variable structurée ''T_IRM_Commodo_EG''
T_IRM_Commodo_EG.trame_info.registre=0x00; //On initialise tous les bits à 0
T_IRM_Commodo_EG.trame_info.champ.extend=1; //On travaille en mode étendu
T_IRM_Commodo_EG.trame_info.champ.rtr=0x01; // Type trame -> Interrogative
T_IRM_Commodo_EG.trame_info.champ.dlc=0x08; //Il y aura 8 octets de données
T_IRM_Commodo_EG.ident.extend.identificateur.ident= Ident_T_IRM8_Commodo_EG; //! c'est sur 29 bits Pour définir l'adresse du commodo
Des labels définissant les différents identificateurs ont été déclarés dans le fichier ''[[annex2|CAN_VMD.h]]''
Suite à ces définitions, il faudra :
* envoyer la trame par la fonction ''Ecrire_Trame(T_IRM_Commodo_EG)''
* puis attendre la réponse de type ''OM'' en utilisant la fonction ''Lire_Trame(&T_Recue)''
**Trame reçue en réponse à l'interrogation**
D'après la définition des identificateurs donnée en [[annex1|Annexe 1]], une trame de réponse à une ''IRM'' a le même identificateur que la trame interrogative qui en a été à l'origine.
Vu du module (du MCP25050), la réponse à un ''IRM'' (Information Request Message) est un ''OM'' (Output Message).
La trame réponse, suite à l'IRM, comportera en données associées 8 octets ({{:fr:hardware:didalab:mcp2502x_5x.pdf|doc.}} MCP25050 p. 22):
* octet de rang 0 (data[0])→ valeur IOINTFL non utilisée dans notre cas
* octet de rang 1 (data[1])→ valeur GPIO → Valeur des entrées logiques
* octet de rang 2 (data[2])→ valeur AN0H → 8 bits MSB conversion entrée anologique 0
* octet de rang 3 (data[3])→ valeur AN1H → 8 bits MSB conversion entrée anologique 1
* octet de rang 4 (data[4])→ valeur AN10H → 2 fois 2 bits LSB conversion entrées ana. 1 et 0
Les 3 autres octets ne sont pas utiles dans notre application.
Le résultat de conversion est sur 10bits :
* pour résultat AN0
{{ :fr:examples:can:wiper:an0.png|AN0}}
==== Organigramme ====
{{ :fr:examples:can:wiper:orga.png?600 |Organigramme}}
==== Programme en C ====
/************************************************************************************************
* TPs sur EID210 / Réseau CAN - VMD (Véhicule Multiplexé Didactique)
*************************************************************************************************
* APPLICATION: Commande Essuie-glace à distance
*************************************************************************************************
* TP Exemple n°1: Acquérir l'état des entrées binaires ainsi que la valeur de l'entrée analogique
* du commodo Essuie-Glace
* Afficher séparément les états de ces entrées binaires
* Afficher la valeur de l'entrée analogique
*------------------------------------------------------------------------------------------------
* CAHIER DES CHARGES :
* *********************
* On souhaite qu'à intervalles de temps réguliers on interroge le module 8 entrées sur lequel
* est relié le commodo de commande Essuie-Glace
* -> Les trames reçues et envoyées sur le bus CAN sont affichées
* -> Les états des entrées binaires et de l'entrée analogique sont affichés
* -> La temporisation est de type logiciel
* (comptage du nombre de passages dans la boucle principale)
*----------------------------------------------------------------------------------------------
* NOM du FICHIER : TP_Exemple 2.C
* *****************
*************************************************************************************************/
// Fichiers à inclure
//********************
#include
#include "Structures_Donnees.h"
#include "cpu_reg.h"
#include "eid210_reg.h"
#include "Can_vmd.h"
#include "Aton_can.h"
//==========================
// FONCTION PRINCIPALE
//==========================
main()
{// Définition de variables locales
int Compteur_Passage;
unsigned short S_Temp,Valeur_ANA;
unsigned int Cptr_TimeOut;
unsigned char AN0H,AN10L; // Pour récupérer le résultat de la conversion A->N
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 interroger Module 8E sur Commodo Essuie Glace
// IM -> Information Message -> Trame de commande
// Initialisations
//*****************
clsscr();
/* Initialisation DU SJA1000 de la carte PC104 */
Init_Aton_CAN();
// Pour initialiser les liaison en entrées du noeud "Commodo Essuie-Glace"
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)
{ 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<100000;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
}
}
clsscr();
// Pour afficher le titre du TP
gotoxy(1,4);
printf(" ********************************************************************\n");
printf(" TPs sur Reseau CAN Application: Commande Essui-Glace a distance \n");
printf(" --------------------------------------------------------------------\n");
printf(" TP Exemple n°1 \n");
printf(" ACQUERIR les entrees binaires du COMMODO EG \n");
printf(" ACQUERIR la valeur de l'entree analogique du COMMODO EG \n");
printf(" AFFICHER les valeurs acquises \n");
printf(" ***************************************************************** \n");
// 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 trame interrogative envoyée au commodo EG -> '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 demande la valeur de 8 registre
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
Ecrire_Trame(T_IRM_Commodo_EG); // On envoi une première trame
// Initialiser les variables diverses
Compteur_Passage=0;
// Boucle principale
//*******************
do
{ // On teste si une trame a été reçue
if (1==Lire_Trame(&Trame_Recue)) // La fonction renvoie 1 dans ce cas
{gotoxy(4,18);
printf("Trame recue en reponse a la demande: c'est une 'OM' (Output Messsage) \n");
Affiche_Trame(Trame_Recue);
if (Trame_Recue.ident.extend.identificateur.ident==Ident_T_IRM8_Commodo_EG)
{ // On a reçu l'état du commodo donc on affiche les nouveaux états
Commodo_EG.valeur=~Trame_Recue.data[1]; // Les entrées binaires
AN0H =Trame_Recue.data[2]; // On récupére les MSB de la conversion A->N voie AN0
AN10L =Trame_Recue.data[4]; // On récupére les LSB AN1 et AN0
// Traiter les données et reconstituer le résultat de conversion sur 10 bits
Valeur_ANA=(unsigned short)(AN0H); //Transfert avec transtypage
Valeur_ANA=Valeur_ANA<<2; // Décaler de 2 bits vers poids forts
S_Temp=(unsigned short)(AN10L&0x0C); // Pour ne récupérer que les 2 bits AD1 et AD0
Valeur_ANA=Valeur_ANA|(S_Temp>>2); // On reconstitue les 10 du resultat de conversion
// On affiche les résultats
gotoxy(4,22);
printf("Etat des differentes entrees imposees par le commodo:\n");
printf(" Etat entree binaires (en Hexa) =%2.2x\n",Commodo_EG.valeur);
printf(" Valeur de l'entee analogique =%4d\n",Valeur_ANA);
}
}
Compteur_Passage++;
if (Compteur_Passage==50000)
{Compteur_Passage=0;// C'est la fin de temporisation
gotoxy(4,14);
printf("Trame de demande etat commodo: c'est une 'IRM' Input Request Mesage\n");
Affiche_Trame(T_IRM_Commodo_EG); // La trame interrogative est affichée à l'écran
Ecrire_Trame(T_IRM_Commodo_EG);
}
}while(1); // FIN de la boucle principale
}
// FIN fonction principale