• AVR Freaks

Hot!CCP module for PIC16F1xxxx

Author
fabbrz
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2019/06/24 02:16:23
  • Location: Bretagne,France
  • Status: offline
2021/01/18 08:38:48 (permalink)
0

CCP module for PIC16F1xxxx

Hi everybody,
 
I'm trying to use CCP module (in capture mode) of my PIC16F18445.
 
The goal of this, is to measure a frequency (square form) from 0Hz to 2500Hz.
 
My signal arrives on port RB5 (CCP3IN).
 
For now, I've done the following things :
 
I/O : 
TRISBbits.TRISB5 = 1; /* digital input */

 
CCP module :
    /* PORTB et PIN 5 */
    CCP3PPSbits.PORT = 1;
    CCP3PPSbits.PIN = 5;

    /* CCP is disabled */
    CCP3CONbits.CCP3EN = 0;
    
    /* Capture : Every rising edge of CCPx input */
    CCP3CONbits.CCP3MODE = 5;
    
    /* CCPR3 cleared */
    CCPR3H = 0;
    CCPR3L = 0;
     
    /* Pin selected by CCP3PPS */
    CCP3CAPbits.CTS = 0;
    
    /* CCP3 is based off Timer1 in Capture/Compare mode and Timer2 in PWM mode */
    CCPTMRS0bits.C3TSEL = 1;
    
    /* Interrupt enable */
    PIE6bits.CCP3IE = 1;
    PIR6bits.CCP3IF = 0;
    
    /* CCP is enabled */
    CCP3CONbits.CCP3EN = 1;

 
   /* TIMER 1 */
    /* 1:8 Prescale value */
    T1CONbits.CKPS = 3;
    TMR1H = 0;
    TMR1L = 0;
     
    /* Fosc/4 */
    TMR1CLKbits.CS = 1;
        
    PIR4bits.TMR1IF = 0;
    /* bit 7 : GIE - General Interrupt Enable */
    /* bit 5 : TMR0IE : Timer 0 Interrupt Enable */
    INTCONbits.GIE = 1;
   
    PIE0bits.TMR0IE = 1;
    PIE4bits.TMR1IE = 1;
    
    /* Enables Timer */
    T1CONbits.ON = 1;

 
My Fosc is 32Mhz (HFINT32), so with my prescaler at 1:8, it means 32Mhz/4/8 = 1Mhz => 1µs.
 
If my input signal is 400Hz (2.5ms) soit that means that my CC3PR registers must contains 2500 (If I have well understand the functionning).
 
Now, the flag is well detected in the interrupt. I have put an array of 10 variables to see the values. You can see this array on the picture.
 
The values are moving a lot (from 1200 to 2600), so I think something is wrong in my code.
 
If someone can give me some help, I'll be very happy.
 
 
 
 

Attached Image(s)

#1

12 Replies Related Threads

    JPortici
    Super Member
    • Total Posts : 1285
    • Reward points : 0
    • Joined: 2012/11/17 06:27:45
    • Location: Grappaland
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/18 09:56:31 (permalink)
    +1 (1)
    Code for when you add data in the table?
    Are you resetting the time between captures?
    Altough it's better that you keep track of the last value and table:
    newValue = CCP1PR
    entry = newValue - oldValue
    oldValue = newValue
    #2
    ric
    Super Member
    • Total Posts : 29861
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: CCP module for PIC16F1xxxx 2021/01/18 12:26:48 (permalink)
    +1 (1)
    +1
    Most likely the problem is in the ISR code, which was not posted.
    I notice both TMR0 and TMR1 interrupts are also enabled. Why?
    You must make sure their code executes and exits ASAP.
     
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #3
    fabbrz
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2019/06/24 02:16:23
    • Location: Bretagne,France
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/18 12:42:04 (permalink)
    0
    I'll submit the rest of my code tomorrow morning.
     
    But, Ican answer at some questions :
     
    Yes, I reset time between captures (TMR1H = 0 & TMR1L = 0)
     
    TMR0 interrupt is enabled because I used Timer 0 as a counter (a LED is blinking every second).
    TMR1 interrupt is enabled because I've made some tests with it and I forget to disable it.
    #4
    ric
    Super Member
    • Total Posts : 29861
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: CCP module for PIC16F1xxxx 2021/01/18 12:55:19 (permalink)
    +1 (1)
    fabbrz
    Yes, I reset time between captures (TMR1H = 0 & TMR1L = 0)

    You shouldn't.
    The correct method is as JPortici mentioned, leave the timer running, and subtract the preceding reading from the next one. Make sure you use "unsigned" variables.

    TMR1 interrupt is enabled because I've made some tests with it and I forget to disable it.

    Forgetting that old code is still running is a frequent cause of strange behaviour!

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #5
    fabbrz
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2019/06/24 02:16:23
    • Location: Bretagne,France
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/19 00:07:18 (permalink)
    0
    With your comments, I've modified my code.
     
    Below, the code for my interrupt :
     
     
        /* CCP3 */
        if(PIR6bits.CCP3IF == 1)
        {
            PIR6bits.CCP3IF = 0;
            newCCPValue = (CCPR3H << 8) | CCPR3L;
            freq = newCCPValue - oldCCPValue;
            oldCCPValue = newCCPValue;
        }
        else
        {
            NOP();
        }

     
    all variables are declared in unsigned int.
     
    Below, my code for initialization of timers 0 & 1 :
     
    /* TIMER 0 */
        /* The module is enabled and operating */
        T0CON0bits.EN = 1;
        /* TMR0 is an 8-bit timer */
        T0CON0bits.T016BIT = 0;
        /* 1:1 Postscaler */
        T0CON0bits.OUTPS = 0;
        
        /* 010 - FOSC/4 */
        T0CON1bits.CS = 2;
        /* 0 - The input to the TMR0 counter is synchronized to FOSC/4 */
        T0CON1bits.ASYNC = 0;
        /* 0000 - 1:64 */
        T0CON1bits.T0CKPS = 6;
        
        /* 32MHz / 4 = 8Mhz / 64 = 125k => 1/x = 8µs */
        /* Timer0 à 1ms, soit 1ms/8µs = 125 */
        /* TIMER0 ; interruption lorsque l'on arrive à la valeur programmée */
        TMR0H = TIMER_1MS;
          
        /* TIMER 1 */
        /* 1:8 Prescale value */
        T1CONbits.CKPS = 3;
        TMR1H = 0;
        TMR1L = 0;
         
        /* Fosc/4 */
        TMR1CLKbits.CS = 1;
            
        /* bit 7 : GIE - General Interrupt Enable */
        /* bit 5 : TMR0IE : Timer 0 Interrupt Enable */
        INTCONbits.GIE = 1;
       
        PIE0bits.TMR0IE = 1;
        
        /* Enables Timer */
        T1CONbits.ON = 1;

     
    With this code, values in my variable freq are moving from 1900 to 3600 instead of 2500.
    #6
    davea
    Super Member
    • Total Posts : 626
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: Tampa Bay FL USA
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/19 10:30:40 (permalink)
    0
            PIR6bits.CCP3IF = 0;
            newCCPValue = (CCPR3H << 8) | CCPR3L;
            freq = newCCPValue - oldCCPValue;
            oldCCPValue = newCCPValue;

            New_data++;

    how does the main know when new data is ready ?
    its usually what you don't show, where the problem is.
     
    #7
    fabbrz
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2019/06/24 02:16:23
    • Location: Bretagne,France
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/20 01:11:53 (permalink)
    0
    Thank you for your answer, but I'm sorry, I don't understand what I'm supposed to do.
     
    NewData must be incremented up to ??? or must be incremented up to 1, and when the variable is at 1, that means that the data is available  and then I reset it ?
    #8
    fabbrz
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2019/06/24 02:16:23
    • Location: Bretagne,France
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/20 07:18:39 (permalink)
    0
    I've modified a little bit my code. In my interrupt, I have the following code : 
     
    if(PIR6bits.CCP3IF == 1)
        {
            if(CCP_State == 0)
            {
                t1 = (CCPR3H << 8) | CCPR3L;
                PIR6bits.CCP3IF = 0;
                CCP_State = 1;
            }
            else if(CCP_State == 1)
            {
                t2 = (CCPR3H << 8) | CCPR3L;
                PIR6bits.CCP3IF = 0;
                freq = t2-t1;
                CCP_State = 0;
            }
    }

     
    Sometimes, I've the right value (1005 for 1kHz signal) and sometimes, something wrong. Can it be due to debug mode ?
    #9
    fabbrz
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2019/06/24 02:16:23
    • Location: Bretagne,France
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/20 09:07:32 (permalink)
    0
    Now, it seems to work but only up 1Khz. After I've some wrong values.
    #10
    davea
    Super Member
    • Total Posts : 626
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: Tampa Bay FL USA
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/20 09:29:03 (permalink)
    0
    1 that means that the data is available and then I reset it ?

    yes NON zero
    insert freq into buffer, inc and wrap buffer and clear NEW_data
    2500hz = 400us
    1000hz = 1000us
    #11
    davea
    Super Member
    • Total Posts : 626
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: Tampa Bay FL USA
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/20 12:04:27 (permalink)
    0
    fabbrz
    I've modified a little bit my code. In my interrupt, I have the following code : 
     
    if(PIR6bits.CCP3IF == 1)
        {
            if(CCP_State == 0)
            {
                t1 = (CCPR3H << 8) | CCPR3L;
                PIR6bits.CCP3IF = 0;
                CCP_State = 1;
            }
            else if(CCP_State == 1)
            {
                t2 = (CCPR3H << 8) | CCPR3L;
                PIR6bits.CCP3IF = 0;
                freq = t2-t1;
                CCP_State = 0;
            }
    }

      Can it be due to debug mode ?

    No
    all you have done is insure that the first reading is valid  
    and wasted more time in a ISR by using a switch statement
    that you don't need..
    for reference only 

        if(PIR6bits.CCP3IF){
          if(!CCP_State & 0x01) // odd/even (bit test)
           {
           t1 = (CCPR3H << 8) | CCPR3L;
           }
           else
          {
          t2 = (CCPR3H << 8) | CCPR3L;
          freq = t2-t1;    
          NEW_data++;   //  half speed data
          }
      CCP_State++;
      PIR6bits.CCP3IF = 0; 
    }

     
     
    #12
    fabbrz
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2019/06/24 02:16:23
    • Location: Bretagne,France
    • Status: offline
    Re: CCP module for PIC16F1xxxx 2021/01/21 01:26:54 (permalink)
    0
    Thank for your help, I've finally found my solution.
     
    I have noticed that I forget to enable the bit PEIE.
     
    post edited by fabbrz - 2021/01/21 05:11:55
    #13
    Jump to:
    © 2021 APG vNext Commercial Version 4.5