View previous topic :: View next topic |
Author |
Message |
art
Joined: 21 May 2015 Posts: 181
|
delay_cycles function |
Posted: Sat Dec 17, 2016 6:20 am |
|
|
Hi,
I'm trying to make a SIRC project. Im using a pic18f4550 and a 20MHmz crystal.
I would like to know regarding delay_cycles functions.
If I'm using delay_cycles(54), how to convert this 54 to microsecond?
If i use pic16f84, is this 54 will give the same result in microsecond? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sat Dec 17, 2016 6:41 am |
|
|
Your 20MHz oscillator gives 5 machine cycle per micro-second. (20/4 =5)
You can now work out how long 54 machine cycles take.
(It's all in the data sheets / manuals.)
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sat Dec 17, 2016 1:28 pm |
|
|
Except (of course), on this chip, he could be clocking at 20MHz, 10MHz, 6.66MHz, 5MHz, 48MHz, 24MHz, 12MHz or 8MHz, using that crystal, depending on the fuse settings.
On the f84, with the same crystal, the chip can only run at 20MHz.
This is why CCS has the clock setting, so it can do such calculations. Then delay_us(10); gives 10uSec of delay whatever the clock rate actually is.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sat Dec 17, 2016 3:52 pm |
|
|
OK, I have to ask, just what does SIRC mean? |
|
|
art
Joined: 21 May 2015 Posts: 181
|
|
Posted: Sat Dec 17, 2016 7:42 pm |
|
|
SIRC means Sony Infrared remote control |
|
|
art
Joined: 21 May 2015 Posts: 181
|
|
Posted: Sat Dec 17, 2016 8:10 pm |
|
|
Hi, just now Mike inform that 20/4=5 machine cycle per microsecond. Why it must be divide by 4?. Are you referring to table 2-3 in the pic18f4550 data sheet manual? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Dec 17, 2016 10:07 pm |
|
|
Read the 18F4550 data sheet. It contains all the information you need:
Quote: |
5.2.1 CLOCKING SCHEME
The microcontroller clock input, whether from an
internal or external source, is internally divided by four to generate four non-overlapping quadrature clocks
(Q1, Q2, Q3 and Q4).
5.2.2 INSTRUCTION FLOW/PIPELINING
An “Instruction Cycle” consists of four Q cycles: Q1 through Q4.
|
So 20 MHz / 4 = 5 MHz instruction cycle rate. |
|
|
art
Joined: 21 May 2015 Posts: 181
|
|
Posted: Sat Dec 17, 2016 11:00 pm |
|
|
Thank you very much PCM,
I've just check almost all PIC clock input from external source, is internally divided by four. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sun Dec 18, 2016 1:56 am |
|
|
This is the difference between Fosc, and Fcy (oscillator versus instruction cycles).
However the point I was trying to make, is that on the chip you start by mentioning (2550) Fosc, does not necessarily match Fxtal.
On this chip, there are two different routes from the crystal to Fosc. One 'direct' with a programmable divider (/1, /2, /3 & /4), and the second via the PLL.
This second route, is triggered by the 'HSPLL' fuse combination.
So with 'HS' selected, you have CPUDIV1 giving 20Mhz Fosc
CPUDIV2 giving 10MHz.
CPUDIV3 giving 6.66 MHz
CPUDIV4 giving 5MHz.
Then select HSPLL, and the clock instead comes from the PLL. This has to be fed with 4MHz, so 'PLL5' has to be selected (to divide the crystal by 5 to feed the PLL). The PLL then generates 96MHz from this. You can then choose:
CPUDIV1 giving 48MHz (there is an internal /2 between the PLL and the CPU divider).
CPUDIV2 giving 32MHz.
CPUDIV3 giving 24Mhz.
CPUDIV4 giving 16Mhz.
So with your 20Mhz crystal, the internal 'Fosc' does not have to be 20Mhz.....
Fcy is then this frequency/4 for a PIC16 or 18. Fcy as well as being the 'cycle time', is also the peripheral clock on these.
Now you make a comment:
"almost all PIC clock input from external source, is internally divided by four."
What is actually happening, is 'machine cycles', versus 'instruction cycles'. Think about actually performing an 'instruction'. It is internal code (often called microcode), and the chip has to do multiple things. Read the instruction from flash, then do operations on what is read, and on the internal RAM as well. These are the internal machine cycles, forming parts of each instruction. The traditional PIC does 99% of instructions (the exceptions are calls and jumps), using four clock cycles per instruction. Quite a lot of things have defined which actual clock cycle they occur on. So (for instance), if you look at the 'instruction set summary' some instructions show 'what happens when'. BNC for example, for the 2550, has a little diagram showing that 'Q1' is 'decode' (work out what the instruction 'is'), Q2, is then reading the second byte (the distance to jump). Q3 is 'process' (calculate whether a jump is to occur), and Q4, is then either do nothing (no branch), or load the distance to the PC. If a jump occurs, the next four clocks are then 'nothing', while the hardware switches to addressing the new location.
This is only true for the PIC12, 16 & 19 families.
On chips like the PIC24 an 30, it changes. You have many with Fcy equalling Fosc/2, and some where there is a completely separate peripheral clock as well.
So, beware of assuming that a 20Mhz crystal means you are running at 20Mhz.... |
|
|
art
Joined: 21 May 2015 Posts: 181
|
|
Posted: Sun Dec 18, 2016 6:47 pm |
|
|
Thank you very much for your detail information.
I will take note.
Thanks again |
|
|
art
Joined: 21 May 2015 Posts: 181
|
|
Posted: Mon Dec 19, 2016 8:54 am |
|
|
Hi,
I've copy this program from year 2004 CCS forum.The code works well and the SIRC can be transmit to SONY TV.
There is a comment " ~3.2uS overhead " in the program. I would like to know how to get this figure and what does " ~3.2uS overhead" means ?.
Code: |
// Start pulse = 2.5mS
// Binary 1 = 1.2mS
// Binary 0 = 0.6mS
// 20-30mS pause between each transmission (packet)
void Send(int x){
int i;
for(i=0; i<x; i++)
{
output_high(PIN_B1);
delay_cycles(54); // ~10.8uS high @ 20MHz
output_low(PIN_B1);
delay_cycles(55); // ~11.0uS low. 21.8uS @ 20MHz
} // + ~3.2uS overhead = 25uS = 40kHz
{
delay_us(500); // 500uS delay between each data bit (40kHz burst)
}
}
void main() {
while (1){ // Modulate IR LED
//command = 19 (volume up)
send(96);// Header
send(48);//1
send(48);//1
send(24);//0
send(24);//0
send(48);//1
send(24);//0
send(24);//0
//device code = 1 (for tv)
send(48);//1
send(24);//0
send(24);//0
send(24);//0
send(24);//0
delay_ms(25); // 25mS delay between data packets
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Dec 19, 2016 8:58 am |
|
|
'overhead' proabably is the time it takes to get in and execute the function BUT that's NOT a complete program..so I'm kinda guessing as I do not know which PIC and what speed( clock) is.
To actually KNOW, you should read the PIC datasheet, the chapter on 'instruction set' to understand how to calculate the various timings.
You'' need to dump the listing as well...
This is very easy to do and understand.. kinda PIC101 stuff.
Jay |
|
|
art
Joined: 21 May 2015 Posts: 181
|
|
Posted: Mon Dec 19, 2016 9:09 am |
|
|
The code use PIC18F4550 and crystal 20MHz, #use delay(clock=2000000).
Can you please show me which part of the instruction set will explain the "overhead" terms. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 19, 2016 9:27 am |
|
|
Overhead is the ASM code necessary to execute the for() loop. Look at
the .LST file to see it. At 20 MHz, the PIC executes about 5 instructions
per usec. Some instructions take two cycles so that's not an exact
number. But anyway, 3.2 usec would mean 16 instruction cycles to
execute the for() loop. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Mon Dec 19, 2016 9:34 am |
|
|
First, 'i' has to be fetched. Then compared with x (this has to be fetched and subtracted). Then i has to incremented and saved, and the code has to jump back to the start if the comparison was '<'. Then in fact your I/O instructions are each actually three instructions (unless you are using 'fast_io', the compiler will set the TRIS for each output).
This is why the chip has hardware programmable PWM outputs. Program the PWM to generate 40KHz, and just enable it for the time required. Accurate without any fiddling.
It's worth also realising that different ways of coding will give different overheads:
Code: |
int i, x;
x=40;
for (i=0;i<x;i++)
delay_cycles(1);
for (i=x;--i;)
delay_cycles(1);
|
The first takes 7 instructions to go round the loop. The second just 5 (both including the one instruction in the delay). Difference is that on the second, only 'i' has to be accessed each time. |
|
|
|