|
|
View previous topic :: View next topic |
Author |
Message |
desert eagle
Joined: 27 Sep 2013 Posts: 7 Location: Frankfurt, Germany
|
PIC24 CCP module |
Posted: Fri Sep 27, 2013 3:14 am |
|
|
Hi,
I'm currently working with PIC24FV32KA301 and I am trying to use input capture module to measure an average time period over 4 rising edges in my input capture routine. I have taken help from earlier posts as well. I am able to generate pulses of 1ms pulse width using Output compare but I want to use the avg time period calculated from Input capture module. This means if input capture gives an avg time of a wave as 20ms, I want to generate a pulse of 1ms which repeats every 20ms using Output compare. How can I do it? _________________ Asghar |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Sep 30, 2013 11:44 am |
|
|
Why not use the PWM module?
Should be a piece of cake.
Mike |
|
|
desert eagle
Joined: 27 Sep 2013 Posts: 7 Location: Frankfurt, Germany
|
PIC24 CCP module |
Posted: Tue Oct 01, 2013 12:51 am |
|
|
@Mike well the problem is, I don't want the output pulse width to change. I want to have it fixed, say at 250us. Only the frequency should vary depending upon the input frequency. But I want to measure average period first, since the input pulses appear with variable frequency. _________________ Asghar |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Oct 01, 2013 1:53 am |
|
|
I don't have PIC24's but I do have PIC18's
On PIC18's, set_pwmx_duty(value) fixes the PWM ON_PERIOD not the DUTY_RATIO.
Changing the PWM frequency then alters the DUTY_RATIO but has no effect on the PULSE WIDTH.
This appears to be exactly what you want.
It would be rather perverse if PIC24's worked differently.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Oct 01, 2013 2:10 am |
|
|
OK.
On the old PIC18, this is obvious, and pretty simple. You'd have the CCP, using the same clock source as the timer feeding the PWM, and leave the pulse 'width' programmed to a fixed value, then change the timer reset point to match the recorded CCP value.
So how do we do the same on the PIC24?.
Now first thing with these chips, is that the data sheet, has only the 'chip specifics' in it. The general data is at:
<http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2575>
These are the 'module reference manuals' for each part, and are vital.
Now, if you pull section 16, this covers how to use the output compare ability to generate a PWM. 16.3.3, for a simple PWM. Now the key here is if you setup the PWM, using the CCS functions, for the longest period time you want, all that has to be changed to give the shorter repeat period, is the value in the PRy register. The OCxRS register defines the 'on' time, which can be left unchanged.
So, I'd suggest doing exactly that. Use #word, and 'getenv', to give you a direct definition of the PR register for the PWM you are using. Calculate your period from your recorded times (sounds as if you want to record four, sum them, and divide by four to give a slight 'averaging'?), then write this value, to the PR register to update the PWM period.
Since TyIF is set when the timer resets at the end of the period, this should be used as the point to update the value.
Best Wishes |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Oct 01, 2013 2:19 am |
|
|
I see Mike posted while I was posting.
The PIC24's, are different, but similar. All the timers are individually programmable for a reset count. There is then an option to set or clear the output pin at this reset. Then you have a function similar to the PIC18 'output compare', which allows you to change the output pin at the compare match. So the timer resets to zero, and counts till it reaches it's 'reset' point, and keeps doing this to give the 'period'. Then you use the 'compare' function to reset the output pin at the count required for the pulse width.
So only the period setting for the timer being used needs to change, but to do this without interfering with the pulse train, I'd suggest just updating the register directly, when the interrupt for a completed cycle is seen.
Best Wishes |
|
|
desert eagle
Joined: 27 Sep 2013 Posts: 7 Location: Frankfurt, Germany
|
|
Posted: Tue Oct 01, 2013 5:48 am |
|
|
Thanks guys for your replies. Can u please have a look at the following code? I wrote it a couple of days back and it works fine. But when i try to calculate Period of the input waveform in the input capture ISR, the output compare generates pulses after every 2nd rising edge of input(it shud generate after every rising edge as Input capture is configured for it)but without the 'period' calculation in the ISR, the program works fine. I dont understand the problem. Is it bec of the delay caused by the execution of calculation? Also I want to use this 'period' value further to control the period of output as in real, the input period is not constant. so i want to take average input period
[code]
#include <24FV32KA301.h>
#define Out PIN_B1
#define In PIN_B9
#fuses FRC,NOWDT,PROTECT,MCLR // Konfigurationswort
#use fast_io(B)
#use delay(clock=8000000)
unsigned int period;
unsigned int flag_counter=0;
unsigned int multiple;
static unsigned long pre_timervalue=0;
unsigned long new_timervalue;
long int OCR_3 =0x0000; //1ms Pulse generation start value for output compare mode
long int OCRS_3=0x0005; //0.25ms Pulse
//Pulse stop value 0.25ms/(2/8MHz*256) where 256 is Timer 3 prescalar
unsigned int flag_counter1=0;
void main(void)
{
// INITIALIZATION
SETUP_WDT(WDT_OFF);
SETUP_OSCILLATOR(OSC_INTERNAL);
SETUP_ADC(ADC_OFF);
SET_TRIS_B(0x0200); //Input and Output pin definition (0000 0010 0000 0000)
//FEDC BA98 7654 3210
//Interrupt initialization
ENABLE_INTERRUPTS(INTR_GLOBAL);
ENABLE_INTERRUPTS(INT_TIMER2);
ENABLE_INTERRUPTS(INT_IC2);
ENABLE_INTERRUPTS(INT_OC3);
// ENABLE_INTERRUPTS(INT_TIMER4);
//Capture module initialization
SETUP_TIMER2(TMR_INTERNAL); //Timer 2 with System clock as a source for IC
SETUP_CAPTURE(2, CAPTURE_RE|CAPTURE_TIMER2|INTERRUPT_EVERY_CAPTURE); //capture mode capturing every rising edge for period measurement
while(1)
{};
}
#INT_IC2
void IC2_isr(void)
{
/* multiple=flag_counter;
flag_counter=0;
period = get_capture(2,TRUE);
// period=(new_timervalue)-(pre_timervalue);
period=((new_timervalue)-(pre_timervalue)+(65536*(multiple+1))) ; //multiple indicates 16-bit timer overflow count
pre_timervalue=new_timervalue; */
SETUP_TIMER3(TMR_INTERNAL|TMR_DIV_BY_256);
SET_COMPARE_TIME(3,OCR_3, OCRS_3); //Output pulse width
//but we need a dynamic value from Input Capture
SETUP_COMPARE(3,COMPARE_SINGLE_PULSE | COMPARE_TIMER3);
clear_interrupt(INT_IC2); //clear IC flag to run for next edge
}
#INT_TIMER2
void TIMER2_isr(void) //timer2 interrupt
{
flag_counter++; //this is a counter for timer2 overflows
clear_interrupt(INT_TIMER2); // clear timer2 interrupt's flag
} _________________ Asghar |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Oct 01, 2013 6:00 am |
|
|
quick answer yes....
ISR must be short! having any kind of 'math' inside an ISR is,well, terrible. Just set a flag, record some data, and get out...fast...
in 'main', do the math...
also
you do not need to clear_ints inside the ISR( CCS does that for you)
and
usually you 'enable' interrupts, then 'enable' the global interrupt.
hth
jay |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|