View previous topic :: View next topic |
Author |
Message |
harel12k
Joined: 26 Nov 2020 Posts: 11
|
Problem with times (pic18F8722) |
Posted: Thu Nov 26, 2020 11:45 am |
|
|
Hey,
I'm using pic18F722 with 8 MHz oscillator.
I'm interesting to get interrupt every 10us.
From unknown reason i can't get an interrupt in less then 50us intervals.
When I'm using delay_us(10) appropriately with digital I/O output toggling still see 50us between toggles.
This is the loop of the delay_us() function test:
Code: |
While (1){
output toggle(PIN);
delay_us(1);
} |
After running this loop still gets square signal with 50us between toggles.
Does anyone faced with that problem?
Any recommendations?
Thank you |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Nov 26, 2020 12:27 pm |
|
|
You can't interrupt that fast. You are only running at 2MIPS. It takes
typically about 30 instructions to actually get into an interrupt, and another
25 to get out. So at 8MHz, just under 30uSec. If the interrupt then does
anything, the time in the interrupt goes up.
You only have 20 instruction times between something happening at 10uSec.
Not time enough to really do anything much..... |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Thu Nov 26, 2020 2:47 pm |
|
|
I can't find a CCS device file for the PIC18F722 in
either version 5 or version 4.
Also can't find a datasheet online, is this the correct device name? _________________ Google and Forum Search are some of your best tools!!!! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Nov 26, 2020 3:17 pm |
|
|
Maybe he has an 18F87K22 ?? |
|
|
harel12k
Joined: 26 Nov 2020 Posts: 11
|
Correct device name |
Posted: Thu Nov 26, 2020 10:22 pm |
|
|
dyeatman wrote: | I can't find a CCS device file for the PIC18F722 in
either version 5 or version 4.
Also can't find a datasheet online, is this the correct device name? |
The correct device is :
pic18f8722
I forgot a digit |
|
|
harel12k
Joined: 26 Nov 2020 Posts: 11
|
|
Posted: Fri Nov 27, 2020 4:16 am |
|
|
temtronic wrote: | Maybe he has an 18F87K22 ?? |
The correct device name is pic18f8722 |
|
|
harel12k
Joined: 26 Nov 2020 Posts: 11
|
|
Posted: Fri Nov 27, 2020 11:57 pm |
|
|
Ttelmah wrote: | You can't interrupt that fast. You are only running at 2MIPS. It takes
typically about 30 instructions to actually get into an interrupt, and another
25 to get out. So at 8MHz, just under 30uSec. If the interrupt then does
anything, the time in the interrupt goes up.
You only have 20 instruction times between something happening at 10uSec.
Not time enough to really do anything much..... |
Thanks about your detailed answer.
Why when I'm using delay_us like this:
I'm getting a real delay of about 50us? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sat Nov 28, 2020 2:23 am |
|
|
Then your #use delay, and clock setup are wrong.
The actual output instruction again takes time, but you should see perhaps
55uSec.
Post your full code. Clock setup fuses etc..
Also what physical oscillator you are actually using. |
|
|
harel12k
Joined: 26 Nov 2020 Posts: 11
|
|
Posted: Sun Nov 29, 2020 1:36 am |
|
|
Ttelmah wrote: | Then your #use delay, and clock setup are wrong.
The actual output instruction again takes time, but you should see perhaps
55uSec.
Post your full code. Clock setup fuses etc..
Also what physical oscillator you are actually using. |
My full code
Code: |
#include <18F8722.h>
#fuses HS,nowdt, noprotect, noput, nobrownout
#use delay(clock=8000000)
#int_timer3
void timer_3_interrupt_handler(){
output_toggle(PIN_A1);
clear_interrupt(INT_TIMER3);
set_timer3(65533);
}
void run_timer_3(){
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER3);
interrupt_active(INT_TIMER3);
setup_timer_3(T3_INTERNAL | T3_DIV_BY_8);
setup_timer3(65533);
}
Void main(){
run_timer_3();
while (1){
//None
}
}
|
Our scope image looks like:
[img]https://ibb.co/q9fWVhj[/img]
What can cause this big interval delay?
Thank you |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sun Nov 29, 2020 2:34 am |
|
|
You are missing the point about time.
Understand that a single C instruction can be hundreds of machine instructions.
Even something as simple as the actual interrupt call takes two instruction
cycles to complete. The processor then has to save the registers before
executing the actual handler, and restore these after it has finished.
At 2MIPS, it takes 25uSec to actually reach the start of the interrupt
handler when the event triggers. It then takes two instructions to toggle
the pin. Then you waste one clearing the interrupt (the compiler automatically
does this). Then four instructions to load the 16bit value
into the timer (your chip has an erratum, so an extra NOP has to be added
after the second byte is loaded). Then the interrupt is cleared and the
routine exits, restoring the registers saved (another 25uSec). It actually
executes the return, 52uSec after the original routine call. At this point the
interrupt has already triggered, so the whole cycle starts again.
Your processor just cannot do an interrupt this fast.
You spoke about using delay:
Code: |
while (TRUE)
{
output_toggle(PIN_A1);
delay_us(10);
}
|
Even this will take 12uSec to do. 2uSec for the loop and two for the
actual toggle instruction. |
|
|
harel12k
Joined: 26 Nov 2020 Posts: 11
|
|
Posted: Tue Dec 01, 2020 4:06 am |
|
|
Ttelmah wrote: | You are missing the point about time.
Understand that a single C instruction can be hundreds of machine instructions.
Even something as simple as the actual interrupt call takes two instruction
cycles to complete. The processor then has to save the registers before
executing the actual handler, and restore these after it has finished.
At 2MIPS, it takes 25uSec to actually reach the start of the interrupt
handler when the event triggers. It then takes two instructions to toggle
the pin. Then you waste one clearing the interrupt (the compiler automatically
does this). Then four instructions to load the 16bit value
into the timer (your chip has an erratum, so an extra NOP has to be added
after the second byte is loaded). Then the interrupt is cleared and the
routine exits, restoring the registers saved (another 25uSec). It actually
executes the return, 52uSec after the original routine call. At this point the
interrupt has already triggered, so the whole cycle starts again.
Your processor just cannot do an interrupt this fast.
You spoke about using delay:
Code: |
while (TRUE)
{
output_toggle(PIN_A1);
delay_us(10);
}
|
Even this will take 12uSec to do. 2uSec for the loop and two for the
actual toggle instruction. |
Thank you very much about your full of details answer. I have learned a lot!
I have found some possible solution but for very fast interrupts I'm using PLL mode (Fosc*4). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Dec 01, 2020 11:11 am |
|
|
I have to make the comment, that if you just want to toggle a pin, just use the
hardware CCP. Zero processor usage, and dead accurate timings.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Dec 01, 2020 11:27 am |
|
|
Another comment...
Generally speaking, run the PIC as fast as possible. For your PIC, that'd be 40MHz. This will allow the PIC to do more, in a shorter time. You don't say what is the interupt source, but if you need quicker response, consider a faster PIC, like the 18F46K22. It'll run at 64MHz so +-180% faster.
However...be SURE to properly design the PCB layout, best components, PSU design and external wiring !
Jay |
|
|
|