PIC18F4550 Tutorial: Blink LED - 2
Hi welcome to my 4th chapter of PIC18F4550 programming. Here we are going to learn another methodology or technique for programming a pic18f microcontroller which would be helpful in future while dealing with complex coding. We are going to define our own header file. We are also going to see the Source Code and will understand the importance, benefits of programming a microcontroller this way on Mplab ide. In Chapter3, we saw the basic programming template for pic18f4550 which is a very common style of programming. In this programming tutorial we are going to breakdown the same source code into some header files to make things simple.
In our previous chapter on pic18f4550 programming we did all the coding in just one file main.c for blinking an LED with pic18f4550 which is a very common method adapted by many beginners. However here we are going to break down the same program and define our own header file. For our example we are going to use the same old example of blinking an LED. This strategy of programming helps in long run for beginners.
Why do we need to define an external header file?
For a simple example of blinking or flashing an led it is pretty much okay to code everything in one file main.c. But in future when you are dealing with complex coding functions and logics, things might get messy if all the coding is done in just one file. Rather sometimes it becomes difficult for even the actual programmer to find their own mistakes, or to makes changes if some coding needs to be modified after a couple of months. Hence dividing things makes it easy for keeping the track of code blocks.
For example, the source code in our previous tutorial started with a general programming style where you have the includes in the beginning (#include<p18f4550.h>), and then followed by lengthy Compiler directives (#pragma config) to set the chip configuration bits.
Instead of writing the lengthy chip config bits in the main.c, you can create a separate header file with headername.h and then write all the compiler directives in the header file headername.h. Finally include it the main.c like the regular #includes in the beginning of the code. A typical user created header include syntax would look like..
#include "headername.h" //User defined header
While executing the main.c all the compiler directives will be parsed by the compiler defined inside #include " headername.h”, In future if you want to change some settings in the chip config bits when without touching the main.c you could directly open the respective header file and make changes.
Creating a Header file
-Create a new file.
-Type the compiler directives in the new file created.
-Save the file with a name and extension “.h”. Example: headername.h
-Check mark “Add File to project” >> Hit save.
If everything goes well the then you would see your created header file included in the Project Explorer under “Header Files” , if its not showing then probably while saving the file you forgot to check mark “Add to Project Files”.
-Open main.c and add the line #include " headername.h ".
By this way you can create your own header files with codes such as compiler directives, timers or port settings and have them included in the main block. The functions defined inside the header files can be also called from main. This strategy would keep the main.c block clean and would also be easy to makes changes with coding in the future. Instead of messing with entire coding you can specifically reach the section you wish to make changes.
Let’s review the schematic and the source code for a example below.
Schematic
In our previous Tutorial we made two LED's to blink. Here we are going to blink four led's on port B , RB0, RB1, RB2 and RB3 . Here is a sample schematic. The circuit can be easily built on a breadboard in no time.
Source Code: Blinking led Method 2 with header Files
The source code below will blink the led the same way as in previous tutorial, but here I have defined two header files compdirectives.h and ledsettings.h. compdirectives.h contains all the Chip configuration settings And ledsettings.h has all the necessary port settings and timers for blinking the led.
SOURCE CODE : main.c
/* ****************** main.c ****************** */
#include<p18f4550.h> // Include Header for PIC18F4550
#include "compdirectives.h" // User defined header: Chip Config | Complier directive
#include "ledsettings.h" // Port settings
/* *************** TIMER *************** */
void delayzz(void)
{ int i, j;
for(i=0;i<5000;i++)
{ for(j=0;j<2;j++)
{ /* Well its Just a Timer */ } } }
/* ****************** MAIN ****************** */
void main(void)
{
setpin(); // PORT B Setting: Set all the pins in port B to Output
while(1)
{
LED1_on(); // Glow led 1
LED2_off(); // OFF led 2
LED3_on(); // Glow Led 3
LED4_off(); // OFF led 4
delayzz();
LED1_off(); // OFF led 1
LED2_on(); // Glow led 2
LED3_off(); // OFF led 3
LED4_on(); // GLow led 4
delayzz();
}
}
/* THE END */
DOWNLOAD main.c or the entire project file at the end of this tutorial.
SOURCE CODE : ledsettings.h
/* ****************** ledsettings.h ****************** */
//LED settings
#define setpin() TRISB = 0; //Setting all PORTB pins to output pin RB0-7
#define LD1 LATBbits.LATB0 // RB0
#define LD2 LATBbits.LATB1 // RB1
#define LD3 LATBbits.LATB2 // RB2
#define LD4 LATBbits.LATB3 // RB3
#define LED1_on() LD1 = 1; // High
#define LED2_on() LD2 = 1; // High
#define LED3_on() LD3 = 1; // High
#define LED4_on() LD4 = 1; // High
#define LED1_off() LD1 = 0; // Low
#define LED2_off() LD2 = 0; // Low
#define LED3_off() LD3 = 0; // Low
#define LED4_off() LD4 = 0; // Low
DOWNLOAD ledsettings.h or the entire project file at the end of this tutorial.
SOURCE CODE : Compdirectives.h
/* ****************** compdirectives.h ****************** */
#pragma config VREGEN = OFF // Voltage regulator USB , is Suspended
#pragma config WDT = OFF // Watchdog timer is suspended
#pragma config PLLDIV = 5 // Internal Oscillator engaged
#pragma config MCLRE = OFF
#pragma config WDTPS = 32768
#pragma config CCP2MX = ON
#pragma config PBADEN = OFF
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2
#pragma config FOSC = INTOSCIO_EC
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = OFF
#pragma config BORV = 3
#pragma config LPT1OSC = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF // CPB off
#pragma config CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTC = OFF
#pragma config WRTB = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF
#pragma config EBTRB = OFF
DOWNLOAD compdirectives.h or the entire project file at the end of this tutotial.
Here for instance if you wish to make changes with the Port settings, and led configuration then instead of searching for specific line of code in main.c , you could directly open the ledsettings.h and make changes without touching main.c much. Rather by this approach your main.c looks neat and clean much more understandable.
As shown in the code above you can also define your own names according to your understanding for some blocks of code. For example: For blinking an led on RB0 the usual way is LATBbits.LATB0=1; For your understanding you can pretty well define it with some name you want, something like #define LED1_on() LATBbits.LATB0=1; , so now from main block you can call the function LED1_on(); which would execute LATBbits.LATB0=1; which is to set the pin RB0 to high and resulting in glowing the led.
NOTE: I would strongly suggest to place a comment line with your liberty of understanding next to important sections of code while you are learning programming. It not only helps others who read your code to understand its content but helps you a lot when you see the code after a few weeks yourself.