Est-ce possible en langage C?
Répondre à la discussion
Page 1 sur 3 12 DernièreDernière
Affichage des résultats 1 à 30 sur 79

Est-ce possible en langage C?



  1. #1
    flolarajasse

    Est-ce possible en langage C?


    ------

    Bonjour à tous,

    Je suis confronté à une énigme, je vous explique.
    Sur mon PIC (18F4431), je réalise une conversion analogique numérique (entrée d'un potentiomètre), et je souhaite ensuite envoyer cette valeur sur un PWM. Pour le CAN, j'ai seulement garder les 8 bits de pois fort ; je souhaite les copier dans les 8 bits de poids fort du PWM, comme sous le schéma ci dessous :

    Nom : Sans titre.jpg
Affichages : 137
Taille : 43,3 Ko

    Ma question est, comment procéder? Je sais qu'en assembleur, c'est peut-être possible ; mais en C, est ce qu'il est possible de copier bit à bit, exemple :
    - je veux que le bit 5 de PDC0H soit égale au bit 7 de ADRESH?

    Merci de m'éclairer.
    Bonne journée.

    -----
    Java is the best!

  2. #2
    paulfjujo

    Re : Est-ce possible en langage C?

    bonjour,


    Resultat de ADC a mettre dans un entier 16 bits et decaler le tout de 6 bits à gauche
    à verifier si le registre PDC0 peut s'ecrire en 1 fois (16 bits)

    Code:
    unsigned int value;
    
    value=ADRESH;
    value=value<<6;
    
    PDC0=value;
    
    ou
    PDC0H=(value & 0xFF00)>>8;   
    PDC0L=value & 0x00C0;

  3. #3
    flolarajasse

    Re : Est-ce possible en langage C?

    Est ce que cette solution fonctionne si je veux utiliser seulement les 8 bits de poids fort de ADRESH ; car le résultat de l'ADC est un 10 bits.

    Malheureusement, je ne crois pas que PDC0 puisse s'écrire en une fois.
    Java is the best!

  4. #4
    paulfjujo

    Re : Est-ce possible en langage C?

    meme si l'ADC est sur 10 bits ADRESH est un registre sur 8 bits ..
    verifier tout de meme que le resultat de mesure demandé (dans l' init ADC) est cadré à gauche ! (et non à droite)

    Citation Envoyé par flolarajasse Voir le message
    Malheureusement, je ne crois pas que PDC0 puisse s'écrire en une fois.
    donc utiliser la 2em solution

    Code:
    PDC0H=(value & 0xFF00)>>8;   
    PDC0L=value & 0x00C0;

  5. A voir en vidéo sur Futura
  6. #5
    flolarajasse

    Re : Est-ce possible en langage C?

    Citation Envoyé par paulfjujo Voir le message
    verifier tout de meme que le resultat de mesure demandé (dans l' init ADC) est cadré à gauche ! (et non à droite)
    ça, c'est moi qui le définit et je l'ai bien justifié à gauche.

    J'ai compris le principe, malheureusement, mon PWM ne monte qu'à 25% au maximum.
    Java is the best!

  7. #6
    Bluedeep

    Re : Est-ce possible en langage C?

    Citation Envoyé par flolarajasse Voir le message

    J'ai compris le principe, malheureusement, mon PWM ne monte qu'à 25% au maximum.
    Ce qui est assez logique, car pour être à 100%, il attend tous les 10 bits à 1.
    Il faut "éparpiller" les 8^2 valeurs sur 10^2.

    C'est parfaitement possible en C en utilisant les opérations bit à bit (<< , >> pour les décalages et les opérations logiques).

  8. #7
    flolarajasse

    Re : Est-ce possible en langage C?

    Je t'explique rapidement mon programme ; j'ai une interruption, à chaque fois qu'une conversion ADC se termine, je stocke la valeur dans un tableau de 16 cases:

    Code:
    void interrupt high_priority conv_CAN ()
    {
       if (PIR1bits.ADIF == 1) // Si conversion terminée
       {
           result_conv[compte] = (int) ADRESH; // Résultat de la conversion sur 8 bits.
           compte++;
           Nop();
           Nop();
           Nop();
           PIR1bits.ADIF = 0; // On réintialise ADIF
           ADCON0bits.GO = 1; // On lance une conversion
       }
    }
    Ensuite dans mon programme principal, quand un compteur atteint une valeur (16), je fais la moyenne et j'écris la valeur dans les registres PWM :

    Code:
    int main(int argc, char** argv)
    {
    //différentes initialisations
    ..
    ..
    ..
    
        ADCON0bits.GO = 1; // On lance une conversion
        while(1)
        {
            if (compte == 16)
            {
                INTCONbits.GIE = 0; // Désactive les interruptions
                for (i = 0 ; i < 16 ; i++)
                {
                    moyenne = moyenne + result_conv[i];
                }
                
                moyenne = moyenne >> 4 ; // Décalage de 4 bits à droite correspond à division par 16
                valeur_PWM = moyenne ;
                PDC0H = (valeur_PWM & 0xFF00) >> 8; // On stocke les 6 bits de poids fort dans PDC0H
                PDC0L = valeur_PWM & 0x00C0; //On stocke les 8 bits de poids faible dans PDC0L
                compte = 0;
                result_conv[16] = 0;
                INTCONbits.GIE = 1; // Active les interruptions
            }
            else
            {
            }
            moyenne = 0;
        }
    }
    Malheureusement, je ne monte qu'à 25% ; soucis dans mes variables ou dans mes décalages?
    Java is the best!

  9. #8
    paulfjujo

    Re : Est-ce possible en langage C?

    mon PWM ne monte qu'à 25% au maximum.
    c'est pareil si tu fais une commande directe des registre PDC0H et PDC0L ?
    en verifiant par exemple dans une boucle

    Code:
    for (value=0; value <16384;value=value+128)
    {
    PDC0H=(value & 0xFF00)>>8;   
    PDC0L=value & 0x00C0;
    Delay_ms(1000);  // le temps de voir le resultat
    }

  10. #9
    flolarajasse

    Re : Est-ce possible en langage C?

    Citation Envoyé par paulfjujo Voir le message
    c'est pareil si tu fais une commande directe des registre PDC0H et PDC0L ?
    en verifiant par exemple dans une boucle

    Code:
    for (value=0; value <16384;value=value+128)
    {
    PDC0H=(value & 0xFF00)>>8;   
    PDC0L=value & 0x00C0;
    Delay_ms(1000);  // le temps de voir le resultat
    }
    Non dans ce cas, je monte bien de 0% à 100%.
    Java is the best!

  11. #10
    paulfjujo

    Re : Est-ce possible en langage C?

    Si tu utilise C18
    attention à declarer volatile les variables utilisees dans l'interrupt ET le main

    si tu veux garder une resultat sur 14 bits , il faut conserver le decalage à gauche de ADRESH

    Code:
        
    ----------------------------
                moyenne = moyenne >> 4 ; // Décalage de 4 bits à droite correspond à division par 16
                valeur_PWM = moyenne <<6 ;
    --------------------------
    ou     
    -------------------------
        valeur_PWM=myenne<<2;      // >>4 puis <<6  => <<2
    --------------------------
    
                PDC0H = (valeur_PWM & 0xFF00) >> 8; // On stocke les 6 bits de poids fort dans PDC0H
                PDC0L = valeur_PWM & 0x00C0; //On stocke les 8 bits de poids faible dans PDC0L
                compte = 0;
                result_conv[16] = 0;
                INTCONbits.GIE = 1; // Active les interruptions

  12. #11
    flolarajasse

    Re : Est-ce possible en langage C?

    Citation Envoyé par paulfjujo Voir le message
    Si tu utilise C18
    Non, j'utilise XC8.
    Java is the best!

  13. #12
    flolarajasse

    Re : Est-ce possible en langage C?

    Ok, je viens de comprendre ton code paulfjujo, et j'ai compris le principe, astucieux.
    En revanche, quand je réglais pon PWM à la main ( PWM_val = 16383), j'arrivais bien à 100%.

    Là, je n'y arrive pas tout à fait, est-ce du au fait que :
    Code:
    PDC0L = valeur_PWM & 0x00C0;
    donc

    Code:
    PDC0L = 11000000; (valeur max?)
    Merci.
    Java is the best!

  14. #13
    paulfjujo

    Re : Est-ce possible en langage C?

    dans ton post#1 , tu ne voulais pas remplir les 6 premiers bit de PDC0L !
    puisque que tu ne disposes que de 8 bits (ADRESH) de commande
    Chaque bit de commande a donc un poids de 64 unites (16384/256=64)
    il manque donc en effet 64 points pour arriver au maxima



    Code:
    PDC0L = valeur_PWM & 0x00FF;
    pourquoi ne pas exploiter le resultat ADC sur 10 bits ?

  15. #14
    flolarajasse

    Re : Est-ce possible en langage C?

    Tu as tout à fait raison, je viens de m'en rendre compte et c'est logique.
    Java is the best!

  16. #15
    flolarajasse

    Re : Est-ce possible en langage C?

    Dernière petite question, est-il possible de stocker mes 6 bits de PDC0H et mes 2 bits de poids fort de PDC0L dans une variable?
    Il faut faire l'inverse?

    Code:
    PWM_Val = ( (int) PDC0H ) + PDC0L
    Est ce que ça peut marcher?
    Java is the best!

  17. #16
    paulfjujo

    Re : Est-ce possible en langage C?

    on suppose que PMW_val est un unsigned int .(16 bits)
    il faut faire effectivement l'inverse
    Code:
    PWM_Val = ( (int) PDC0H )<<8 + PDC0L

  18. #17
    flolarajasse

    Re : Est-ce possible en langage C?

    En fait, ce que je voudrais avoir si possible, c'est avoir 3 variables :

    - une 1ère, ou j'ai mes 8 bits de poids fort de mon PWM.
    - une seconde, ou je pourrais écrire dans mes 6 bits de poids faible de mon PWM.
    - une 3ème, qui comprend mes 14 bits de PWM.

    Est-ce possible qu'avec les décalages de bits?
    Java is the best!

  19. #18
    flolarajasse

    Re : Est-ce possible en langage C?

    Est-ce que ce code est bon?

    8 bits de poids fort de PWM :
    Code:
    PWM_Val = ( (int) PDC0H) <<4+ PDC0L;
    14 bits de PWM :
    Code:
    PWM_Val14 = ( (int) PDC0H) <<8+ PDC0L;
    Java is the best!

  20. #19
    flolarajasse

    Re : Est-ce possible en langage C?

    Ce que je voudrais faire, c'est par exemple incrémenter une variable, et que le programme écrive directement la nouvelle valeur dans les registres, sans que je sois obligé de mettre à chaque fois :

    Code:
    PDC0H = (PWM_Val & 0xFF00) >> 8; // On stocke les 6 bits de poids fort dans PDC0H
    Mais je ne vois pas comment procéder. Faut-il que je déclare une variable qui contient mes registres ; ex :

    Code:
    PWM_Val = ( (int) PDC0H) <<4 + PDC0L;
    Mais si après je fais mon instruction PWM_Val++, la valeur ne sera pas copié dans les registres?
    Java is the best!

  21. #20
    paulfjujo

    Re : Est-ce possible en langage C?

    regardes la notion de STRUCTURE et UNION
    pour associer 2 octets avec un entier
    pour utiliser indifféremment l'un ou l'autre

  22. #21
    flolarajasse

    Re : Est-ce possible en langage C?

    Ok, je ne connais pas du tout ces notions, je vais regarder.
    Java is the best!

  23. #22
    flolarajasse

    Re : Est-ce possible en langage C?

    Ok, j'ai compris le principe, mais comment intégrer mes registres?
    En clair, une structure permet de regrouper des variables qui peuvent être de type différents.
    Mais moi concrètement dans mon cas, quelle est l'utilité?
    Je suis désolé mais je ne comprends pas trop.
    Java is the best!

  24. #23
    paulfjujo

    Re : Est-ce possible en langage C?

    bonsoir,

    utiliser une consigne avec un int 16 bits, qui charge les 2 registre 8 bits
    2 façons
    l'une via UNION et STRUCTURE .. usage du langage C
    l'autre via definitions (like Macro) et decalages

    Code:
    #define LO(x)     ((unsigned char)((x)&0xFF)) 
    #define HI(x)    ((unsigned char)(((x)>>8)&0xFF)) 
    
    unsigned char sh,sl;
    
    struct TwoByte
    {
    	near unsigned char L;
    	near unsigned char H;
    	} PDC0;          
                
    union 
    {
       near unsigned int Consigne;
       near struct TwoByte PDC0;
     }PWM;
       
        
    ...     
     for (i=0;i<16383;i=i+64)
     {
     PWM.Consigne=i;
     strcpypgm2ram(txt,"Consigne PWM= ");
     k=PutStr_RS(txt);
     Write_Word( PWM.Consigne,0); 
     Put_RS(TAB);
     strcpypgm2ram(txt,"PDCOH= ");k=PutStr_RS(txt);
     Octet2Hex(PWM.PDC0.H);
     Put_RS(TAB);
     strcpypgm2ram(txt,"PDCOL= ");k=PutStr_RS(txt);
      Octet2Hex(PWM.PDC0.L);
       Put_RS(TAB);
       
      // il faudra remplacer sh et sl par PDC0H et PDC0L 
      // et i par la varaible contenant la consigne PWM
       strcpypgm2ram(txt," Autrement:  ");k=PutStr_RS(txt);
       sh=HI(i);  // i represente la consigne sur 16 bits
       sl=LO(i);
       Octet2Hex(sh); Put_RS(TAB);
       Octet2Hex(sl);
       CRLF();
      
     }
     while(1);


    Consigne PWM= 0 PDCOH= 00h PDCOL= 00h Autrement: 00h 00h
    Consigne PWM= 64 PDCOH= 00h PDCOL= 40h Autrement: 00h 40h
    Consigne PWM= 128 PDCOH= 00h PDCOL= 80h Autrement: 00h 80h
    Consigne PWM= 192 PDCOH= 00h PDCOL= C0h Autrement: 00h C0h
    Consigne PWM= 256 PDCOH= 01h PDCOL= 00h Autrement: 01h 00h
    Consigne PWM= 320 PDCOH= 01h PDCOL= 40h Autrement: 01h 40h
    Consigne PWM= 384 PDCOH= 01h PDCOL= 80h Autrement: 01h 80h
    Consigne PWM= 448 PDCOH= 01h PDCOL= C0h Autrement: 01h C0h
    Consigne PWM= 512 PDCOH= 02h PDCOL= 00h Autrement: 02h 00h
    Consigne PWM= 576 PDCOH= 02h PDCOL= 40h Autrement: 02h 40h
    Consigne PWM= 640 PDCOH= 02h PDCOL= 80h Autrement: 02h 80h
    Consigne PWM= 704 PDCOH= 02h PDCOL= C0h Autrement: 02h C0h
    un exemple d'usage de structure et union bien plus parlant avec l'exemple ci dessous


    Code:
    
    /* illustration des structures de bits et des unions */
    
    #include <stdio.h>
    
    main() {
      struct s_float {
        unsigned signe : 1;
        unsigned exposant : 8;
        unsigned mantisse : 23;
      };
    
      union {
        float f;
        struct s_float sf;
      } ieee;
    
      float fl, mant;
      int signe, exp;
    
      ieee.f = 12.345678;
    
      printf("signe    : %d\n", ieee.sf.signe);
      printf("exposant : %d\n", ieee.sf.exposant);
      printf("mantisse : %d\n", ieee.sf.mantisse);
    
      exp = 1 << (ieee.sf.exposant - 127);
      mant = ( float) ieee.sf.mantisse  / ( 1 << 23);
      signe = (ieee.sf.signe == 1) ? -1 : 1;
    
      fl = signe * exp * ( 1 + mant );
      printf("%d * 2^%d * (1 + %f) = %f\n", signe, exp, mant, fl);
    
      return 0;
    }
    /*-- résultat de l'exécution -----------------------------------
    signe    : 0
    exposant : 130
    mantisse : 4556774
    1 * 2^8 * (1 + 0.543210) = 12.345678
    ----------------------------------------------------------------*/

  25. #24
    flolarajasse

    Re : Est-ce possible en langage C?

    Vu le code, je pense que je vais bien galérer...
    Java is the best!

  26. #25
    flolarajasse

    Re : Est-ce possible en langage C?

    Bonjour paulfjujo,

    Est ce que les structures et unions sont le seul moyen d'arriver à ce que je veux faire?

    J'ai bien essayé de comprendre ton 1er code, qui semble fonctionner et qui réalise exactement ce que je veux (suivant la valeur que tu mets dans une variable, ça écrit dans les registres), malheureusement je ne comprends pas tout.
    Et j'ai envie de comprendre car ça m'a l'air très intéressant.
    Mais j'admets que je galère un peu..
    Java is the best!

  27. #26
    paulfjujo

    Re : Est-ce possible en langage C?

    bonjour,


    Effectivement il faut potasser le langage C pour comprendre..mais aussi avec des cours trouvés sur le web
    el que celui ci..
    les exemples de structures dédiée au PIC
    Diapos Langage Cmini PIC.pdf


    edit un 18F26k22.h (ou autre PIC)
    tu vas y trouver des tonnes de structures et union
    qui definissent les registres et associations de bits..


    un extrait :
    union de structure portant rien que sur le PORTA
    qui est une adresse 8 bits dans la zone registre du MCU
    mais qui peut s'appeler de maintes façon..

    Code:
    extern volatile near unsigned char       PORTA;
    extern volatile near union {
      struct {
        unsigned RA0:1;
        unsigned RA1:1;
        unsigned RA2:1;
        unsigned RA3:1;
        unsigned RA4:1;
        unsigned RA5:1;
        unsigned RA6:1;
        unsigned RA7:1;
      };
      struct {
        unsigned AN0:1;
        unsigned AN1:1;
        unsigned AN2:1;
        unsigned AN3:1;
        unsigned :1;
        unsigned AN4:1;
      };
      struct {
        unsigned C12IN0M:1;
        unsigned C12IN1M:1;
        unsigned C2INP:1;
        unsigned C1INP:1;
        unsigned C1OUT:1;
        unsigned C2OUT:1;
      };
      struct {
        unsigned C12IN0N:1;
        unsigned C12IN1N:1;
        unsigned VREFM:1;
        unsigned VREFP:1;
        unsigned T0CKI:1;
        unsigned SS:1;
      };
      struct {
        unsigned :2;
        unsigned VREFN:1;
        unsigned :1;
        unsigned SRQ:1;
        unsigned NOT_SS:1;
      };
      struct {
        unsigned :2;
        unsigned CVREF:1;
        unsigned :1;
        unsigned CCP5:1;
        unsigned LVDIN:1;
      };
      struct {
        unsigned :2;
        unsigned DACOUT:1;
        unsigned :2;
        unsigned HLVDIN:1;
      };
      struct {
        unsigned :5;
        unsigned SS1:1;
      };
      struct {
        unsigned :5;
        unsigned NOT_SS1:1;
      };
      struct {
        unsigned :5;
        unsigned SRNQ:1;
      };
    } PORTAbits;
    Dernière modification par paulfjujo ; 11/11/2014 à 14h07.

  28. #27
    flolarajasse

    Re : Est-ce possible en langage C?

    Par rapport à ton 1er code, ce qui surtout "repoussé", c'est toutes les instructions d'envoi des données.
    Quand on "épure" le code (juste la partie traitement), on obtient ceci :

    Code:
    /* 
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define LO(x)     ((unsigned char)((x)&0xFF)) 
    #define HI(x)    ((unsigned char)(((x)>>8)&0xFF)) 
    
    unsigned char sh,sl;
    
    struct TwoByte
    {
        near unsigned char L;
        near unsigned char H;
    } 
    PDC0;          
                
    union 
    {
       near unsigned int Consigne;
       near struct TwoByte PDC0;
    }
    PWM;
       
        
    int main(int argc, char** argv) 
    {
        int i = 0;
        
        while(1)
        {
            for (i=0 ; i<16383 ; i = i+64)
            {
            PWM.Consigne = i;
    
     
            PDC0H = HI(i);  // i represente la consigne sur 16 bits
            PDC0L  =LO(i);  
            }
        }
    }
    C'est ça ou j'en est trop enlevé?
    Je ne comprends pas l'utilité de sh et sl par contre.
    Et je remplacerais i par PWM_Val.
    Java is the best!

  29. #28
    paulfjujo

    Re : Est-ce possible en langage C?

    c'est tout à fait cela...

    dans 2em partie du code envoyé
    j'avais utilisé d'autre variables pour ne pas melanger les 2 solutions.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define LO(x)     ((unsigned char)((x)&0xFF)) 
    #define HI(x)    ((unsigned char)(((x)>>8)&0xFF)) 
       
        
    int main(int argc, char** argv) 
    {
        int i = 0;
        
        while(1)
        {
            for (i=0 ; i<16383 ; i = i+64)
            {
            PWM.Consigne = i;
    
     
            PDC0H = HI(i);  // i represente la consigne sur 16 bits
            PDC0L  =LO(i);  
            }
        }
    }
    Dernière modification par paulfjujo ; 11/11/2014 à 17h29.

  30. #29
    flolarajasse

    Re : Est-ce possible en langage C?

    Donc dans l'exemple que tu m'a donné, on ne se sert pas ni des structures, ni des unions?
    Java is the best!

  31. #30
    paulfjujo

    Re : Est-ce possible en langage C?

    exact,pas dans ce cas...

Page 1 sur 3 12 DernièreDernière

Discussions similaires

  1. le langage C est t il un langage qui a de l'avenir ?
    Par vince6629 dans le forum Programmation et langages, Algorithmique
    Réponses: 13
    Dernier message: 12/11/2014, 12h01
  2. Langage C et langage HTML
    Par physik_theory dans le forum Programmation et langages, Algorithmique
    Réponses: 19
    Dernier message: 12/08/2013, 19h07
  3. langage c++
    Par inviteb96bbc2c dans le forum Logiciel - Software - Open Source
    Réponses: 3
    Dernier message: 14/02/2010, 10h05
  4. de langage C en langage assembleur
    Par invite284746c1 dans le forum Électronique
    Réponses: 1
    Dernier message: 14/05/2009, 12h42
Découvrez nos comparatifs produits sur l'informatique et les technologies.