Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

Fonction avec du texte en parametre
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#1 Message par Jérémy » dim. 16 oct. 2016 10:08

Bonjour à tous,

Je galère un peu ( pour ne pas dire beaucoup) à fiabiliser à 100% mon programme. Peut être est ce a cause de l'UART qu(il m'arrive parfois d'avoir des bugs inexplicables ( ou incompréhensibles pour moi).

Je cherche donc une manière de ne jamais rendre mon programme bloquant ( pas de boucle infinie). cela implique que sur chaque envoi ou attente de réponse je dois comptabiliser les boucles et si blocage soit en sortir soit carrément reseter le module.

Pour ce faire je souhaiterais créer une fonction avec du texte en paramètre d'entrée. mais je me mélange les pinceaux avec ces pointeurs.
Comme j'ai plusieurs fois le même style de dialogue une fonction me parait approprié. Partons sur un exemple simple : l'effacement des messages.

Je dois envoyer une commande à mon module GSM: AT+QMGDA="DEL ALL" suivis d'un CR
Celui une fois fait doit me répondre avec un Ok

Pour le moment j'en suis la :

Code : Tout sélectionner

        //----- On efface le message (tous les messages)
        i = 0;
        do {
            i++;
            UART1_Write_Text("AT+QMGDA=\"DEL ALL\"\n");
            delay_ms(100);
            if (i>10) break;
          } while(Ok == 0); 


Je RAZ mon index
- J’exécute la boucle au moins une fois
- J’incrémente mon index pour compter le nombre de boucle
- J'envoie mon message
- j'attends 100ms afin de recevoir une réponse (le drapeau Ok se léve)
- Je regarde le nombre de boucle, si supérieur a 10 je sors a quand même ( ou je reset).
- Si je n'ai pas reçu de Ok je réessaye.

Je souhaiterais faire une fonction appelée Envoi_Commande(ma commande) par exemple, avec le texte en paramètres .

La notion de pointeur reste vraiment difficile encore pour moi !

j'ai essayé ceci sans sucés

Création d'un tableau pour enregistre le texte :

Code : Tout sélectionner

char Commande[50]; 


Code : Tout sélectionner

 Envoi_Commande("AT+QMGDA=\"DEL ALL\"\n");


Code : Tout sélectionner

// -----------------      Envoi d'un commande      -----------------------------
// Elle permet d'envoyer une commande et de s'assurer de celle ci
void Envoi_commande(*Commande){
        i = Ok = 0;
        do {
            i++;
            UART1_Write_Text(Commande);
            delay_ms(100);
            if (i>10) break;
          } while(Ok == 0);
 }
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Fonction avec du texte en parametre
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2597
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#2 Message par paulfjujo » dim. 16 oct. 2016 20:23

bonsoir Jeremy et tous


Code : Tout sélectionner

char Commande[50];  

tableau de char en RAM

Code : Tout sélectionner


void Envoi_commande
(*Commande)
{
 ... 


tu envoies en parametre le caractere pointé par Commande,et non pas le pointeur ..

Code : Tout sélectionner


void Envoi_commande
(Commande)
{
.... 


autre probleme:

Code : Tout sélectionner

Envoi_Commande("AT+QMGDA=\"DEL ALL\"\n"); 

texte en ROM (dans le programme)


exemple :

Code : Tout sélectionner

 Send_Cde_display_response("AT+CREG?\r"Drapeaux.Visible); 

avec texte en ROM
usage d'un cast pour sepecifier que le message est en ROM et non en RAM

Code : Tout sélectionner

void Send_Cde_display_response(const charCdechar B)


sinon utiliser prealablement

Code : Tout sélectionner

strConstRamCpy(Commande,"AT+QMGDA=\"DEL ALL\"\n"); 

puis

Code : Tout sélectionner

 Envoi_commande(Commande); 
Aide toi, le ciel ou FantasPic t'aidera

Fonction avec du texte en parametre
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#3 Message par Jérémy » lun. 17 oct. 2016 18:57

Bonsoir Paul et tout le monde,

Entre temps j'avais réussis à faire une espèce de mixe entre l'exemple et ton explication . Mais je reste encore dans le flou, car même si mon test fonctionne plutôt bien, des fois j'ai encore des ratés , je ne comprends vraiment pas je suis a 2400bauds pourtant !
est ce normal de ne pas pouvoir être certains de la reception d'un bon caractère ?

Voila ma fonction actuelle , voyez vous des erreurs ? :

Code : Tout sélectionner

void Envoi_Commande(const char *Commande){
    
char j=i=Ok=0;
    while(
1){
         
         while(*
Commande) {          // Boucle pour balayer le texte a envoyer jusqu'au "NULL"
             
UART_Write(*Commande++);
           }
           
UART_Write(13);           // On envoie un CR

         
while (Ok == 0)             // Je rentre dans une boucle pour attendre la reponse "Ok"
            
{
               
delay_ms(100);
               
i++;
               if (
i>20)             // Si au bout de 20 tentatives je sors pour re-envoyer la commande
                  
{
                     
j++;
                     
i=0;
                     break;
                   }
             }

         if (
j>=5asm reset;        // Au bout de 3 boucles de 20 tentatives je reset
         
if ((Ok) && (erreur==0) ) break;// Si j'ai recu "Ok" et sans erreur , je peux sortir
     
}
     
Ok 0;
 } 


Et voici la commade qui lance ma fonction :

Code : Tout sélectionner

         // ----- On efface les messages
         
Envoi_Commande("AT+QMGDA=\"DEL ALL\""); 
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Fonction avec du texte en parametre
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2597
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#4 Message par paulfjujo » mar. 18 oct. 2016 11:12

bonjour Jeremy et tout le monde


on peut integrer le UART_Write(13) direct dans le message à envoyer

Code : Tout sélectionner

 Envoi_Commande("AT+QMGDA=\"DEL ALL\"\r"); 

"j" me semble mal placé...pour reiterer l'envoi d'une commande

Code : Tout sélectionner

void Envoi_Commande(const char *Commande)
{
    char i=j=Ok=0;
    while(1)
    {
     while(*Commande) 
      
{          // Boucle pour balayer le texte a envoyer jusqu'au "NULL"
           UART_Write(*Commande++);
      }
      while (Ok == 0)   // Je rentre dans une boucle pour attendre la reponse "Ok"
     {
       delay_ms(100);
        i++;
         if (i>20)      // Si au bout de 20 tentatives je sors pour re-envoyer la commande
         {
            break;
         }
      }
       j++;
      if (j>5) asm reset;  // Au bout de 5 boucles de 20 tentatives je reset
      if((Ok) && (erreur==0) ) break;// Si j'ai recu "Ok" et sans erreur , je peux sortir    
    }
 // i = j = Ok = 0;
 // pas la peine de RAZER les variables, Qui sont locales dans ce cas là
 // non visibles depuis le main program
}


au niveau de la machine d'etat, à la reception de "OK" ,
je bloquerai la reception pour ne pas avoir le risque de fausse detection tel
que 'E' ,'M' .. les autres caracteres detectables..de la machine d'etat
et ne reactiverait la reception que sur la commande suivante

je n'utilise pas de machine d'etat,mais un buffer de reception de 384 car,
rempli par interruption RX,
permettant largement de stocker un ou 2 SMS complet (tailla maxi SMS simple= 160 cars)
la reception etant bloquée sur debordement du buffer ou chaine specifique de caractere detectée.
Certaines commandes GSM sont tres BAVARDES : beaucoup d'info en retour !
et je pense que la solution machine d'état ne peut pas repondre aux cas litigieux..
Aide toi, le ciel ou FantasPic t'aidera

Fonction avec du texte en parametre
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2597
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#5 Message par paulfjujo » mar. 18 oct. 2016 11:39

bonjour Jeremy et tout le monde


on peut integrer le UART_Write(13) direct dans le message à envoyer

Code : Tout sélectionner

 Envoi_Commande("AT+QMGDA=\"DEL ALL\"\r"); 

"j" me semble mal placé...pour reiterer l'envoi d'une commande

Code : Tout sélectionner

void Envoi_Commande(const char *Commande)
{
    char i=j=Ok=0;
    while(1)
    {
     while(*Commande) 
      
{          // Boucle pour balayer le texte a envoyer jusqu'au "NULL"
           UART_Write(*Commande++);
      }
      while (Ok == 0)   // Je rentre dans une boucle pour attendre la reponse "Ok"
     {
       delay_ms(100);
        i++;
         if (i>20)      // Si au bout de 20 tentatives je sors pour re-envoyer la commande
         {
            break;
         }
      }
       j++;
      if (j>5) asm reset;  // Au bout de 5 boucles de 20 tentatives je reset
      if((Ok) && (erreur==0) ) break;// Si j'ai recu "Ok" et sans erreur , je peux sortir    
    }
 // i = j = Ok = 0;
 // pas la peine de RAZER les variables, Qui sont locales dans ce cas là
 // non visibles depuis le main program
}


au niveau de la machine d'etat, à la reception de "OK" ,
je bloquerai la reception pour ne pas avoir le risque de fausse detection tel
que 'E' ,'M' .. les autres caracteres detectables..de la machine d'etat
et ne reactiverait la reception que sur la commande suivante

je n'utilise pas de machine d'etat,mais un buffer de reception de 384 car,
rempli par interruption RX,
permettant largement de stocker un ou 2 SMS complet (tailla maxi SMS simple= 160 cars)
la reception etant bloquée sur debordement du buffer ou chaine specifique de caractere detectée.
Certaines commandes GSM sont tres BAVARDES : beaucoup d'info en retour !
et je pense que la solution machine d'état ne peut pas repondre aux cas litigieux..

test de cette cde sur mon programme:
2016-10-18 11:35:33:533_R:] HDecal= 2
[2016-10-18 11:35:33:542_R:] Delete ALL MSG ("AT+QMGDA="DEL ALL"
[2016-10-18 11:35:38:064_R:] AT+QMGDA="DEL ALL"
[2016-10-18 11:35:38:080_R:]
[2016-10-18 11:35:38:087_R:] OK
[2016-10-18 11:35:38:097_R:] Step: 5
[2016-10-18 11:35:39:588_R:] Phase d'init en 5 pas/5.. OK
[2016-10-18 11:35:41:618_R:]
[2016-10-18 11:35:41:631_R:] Constitution du SMS à envoyer
[2016-10-18 11:35:41:649_R:]
[2016-10-18 11:35:41:740_R:] Arme RX IT UART1 ..
[2016-10-18 11:35:41:763_R:] 0 EA1= 1; EA2 Now= 64;Waiting filtering ; No MCP23017;BP1=1; BP2=1; LD1=0; LD2=0;Dialog=1; SOM=0; STAT=1; DTR=0


"OK" arrive 23 ms apres la commande
liaison UART <-> GSM à 19200 bads
FOSC à 48MHz
Aide toi, le ciel ou FantasPic t'aidera

Fonction avec du texte en parametre
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#6 Message par Jérémy » mar. 18 oct. 2016 20:19

Bonsoir,

J'ai essayer d'intégrer tes conseils.

Je pense après mures réflexions que mon programme est mal fichu ( pas nouveau lol) .
Ton idée de variables locales et TRES intéressantes . Mais je n'ai pas assez d’expérience la dessus c'est pourquoi je ne travaille qu'avec des variables globales pour me simplifier la vie, mais j'avoue que ce n'est pas forcement TOP et surtout peut-être la cause de mes erreurs.

Ceci m’amène quelques questions ?
Peut -on déclarer des variables locales avec le même nom que les Globales ? dans ce cas la lesquelles sont prises en compte ? car mon "i" et mon compteur temporaire que j'ai pris l'habitude de mettre un peu partout .

tu déclares 4 variables locales, mais le Ok est une variable modifier en dehors de la fonction ( dans la machine d'état) , sera-t-elle modifier ? ne risque-t-il pas d'avoir conflit ?

Merci pour ton bout de code , je l'étudie.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Fonction avec du texte en parametre
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#7 Message par Jérémy » mar. 18 oct. 2016 20:51

Voila j'ai modifié ma fonction en suivant tes conseils.

Pour le moment je laisse le UART_Write(13);, car je vais oublié de mettre un \r à la fin de mon texte c'est sur . :sifflotte:
Je également laissé les variables en globales, tant que je ne suis pas sur de ce que je fais .

Pour le moment je suis à une trentaine de texto sans aucune erreur ! je touche au BUT !

Sinon cette aprés midi au travail, j'ai pensé a tout passé en machine d'état. même les textos recus et pas seulement les réponses du modules .
cela m'aurait allonger la machine d'état, mais je pense que ca aurait été mieux au final. Car au saut de switch case reste un saut ? en terme de temps ? qu'il saute à la fin ou au début c'est pareil non ? A partir du moment ou j'ai peu de traitement dans l'INT peut importe le nombre de cas de figure possible ?

Voila ma fonction qui pour le moment fonctionne bien , je croise les doigts pour la suite .

Code : Tout sélectionner


void Envoi_Commande
(const char *Commande){
    
j=i=Ok=Erreur=0;
    while(
1){
         
         while(*
Commande) {          // Boucle pour balayer le texte a envoyer jusqu'au "NULL"
             
UART_Write(*Commande++);
           }
           
UART_Write(13);           // On envoie un CR

         
while ((Ok==0) && (Erreur==0)) // Je rentre dans une boucle pour attendre la reponse "Ok"
            
{
               
delay_ms(100);
               
i++;
               if (
i>20)             // Si au bout de 20 tentatives je sors pour re-envoyer la commande
                  
{
                     
j++;
                     if (
j>=5asm reset;        // Au bout de 3 boucles de 20 tentatives je reset
                     
i=0;
                     break;
                   }
             }
         if ((
Ok) && (Erreur==0) ) break;// Si j'ai recu "Ok" et sans erreur , je peux sortir
     
}
     
i=j=Ok=0;
 }
  
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Fonction avec du texte en parametre
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2597
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#8 Message par paulfjujo » mer. 19 oct. 2016 17:54

le probleme etait bien sur l'usage de ok en variable locale au lieu de globale
par le fait d'ecrire
char i=j=ok=0;

sans la definition char
on reste en variable globale pour i,j et ok

mais tu pourrais conserver i et j en locale
puisque ne servent que dans la procedure
d'ou
char i=j=0; // sans le ok

au cas ou i et j serait utilsé par ailleurs..
Aide toi, le ciel ou FantasPic t'aidera


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 64 invités