Simple problem, yet I do a lot of readings before I successfully compile the led blinking (with 1 second delay).
The first problem is setting the system clock. And the second problem is using the C18 default delay routine.
The PIC18f4550/PIC18f4553 has three clock blocks which are primary oscillator, secondary oscillator, and internal oscillator.
The primary oscillator is normally used for high speed oscillator (>=4MHz), secondary oscillator for low speed oscillator such as 32.768kHz. Internal oscillator has two different clock signals; main output is an 8 MHz clock source and second clock source is the internal RC oscillator provides a nominal 31 kHz output.
Primary oscillator has 4 modes which are HS, HSPLL, XT, XTPLL. Depending of frequency of oscillator, suitable mode need to be assigned as shown as table below:
Resonators Freq
|
Mode
|
4.0MHz
|
XT
|
8.0MHz/16.0MHz
|
HS
|
Crystal Freq
|
Mode
|
4.0MHz
|
XT
|
4.0MHz/8.0MHz/20.0MHz
|
HS
|
For some projects, MCU doesnt need to operate at high speed, config CPUDIV can be used to scale the operating frequency into lower speed.
For some applications that require high speed clock, MICROCHIP provides PLL (phase locked loop) function, it is a frequency multiplier to generate a fixed 96MHz from a fixed 4MHz input. On top of that, a PLLDIV is assigned to divide the oscillator frequency to 4MHz which enable the adoption of oscillator with various frequency range.
The PIC18f's maximum allowable frequency is 48MHz, so after the PLL the 96MHz is divided into half to suit the MCU operating frequency.
The overall setting for CPU frequency is as follow:
1: #pragma config PLLDIV = 5 // (20 MHz crystal)
2: #pragma config CPUDIV = OSC1_PLL2 // Divide 96MHz with two
3: #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
4: #pragma config FOSC = HSPLL_HS // HS oscillator, PLL enabled (HSPLL)
For more information on setting, open the mplab, go to Help->Topics...->PIC18 Config Settings. From there, choose selected microcontroller, and all settings are listed and explained.
........................................................................................................................................
For PIC18f4553/4550, maximum CPU Speed is 48 MHz (12 MIPS) which means at CPU operating frequency of 48 MHz, it is able to run 12 millions instruction per second. So one instruction need 4 cycles to process.
In order to have one second delay, you need to do nothing for 12 millions instruction time.
For one micro second delay, 12 instructions of _do_nothing are needed. Which in turn, two micro second delay, 24 (12x2) instructions of _do_nothing are needed.
Microchip c18 provides <delays.h> library to help set the timing, the <delays.h> is located at
"C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\delays.h"
I wrote my own routine on top on <delays.h> and name it as "delay.h"
For one micro second -
#define delay1MicroSecond() {Delay10TCYx(1); Delay1TCY(); Delay1TCY();}
// delay 12 instructions
#define delay10MicroSecond() Delay10TCYx(12) // delay 120 instructions
#define delay1MiliSecond() Delay1KTCYx(12) //delay 12000 instructions
#define delay100MiliSecond() Delay10KTCYx(120) //delay 1,200,000 instructions
#define delay200MiliSecond() Delay10KTCYx(240) //delay 2,400,000 instructions
All delay routines are in the multiplication of 12 (provided that the CPU operating frequency is 48MHz).
For other CPU frequency, scaling is needed to get the correct timing.
Examples:
48MHz = 12 MIPS // for one micro second, delay 12 instructions
32MHz = 9 MIPS // for one micro second, delay 9 instructions
24MHz = 6 MIPS // for one micro second, delay 6 instructions
16MHz = 3 MIPS // for one micro second, delay 3 instructions
To blink led,
the pic18f has one general rule to read/write IO - read from port and write to latch.
First set the IO pin to output,
#define mInitAllLEDs() TRISBbits.TRISB6=0; TRISBbits.TRISB7=0; //define output
//pic18f rule for input/output is
//0 = output;
//1 = input;
#define mLED_1 LATBbits.LATB6 // write to particular bit (pin b6)
#define mLED_2 LATBbits.LATB7 // write to particular bit (pin b7)
// to on led just assigned mLED_1 = 1;
// to off led just assigned mLED_1 = 0;
..............................................................................................................................................
Now you can start with blinking led, all the source codes can be downloaded at github.