Understanding timing and delays on the PIC18F4620

One of the most important things to understand when programming a microcontroller is how the timing works. It’s slightly different on each device, but the fundamentals are generally more or less the same. In this post, I will describe the timing on the PIC18F4620 microcontroller.

The basic unit of time in every program that runs on a PIC18F4620 is the instruction cycle, which is the time taken to execute one machine code instruction. Every microprocessor uses a clock signal (basically a square wave signal) to pace its operation. Different processor architectures require a different number of clock cycles to perform each machine code instruction. The PIC18F4620 (like many other PIC microcontrollers) performs one machine code instruction every four clock cycles.

When the clock signal is provided by the PIC’s internal RC oscillator, and assuming the oscillator frequency (Tosc) is not changed from its default value of 1MHz, then the clock period (Tosc) is 1us and the instruction cycle (Tcy) is 4μs.

The PIC18F4620 can use a very wide range of clock frequencies. Typical values range from tens of kHz to tens of MHz. The clock signal is often provided by the internal RC oscillator, which requires no additional hardware components, and which can be configured to run at a range of frequencies (the default is 1MHz). However, an external clock source can also be used. If precision timing is a priority, an external crystal oscillator is often used. In simple terms, the choice of clock speed boils down to a trade-off between computing power and energy efficiency. When the PIC runs at a higher clock speed it performs more computations per second, but it also consumes more power.

The instruction cycle is the basic unit of time in every PIC program – all other time delays are measured in multiples of it. When you’re writing a PIC program, you should therefore usually have this figure in mind. PIC microcontrollers provide a number of built-in hardware timers that can be used for calling functions repeatedly at fixed intervals or for generating periodic waveforms. However, the simplest thing you can do once you know the instruction cycle is to calculate fixed length delays.

Let’s look at a couple of examples using the function Delay10KTCYx(), which allows the programmer to specify a time delay in multiples of 10,000 instruction cycles. This function, which is provided with the C18 compiler, is defined in the header file “delays.h”. (Note that the newer XC8 compiler provides a simpler function called _delay() which specifies a delay as a multiple of the instruction cycle.)

The function name Delay10KTCYx() is a bit of a mouthful, so let’s begin by breaking it down:

  • "Delay": This function is used to create a delay of a fixed duration.
  • "10K": Ten thousand.
  • "TCY": The instruction cycle, Tcy.
  • "x": multiplied by the argument (the number specified in the bracket).

So the duration of the delay produced is the number in brackets multipled by 10,000 instruction cycles. The number in brackets must be an 8-bit unsigned integer value (i.e. a whole number in the range 0-255). Note that there are also functions called Delay1TCY(), Delay10TCYX(), Delay100TCYx(), and Delay1KTCYx() for specifying shorter delays with greater precision.

Example 1: Flash LED

In this example, an LED connected to RD0 toggles on or off once every second. Here’s the C code:

//
// PIC18F4620 delay example 1
// Written by Ted Burke
// Last update 26-3-2013
//
 
#include <18f45620.h>
#include <delays.h>
 
#pragma config OSC=INTIO67,MCLRE=OFF,WDT=OFF,LVP=OFF,BOREN=OFF
 
int main(void)
{
    // Make RD0 a digital output
    TRISD = 0b11111110;
    
    // Toggle an LED on RD0 once per second
    while(1)
    {
        LATDbits.LATD0 = 1 - LATDbits.LATD0; // Toggle RD0
        Delay10KTCYx(200);                   // 1 second delay
    }
}

Explanation

The configuration option “OSC=INTIO67” specifies that the internal RC oscillator will be used and that pins RA6 and RA7 are available to be used as normal input/output pins (these pins can be used to connect an external clock source when the internal RC oscillator is not used).

Since the clock oscillator frequency (Fosc) has not been changed from its default value,

F_{osc} = 1\mathrm{MHz}

and

T_{osc} = 1\mathrm{\mu s}

In the PIC18F4620, the instruction cycle (Tcy) is always four times the clock cycle:

T_{cy} = 4 \times T_{osc} = 4\mathrm{\mu s}

The function Delay10KTCYx() specifies a delay in multiples of 10,000 instruction cycles which in this case means multiples of 40ms.

The line “Delay10KTCYx(25)” specified a delay of the following duration:

T_{delay} = 25 \times 10000 \times T_{cy} = 1 \textrm{ second}

So the LED toggles once per second.

Example 2: Guitar tuning guide

This example concerns the generation of a 110Hz audio signal as a guitar tuning guide. A small speaker connected to RD0 is driven with a square wave signal with a frequency of 110Hz to produce a musical tone with the same pitch as the “A” string on a guitar. As in the previous example, the internal RC oscillator is used, but this time its frequency is modified by writing a value into the OSCCON register.

//
// PIC18F4620 delay example 1
// Written by Ted Burke
// Last update 26-3-2013
//
 
#include <18f45620.h>
#include <delays.h>
 
#pragma config OSC=INTIO67,MCLRE=OFF,WDT=OFF,LVP=OFF,BOREN=OFF
 
int main(void)
{
    // Set Fosc to 8MHz
    OSCCON = 0b0111000;
    
    // Make RD0 a digital output
    TRISD = 0b11111110;
    
    // Generate 110Hz square wave on RD0
    while(1)
    {
        LATDbits.LATD0 = 1 - LATDbits.LATD0; // Toggle RD0
        Delay1KTCYx(9); // 4.5ms delay
        Delay10TCY(9);  // 45us delay
    }
}

Explanation

As in the previous example, the configuration option “OSC=INTIO67” selects the internal RC oscillator.

As explained in Section 2.7.1 of the PIC18F4620 datasheet, the following line sets the oscillator frequency to 8MHz:

OSCCON = 0b01110000;

Therefore,

F_{osc} = 8 \mathrm{ MHz}

and

T_{osc} = 125 \mathrm{ ns}

The instruction cycle is therefore

T_{cy} = 4 \times T_{osc} = 0.5 \mathrm{ \mu s}

The function Delay1KTCYx() specifies a delay as a multiple of 1000 instruction cycles. The line “Delay1KTCYx(9);” therefore generates a delay of the following duration:

T_{1} = 9 \times 1000 \times T_{cy} = 4.5 \mathrm{ ms}

The function Delay10TCYx() specifies a delay as a multiple of 10 instruction cycles. The line “Delay10TCYx(9);” therefore generates a delay of the following duration:

T_{2} = 9 \times 10 \times T_{cy} = 45 \mathrm{ \mu s}

The total delay is therefore

T_{delay} = T_{1} + T_{2} = 4.545 \mathrm{ ms}

The period of the resulting waveform is twice the length of this delay value since the signal remains high for half of each cycle and low for the other half. Hence,

\textrm{waveform frequency } = \frac{1}{2 \times T_{delay}} = 110 \mathrm{ Hz}

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

6 Responses to Understanding timing and delays on the PIC18F4620

  1. Patrick Demke says:

    ‘The PIC18F4620 (like many other PIC microcontrollers) performs one machine code instruction every four clock cycles.’

    Where do I / where do you pick up this information? I can’t find this information in the datasheet (http://ww1.microchip.com/downloads/en/DeviceDoc/39626e.pdf), nor on the microchip homepage (http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010304).

    • batchloaf says:

      Hi Patrick,

      Well, it could certainly be clearer in the datasheet! It’s kind of hard to work out where exactly they say it, but check out section 5.2 of the datasheet:

      http://ww1.microchip.com/downloads/en/DeviceDoc/39626e.pdf

      As they say there, “An ‘Instruction Cycle’ consists of four Q cycles”. You can see in the diagram just after that how the instruction cycle corresponds to four oscillator cycles.

      Also, in Table 17-3 on page 187, you can see that Fcy (the instruction frequency) is always one quarter of the value of Fosc (the oscillator frequency).

      Ted

      • Patrick Demke says:

        Hi Ted,

        thank you for those hints! In my opinion, this is such an important and general information/property of an uC, that it should be more clearly, easily visible/pointed out. This should be noted on the first overview page, (page 3 in the datasheet here), along with the microcontroller features, or at least on page 9 in the device overview and not (at least not only) within the Memory organization. Something like Tcy = 4 * Tosc would be clear to grasp…. this is my opinion at least, but maybe I am just not yet used enough to work with uCs…

        Further I am not yet 100% sure how to map this with the property of the CPU speed (Up to 10 MIPS Performance at 3V) found ont the website.

        I am actually working with/studying the PIC24FJ128GA010 (http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en024805). There in the datasheet (http://ww1.microchip.com/downloads/en/DeviceDoc/39747F.pdf) the following is said on the very first page: Up to 16 MIPS Operation @ 32 MHz.. Out of this, I read that, one Instruction (cycle) needs 2 oscillator cycles (Tcy = 2 * Tosc), right? This is also mention sometimes in the datasheet (like ‘Note 1: Based on TCY = TOSC* 2; Doze mode and PLL are disabled.’). Later in Section 3 (CPU) the following is stated: ‘All instructions execute in a single cycle, with the exception of instructions that change the program flow, […]’. But I guess strong, that is related to an instruction cycle, not to an oscillator cycle.

        For further understandings: If I choose the oscillator setup (with the PIC24) to be 8MHz with use of the 4xPLL option resulting in 32MHz, the result will be 16MIPS. With a configuration without the 4xPLL otption for example, it would be a 8MHz f_osc resulting in 4MIPS, right?

        Again thanks for your time and help, and I am looking forward for an answer šŸ™‚

        Kind regards, Patrick

      • batchloaf says:

        Hi Patrick,

        I agree that it’s something which could usefully be stated in a clearer way in the datasheet. In the past, I’ve been caught out by this when using some PICs with which I was less familiar. I simply assumed that they all had Tcy = 4 * Tosc, but then discovered to my surprise that some of them have Tcy = 2 * Tosc, as seems to be the case with your PIC24FJ128GA010 (not a very catchy name!).

        One thing that’s for sure is that no instruction can execute in less than 1 instruction cycle (Tcy). Also, the instruction cycle can never be shorter than the oscillator cycle. In fact, for every PIC I’ve worked with, the instruction cycle has either been Tcy=2*Tosc or Tcy=4*Tosc. For a given chip, this relationship between Tosc and Tcy is fixed and cannot change. Even if there are PICs for which Tcy is not 2*Tosc or 4*Tosc, the instruction cycle can never be shorter than Tosc.

        To answer your question about the oscillator setup on the PIC24FJ128GA010, as I understand it Tcy=2*Tosc and if you therefore use the internal 8MHz oscillator with the 4xPLL multiplier, resulting in Fosc=32MHz, you will achieve 16 MIPS. Also, as you said, without the 4xPLL you would only get 4 MIPS.

        Finally, I couldn’t find that claim you mentioned about the “10 MIPS performance at 3V”. Was that for a dsPIC30F or the PIC24FJ128GA010? I do know that the maximum achievable Fosc is lower for these microcontrollers when you reduce the supply voltage, so it sounds like whatever chip you’re talking about has a maximum Fosc of either 20MHz or 40MHz at 3V (depending whether Tcy=2*Tosc or Tcy=4*Tosc).

        Ted

  2. Patrick Demke says:

    Hi Ted,

    thank you again for your notes and the confirmations. I get more self-confident šŸ™‚

    The ’10 MIPS performance at 3V’ is listet as a feature of the PIC18F4620 you described obove (http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010304). In comparison to the PIC24FJ128GA010 datasheet (which tells ‘ Up to 16 MIPS Operation @ 32 MHz’), I could not get out the ratio of Tcy to Tosc from this info. But, there are other places in the datasheet to get this ratio, as you pointed out.

    So, your post/recipe and your answers helped me a lot, thank you very much!

    Kind regards, Patrick

    • batchloaf says:

      Hi Patrick,

      I think that ’10 MIPS performance at 3V’ refers to the fact that the 18F4620 can run as high as Fosc=40MHz when an external clock is used. For example, I think you could use a 10MHz crystal with 4xPLL to achieve 10 MIPS. I don’t think it’s achievable using only the internal oscillator though.

      Anyway, best of luck getting whatever you’re working on done!

      Ted

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s