Menu

How to manage interrupts using only Timer1 for 2 x CCP ports (Pic16F1829)

Phil D
2022-03-17
2022-03-17
  • Phil D

    Phil D - 2022-03-17

    Hi there,

    I have been using GCB for the last couple of years, but only recently delved into using CCP ports using interrupts with 'relative' ease to control LED output based upon pulse width duty cycle input. However, I have am now wanting to use two CCP ports on a PIC16F1829 with both ports using Timer1.

    I have been working on this for a week now and cannot for the life of me figure out how to manage the ISR's correctly with both CCP1 and CCP4 operating using Interrupts with Timer1 (i.e. 16 bit). If I comment out the first to two LOOP 'Calls' for CCP1, then CCP4 works fine and visa versa, commenting out CCP4 makes CCP1 work fine. But they will not work if both are left to function consecutively - I have been using Proteus simulator to test.

    Once I can get this working, then I will want to expand this to 4 x CCP through Timer1, which I should be able to do, once I understand what I am doing wrong to get this working with just 2 x CCP's.

    I am pulling out what little hair I have and I know I am not handling the Interrupts/ISR's correctly, but cannot work out exactly where the problem is?!

    I have attached the code below and am hoping someone can help me before I am completely bald!

    Thanks in advance!!

     

    Last edit: Phil D 2022-03-17
  • Phil D

    Phil D - 2022-03-17

    NOTE: "I should have made it a little more clear, I am using internal weak pull ups, so I have reversed the pulse width high and low variable names accordingly.

     
  • Anobium

    Anobium - 2022-03-17

    Interesting.

    I think I would need a simple description of what you are trying to achieve. I am not sure I understand from the intro.


    A comment... On Interrupt Timer1Overflow Call IncCounter these do the same thing. I cannot see that you are clearing the bit PIE1.TMR1IE there is no point in setting more than once.

     
  • Anobium

    Anobium - 2022-03-17

    I just took the code you posted and tried to start from first principles. Many questions already.

    I have changed SOU and TOU to suit the board I had to hand.

    But, as you will see SOU is toggling as the program logic, so far, does not make sense to me.


    I do not recommend that you/we all post and repost this to the forum. Can you move this code to GitHub where folks can edit and help online?

    Evan

    #Chip 16F1829, 32
    #Option Explicit
    #CONFIG MCLRE = OFF
    
        '******WEAK PULL UP CONFIGURATION******
        Set Not_WPUEN = 0 'Enable pullups in general.
        Set WPUA0     = 0
        Set WPUA1     = 0
        Set WPUA2     = 0
        Set WPUA3     = 0
        Set WPUA4     = 0
        Set WPUA5     = 0
        Set WPUB4     = 0
        Set WPUB5     = 0
        Set WPUB6     = 0
        Set WPUB7     = 0
        Set WPUC0     = 0
        Set WPUC1     = 0
        Set WPUC2     = 0
        Set WPUC3     = 0
        Set WPUC4     = 0
        Set WPUC5     = 1 'RCL - CCP1 (Pin 5)
        Set WPUC6     = 1 'TIN - CCP4 (Pin 8)
        Set WPUC7     = 0
    
        '******Input IO config******
        #define RCL RC5 'PWM INPUT (CCP1)
        #define TIN RC6 'PWM INPUT (CCP4)
        #define SOU RC1 'LED OUTPUT BASED ON CONDITION OF INPUT (I.E. PORTC.5)   ERV Changed to suit my board
        #define TOU RC2 'LED OUTPUT BASED ON CONDITION OF INPUT (I.E. PORTC.6)   ERV Changed to suit my board
    
        '******Dir Config******
        DIR RCL IN
        DIR TIN IN
        Dir SOU OUT
        Dir TOU OUT
    
        '******DIM Variable Config******
        DIM RCLPWH AS WORD       'PORTC.5 - PULSE HIGH MEASUREMENT
        DIM RCLPWL AS WORD       'PORTC.5 - PULSE LOW MEASUREMENT
        DIM TINPWH AS WORD       'PORTC.6 - PULSE HIGH MEASUREMENT
        DIM TINPWL AS WORD       'PORTC.6 - PULSE LOW MEASUREMENT
        DIM RCLDCPC AS WORD      'LOGIC TO DECIDE WHAT TO DO WITH PORTC.5 INPUT PULSE WIDTH DUTY CYCLE
        DIM TINDCPC AS WORD      'LOGIC TO DECIDE WHAT TO DO WITH PORTC.6 INPUT PULSE WIDTH DUTY CYCLE
        DIM RCLPeriod AS WORD    'VARIABLE FOR CALCULATING PORTC.5 PULSE PERIOD
        DIM TINPeriod AS WORD    'VARIABLE FOR CALCULATING PORTC.6 PULSE PERIOD
        DIM CounterValue as Word 'VARIABLE FOR IncCounter 'COUNTER VALUE'
        DIM RCLFreq as Word      'VARIABLE FOR CALCULATING PORTC.5 PULSE FREQUENCY
        DIM TINFreq as Word      'VARIABLE FOR CALCULATING PORTC.6 PULSE FREQUENCY
    
        'Setup timer
        InitTimer1 OSC, PS1_8
    
        'Counter Value Initialized Value
        CounterValue = 0
    
        On Interrupt Timer1Overflow Call IncCounter 'Set "On Interrupt"
        'At this point Timer1 is not running
    
        do
            Call PWMRCL            'MEASURE PORTC.5 PULSE WIDTH HIGH AND LOW TIMER VALUES
    
    
        loop
    
        Sub IncCounter  'ON INTERRUPT Counter
            CounterValue ++
        End Sub
    
    
        Sub PWMRCL
    
    
            CCP1CON = 4                     'Set the  Capture mode: every falling edge
            StartTimer 1                    'Start the timer... but, is the valie of CounterValue important ? I guess not. 
                                            'Now timer is running and CounterValue is incrementing
            CCP1IF = 0                      'Clear the CCP1F interrupt flag, but, we have not enabled the CCP1 interrupt. Will CCP1IF ever become 1?
            do while CCP1IF = 0
    
            If CounterValue >= 1 Then       'The chances of CounterValue are pretty high as CCP1IF will always be 0
                Call RCLISR
            End If
    
            loop
    
    
    
        End Sub
    
        Sub RCLISR
    
            SOU = !SOU
    
        End Sub
    
     
    • Phil D

      Phil D - 2022-03-17

      Thanks Evan, I have attached the file in my original post.

      OK, yes, I see there is a fair bit not correct, surprised it even works for me even using just one CCP.

      Looking into your Serial debug attachment now...

       
  • Anobium

    Anobium - 2022-03-17

    The attachment has Serial debug added and version control.

    By showing the value of PIR1.. the CCP1IF bit never changes. From this basis - what am I missing?

     

    Last edit: Anobium 2022-03-17
  • Phil D

    Phil D - 2022-03-17

    Hi Anobium,

    Thanks for the quick response!

    Basically, at this stage I am just wanting to take a duty cycle measurement from each CCP input and apply a corresponding output to an LED. for example, If CCP1 duty cycle is between 50% to 100%, Then LED1 (SOU in my code) will turn on, otherwise it will be off. At the same time, if CCP4 input duty cycle is between 1% and 49% then LED2 (TOU in my code) will turn on. 0% is the off state for both LEDs. The LEDs will operate independently of each other, so CCP1 (RCL) will only control output SOU, while CCP4 (TIN) will only control output TOU.

    Thanks for the feedback re the clearing of bit PIE1.TMR1IE! I have had a look in other open discussions over the last half hour and the usage i have found is in assembly code examples (I am not proficient in assembly.... but, you probably guessed that already! :-) Is it possible to include it in SynWrite? If yes, where should it be placed? Perhaps even a previous open discussion if you are aware of one that has already covered the PIE1.TMR1IE usage would be very much appreciated!

     
    • Anobium

      Anobium - 2022-03-17

      Back basics, so I can understand your design goals.

      You are using timer1 to do what? at the moment islt simlple increments and (in my code does nothing), are you waiting for an event on Ccp1 input?

       
  • Phil D

    Phil D - 2022-03-17

    I am using Timer1 to measure/time the pulse width high and low, so I can calculate the duty cycle. If the duty cycle is 0% or 100% I am wanting to use an interrupt to handle this. If 0% duty cycle, SOU = 0, if 100% SOU = 1 . The duty cycle from 1% to 99% will turn SOU either on or off, depending upon what duty cycle values I determine. Say anything from 50% up, SOU = 1, anything below 50% SOU = 0.
    My understanding is when working with 0% and 100% duty, an ISR is needed to manage this. While I have got this working with CCP1 on TMR1 (somehow, given I appear to be way off!), I want to do the same thing with CCP4, with CCP4 also using Timer1.

    I included the IncCounter because it was included in one of the the GCB 16f887A help pages... I used it to help me get started when first getting started with Interrupts and just realized that I never took it out and is totally pointless for my project.

     
  • Phil D

    Phil D - 2022-03-17

    No I haven't but I will! Thanks Evan and will let you know how I get on.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.