![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Matthias Guest
|
PIC24 running at 80MHz and Timer1 is too slow? |
Posted: Wed Dec 17, 2008 9:58 am |
|
|
Hi all,
I use a PIC24HJ238GP306. Now I discovered 2 problems.
Problem no. 1:
As it looks like I can not use the FUSES to speed up my 16MHz oscillator with a PLL to 80MHz automaticly. So I use this code in my .h-File
Code: | #WORD OSCCON = 0x742 //Definieren der Oszillatorregister
#WORD CLKDIV = 0x744 //Definieren der Oszillatorregister
#WORD PLLFBD = 0x746 //Definieren der Oszillatorregister
#BIT CLKDIV6 = CLKDIV.6 //Definieren der zu ändernden Oszillatorregisterpins
#BIT CLKDIV12 = CLKDIV.12 //Definieren der zu ändernden Oszillatorregisterpins
#BIT CLKDIV13 = CLKDIV.13 //Definieren der zu ändernden Oszillatorregisterpins
#BIT PLLFBD1 = PLLFBD.1 //Definieren der zu ändernden Oszillatorregisterpins
#BIT PLLFBD5 = PLLFBD.5 //Definieren der zu ändernden Oszillatorregisterpins
#use delay(clock=16000000) |
In my main-file I set my missing bits to 80MHz operation.
Code: | CLKDIV6 = 0;
CLKDIV12 = 0;
CLKDIV13 = 0;
PLLFBD1 = 1;
PLLFBD5 = 0; |
The problem is that all timings now have to be divided by 5 to work at the desired speed. Is there a method to get the timings right? I found no fuse where I can set the PLL to x5 my external osc so I did it manually.
This problem is more about good looking and not a real one.
problem no. 2:
I want to use my timer1 to generate Interrupts with a frequency of about 1.6MHz. With a 80MHz of clock-cycle I get 40MIPS. This is my code to check the maximum speed of Timer1:
Code: | setup_timer1(TMR_INTERNAL|TMR_DIV_BY_1,1);
enable_interrupts(INT_TIMER1);
#int_Timer1
void timer1_ISR(void) {
static int a = 0;
if (a == 0) {
output_high(PIN_C2);
a = 1;
}
else {
output_low(PIN_C2);
a = 0;
}
} |
The result is a frequency of about 388kHz (388.348kHz) at Pin C2. Using code like this
Code: | while(true) {
output_high(PIN_C2);
delay_us(1);
output_low(PIN_C2);
delay_us(1);
} |
I can reach frequencies of more than 1 MHz at Pin C2. Due to my Module Block Diagram Timer1 can be feeded with Tcy (which should have at least a speed of around 10MHz) with a prescaler of 1. What is wrong with my timer1? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 17, 2008 12:08 pm |
|
|
I don't have the PCD compiler, but if the interrupt handling is done similar
to the PCH compiler, then 388 KHz is about right. Here's my reasoning:
It takes roughly 40 instruction cycles for the interrupt dispatcher code to
get in and out of your isr. Then let's say another 10 instructions for your
actual isr code, giving 50 instruction cycles total. This gives:
Code: | 40 MHz
-------- = 800 KHz
50 |
But, each pass through the isr only creates a rising or falling edge on
pin C2, so the actual frequency would be half of that:
Code: |
800 KHz
-------- = 400 KHz
2
|
You'll have to look at the .LST file to confirm the length of the interrupt
dispatcher code, but I suspect that my thinking is correct. |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Dec 17, 2008 12:16 pm |
|
|
Quote: | As it looks like I can not use the FUSES to speed up my 16MHz oscillator with a PLL to 80MHz automaticly. | Yes, the PLL isn't set from config bits, so CCS C has no #fuses statement for it. Generally, the compiler expects the real fosc value in the #use delay statement, so you have to write clock=80000. |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Thu Dec 18, 2008 5:08 am |
|
|
Quote: | #use delay statement, so you have to write clock=80000 |
i did that but then my PIC isn't starting because i can set my bits later in my code only. When i try to set them before #use delay ... then i get a compiler error. |
|
![](templates/subSilver/images/spacer.gif) |
Matthias Guest
|
|
Posted: Thu Dec 18, 2008 5:15 am |
|
|
edit:
this is the code form the .lst file for timer 1:
....................
.................... #int_Timer1 level=2
.................... void timer1_ISR(void) {
*
00200: PUSH 42
00202: PUSH 36
00204: MOV W0,[W15++]
00206: MOV #2,W0
00208: REPEAT #C
0020A: MOV [W0++],[W15++]
.................... static int a = 0;
*
00320: MOV #0,W4
00322: MOV W4,3F38
.................... if (a == 0 && schalter_an == 1) {
*
0020C: MOV 3F38,W0
0020E: CP0 W0
00210: BRA NZ,224
00212: MOV 3F36,W0
00214: CP W0,#1
00216: BRA NZ,224
.................... output_high(PIN_C2);
00218: BCLR.B 2CC.2
0021A: BSET.B 2D0.2
.................... a = 1;
0021C: MOV #1,W4
0021E: MOV W4,3F38
.................... }
.................... else {
00220: GOTO 22C
.................... output_low(PIN_C2);
00224: BCLR.B 2CC.2
00226: BCLR.B 2D0.2
.................... a = 0;
00228: MOV #0,W4
0022A: MOV W4,3F38
.................... }
.................... }
....................
0022C: BCLR.B 84.3
0022E: MOV #1A,W0
00230: REPEAT #C
00232: MOV [--W15],[W0--]
00234: MOV [--W15],W0
00236: POP 36
00238: POP 42
0023A: RETFIE
This is what i was measuring for different timer counter values:
counter -- frequency in kHz
1 -- 377
2 -- 377
3 -- 377
5 -- 377
10 -- 377
20 -- 377
30 -- 322
40 -- 325
50 -- 356
60 -- 328
70 -- 281
80 -- 247
90 -- 220
100 -- 198
150 -- 132
200 -- 99
300 -- 66
400 -- 50
500 -- 40
600 -- 33.3
700 -- 28.5
1000 -- 20
2000 -- 10
3000 -- 6.66
4000 -- 5
5000 -- 4
10000 -- 2
15000 -- 1.33
20000 -- 1.00
As you can see up to 200kHz it is no problem for the timer but above there are strange things happening whatever my counter value is (in that specific area). |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Dec 18, 2008 6:19 am |
|
|
Quote: | When i try to set them before #use delay ... then i get a compiler error. | No reason, to do that.
Quote: | i did that but then my PIC isn't starting because i can set my bits later in my code only. | I don't see a relation. #use delay is only informing the compiler, how to calculate constants, it's not configuring the CPU. |
|
![](templates/subSilver/images/spacer.gif) |
Matthias Guest
|
|
Posted: Thu Dec 18, 2008 6:45 am |
|
|
Quote: | I don't see a relation. #use delay is only informing the compiler, how to calculate constants, it's not configuring the CPU. |
I tested it again and now it worked. Perhaps i had another error before.
But my main problem still remains |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Dec 18, 2008 1:22 pm |
|
|
Your code is exactly behaving as expectable. The present version takes 49 respectively 54 instruction cycles, depending on the state of variable a. If the configured timer period is lower than 54 (period register value of 53) the interrupt execution stays behind timer events and you loose some interrupts, resulting in the interrupt frequencies as observed. An interrupt frequency of 1.6 MHz can't be achieved at all.
The most illustrative way, to visualize this behaviour is MPLAB simulator, using the stopwatch.
By the way, you didn't tell, what you exactly want to achieve, there may be better ways.
Best regards,
Frank |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|