IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Modulo pour la gestion d'un mémoire


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 58
    Par défaut Modulo pour la gestion d'un mémoire
    Bonjour,

    Pour mon projet, j'ai dû créer un buffer circulaire. Il reçoit les données d'un bus CAN et les envoi vers une sortie créneau (il s'agit de programmation microcontrôleur).

    J'ai donc créé deux compteurs qui sincrémentent à l'écriture et à la lecture des données.
    J'utilise aussi deux modulo qui me donnent l'état de ma mémoire. Le premier donne l'espace utilisé et le second l'espace libre.
    Mon programme tourne sans soulevé d'erreur au deboggage.

    Par contre, afin de vérifier le bon fonctionnement de mon programme, je m'envoi une trame d'acquittement qui contient les valeurs de mes modulo et de mes compteurs et il apparait que le résultat du calcul modulo n'est pas toujours juste.
    (dans des situations aléatoires et non répétables)

    Voici le code que j'ai réalisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
     
     
    //---------------SendOnCan-------------------------------------------------
     
    void sendOnCan (){
     
      unsigned char txbuffer;
     
      while (!CAN2TFLG){        //test tampon de libre
       ;
      }
     
       CAN2TBSEL=CAN2TFLG;             //selection du buffer ayant la plus petite adresse
       txbuffer = CAN2TBSEL;
        CAN2TXDLR = 0x04 ;	  //Détermine la lenght de la trame de donnée.
        CAN2TXIDR0 = 0xD3;	  //IDE = Détermine l’identificateur du message ID recu 69E
        CAN2TXIDR1 = 0xC0;	  //Bit 3 IDE = 0 format standard Bit 4 RTR = 0 Trame de donnée Bit [5…7] ID = Détermine l’identificateur du message
        CAN2TXDSR0 = buffer_full1;	  // Insertion des données que l’on souhaite transmettre.
        CAN2TXDSR1 = buffer_empty1  ;
        CAN2TXDSR2 = write_buffer_wheel1;
        CAN2TXDSR3 = read_buffer_wheel1;
        //CAN2TXDSR7 = 0xFF;
     
      CAN2TFLG = txbuffer;
     
      while ((CAN2TFLG & txbuffer) != txbuffer) {     //attendre la fin de la transmissin
      ;
      }
     
     
    } 
    //------------------TestCan-------------------------------------------------------
     
    void TestCan (){
     
      unsigned char txbufferE;
     
     
      while (!CAN2TFLG){        //test tampon de libre
       ;
      }
     
       CAN2TBSEL=CAN2TFLG;             //selection du buffer ayant la plus petite adresse
       txbufferE = CAN2TBSEL;
     
     
        CAN2TXDLR = 0x03;	  //Détermine la lenght de la trame de donnée.
        CAN2TXIDR0 = 0x29;	  //IDE = Détermine l’identificateur du message  ID recu 2BD
        CAN2TXIDR1 = 0x80;	  //Bit 3 IDE = 0 format standard Bit 4 RTR = 0 Trame de donnée Bit [5…7] ID = Détermine l’identificateur du message
        CAN2TXDSR0 = Buf1;	  // Insertion des données que l’on souhaite transmettre.
        CAN2TXDSR1 = Buf2  ;
        CAN2TXDSR2 = buffer_full1;
        //CAN2TXDSR3 = 0x9C;
        //CAN2TXDSR7 = 0xFF;
     
      CAN2TFLG = txbufferE;
     
      while ((CAN2TFLG & txbufferE) != txbufferE) {     //attendre la fin de la transmissin
      ;
     }
    }
     
    //------receiveOnCan-----------------------------------------
     
    void receiveOnCan (){
     
      unsigned char lenght, index;
     
      DisableInterrupts;   
     
      if (CAN2RFLG & CAN2RFLG_RXF_MASK) {  //message disponible
     
         lenght = ( CAN2RXDLR & 0x0F);     //prend en compte la taille max du message (message = 8 octets max)
     
      for (index = 1 ; index < lenght; index++) {
     
        receive_data [index] = *(&CAN2RXDSR0 + index);  // Transfert du message vers un tampon
      }
     
      Buf1 = write_buffer_wheel1 - read_buffer_wheel1;
      Buf2 =  buffer_lenght+ Buf1;
      buffer_full1 = Buf2 % buffer_lenght;
      TestCan ();
     
      buffer_empty1 = (buffer_lenght-(write_buffer_wheel1 - read_buffer_wheel1)) % buffer_lenght;
      buffer_full2 = (buffer_lenght+(write_buffer_wheel2 - read_buffer_wheel2)) % buffer_lenght;
      buffer_empty2 = (buffer_lenght-(write_buffer_wheel2 - read_buffer_wheel2)) % buffer_lenght;
      buffer_full3 = (buffer_lenght+(write_buffer_wheel3 - read_buffer_wheel3)) % buffer_lenght;
      buffer_empty3 = (buffer_lenght-(write_buffer_wheel3 - read_buffer_wheel3)) % buffer_lenght;
      buffer_full4 = (buffer_lenght+(write_buffer_wheel4 - read_buffer_wheel4)) % buffer_lenght;
      buffer_empty4 = (buffer_lenght-(write_buffer_wheel4 - read_buffer_wheel4)) % buffer_lenght; 
     
     
    //ecriture memoire roue 1 et test memoire pleine wheel1 ------------------
     
    if (write_buffer_wheel1 != buffer_lenght) {
     
        if (write_buffer_wheel1< buffer_lenght && buffer_full1 != 0)  {           //test de la taille de la memoire
                  wheel1 [write_buffer_wheel1]= receive_data[1] + (256*receive_data[0]) ;      //ecriture dans la memoire
                  write_buffer_wheel1 ++;                   //incrementation du compteur ecriture
     
     
        } else if (write_buffer_wheel1< buffer_lenght && buffer_full1 == 0) {
     
             PORTB =0b00000001  ; 
             sendOnCanFull ()   ;
     
         }
    }else {
                 write_buffer_wheel1 = 0;                  //rebouclage de la memoire
                  wheel1 [write_buffer_wheel1]= receive_data[1] + (256*receive_data[0]) ; 
     
              } 
     
        CAN2RFLG = 0x01;          //flag lors de la reception d'un message
        EnableInterrupts ;  
     
       }
     
        sendOnCan();            
       //CAN2RIER = 0x01; // interruption du recepteur après la réception du message
     
     
    }  
     
    /*----------------------------------Interrupt------------------------------------------------*/        
    #pragma CODE_SEG NON_BANKED   //permet de placer les interruption dans la mémoire en reserve
     
    void interrupt 8 TOC0_ISR () {
     
      TFLG1 = TFLG1_C0F_MASK ;    // rabaisse le flag de l'interruption
     
     // buffer_empty1 = buffer_lenght - buffer_full1;
     
     if (buffer_empty1 == buffer_lenght) {
        PORTB =0b00000100  ; 
         sendOnCanEmpty ()   ;  
     
     }
     
      if ( read_buffer_wheel1 < buffer_lenght ){                    //test taille de la memoire
     
         TC0 = TC0 + wheel1[read_buffer_wheel1] ;                //lecture des donnees
         read_buffer_wheel1 ++    ; //incrementation compteur lecture
     
     
          } else{
     
             read_buffer_wheel1 = 0    ;                           //rebouclage memoire   .
             TC0 = TC0 + wheel1[read_buffer_wheel1] ;                //lecture des donnees 
     
         }                                                            
     
    }         
    #pragma CODE_SEG DEFAULT    
     
    ////////////////////////////////////////////
    #pragma CODE_SEG_NON_BANKED
    Le problème c'est que je ne sais pas s'il s'agit d'une erreur de programmation ou si je ne pas correctement mes tests.
    (Je me réfere à la trame SendOnCan pour vérifier les calculs)

    Merci,

  2. #2
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 58
    Par défaut
    Je peux joindre une copie d'écran des trames reçus si nécessaire.

  3. #3
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    un tampon circulaire est vide si son pointeur d'entrée est égal à son pointeur de sortie. S'il contient quelque chose, les pointeurs sont différents (sauf s'il est TOTALEMENT plein, mais là on rentre dans la gestion d'erreurs). Il n'y a pas besoin de passer par un modulo. Le modulo sert simplement à l'incrémentation d'un pointeur pour garantir qu'il repasse à zéro s'il sort de la plage voulue.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #include <stdio.h>
    #include <stdlib.h>
     
    #define BUFFER_SIZE 10
     
    typedef struct
    {
        float data[BUFFER_SIZE];
        int ptrin;
        int ptr_out;
    }BUFFER;
     
    void bufferInit(BUFFER* pbuf)
    {
        pbuf->ptrin = 0;
        pbuf->ptr_out = 0;
    }
     
    int isBufferEmpty(BUFFER* pbuf)
    {
        return(pbuf->ptrin == pbuf->ptr_out);
    }
     
    void incPointer(int* ptr)
    {
        *ptr = (*ptr + 1) % BUFFER_SIZE;
    }
     
    int main(void)
    {
        BUFFER buffer;
        int cpt;
     
        bufferInit(&buffer);
        printf("ptr_in:%i ptrout:%i isBufferEmpty():%i\n", buffer.ptrin, buffer.ptr_out, isBufferEmpty(&buffer));
        incPointer(&buffer.ptrin);
        printf("ptr_in:%i ptrout:%i isBufferEmpty():%i\n", buffer.ptrin, buffer.ptr_out, isBufferEmpty(&buffer));
        cpt = 11;
        while(cpt--)
        {
            incPointer(&buffer.ptrin);
            printf("ptr_in:%i\n", buffer.ptrin);
        }
        return 0;
    }
    Peux tu préciser un peu le contexte? En can, on travaille souvent au niveau du message et non pas au niveau de l'octet reçu. Le programmeur n'a pas besoin de passer par un tampon circulaire, sauf s'il est sur un tout petit micro ou sans librairies fournies. On pourrait concevoir un tampon circulaire, mais qui contiendrait des messages et non pas des octets.

  4. #4
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 58
    Par défaut
    Il s'agit de traiter un bus CAN véhicule. Le but du projet est de pouvoir envoyer des données (d'extension .mat) vers la carte µcontroleur et en sortie d'obtenir un signal créneaux.

    Pour le traitement des messages, j'utilise le logiciel CANalyzer. Pour le moment, je dois seulement envoyer une trame basique de 8 octets vers la carte.

    Pour le microncontrôleur, il s'agit d'un MC9S12XDP512.

    Qu'est-ce que tu entends par message et octet ? Je ne vois pas la différence, une trame de bus CAN est constituée d'octet, non ?

  5. #5
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 58
    Par défaut
    Le truc c'est que les données ne vont pas arriver à la même vitesse.
    Je pense qu'il vaut mieux maintenir le buffer circulaire. Par contre je peux me passer de modulo.

    En fait le but est de pouvoir faire correctement le rebouclage et la gestion d'erreur (mémoire vide et pleine). Je ne dois perdre aucune données (si la mémoire est pleine la première valeur est remplacée par la dernière et je veux surtout l'éviter)

    Est-ce que les pointeurs sont vraiment obligatoires ? J'ai un peu de mal à les gérer (enfin si c'est nécessaire je vais m'y mettre) et on m'a conseillé de ne pas les utiliser.

  6. #6
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par BlueWolf9 Voir le message
    Est-ce que les pointeurs sont vraiment obligatoires ?
    Les deux index sont obligatoires, c'est le fondement du tampon circulaire.

    Citation Envoyé par BlueWolf9 Voir le message
    une trame de bus CAN est constituée d'octet, non ?
    Dans la couche la plus basse, oui, mais au niveau du développeur, il faudrait un système de messages. Un message a une taille fixe, plus besoin de tampon circulaire. Voici la structure de base d'un message:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct
    {
        unsigned long cob_id;   /* 11/29-bit message identifier */
        int type;               /* type of the message */
        int nb_bytes;           /* data length of the message (0..8) */
        unsigned char data[8];  /* data of the message (DATA[0]..DATA[7] */
    }CAN_MESSAGE;
    L'idéal est de séparer les tâches. Une tâche qui reçoit les octets et construit les messages. l'autre tâche qui traite les messages. Tout est compliqué par le fait que tu ne puisses pas faire de free/malloc. Dans ce cas là, j'ai bien peur qu'on assiste au retour du tampon circulaire... Mais un tampon circulaire sur les messages et en variable globale.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #define MAILBOX_SIZE 10
    typedef struct
    {
        CAN_MESSAGE messages[MAILBOX_SIZE];
        int ptr_in;
        int ptr_out;
    }MAILBOX;
     
    MAILBOX mail_box; /* global mailbox creation */
    Là, tu as un tampon de 10 messages, de quoi voir venir. Je pense à te lire (mais je peux me tromper) qu'un détail t'as échappé, c'est qu'un message can n'est pas uniquement constitué des 0 à 8 octets de données.

    Je te conseille la lecture de ce document à partir de la page 419, il y est clairement dit que le can de ton micro tamponne la réception de 5 messages et l'émission de 3 messages. Aucun besoin de passer par un UART.

  7. #7
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 58
    Par défaut
    D'accord. Je ne l'avais pas compris comme ça (pour la transmission des données)
    Donc en fait cela signifie que je n'ai pas besoin d'un buffer circulaire ?

    Par contre (je reviens sur le problème de conversion de la discussion previous state) je dois tout de même créer une mémoire de taille 2 (minimum)

    Pour la conversion je n'ai pas le choix le calcul utilise la donnée envoyée actuelle et précédente

  8. #8
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par BlueWolf9 Voir le message
    je dois tout de même créer une mémoire de taille 2 (minimum)
    Qu'est ce qu'une mémoire de taille 2? Les messages reçus ne sont pas en mémoire, mais dans les registres du périphérique can. Tu devrais vraiment lire la doc dont je t'ai donné le lien. Toutes les questions que tu te poses y ont leurs réponses. Un petit extrait:

    10.4.2.3 Receive Structures
    The received messages are stored in a five stage input FIFO. The five message buffers are alternately
    mapped into a single memory area (see Figure 10-39). The background receive buffer (RxBG) is
    exclusively associated with the MSCAN, but the foreground receive buffer (RxFG) is addressable by the
    CPU (see Figure 10-39). This scheme simplifies the handler software because only one address area is
    applicable for the receive process.:


    Il y est dit qu'un tampon circulaire de 5 messages en réception est géré par le périphérique can, donc avant toute chose, lire la doc.

Discussions similaires

  1. Réponses: 4
    Dernier message: 14/02/2007, 10h02
  2. Gestion de la mémoire entre plusieurs DLL
    Par Laurent Gomila dans le forum C++
    Réponses: 7
    Dernier message: 27/07/2004, 15h28
  3. [LG]tests pour la gestion d'erreur
    Par le 27 dans le forum Langage
    Réponses: 3
    Dernier message: 22/12/2003, 20h44
  4. Détourner une fonction pour copier un fichier en mémoire
    Par Rodrigue dans le forum C++Builder
    Réponses: 6
    Dernier message: 12/11/2003, 08h29
  5. Gestion des variables - mémoire ?
    Par RIVOLLET dans le forum Langage
    Réponses: 4
    Dernier message: 26/10/2002, 12h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo