CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem with PIC24FJ timers

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Damaso



Joined: 07 Nov 2012
Posts: 11

View user's profile Send private message

Problem with PIC24FJ timers
PostPosted: Tue Jan 15, 2013 4:16 am     Reply with quote

I'm using a PIC24FJ128GB106 with USB support and a external 20MHz crystal. I used these fuses and the USB works flawlessly:
Code:

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES ICSP2                    //ICD uses PGC2/PGD2 pins
#FUSES NOJTAG                   //JTAG disabled
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOIOL1WAY                //Allows multiple reconfigurations of peripheral pins
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES PR_PLL                   //Primary Oscillator with PLL
#FUSES PLL5                     //Divide By 5(20MHz oscillator input)
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES DISUVREG

#use delay(clock=20MHz)

I'm planning on using timers in my project, so I made the usual simple program for blinking a led. But, no matter which value I put in set_timer1(), the result is always the same, the interrupt happens every 1 second. Here is my code:


Code:

#include <24FJ128GB106.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES ICSP2                    //ICD uses PGC2/PGD2 pins
#FUSES NOJTAG                   //JTAG disabled
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOIOL1WAY                //Allows multiple reconfigurations of peripheral pins
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES PR_PLL                   //Primary Oscillator with PLL
#FUSES PLL5                     //Divide By 5(20MHz oscillator input)
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES DISUVREG

#use delay (clock=20MHz)
#include <usb_cdc.h>

#int_TIMER1
void  TIMER1_isr(void)
{
   set_timer1 (50000);
   output_toggle(PIN_G8);
}


void main()
{
   setup_spi( FALSE );
   setup_spi2( FALSE );

   setup_timer2(TMR_DISABLED |TMR_DIV_BY_1 ,0);
   setup_timer4(TMR_DISABLED |TMR_DIV_BY_1 ,0);
   setup_timer3(TMR_DISABLED |TMR_DIV_BY_1 ,0);
   setup_timer5(TMR_DISABLED |TMR_DIV_BY_1 ,0);


   usb_cdc_init();
   usb_init();

   setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256);
   set_timer1 (50000);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INTR_GLOBAL);
   output_low (PIN_G8);
   while (TRUE);
}


With set_timer1(50000), the interrupt should happen every 0.4s. How can this be even possible?
And yes, I also tried it without loading the usb part and the result is the same.
Damaso



Joined: 07 Nov 2012
Posts: 11

View user's profile Send private message

PostPosted: Tue Jan 15, 2013 5:01 am     Reply with quote

I changed the #use delay to:

Code:
#use delay(clock=20MHz, xtal=20MHz)


and the blinking period changed to 1.6s. That is the exact period for when the timer goes from 0x0000 to 0xFFFF with the 256 divider. The problem seems to be that the PIC ignores the set_timer1() instruction.

If I change the setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256); to

Code:
setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256, xxx);


it works correctly for every xxx value that I enter.

This is my first project with a PIC24, I'm used to PIC18. Does the set_timer1() works differently?
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Tue Jan 15, 2013 5:29 am     Reply with quote

Timers in the PIC24, are completely different from those on the older PIC's.

Instead of counting up to 0xFFFF, and then resetting, they count to the value specified in the period register. This is the second number in the setup_timer command.

Hence you never need to set the timer 'to' a value to get a time interval, the hardware does all of this for you.

Now if you are setting a value in the period, that is below the value you set in the timer interrupt, it'll have no effect (since you are past the count already....).

Second thing is that the timers are clocked off oscillator/2, not oscillator/4, so calculations change.
If you want 0.4 seconds, then all you need is:

10000000*0.4 = 4000000
4000000/256 = 15625

Remember it counts from 0 to the period value, so:
Code:

setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256, 15624);

Then get rid of all the set_timer lines.

Problem is that you are setting the count value 'past' the programmed reset point, so it gets ignored.

This merrily gives 0.4second interrupts with your chip/clock.

Best Wishes
Damaso



Joined: 07 Nov 2012
Posts: 11

View user's profile Send private message

PostPosted: Tue Jan 15, 2013 9:02 am     Reply with quote

So, by default, the setup_timer1() sets a 0xFF period and that's why the interrupts happens every 1.6s, isn't it?
In my application I need to change the interrupt frequency during execution, and that's why I used set_timer1() inside the isr. That worked with PIC18s, but it seems that I need to find another way to do it with this new pic. The solutions that occurs to me is to directly change the "Period Register 1" inside the isr whenever I need it.
Code:
#word     PR1  = 0X0102
...
#int_TIMER1
void  TIMER1_isr(void)
{
   PR1 = period ;                  //changed elsewhere during execution
   output_toggle(PIN_G8);
}
...


But I have one more question. Does the interrupt happens when the timer equals the PR1 value and then goes back to zero? Or does the interrupt happens when the timer equals 0xFF and then goes back to (0xFF-PR1)? I suppose it's the first one, but I would like some clarification if you don't mind
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Tue Jan 15, 2013 9:48 am     Reply with quote

The first.

The data sheet tells all.

However the period register, is a _16bit_ register, not an 8bit register. None of the PIC24 timers are 8bit. 0xFFFF period by default, not 0xFF.

Use the compilers ability to find registers for you - safer:
Code:

#word PR1=getenv("SFR:PR1")


Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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