fonction DelayMs()
Répondre à la discussion
Affichage des résultats 1 à 15 sur 15

fonction DelayMs()



  1. #1
    pseudoguyanais

    fonction DelayMs()


    ------

    Bonjour,

    J'utilise dans un programme la fonction DelayMs() comme définie dans le programme "blinkled" qui est utilisé pour comprendre MPLAB.

    Mais je ne comprends pas trop certaines opérations.
    Voici la fonction :
    Code:
    /* Adds support for PIC32 Peripheral library functions and macros */
    #include <plib.h>
    
    
    // Configuration Bits
    #pragma config FNOSC    = PRIPLL        // Oscillator Selection
    #pragma config FPLLIDIV = DIV_2         // PLL Input Divider (PIC32 Starter Kit: use divide by 2 only)
    #pragma config FPLLMUL  = MUL_20        // PLL Multiplier
    #pragma config FPLLODIV = DIV_1         // PLL Output Divider
    #pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
    #pragma config FWDTEN   = OFF           // Watchdog Timer
    #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
    #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
    #pragma config OSCIOFNC = ON           // CLKO Enable
    #pragma config POSCMOD  = XT            // Primary Oscillator
    #pragma config IESO     = OFF           // Internal/External Switch-over
    #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable
    #pragma config CP       = OFF           // Code Protect
    #pragma config BWP      = OFF           // Boot Flash Write Protect
    #pragma config PWP      = OFF           // Program Flash Write Protect
    #pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select
    #pragma config DEBUG    = ON           // Debugger Disabled for Starter Kit
    
    // application defines
    #define SYS_FREQ		(100000000)
    
    // prototype
    void DelayMs(unsigned int);
    
    //  blink_leds application code
    int main(void)
    {
    ...
    }
    void DelayMs(unsigned int msec)
    {
        unsigned int tWait, tStart;
        tWait=(SYS_FREQ/2500)*msec;		//SYS_FREQ(100000000)
        tStart=ReadCoreTimer();
        while((ReadCoreTimer()-tStart)<tWait);	// wait for the time to pass
    
    }
    J'utilise un PIC32MX79, et un quartz externe de 10MHz.
    Je ne comprends pas pourquoi on divise "SYS_FREQ" par 2500 puisque on veut avoir une 1ms. Il faudrait divisé par 10000 nan?? 1ms=10-3=1/1000 ! Et après on multiplie par "msec" pour attendre le nbr de ms souhaité nan?

    -----

  2. #2
    pseudoguyanais

    Re : fonction DelayMs()

    Après je me suis dit que c'était peut être à cause de "ReadCoreTimer()" qui ne prenait pas l'horloge du quartz de 10Mhz.
    Je suis allé voir sa déclaration, elle est dans "timer.h" :

    Code:
    unsigned int __attribute__((nomips16)) ReadCoreTimer(void);
    J'ai cherché ce que voulais dire "nomips16" et je n'ai trouvé que cette explication :

    nomips16

    Always generate code for the function in the MIPS32® instruction set, even when compiling the translation unit with the -mips16 command line option.

    Dans une datasheet de Microchip.

    Mais j'ai pas compris comment ca pouvait renseigner ma fonction sur le temps qu'il s'est écoulé...
    Et MIPS32 et en fait apparemment un processeur développé par une autre société, nan?

  3. #3
    Aurélien

    Re : fonction DelayMs()

    La question est : est ce que le code actuel marche et te donne la bonne tempo. Si oui, regardes les prescaler et quelle clock réelle alimente ton timer, et sinon change la valeur en fonction.

  4. #4
    pseudoguyanais

    Re : fonction DelayMs()

    Oui oui ca fait bien des milisec!!

    Donc comment je pourrais trouver prescaler dont tu me parles?

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

    Re : fonction DelayMs()

    Dans la doc de ton pic, tu as un préscaler qui divise la fréquence de ton quartz par un certain nombre genre 2 / 4 / 8 / 16 / 128 etc

    Tu met un quartz de 10MHz mais ton pic travail pas à cette fréquence.

    Je me souviens que pour un quartz de 4MHZ, le pic tourne à 1MHz et après ça tu peux encore activer d'autres diviser.

    Regarde dans le registre comment il est configuré.

    Je dis peu être des bêtises, j'ai développé un programme pour pic une fois dans ma vie...je boss qu'avec des Atmels.

  7. #6
    pseudoguyanais

    Re : fonction DelayMs()

    ok, et comment je regarde dans le registre??

  8. #7
    blinbling

    Re : fonction DelayMs()

    salut,

    une instruction dure 4 temps d'horloge (voir ici : wiki). Donc tout s'explique =)
    Dernière modification par blinbling ; 09/09/2010 à 16h41. Motif: erreur

  9. #8
    sdec25

    Re : fonction DelayMs()

    Citation Envoyé par pseudoguyanais Voir le message
    ok, et comment je regarde dans le registre??
    C'est toi qui définis les valeurs des registres.
    Soit manuellement "registre = valeur" si le registre est modifiable dans le code.
    Soit avec des #pragma (#pragma config registre = valeur), ou dans le menu de configuration de MPLAB.
    Dans tous les cas, lis la datasheet de ton PIC pour voir comment configurer les registres.

  10. #9
    RISC

    Re : fonction DelayMs()

    Salut,

    La fonction ReadCoreTimer(void) permet de lire le Timer qui existe dans le coeur MIPS32 M4K. Ce timer a la particularité de tourner à la moitié de la fréquence du processeur.

    Le mode MIPS16 concerne uniquement la taille des instructions. Si on compile dans ce mode, le compilateur génère des instructions sur 16 bits au lieu de 32 bits ce qui permet généralement de réduire la taille du programme (FLASH) de l'ordre de 20 à 40% en fonction du code de ton application.

    Concernant ta fréquence de fonctionnement, je suis un peu étonné...
    Tu dis que tu utilises un quartz à 10MHz, mais d'après tes bits de configuration tu fais apparemment tourner ton PIC32MX à 100MHz...(je ne connais que les versions à 80 MHz). Quellle est la référence précise de ton PIC32 ?
    Es-tu sur que le quartz est à 10MHz et pas à 8MHz ?

    Avec 10MHz en entrée :
    #pragma config FNOSC = PRIPLL // Oscillator Selection
    #pragma config FPLLIDIV = DIV_2 // Division par 2 de la freq quartz = 5MHz
    #pragma config FPLLMUL = MUL_20 // Multiplication par 20 = 100MHz
    #pragma config FPLLODIV = DIV_1 // Division par 1 en sortie = 100MHz
    Quelle carte utilises-tu ?

    Les PIC32 exécutent (environ) 1 instruction par cycle horloge (cela dépend du cache) ce qui donne 80MIPS. Ce qui donne 40MHz max pour le timer interne (25ns). Cela donnerait 50MHz pour un PCI32 à 100MHz (20ns).

    Donc pour mois ta routine DelayMs donne :
    20ns * 2500 = 50000ns => 50us * nb de ms

    a+

  11. #10
    pseudoguyanais

    Re : fonction DelayMs()

    Citation Envoyé par blinbling Voir le message
    salut,

    une instruction dure 4 temps d'horloge (voir ici : wiki). Donc tout s'explique =)

    Hey! Merci oui j'etais passé à côté de ça...!
    Reste à comprendre ce que me dit RISC car si c'est bien une horloge de 100MHz ca colle plus...

    Donc RISc, je pense bien que tu as raison pour le 100MHz car le code :
    Code:
    #define SYS_FREQ        (100000000)
    le confirme. (J'avais mal compté les 0, et ca fait bien 100Mhz pas 10MHz...)

    Mais à la fin de ton message j'ai l'impression que tu te trompes :
    Les PIC32 exécutent (environ) 1 instruction par cycle horloge (cela dépend du cache) ce qui donne 80MIPS. Ce qui donne 40MHz max pour le timer interne (25ns). Cela donnerait 50MHz pour un PCI32 à 100MHz (20ns).

    Donc pour mois ta routine DelayMs donne :
    20ns * 2500 = 50000ns => 50us * nb de ms
    Si on a 100MHz, tu divise par 4 => 25MHz=>0.04 us=>
    0.04us*2500=0.1ms

    et pas 50 us.

    J'ai repris exactement le programme de microchip qui utilisait l'horloge de 8MHz du pic :
    Code:
    ////#define SYS_FREQ        (80000000)
    et apres eux ils divisaient par 2000 donc avec le rapport moi je dois diviser par 2500. Donc ce doc vient de Microchip je pense pas qu'il soit faux. Il doit avoir qqch qui nous a échappé.

  12. #11
    RISC

    Re : fonction DelayMs()

    Salut,

    Tu ne m'a pas répondu concernant la référence de ton PIC32. Je pense qu'il n'existe aucune version à 100MHz mais qu'elles sont toutes à 80MHz

    Si tu utilises un quartz à 10MHz, il faut donc changer les bits de configuration pour respecter 80MHz max sans quoi tu es hors spécification et tu risques fortement d'avoir des problèmes... :

    Avec 10MHz en entrée :
    Code:
    #pragma config FNOSC = PRIPLL // Oscillator Selection
    #pragma config FPLLIDIV = DIV_2 // Division par 2 de la freq quartz = 5MHz
    #pragma config FPLLMUL = MUL_16 // Multiplication par 16 = 80MHz
    #pragma config FPLLODIV = DIV_1 // Division par 1 en sortie = 80MHz
    Concernant le timer interne, je ne me trompes pas : il n'est nulle part mentionné qu'il divise par 4 mais il divise par 2 (voir la datasheet).

    Pourrais-tu poster le projet que tu utilises comme référence (l'original non modifié). Cela sera plus simple à analyser pour voir ou se situe le problème.

    Dans tous les cas je te recommande d'utiliser les API du compilateur C32. C'est beaucoup plus simple à utiliser pour gérer les périphériques

    a+

  13. #12
    pseudoguyanais

    Re : fonction DelayMs()

    Hey! Merci pour ton aide déjà, et désolé pour l'oubli sur ma config.

    Donc j'ai un PIC32MX795F512L avec un quartz externe de 10MHz.

    Pourquoi y aurait il un souci si je prends une horloge de 10MHz? J'ai juste remplacé dans le code original, les SYS_FREQ (80000000) par (100000000) et donc fais le rapport pour diviser dans tWait. Je te met le code : (c'est de microchip)
    Code:
    /***********************************************************************************
                    
                    PIC32MX Starter Kit Example Code - Blink Leds
    
     ***********************************************************************************
     * FileName:        blink_leds.c
     * Dependencies:    None
     * Company:         Microchip Technology, Inc.
     *
     * Copyright (c) 2008 Microchip Technology, Inc.
     * Software License Agreement
     *
     * The software supplied herewith by Microchip Technology Incorporated
     * (the “Company”) for its PIC32 Microcontroller is intended
     * and supplied to you, the Company’s customer, for use solely and
     * exclusively on Microchip PIC32 Microcontroller products.
     * The software is owned by the Company and/or its supplier, and is
     * protected under applicable copyright laws. All rights are reserved.
     * Any use in violation of the foregoing restrictions may subject the
     * user to criminal sanctions under applicable laws, as well as to
     * civil liability for the breach of the terms and conditions of this
     * license.
     *
     * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
     * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
     * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
     * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
     * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
     *
     ***************************************************************************
     * Description:
     *            The example demonstrates a simple blink led application.
     *
     * Additional Info:
     *          Refer to readme.txt
     *
     * Platforms:
     *            PIC32MX Starter Kit DM320001
     *            PIC32MX USB Starter Kit DM320003
     *
     * Tools:
     *            1. MPLAB IDE 8.20 or higher
     *            2. MPLAB C Compiler for PIC32 v1.04 or higher
     *            3. General Purpose Starter Kit DM320001 or USB Starter board DM320003
     *            4. USB Cable
     *
     * Debug Print Library: SUPPORTED IN DEBUG MODE ONLY
     *            The Debug Print Library adds user debugging input/output capability
     *          to the MPLAB IDE Starter Kit console window using DBPRINTF, DPUTS,
     *          DBGETC and DBGETS.
     *
     *          To use the Debug Print Library with the PIC32 Starter Kit, do the following:
     *            1. Add '#include "db_utils.h"' to the source code.
     *               Note: you may need to copy db_utils.h into your working directory or
     *               specify a path to its location.
     *               It is located in "<install dir>\PIC32 Starter Kits\Microchip\Include".
     *            2. Add 'db_utils.a' to the library branch of MPLAB IDE project tree.
     *               It is located in "<install dir>\PIC32 Starter Kits\Microchip\Common".
     *            3. Add "PIC32_STARTER_KIT" macro definition to the project build options
     *               for the C compiler.
     *            4. Be sure to call DBINIT() first before any other Debug Print Library macros.
     *
     * Starter Board Resources:
     *            LED1 (RED)        = PORTD.RD0
     *            LED2 (YELLOW)    = PORTD.RD1
     *            LED3 (GREEN)    = PORTD.RD2
     *            SW1                = PORTD.RD6  (change notice pin CN15)
     *            SW2                = PORTD.RD7     (change notice pin CN16)
     *            SW3                = PORTD.RD13 (change notice pin CN19)
     *            JTAG.TMS        = PORTA.RA0  (used by debugger)
     *            JTAG.TCK        = PORTA.RA1  (used by debugger)
     *            JTAG.TDO        = PORTA.RA5  (used by debugger)
     *            JTAG.TDI        = PORTA.RA4  (used by debugger)
     *            PGC2            = PORTB.RB6     (used by debugger)
     *            PGD2            = PORTB.RB7  (used by debugger)
     *
     * Starter Board Notes:
     *            1.    There are no pullup resistors on SW1, SW2 or SW3.
     *                To enable the PORTD pullups for SW1, SW2 and SW3, use the following:
     *                CNPUE = (CN15_PULLUP_ENABLE | CN16_PULLUP_ENABLE | CN19_PULLUP_ENABLE);
     *            2.  Do not disable the PIC32MX JTAG.  This will prevent the PIC32MX Starter Kit
     *                debugger(PIC18F4550) from communicating with the PIC32MX device.
     *            3.  Do not configure the SYSTEM CLOCK to operate faster than 80MHz.
     *************************************************************************************
     * Change History:
     * ID            Date            Changes
     * C11842        12/01/2008        Updated comments, 80MHz operation
     *************************************************************************************/
    
    /* Adds support for PIC32 Peripheral library functions and macros */
    #include <plib.h>
    
    
    // Configuration Bits
    #pragma config FNOSC    = PRIPLL        // Oscillator Selection
    #pragma config FPLLIDIV = DIV_2         // PLL Input Divider (PIC32 Starter Kit: use divide by 2 only)
    #pragma config FPLLMUL  = MUL_20        // PLL Multiplier
    #pragma config FPLLODIV = DIV_1         // PLL Output Divider
    #pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
    #pragma config FWDTEN   = OFF           // Watchdog Timer
    #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
    #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
    #pragma config OSCIOFNC = ON           // CLKO Enable
    #pragma config POSCMOD  = XT            // Primary Oscillator
    #pragma config IESO     = OFF           // Internal/External Switch-over
    #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable
    #pragma config CP       = OFF           // Code Protect
    #pragma config BWP      = OFF           // Boot Flash Write Protect
    #pragma config PWP      = OFF           // Program Flash Write Protect
    #pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select
    #pragma config DEBUG    = ON           // Debugger Disabled for Starter Kit
    
    // application defines
    #define SYS_FREQ        (80000000)
    
    // prototype
    void DelayMs(unsigned int);
    
    //  blink_leds application code
    int main(void)
    {
    
        DBINIT();
    
        // Configure the device for maximum performance, but do not change the PBDIV clock divisor.
        // Given the options, this function will change the program Flash wait states,
        // RAM wait state and enable prefetch cache, but will not change the PBDIV.
        // The PBDIV value is already set via the pragma FPBDIV option above.
           SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
    
        // LED setup
        // Turn off leds before configuring the IO pin as output
          mPORTDClearBits(BIT_0 | BIT_1 | BIT_2);             // same as LATDCLR = 0x0007
    
    
        // Set RD0, RD1 and RD2 as outputs
           mPORTDSetPinsDigitalOut(BIT_1 | BIT_2 | BIT_3);    // same as TRISDCLR = 0x0007
    
        //Initialize the DB_UTILS IO channel
    ////    DBINIT();
        
        // Display a message using db_utils
    ////    DBPRINTF("Welcome to the PIC32 Blink Leds example. \n");
    ////    DBPRINTF("The build date and time is ... (" __DATE__ "," __TIME__ ")\n");
    ////    DBPRINTF("This example demonstrates a simple method to toggle LEDs. \n");
    
        // endless loop
           while(1)
           {
               DelayMs(100);
           mPORTDToggleBits(BIT_0);     // toggle LED0 (same as LATDINV = 0x0001)
    
            DelayMs(100);
           mPORTDToggleBits(BIT_1);     // toggle LED1 (same as LATDINV = 0x0002)
    
            DelayMs(100);
           mPORTDToggleBits(BIT_2);     // toggle LED2 (same as LATDINV = 0x0004)
     
           };
       return 0;
    }
    
    
    /******************************************************************************
    *    DelayMs()
    *
    *    This functions provides a software millisecond delay
    ******************************************************************************/
    void DelayMs(unsigned int msec)
    {
        unsigned int tWait, tStart;
            
       tWait=(SYS_FREQ/2000)*msec;        //    SYS_FREQ        (80000000)
    
        tStart=ReadCoreTimer();
        while((ReadCoreTimer()-tStart)<tWait);        // wait for the time to pass
    
    }
    Concernant le timer interne, je ne me trompes pas : il n'est nulle part mentionné qu'il divise par 4 mais il divise par 2 (voir la datasheet).
    Je ne conteste pas du tout ca. Je pensais juste aussi que lui une fois divisé par deux était aussi sujet àla regle : 1 cycle = 4 temps d'horloge.

  14. #13
    RISC

    Re : fonction DelayMs()

    Salut,

    Concernant la fréquence du PIC32 regarde bien le fichier source ligne 3 qui confirme ce que je t'ai dit :
    Code:
    3.  Do not configure the SYSTEM CLOCK to operate faster than 80MHz.
    Contrairement à ce que tu as l'air de penser la ligne :
    Code:
    // application defines
    #define SYS_FREQ        (80000000)
    ne sert pas à définir la fréquence du processeur. Cette ligne indique au programme C quelle est la fréquence du processeur pour pouvoir faire des calculs.
    La fréquence du processeur est définie dans les bits de configuration (voir mon précédent post). Il faut donc changer la valeur du multiplicateur de fréquence à 16 si tu utilises un quartz de 8MHz :
    Code:
    #pragma config FPLLMUL = MUL_16 // Multiplication par 16 = 80MHz
    Pour la routine de delay, les choses sont maintenant claires :
    La routine DelayMs donne :
    80.000.000 / 2000 = 80.000.000 / ( 2 *1000) = 40.000 coups d'horloge par ms
    Pour 100ms ==> 100 x 40.000 = 4.000.000 coups d'horloge comme le core timer tourne à 40.000.000 cela fait bien 100ms ( 1/10).
    J'ai vérifié au simulateur c'est pile poil

    a+

  15. #14
    RISC

    Re : fonction DelayMs()

    Salut,

    Il y a un petit bug dans le programme de démo concernant la déclaration en sortie des ports.

    La ligne corrigée est :
    Code:
    // Set RD0, RD1 and RD2 as outputs
           mPORTDSetPinsDigitalOut(BIT_0 | BIT_1 | BIT_2);    // same as TRISDCLR = 0x0007
    sans quoi seulement 2 des leds fonctionnent au lieu de trois ;=)

    a+

  16. #15
    pseudoguyanais

    Re : fonction DelayMs()

    Ok merci beaucoup!
    Maintenant j'ai compris et pour mon cas, comme j'ai un quartz à 10MHz il faut que je divise toujours par 2000 et non 2500. Celui qui avait adapter le programme au départ n'avais fait en fait que le rapport pour trouver 2500! Et je ne voyais pas le problème puisque au lieu de 1ms on avait 0.8ms donc la différence n'était pas facile à percevoir au niveau du clignotement des leds!

    Merci bcp!

Discussions similaires

  1. Limite d'une fonction quotient de fonction trigonométriques
    Par inviteae9b49ef dans le forum Mathématiques du supérieur
    Réponses: 13
    Dernier message: 24/08/2010, 17h11
  2. Comment insérer une fonction Matlab dans les paramètres d'entrée d'une autre fonction ??
    Par inviteac36b108 dans le forum Mathématiques du supérieur
    Réponses: 3
    Dernier message: 04/01/2010, 07h16
  3. Fonction racine carrée et fonction cube
    Par invite1d9a0420 dans le forum Mathématiques du collège et du lycée
    Réponses: 10
    Dernier message: 15/10/2008, 15h43
  4. besoin d'aide étude de fonction (2 petite fonction)
    Par invite97f0a0d8 dans le forum Mathématiques du collège et du lycée
    Réponses: 2
    Dernier message: 07/09/2008, 18h40
  5. Passage fonction définie en paramétrique à fonction implicite ?
    Par invite9e01212f dans le forum Mathématiques du supérieur
    Réponses: 0
    Dernier message: 27/03/2007, 22h38
Découvrez nos comparatifs produits sur l'informatique et les technologies.