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

PWM sur PIC16F1779
Superphénix
Débutant
Débutant
Messages : 54
Enregistré en : mars 2020

#1 Message par Superphénix » ven. 17 avr. 2020 18:34 lien vers la Data-Sheet : Cliquez ici

Bonjour!

Je cherche à faire fonctionner un signal PWM sur le PIN de RB5 d'un PIC16F1779. J'ai l'impression que le datasheet demande de faire plusieurs choses différents. Par exemple à la page 317 dans les étapes à suivre on ne parle pas de PR2 alors qu'à la page d'après il y en a besoin pour définir la période??
Il faut deviner des registres... J'ai déjà plusieurs fois programmé un signal PWM sur des PICs mais sur celui là j'ai vraiment du mal.
Voilà ce que j'ai pour l'instant. J'utilise le Timer6 (juste pour mieux me repérer avec les indices) et le programme reste bloqué dans le while. Probablement c'est pas PWM6IF le bon timer interrupt bit du point 7) :?: :?:

Code : Tout sélectionner

    CCP1PPS = 0b00001101 ;  // RB5

    // 1) :
    TRISBbits.TRISB5 = 1 ;  // "éteindre" pin RB5
   
    // 2) :
    CCPTMRS1bits.C1TSEL = 0b10 ;  //  Timer6 pour CCP1
   
    // 3) :
    PR2 = 0b11111111 ;  // 255
   
    // 4) :
    CCP1CON = 0b10001100 ;  // Enable + PWM mode
   
    // 5) :
    CCPR1H = 0b00000010 ;
    CCPR1L = 0b00000000 ;
   
    // 6) :
    PIR6bits.PWM6IF = 0 ;  // Timer interrupt flag
    T6CONbits.CKPS = 0b000 ;  // Prescal = 1:1
    T6CONbits.ON = 1 ;
   
    // 7) :
    while(PIR6bits.PWM6IF==0) ;
    TRISBbits.TRISB5 = 0 ;  // "allumer" pin RB5


Voilà les étape du datasheet Page 317 que je suis :

Code : Tout sélectionner

1. Disable the CCPx pin output driver by setting the
associated TRIS bit.
2. Select the timer associated with the PWM by
setting the CCPTMRS register.
3. Load the associated T2PR/T4PR/T6PR/T8PR
register with the PWM period value.
4. Configure the CCP module for the PWM mode
by loading the CCPxCON register with the
appropriate values.
5. Load the CCPRxH:CCPRxL register pair with
the PWM duty cycle value.
6. Configure and start the timer selected in step 2:
• Clear the timer interrupt flag bit of the PIRx
register. See Note below.
• Configure the CKPS bits of the TxCON
register with the Timer prescale value.
• Enable the Timer by setting the ON bit of
the TxCON register.
7. Enable PWM output pin:
• Wait until the Timer overflows and the timer
interrupt bit of the PIRx register is set. See
Note below.
• Enable the CCPx pin output driver by
clearing the associated TRIS bit.

PWM sur PIC16F1779
Temps-x
Avatar de l’utilisateur
Expert
Expert
Messages : 2616
Enregistré en : juillet 2016
Localisation : Terre

#2 Message par Temps-x » ven. 17 avr. 2020 20:19 lien vers la Data-Sheet : Cliquez ici

Bonjour,

Si tu utilises un quartz quelle est sa fréquence, si tu utilise l'oscillateur du pic quelle est sa fréquence.

Est quelle est la fréquence que tu veux obtenir sur ton PWM

==> A+
:roll: Les requins, c'est comme le langage ASM, c'est le sommet de la chaîne alimentaire. :wink:

PWM sur PIC16F1779
Superphénix
Débutant
Débutant
Messages : 54
Enregistré en : mars 2020

#3 Message par Superphénix » ven. 17 avr. 2020 21:28 lien vers la Data-Sheet : Cliquez ici

J'utilise un quartz à 4MHz et j'aimerais obtenir quelque chose entre 200 et 10kHz. Ce que j'ai fait là est sensé donner 3906Hz.

PWM sur PIC16F1779
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#4 Message par satinas » sam. 18 avr. 2020 08:03 lien vers la Data-Sheet : Cliquez ici

Bonjour,

The PR2 period register (T2PR) is double-buffered
Tu as cherché l'adresse du registre PR2 dans la doc ?
Le registre n'existe pas, ou plutôt on n'y a pas accès directement. Ils parlent de PR2 period register numéro 2, accessible sous le nom T2PR. C'est comme ça, la la la la (comme dans la chanson). Cela aurait pu être plus clair dans l'explication.
D'autant plus que pour des raisons de compatibilité avec les anciens pic, ils ont gardé le nom PR2, voir le fichier
C:\Program Files\Microchip\xc8\include\pic16f1779.h

Code : Tout sélectionner

extern volatile unsigned char           T2PR                @ 0x494;
extern volatile unsigned char           PR2                 @ 0x494;

Donc dans ton cas c'est T6PR, ou PR6. Bien que PR6 ne soit pas vraiment PR6, c'est un registre tampon permettent de lire ou écrire au bon moment dans le registre PR6 présent dans le schéma du timer.

Le bit PWM6IF concerne le module PWM6 16 bits spécialisé du chapitre 26, qui a ses propres registres pour régler la période et le rapport cyclique. Il y a aussi des modules PWM 10 bits spécialisés basés sur le timer 2, voir chapitre 25.

Pour ton PWM1 10 bits du module CCP1 du chapite 24, si on sélectionne le timer 6, c'est PIR4.TMR6IF.
Le fait d'attendre le premier interrupt flag à 1, c'est si on veut un premier créneau PWM propre, sinon on peut s'en passer.

PWM sur PIC16F1779
Superphénix
Débutant
Débutant
Messages : 54
Enregistré en : mars 2020

#5 Message par Superphénix » sam. 18 avr. 2020 16:38 lien vers la Data-Sheet : Cliquez ici

Merci pour ces précisions. Bon à savoir qu'ils gardent des noms de registres d'anciens µCs dans la doc.

The PR2 period register (T2PR) is double-buffered

Je ne savais pas ce que voulais dire "double-buffered", maintenant oui ^^
Effectivement dans mon cas j'ai pas besoin d'attendre un premier créneau PWM propre. (pour varier l'intensité lumineuse de 4 LEDs...)
Du coup je suppose que dans ce cas les TRISB5 = 1/0, sont pas nécessaires non plus ?

Par contre j'ai toujours rien en sortie :

Code : Tout sélectionner

    CCP1PPS = 0b00001101 ;  // RB5

    TRISBbits.TRISB5 = 1 ;  // éteindre pin RB5

    CCPTMRS1bits.C1TSEL = 0b10 ;  //  Timer6 pour CCP1

    T6PR = 0b11111111 ;  // 255

    CCP1CON = 0b10001100 ;  // Enable + Right-aligned + PWM mode

    CCPR1H = 0b00000010 ;
    CCPR1L = 0b00000000 ;

    PIR4bits.TMR6IF = 0 ;  // Timer interrupt flag
    T6CONbits.CKPS = 0b000 ;  // Prescal = 1:1
    T6CONbits.ON = 1 ;

    TRISBbits.TRISB5 = 0 ;  // allumer pin RB5

PWM sur PIC16F1779
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#6 Message par satinas » sam. 18 avr. 2020 17:27 lien vers la Data-Sheet : Cliquez ici

- Tu fais deux fois la même erreur, CCP1PPS est une input PPS, pour le mode Capture du module CCP (Table 12-1). Pour une output PPS, il faut faire RB5PPS = CCP1_out (Table 12-2).
- Pas la peine de mettre le flag PIR4bits.TMR6IF à 0, on ne l'utilise pas (pas d'irq ni polling).
- D'après le diagramme PWM CCP, il faut mettre le TRIS a 0, il est derrière le PPS (Figure 24-3).
- Si la valeur de CCPR1H:CCPR1L est trop grande, le signal peut ne pas varier, il reste haut.

PWM sur PIC16F1779
Superphénix
Débutant
Débutant
Messages : 54
Enregistré en : mars 2020

#7 Message par Superphénix » sam. 18 avr. 2020 23:29 lien vers la Data-Sheet : Cliquez ici

Tu fais deux fois la même erreur

Ah oui oops

Si la valeur de CCPR1H:CCPR1L est trop grande, le signal peut ne pas varier, il reste haut.

Selons mes calculs elle devrait pouvoir monter à 1023. Là j'ai mis 512.

Par contre j'ai toujours rien :?:

Code : Tout sélectionner

    TRISBbits.TRISB5 = 1 ;  // éteindre pin RB5

    RB5PPS =  0b00010101 ;  // CCP1_out

    CCPTMRS1bits.C1TSEL = 0b10 ;  //  Timer6 pour CCP1

    T6PR = 0b11111111 ;  // 255

    CCP1CON = 0b10001100 ;  // Enable + Right-aligned + PWM mode

    CCPR1H = 0b00000010 ;
    CCPR1L = 0b00000000 ;

    T6CONbits.CKPS = 0b000 ;  // Prescal = 1:1
    T6CONbits.ON = 1 ;

    TRISBbits.TRISB5 = 0 ;  // allumer pin RB5

PWM sur PIC16F1779
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#8 Message par satinas » dim. 19 avr. 2020 06:17 lien vers la Data-Sheet : Cliquez ici

Bonjour,
Nouveau pic, nouveaux registres, regarde T6CLKCON.
The CCP operation requires that the timer used as the PWM time base has the FOSC/4 clock source selected.
Il faut Fosc/4 pour pouvoir ajouter 2 bits aux 8 bits de TMR6, et comparer aux 10 bits de CCPR1.
Une fois que cela marche, pour la clarté du code, tu pourrais reconfigurer dans l'ordre :
-> timer6, ccp1, ccp1 sur timer6, pps, tris=0, timer6 on.
Au reset, TRISB5 est déjà à 1 et CCPR1L déjà à 0, je déteste les instructions en trop :) je les enlève ou les mets en commentaire selon le cas.

PWM sur PIC16F1779
Superphénix
Débutant
Débutant
Messages : 54
Enregistré en : mars 2020

#9 Message par Superphénix » dim. 19 avr. 2020 20:00 lien vers la Data-Sheet : Cliquez ici

Yes! Ça fonctionne enfin :-D

Je sais pas si j'ai bien compris l'ordre logique que vous m'avez donné, mais je poste le code qui fonctionne actuellement :

Code : Tout sélectionner

    T6PR = 0b11111111 ;
    T6CLKCON = 0b00000001 ;
    T6CONbits.CKPS = 0b000 ;
    CCP1CON = 0b10001100 ;
    CCPR1H = 0b00000000 ;
    CCPR1L = 0b01000000 ;
    CCPTMRS1bits.C1TSEL = 0b10 ;
    RB5PPS =  0b00010101 ; // CCP1_out
    TRISBbits.TRISB5 = 0 ;  // allumer pin RB5
    T6CONbits.ON = 1 ;


Merci !

PWM sur PIC16F1779
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#10 Message par satinas » dim. 19 avr. 2020 20:55 lien vers la Data-Sheet : Cliquez ici

Bravo :-) fallait bien que cela marche, le mot PWM est introuvable dans l'Errata Datasheet du 16F1779. J'avais vérifié au préalable.

La logique elle est contenue dans le diagramme de fonctionnement du PWM.
Pour moi, l'élément central est le timer, c'est celui qui donne le tempo. D'abord on le configure, sans le démarer.
Ensuite on lui adjoint un module CCP/PWM que l'on configure d'abord, ensuite on le relie au timer.
De cet accouplement naît un joli signal qui va vers le mapping PPS qu'on programme.
En sortie de PPS on entre dans la cellule TRIS qu'on programme.
Il n y a plus qu'a démarrer le timer, TMR6 est à 0 par défaut et commence à compter, avec les 2 consignes CCPR1H:L et T6PR prêtes. Je vois pas pourquoi la première période ne serait pas correcte, il faudrait regarder avec un oscillo à mémoire.

Et les commentaires sont plus faciles à mettre, par exemple (en peu détaillé)

Code : Tout sélectionner

    T6PR = 0b11111111 ;               // config Timer6
    T6CLKCON = 0b00000001 ;
    T6CONbits.CKPS = 0b000 ;
    CCP1CON = 0b10001100 ;            // config CCP1 -> PWM
    CCPR1H = 0b00000000 ;
    CCPR1L = 0b01000000 ;
    CCPTMRS1bits.C1TSEL = 0b10 ;      // PWM on Timer6
    RB5PPS =  0b00010101 ;            // PPS CCP1_out -> RB5
    TRISBbits.TRISB5 = 0 ;            // RB5 output
    T6CONbits.ON = 1 ;                // start PWM


Retourner vers « Langage C »

Qui est en ligne

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