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

Regler le timer d'une PWM
HULK28
Avatar de l’utilisateur
Amateur
Amateur
Messages : 106
Enregistré en : août 2015
Localisation : IdF

#11 Message par HULK28 » dim. 29 janv. 2017 09:54 lien vers la Data-Sheet : Cliquez ici

Bonjour,

voici un code pour PIC16F628, à l'époque écrit avec HitechC.
Il gère 3 PWM avec 2 BP pour un PIC ne possédant qu'un PWM

Code : Tout sélectionner

/*===============================================================================
 Composant : PIC16F628A
                                                                               
Essais PWM.
Auteur: HULK28
===============================================================================*/

#include        <pic.h>
#include        "ecl_pwm.h"        // Définitions spécifiques

/*================================================================================

 |Historique        | Date                        | Modification       
 ---------------------------------------------------------------------------------
 | V1.0         | 12/07/2006    | - Date de création
 | V1.1         | 29/07/2006    | - correction
 ---------------------------------------------------------------------------------
                                                                                               
 Fichier c                       : ecl_pwm.c
 Fichier définition              : ecl_pwm.h
 Fichier définition PIC          : pic.h -> pic16f6x.h
 Fichier Hex                     : ecl_pwm.hex

==================================================================================

PRÉSENTATION DU PROGRAMME

 Ce programme tourne sur un PIC16F628.
                                                                                           
 Les entrées / Sorties sont définies comme suit :
                                                                                                   
        * Sorties :        - Sortie PWM (0-255) S1    ---> RA6
                           - Sortie PWM (0-255) S2    ---> RA7
                           - Sortie PWM (0-255) S3    ---> RB3

        * Entrées :  - Bouton poussoir UP             ---> RB6
                     - Bouton poussoir DOWN        ---> RB7

        * Entrée ANA :        aucune

        * E/S :

=====================================================================================

 Tous les "timing" sont basés sur un résonateur de fréquence 4 Mhz.
 Le temps de cycle par instruction est de 1 µs.

 Toutes les données utilisées sont exprimées en décimal, sauf celles
 spécifiées.                                                       

================================================================================*/

//***************************************************************
ushort        Compteur62us ;
uchar         Flag62us ;

ushort        ValeurPwmS1 ;
ushort        ValeurPwmS2 ;
ushort        ValeurPwmS3 ;

uchar         Valeur3Pas ;

uchar         CompteurPression ;
uchar         CombinaisonBPs ;

//***************************************************************
void init_pic(void);
void interrupt traite_int(void);
void clock_pic(void);

void DelayMs(uchar cpt) ;
void init_var(void) ;

void init_pwm(void) ;
void stop_pwm(void) ;
void setDC_pwm(ushort dc) ;

uchar TestBPs(void) ;
void GestionBPs(void) ;

//***************************************************************

/****************************************************************
                Temporisation en millisecondes
****************************************************************/
void DelayMs(uchar cpt)
{
        ushort t ;
        while (cpt != 0)
        {
                CLRWDT() ;
                -- cpt ;
                t = 112 ;
                while (t !=0)        -- t ;
        }
}

/****************************************************************
                Traitement des interruptions
****************************************************************/
void interrupt traite_int(void)
{
        if(TMR1IF)
        {
                TMR1IF = 0 ;
                Flag62us = 1 ;
                TMR1H = 0xFF ;
                TMR1L = 0xC1 ;     // 0xFFFF - 0xFFC1 = 62 => 62 x 1 µs = 62 µs
        }

}

/****************************************************************
                Initialisation du PIC
****************************************************************/
void init_pic(void)
{
        // Configuration du module CCP
        CCP1CON = 0x00 ;        // module CCP1 désactivé

        // Configuration du port B
        RBPU = 0 ;                        // active pull up
        RBIE = 0 ;

        // Configuration des I/O
        PwmS1 = 0 ;                        // à l'init.        S1 = 0
        PwmS2 = 0 ;                        // à l'init.        S2 = 0
        PwmS3 = 0 ;                        // à l'init.        S3 = 0
        TRISA = ConfigIOPortA ;
        TRISB = ConfigIOPortB ;

        // Timer 0 (8 bits) est utilisé pour le wachtdog à 2,3 s.
        T0CS = 0 ;                      // Clock interne
        PSA = 1 ;                        // timer0 = Wachtdog
        PS2 = 1 ;                        // \
        PS1 = 1 ;                        //   => 111 + WDT => 18 ms x 128 = 2,304 s
        PS0 = 1 ;                        // /

        // Timer 1 (16 bits) est utilisé pour l'horloge: base de 62 µs. Quartz 4 Mhz => 1 instruction = 1 µs
        T1CON = 0x00 ;                        // Prédivision de l'horloge par 1
        TMR1H = 0xFF ;
        TMR1L = 0xC1 ;                    // 0xFFFF - 0xFFC1 = 62 => 62 x 1 µs = 62 µs
        TMR1ON = 1 ;                       // On lance le timer 1
        TMR1IE = 1 ;                        // On autorise les interruptions du timer 1

        // Autorisation des interruptions
        PEIE = 1 ;                        // Autorisation des IT peripherique
        GIE = 1 ;                        // Autorisation général des IT
}

/****************************************************************
                Initialisation des variables globales
****************************************************************/
void init_var(void)
{
        Flag62us = 0 ;
        Compteur62us = 0 ;                // Raz compteur clock

        ValeurPwmS1 = 0 ;
        ValeurPwmS2 = 0 ;
        ValeurPwmS3 = 0 ;

        Valeur3Pas = 0 ;
}

/****************************************************************
                Initialisation du périphérique PWM
****************************************************************/
void init_pwm(void)
{
        CCP1CON = 0x00 ;                // module off
        TMR2 = 0 ;                           // raz timer2 value
        PR2 = 0x7C ;                        // PR2 = 124 --> f = 500 Hz
        CCPR1L = 0 ;                        // Duty cycle = 0 à l'init
        TRISB3 = 0 ;                         // RB3 = output
        T2CKPS1 = 1 ;                      // Prescaler = 1:16
        T2CKPS0 = 1 ;
        CCP1CON = 0x0C ;                // Mode PWM 10 bits + init two LSBs of PWM duty cycle at 0
        TMR2ON = 1 ;                       // Timer2 ON
}

/****************************************************************
                Arrête le périphérique PWM
****************************************************************/
void stop_PWM(void)
{
        RB3 = 0 ;
        TMR2ON = 0 ;
        CCP1CON = 0x00 ;
}

/****************************************************************
        Charge le rapport cyclique PWM [0-1023] -> [0-100%]
****************************************************************/
void setDC_PWM(ushort dc)
{
        CCP1CON = CCP1CON & 0b11001111 ;     // clear CCP1CON<5:4>
        CCP1CON = CCP1CON | ((dc << 4) & 0b00110000) ;        // set the two LSBs duty cycle
        CCPR1L = dc >> 2 ;        // set the eight MSBs duty cycle
}

/****************************************************************
                Gestion horloge du PIC
****************************************************************/
void clock_pic(void)
{
        Flag62us = 0 ;

        // ValeurPwmSx  [0-256]
        // Compteur62us [0-256]

        if (ValeurPwmS1 == 0)                        PwmS1 = 0 ;
        else
        {
                if         (Compteur62us == 0)                PwmS1 = 1 ;                       
                else if (Compteur62us == ValeurPwmS1)        PwmS1 = 0 ;
        }

        if (ValeurPwmS2 == 0)                        PwmS2 = 0 ;
        else
        {
                if         (Compteur62us == 0)                PwmS2 = 1 ;
                else if (Compteur62us == ValeurPwmS2)        PwmS2 = 0 ;
        }

        Compteur62us = Compteur62us + 8 ;

        if (Compteur62us == 256)                Compteur62us = 0 ;        // période = 2 ms

}

/****************************************************************
        Test périodiquement l'action sur les boutons poussoirs
****************************************************************/
uchar TestBPs(void)
{
        CompteurPression = 0 ;
        CombinaisonBPs = AUCUNE ;

        while (!BoutonUp)
        {
                DelayMs(10) ;
                ++CompteurPression ;
                if (!BoutonDown)
                CombinaisonBPs = UP_ET_DOWN ;
                else       
                CombinaisonBPs = UP ;
                if (CompteurPression > 200)        break ;                // expiration
        }

        while (!BoutonDown)
        {
                DelayMs(10) ;
                ++CompteurPression ;
                if (!BoutonUp)
                CombinaisonBPs = UP_ET_DOWN ;
                else
                CombinaisonBPs = DOWN ;
                if (CompteurPression > 200)        break ;                // expiration
        }

        return(CombinaisonBPs) ;
}

/****************************************************************
                Gestion des boutons poussoirs
****************************************************************/
void GestionBPs(void)
{
        switch (CombinaisonBPs)
        {
                case UP :
                        if (CompteurPression > 1)
                        {
                                if (ValeurPwmS1 < 248)        ValeurPwmS1 = ValeurPwmS1 + 8 ;
                                if (ValeurPwmS2 < 248)         ValeurPwmS2 = ValeurPwmS2 + 8 ;
                                if (ValeurPwmS3 < 248)         ValeurPwmS3 = ValeurPwmS3 + 8 ;
                        }
                        else
                                {
                                if (ValeurPwmS1 < 224)        ValeurPwmS1 = ValeurPwmS1 + 32 ;
                                if (ValeurPwmS1 < 224)        ValeurPwmS2 = ValeurPwmS2 + 32 ;
                                if (ValeurPwmS1 < 224)        ValeurPwmS3 = ValeurPwmS3 + 32 ;
                                }
                        break ;
                case DOWN :
                        if (CompteurPression > 1)
                                {
                                if (ValeurPwmS1 >  7)        ValeurPwmS1 = ValeurPwmS1 - 8 ;
                                if (ValeurPwmS2 >  7)         ValeurPwmS2 = ValeurPwmS2 - 8 ;
                                if (ValeurPwmS3 >  7)         ValeurPwmS3 = ValeurPwmS3 - 8 ;
                                }
                                else
                                {
                                if (ValeurPwmS1 > 31)        ValeurPwmS1 = ValeurPwmS1 - 32 ;
                                if (ValeurPwmS1 > 31)        ValeurPwmS2 = ValeurPwmS2 - 32 ;
                                if (ValeurPwmS1 > 31)        ValeurPwmS3 = ValeurPwmS3 - 32 ;
                                 }
                        break ;
                case UP_ET_DOWN :
                        if (CompteurPression > 1)
                        {
                                switch (Valeur3Pas)
                                {
                                        case 0 :
                                                Valeur3Pas = 50 ;        // 50%
                                                ValeurPwmS1 = 128 ;
                                                ValeurPwmS2 = 128 ;
                                                ValeurPwmS3 = 128 ;
                                                break ;
                                        case 50 :
                                                Valeur3Pas = 100 ;        // 100%
                                                ValeurPwmS1 = 256 ;
                                                ValeurPwmS2 = 256 ;
                                                ValeurPwmS3 = 256 ;
                                                break ;
                                        case 100 :
                                                Valeur3Pas = 0 ;        // 0%
                                                ValeurPwmS1 = 0 ;
                                                ValeurPwmS2 = 0 ;
                                                ValeurPwmS3 = 0 ;
                                                break ;
                                }
                        }
                        break ;
        }

        // S1 est mis à jour par ValeurPwmS1 --> Timer1
        // S2 est mis à jour par ValeurPwmS2 --> Timer1
        // S3 est mis à jour par ValeurPwmS3 --> PWM

        setDC_PWM((ValeurPwmS3 * 4)-1) ;   // on se ramène à l'échelle [0-1023]

        while (TestBPs() != AUCUNE)        // on attend le relâchement du bouton.
        CLRWDT() ;       

        Compteur62us = 0 ;

}

/****************************************************************
                        Programme principale
****************************************************************/
main()
{
        CLRWDT() ;

        // init registres
        init_pic();
        // init variables globales
        init_var() ;
       
        // init PWM hard
        init_pwm() ;
        //setDC_PWM(128) ;

        while(1)
        {
                // raffraichi le watchdog
                CLRWDT() ;

                // gestion 62 µs
                if (Flag62us)
                         clock_pic();

                // gestion des boutons poussoirs
                if (TestBPs() != AUCUNE)
                        GestionBPs() ;
        }
}


Et le fichier header ecl_pwm.h

Code : Tout sélectionner

// Définitions spécifiques

/********************************************************************
*   Librairie de définitions Centrale tableau                       *
*   Ecrit en C pour être compilé avec HI-TECH, testé avec MPLAB     *
*********************************************************************
*********************************************************************
*   Fichier : ecl_pwm.h         HULK28                              *
*   Date: 16/09/2006                                                *
*   Version: 1.00                                                   *
*********************************************************************
*   Fonctions:                                                      *
*                                                                   *
*********************************************************************
*   Revision History:                                               *
*      V1.00 - Version beta                                         *
********************************************************************/

/*====================================================================
                 -----= Predefined instructions =-----
====================================================================*/
// Predefined instructions
#define        PORTBIT(adr, bit)   ((unsigned)(&adr)*8+(bit))
#define        NOP()               asm(" nop")
#define        FALSE               0
#define        TRUE                !FALSE
#define        BYTE                unsigned char    /* sizeof(BYTE) must == 1 */
#define        uchar               unsigned char
#define        ushort              unsigned short
#define        ulong               unsigned long

// Descriptions des différentes entrées et sorties
static bit        PwmS1           @        PORTBIT(PORTA, 6) ;  // sortie S1 PWM
static bit        PwmS2           @        PORTBIT(PORTA, 7) ;  // sortie S2 PWM
static bit        PwmS3           @        PORTBIT(PORTB, 3) ;  // sortie S3 PWM
static bit        BoutonUp        @        PORTBIT(PORTB, 6) ;  // entrée poussoir UP
static bit        BoutonDown      @        PORTBIT(PORTB, 7) ;  // entrée poussoir DOWN

// Définition des différentes constantes spécifiques à la centrale
// Remarque: 1 = entrée, 0 = sortie
#define    ConfigIOPortA        0x3F        // RA6 et RA7 = output--> PWM, le reste en input
#define    ConfigIOPortB        0xFF        // port B en input

#define    AUCUNE               0x00        // none
#define    UP                   0x01        // +
#define    DOWN                 0x02        // -
#define    UP_ET_DOWN           0x03        // + AND -
"Pour la carotte, le lapin est la parfaite incarnation du mal" -Robert Shecley-


Retourner vers « Langage C »

Qui est en ligne

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