====== 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