Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] problem with CCP module

Status
Not open for further replies.

mnsp90

Newbie level 4
Newbie level 4
Joined
May 22, 2014
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
76
HI all,
I am working on a display card based on PIC16F877A for a ups system.
In that all the input and output voltages and currents are measured using timer1 interrupt.
But to measure input and output frequency I am using CCP module.
But here I am facing an issue. When I write code for both CCP1 and CCP2 modules, Only one of them is working and the other is not at all working.
Since I have used interrupt for measuring voltages and currents I have not used CCP interrupt. I am just monitoring CCPIF and once it is set I am storing the CCPR value in a variable and disabling the CCPIF flag. the code for frequency measurement I am using is shown below.
IN that code only CCP1 is working and CCP2 is not working.Can anyone please let me know the mistake??
And also Can We use 2 interrupt service routines here? If yes how can we differentiate them??


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if(PIR1bits.CCP1IF)
                {
                                 PIR1bits.CCP1IF=0;
                out_prd1 = CCPR1;
                }
            if(PIR1bits.CCP1IF)
                {
                CCP1CON=0x00;   
                out_prd = CCPR1-out_prd1;
                temp = out_prd>>2;
                F_out = TIMERFREQ/temp;
                //F_out = F_out>>3;
                out_prd1=CCPR1;
                }
            if(PIR2bits.CCP2IF)
                {PIR2bits.CCP2IF=0;
                in_prd1= CCPR2;
                }
            
            if(PIR2bits.CCP2IF)
                {
                CCP2CON=0x00;
                in_prd = CCPR2-in_prd1;
                temp1 = in_prd>>2;
                F_in = TIMERFREQ/temp1;
                //F_in = F_in>>3;
                in_prd1=CCPR2;
                }

 
Last edited by a moderator:

I think your problem is that you are using timer1 for syncing you code. The problem is that this is that timer1 is being used by the CCP module. So you do not want to use timer1 for anything other than CCP. My guess is that the working channel has a higher frequency than the none working channel.

The PIC16 has one interrupt level. So if any interrupt is generated the processor jumps to the same location in memory. This means that you can have only one interrupt service routine. However within the service routine you can poll for the various interrupt status flags. Then call another function to process the interrupt specific tasks there.
 

Thank you for your warm reply bluelasers.
Actually both the channels have same frequency. As you have mentioned,it is the same timer1 that is being used for interrupt and the same timer1 has to be used for CCP module. I was unable to use other timers like timer0 and timer2 as they are 8 bit timers only which cannot generate the required time for reading 7 analog inputs I have to display here. So I am bound to use timer1 for interrupt.
Even when the timer interrupt is disabled and CCP interrupt is enabled and timer1 being used only for CCP module then also I am not getting the output from one channel. This is why I could not understand where the problem is?? Is it with the CCP code I mentioned above or because of using timer1 for both the purposes??
 

I have a question about the code you posted. Why do check for an interrupt clear the interrupt then check for it again? The second check code should never run.

- - - Updated - - -

If you are only using a timer1 to sync between the 7 analog input conversions, then you do not need timer1. Instead you should use the ADC's interrupt.

This interrupt goes off after the completion of an analog conversion. Inside the interrupt service route for the adc you can increment a counter, clear interrupt flag, change the analog input mux and then start the next conversion. This will free up timer1 for the CCP.

Also are you using the CCP to output or just input?
 

I have a question about the code you posted. Why do check for an interrupt clear the interrupt then check for it again? The second check code should never run.

In CCP module if we have to measure frequency we have to check for two consecutive events inCCP. Hence I used two conditions. 1st time I am noting the CCPR1 value and clearing the interrupt and 2nd time I am noting the CCPR1 value and subtracting it from 1st noted value. Thats why in the 2nd loop I am disabling the CCP module by
making CCPCON 0x00.

I have one more doubt here.
I understood the use of ADC interrupt instead of timer1 interrupt which is good. But even then with ADC Interrupt service routine, we cannot use the CCP interrupt know. So my doubt is even then we have to use such a code that I have mentioned above.

while using ADC Interrupt my understanding is that we have to initiate ADC conversion for a single channel and when the conversion is complete it will generate an interrupt and in the interrupt service routine we can increment a counter,clear interrupt flag,change the analog channel and call the ADC read once again. Please correct me if I am wrong??
 

In CCP module if we have to measure frequency we have to check for two consecutive events inCCP. Hence I used two conditions. 1st time I am noting the CCPR1 value and clearing the interrupt and 2nd time I am noting the CCPR1 value and subtracting it from 1st noted value.

The problem is the second block never runs, the first block runs. The first block clears the interrupt so the second block never runs. Why do you reset the CCP module after the second event.

You could do the following for the CCP in the interrupt service routine:

Code:
if(PIR1bits.CCP1IF)
{
	out_prd = CCPR1-out_prd1;
	temp = out_prd>>2;
	F_out = TIMERFREQ/temp;
	out_prd1=CCPR1;
	CCP1_FLAG = 1;	// This is a flag to tell any application code in main while loop that new data for CCP1 is available.
	PIR1bits.CCP1IF=0;
}

The benefit to this is that it automatically continuously samples. The CCP1_flag is cleared in the main while loop.

How does this code measure frequency? It appears as though you are measuring the change in frequency.

Your whole program can be done with interrupts from what I am seeing. Can you send me your code?

I understood the use of ADC interrupt instead of timer1 interrupt which is good. But even in CCP module we cannot use the CCP interrupt know. So my doubt is even then we have to use such a code that I have mentioned above.

I believe that the CCP interrupts were not working because you were using timer1. You need to let the CCP module take ownership of timer1 and configure it itself or however it needs to be configured for CCP.

So for the interrupts to work you have to enable the interrupt in PIE1 and/or PIE2. Then you have to enable the global interrupt.

while using ADC Interrupt my understanding is that we have to initiate ADC conversion for a single channel and when the conversion is complete it will generate an interrupt and in the interrupt service routine we can increment a counter,clear interrupt flag,change the analog channel and call the ADC read once again.

Yes, for the ADC you will have to start one manually inside of main before the while loop to start the process off.
 

The problem is the second block never runs, the first block runs. The first block clears the interrupt so the second block never runs. Why do you reset the CCP module after the second event.

If my understanding about CCP module is clear then, once an event is noticed CCPIF is set. Now I am sending a pulse at a frequency of 50Hz to a CCP pin and let us say I am taking every 4th rising edge as my eveent. Then upon 1st event CCPIF is set. again if we dont clear it It will remain set even though the 2nd event does not happen. Our intention is to measure frequency to do so what we should do is to note the timer register values between two successive events. and then do the math.

How does this code measure frequency? It appears as though you are measuring the change in frequency.

I have disabled the CCP module after 2nd check to make sure that no further updates of frequency is possible unless the microcontroller is reset. If you see the code once the main is started CCP module is initialized. then the 1st part is executed where CCPIF is set when a 1st event occured. then the interrupt is disabled But CCP module is enabled.So when 2nd event occurs again CCPIF will be SET. Then in order not to run CCP module further I have disabled it so that no further calculation is done.
I have made sure that timer also runs for around 104msec which is greater than 4 cycles time. So meanwhile there is no chance that timer1 will overflow and by the time timer overflows CCP is disabled. here I have not enabled CCP interrupt.So whenever an event occurs only CCPIF will be set but no interrupt service routine will be executed.
This code is running in the hardware. But the problem I am facing is only CCP1 module is running But CCP2 is not at all displaying any result.

Your whole program can be done with interrupts from what I am seeing. Can you send me your code?

I believe that the CCP interrupts were not working because you were using timer1. You need to let the CCP module take ownership of timer1 and configure it itself or however it needs to be configured for CCP.
I will send the code tomorrow.

My idea of writing the ADC channels in timer interrupt is to see that all my parameters are updated at a particular interval of time continuously.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top