In the simple tutorial we are going to blink few simple led with PIC18F microcontroller, using an external 20MHz crystal oscillator and the ‘__Delay ()’ function of XC8 Compiler. Most of the previous tutorials here dealt with internal oscillator of pic18F4550 where mostly the delays were generated with simple for loops. However those who wish to directly use the default __delay function, it becomes an instant pain as the __Delay () function no longer accepts the variable data unlike the old C18 Compiler.
This simple tutorial is made on few requests and queries I recently received through mails, regarding the delay problems in xc8 compiler, along with configuration of the compiler directives used by pic18F4550 when it comes to using external oscillator. Hence I decided to put it together as tutorial to blink a simple led using external 20 MHZ Crystal oscillator on pic18F4550 with XC8 compiler and Mplab x ide
The 20 MHz crystal oscillator is interfaced with two 22p capacitor as explained in the oscillator section in the pic18F4550 datasheet. Please download the latest version of datasheet for pic18F4550 from the microchip website. A 0.1u cap is also added close to microcontroller.
The basic logic is to turn the led on and then turn off by setting registers, with some good delay in-between them, enough to catch the effect by human eye. There are many ways to generate such delays, such as using delays.h, making your own delay loops, etc.
The theory goes as, if you want to use xc8 delay function then you have include delays.h as a header (preprocessor) and then include __delay_us(); or __delay_ms(); (with double underscore) anywhere you wish to include a delay, with your desired constant value of delay such as ” __delay_ms(500);” which theoretically sounds simple , unlike my methods in previous tutorials where I have always generated delays in the code with simple “for loops”, enclosed within in a function prototype, which could be called anytime you wish to generate a delay in the main() code.
However if you wish to generate the delays in the code with like c18 Compiler, then you have certain limitations with xc8 compiler such as, limit of delays value and inability to assign a variable to delay function. For example __delays_ms(a) where int a is a variable (say the value generated by an ADC ). This is not possible with the new xc8 compiler to define variable delay value “directly”.
Variable delay value issue can be solved by creating a loop, and inclosing the __delay_ms or __delay_us function inside the loop. The number of cycles you would wish to call the loop with delay function in it can be a variable.
Another limitation is the value of the delay. The code I wrote below generates a delay of approximately 200ms, where for 20 MHz I have defined _XTAL_FREQ 20000000UL. Please note that XTAL_FREQ doesn’t really sets the frequency of the hardware, but it’s still required for __delay_ms. If you directly write the milliseconds values as __delay_ms(200); then immediately the compiler would throw an error on compiling the code. For the code below, the xc8 compiler doesn’t want to accept the ms value greater than 39. Hence creating for loop again can be helpful when the ms value can’t be more then 39 for _XTAL_FREQ 20000000UL.
For more detail: Blink LED with XC8 compiler using external Oscillator