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 ---
On parle des Pics, sans rapport avec le langage ou la programmation

Modérateur : Jérémy

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
gwion
Amateur
Amateur
Messages : 192
Enregistré en : février 2022

#1 Message par gwion » dim. 26 févr. 2023 13:46

Bonjour à tous,

Je suis toujours dans ma découverte des PIC.
Je me pose une question après avoir fait des tas d'essais car ça ne fonctionne pas.
D'après la DS, on ne peut pas configurer la capture pour générer une interruption sur les fronts descendants et les fronts montants, c'est l'un ou l'autre. Or moi je veux mesurer la période haute et basse des pulses. J'ai donc tenté de modifier le registre CCP1M à la volée dans le code de détection d'interruption pour faire une bascule entre les 2 modes, mais ça ne semble pas fonctionner... C'est possible ou pas ?

Je précise : la pin RA2 est à l'état haut en permanence, les impulsions la tire à zéro.

Merci et bon dimanche.

Résumé du code de la supposée bascule

Code : Tout sélectionner

        if ( CCP1CONbits.CCP1M3 == 1 )
        {
            CCP1CONbits.CCP1M = 0b0100 ;
        }
        else
        {
            CCP1CONbits.CCP1M = 0b0101 ;
        }


Et le code au complet

Code : Tout sélectionner

#include <xc.h>

#include "E:\XC8_includes\PIC12F1840_UART\my_header.h"

#include "E:\XC8_includes\PIC12F1840_UART\PIC12F1840_UART.h"

unsigned long int _XTAL_FREQ = 32000000UL;
unsigned long int BAUDRATE = 19200;

#define LED_ROUGE   RA5
#define PULSE       RA2

#include <stdio.h>
#include <math.h>

#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

volatile  unsigned long ul_nb_debord_timer1 = 0;
volatile  unsigned long ul_nb_debord_timer2 = 0;

volatile  unsigned long ul_T1_debutbas = 0;
volatile  unsigned long ul_T1_debuthaut = 0;

void __interrupt() isr(void)
{
    if (TMR1IF) // si débordement de timer1
    {   
        ul_nb_debord_timer1++;   
       // sprintf(str_uart,"Nb deb T1 = %lu\n\r",ul_nb_debord_timer1);
        //UART_write_string(str_uart );
        TMR1IF = 0; // raz du flag d'interruption
    }
       
    if (CCP1IF)   // changement d'état sur RA2
    { 
        unsigned long u_capture_T1;       
        u_capture_T1 = (uint16_t)(CCPR1H << 8) + CCPR1L;   
        u_capture_T1 += (ul_nb_debord_timer1 * 65536 ) ;/// ( (32000000/4) * 16 );
       
        ul_nb_debord_timer1 = 0;
       
        //0101 = Capture mode: every rising edge
        //0100 = Capture mode: every falling edge
        if ( CCP1CONbits.CCP1M3 == 0 )
        {
            // début front descendant
            // calcul du temps haut précédent
            LED_ROUGE = 1;
            ul_T1_debutbas = u_capture_T1;
           
            if (ul_T1_debuthaut == 0)
            {
               UART_write_string("Tps H n/a\n\r" );

            }
            else
            { 
                u_capture_T1 = ul_T1_debuthaut - u_capture_T1;
                ul_T1_debuthaut = 0;
                sprintf(str_uart,"DES T1 = %lu\n\r",u_capture_T1);
                UART_write_string(str_uart );
            }
        }
        else
        {
            // début front montant
            // calcul du temps bas précédent
            u_capture_T1 = ul_T1_debutbas - u_capture_T1;
            LED_ROUGE = 0;
            ul_T1_debuthaut = u_capture_T1;
            ul_T1_debutbas = 0;
            sprintf(str_uart,"MONT T1 = %lu\n\r",u_capture_T1);
            UART_write_string(str_uart );
        }
       
        if ( CCP1CONbits.CCP1M3 == 1 )
        {
            CCP1CONbits.CCP1M = 0b0100 ;
        }
        else
        {
            CCP1CONbits.CCP1M = 0b0101 ;
        }
       
        CCP1IF = 0; // raz flag

    }
}



void main(void)
{
    OSCCON = 0b11110000; // oscillateur interne à 32MHz
    OPTION_REGbits.nWPUEN = 0; // pull-up internes modifiables au cas par cas
   
    UART_init(); // Initialise l'UART
   
    // RA5 LED rouge visu debug 
    TRISAbits.TRISA5 = 0; 
    WPUAbits.WPUA5=0;   // pull-up off 
    LED_ROUGE = 0;
       
    // RA2 pour réception des impulsions
    TRISAbits.TRISA2 = 1; // RA2 en entrée
    ANSELAbits.ANSA2 = 0; // RA2 numérique
    WPUAbits.WPUA2=0;   // pull-up off sur RA2
   

    TMR1 = 0;
    T1CONbits.TMR1CS = 0; // fosc / 4
   
    // Choose the desired prescaler ratio (1:1)
    // 1 et 1 : divise par 16
    T1CKPS0 = 1;
    T1CKPS1 = 1;
   
    TMR1H = 0x00;
    TMR1L = 0x00;
 
    TMR1ON = 1;
   
    //--[ Configure The CCP1 Module To Operate in Capture Mode ]--
    //0101 = interruption sur front desc
    //0100 = interruption sur front mont
    CCP1CONbits.CCP1M = 0b0101;
 
    // Enable CCP1 Interrupt
    PIE1bits.CCP1IE = 1;
    CCPR1H = 0x00;
    CCPR1L = 0x00;
    PEIE = 1;
    GIE = 1;

    while(1)
    {
    }
}



PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#2 Message par paulfjujo » dim. 26 févr. 2023 15:41

bonjour,


Avec Uart write dans le traitement d'interruption .... ça craint .

il me semble avoir déja utilisé l'inversion de sens de detection Edge
dans une application ... retrouvée
!mais en mikroC
_12F1840_test_capture.zip


sinon avec un 18F27K42 et le timer 24bits STM1, c'est easy et précis à 0.5/1000 près

exemple de resultat
Test SMT compteur 24 bits (résumé des registres en page 364)
Test SMT1 en mode 2 (voir DS90003129A TB3129 page 4 :
Period an Duty cycle acquisition TMR APRES l'acquisition complete
Init Interrupt UART RX
* Haut = 20012, Periode = 40022 soit 1000550 nS , Freq=999.45 Hz , Duty= 50.00%
* Haut = 20015, Periode = 40025 soit 1000625 nS , Freq=999.38 Hz , Duty= 50.01%
* Haut = 20012, Periode = 40027 soit 1000675 nS , Freq=999.33 Hz , Duty= 50.00%
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Aide toi, le ciel ou FantasPic t'aidera

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#3 Message par satinas » dim. 26 févr. 2023 15:53

Bonjour à tous,

Tout d'abord c'est le bit CCP1CONbits.CCP1M0 qui change entre le front montant et descendant.
D'autre part dans le datasheet, il est dit :
- si changement de mode de capture, désactiver CCP1IE d'abord pour éviter une interruption parasite.
- si changement de prescaler CCP1 il faut mettre CCP1CON à 0 pour remettre à zéro le prescaler.

Tu ne changes pas le prescaler car il reste à 1, mais il vaut mieux en tenir compte.
Donc à essayer :

Code : Tout sélectionner

  CCP1IE = 0;
  if ( CCP1CONbits.CCP1M0 == 1 )
  {
    CCP1CON = 0x00;
    CCP1CONbits.CCP1M = 0b0100 ;
  }
  else
  {
    CCP1CON = 0x00;
    CCP1CONbits.CCP1M = 0b0101 ;
  }
  CCP1IF = 0;
  CCP1IE = 1;

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
gwion
Amateur
Amateur
Messages : 192
Enregistré en : février 2022

#4 Message par gwion » dim. 26 févr. 2023 15:58

paulfjujo a écrit :bonjour,
Avec Uart write dans le traitement d'interruption .... ça craint .

il me semble avoir déja utilisé l'inversion de sens de detection Edge
dans une application ... retrouvée
!mais en mikroC _12F1840_test_capture.zip


Bonjour et merci Paul,

J'ai fini par mettre les traces série dans l'ISR car je doutais de tout.
Mais à la base elles étaient dans le while avec un flag pour les déclencher.

Je vais me pencher sur ton exemple, merci encore. Dans mon cas c'est didactique et je ne cherche donc pas la précision ultime pour l'instant, comprendre me suffira.

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
gwion
Amateur
Amateur
Messages : 192
Enregistré en : février 2022

#5 Message par gwion » dim. 26 févr. 2023 15:59

Oups, ça c'est gros comme une maison effectivement, merci satinas :)
Je confirme que ça marche tout de suite nettement mieux !!!!

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#6 Message par satinas » dim. 26 févr. 2023 16:03

Si on considère que le prescaler ne posera pas de problème

Code : Tout sélectionner

  CCP1IE = 0;
  CCP1CONbits.CCP1M0 = !CCP1CONbits.CCP1M0;
  CCP1IF = 0;
  CCP1IE = 1;

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
gwion
Amateur
Amateur
Messages : 192
Enregistré en : février 2022

#7 Message par gwion » dim. 26 févr. 2023 16:16

Donc il vaut mieux suspendre la capture le temps de faire le flip-flop.

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#8 Message par satinas » dim. 26 févr. 2023 16:37

On la suspend pas, en fait je pense que même le fait de resetter CCP1IE est superflu, car ils doivent prévoir le cas ou on change le mode de capture en étant hors de la routine d'interruption. Le fait de le changer dans l'ISR, même si il ya un trig parasite il ne se passera rien, CCP1IF est déjà à 1. Trop de précautions pour rien.

Il ne faut pas faire CCP1CONbits.CCP1M0 = !CCP1CONbits.CCP1M0; comme écrit ci-dessus, cela génère beaucoup d'instructions machine. tandis que l'exor 1 se termine en une seule instruction BTG.
donc, là c'est mon dernier mot, à vérifier quand même que ça marche :)

Code : Tout sélectionner

  CCP1CONbits.CCP1M0 ^= 1;
  CCP1IF = 0;

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
gwion
Amateur
Amateur
Messages : 192
Enregistré en : février 2022

#9 Message par gwion » dim. 26 févr. 2023 17:17

Il faut de toute manière un test pour savoir si l'on va calculer le temps haut ou bas, donc ce n'est pas gênant d'y intégrer l'inversion de détection.

PIC12F1840 : en mode capture peut-on changer la détection front montant/descendant
gwion
Amateur
Amateur
Messages : 192
Enregistré en : février 2022

#10 Message par gwion » dim. 26 févr. 2023 20:50

@paulfujo
Paul, une petite question stp. Dans ton projet tu mesurais quelle fourchette de période ?


Retourner vers « Généralités sur les PICs »

Qui est en ligne

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