16th November 2009

Tutorial 4 – “Hello World” Program in C

posted in 18F4550 C Tutorial |

Tutorial Goal: Create and test a simple C program

Since the assembly tutorials went up, I’ve had a large number of requests for PIC18F tutorials in C. In this tutorial, I will explain the basics of PIC18F C programming and provide simple sample code for a blinking LED, similar to tutorial 2. If I receive positive feedback, more tutorials will follow. This tutorial assumes minimal understanding of C programming.

I will be working with the following until further notice:

The installation procedure is as follows:

  • Install MPLAB IDE. The default settings should be fine. Hi-Tech C may or may not be covered in future tutorials, but installing it does not take much space.
  • Install MPLAB C compiler (C18).Most of the default settings should be fine, but make sure to select the “Update MPLAB IDE to use this MPLAB C18” installer option.
  • Start MPLAB IDE (Start -> All Programs -> Microchip -> MPLAB IDE v8.40 -> MPLAB IDE).
    • Make sure the project and output windows are open in the IDE by going to the view menu and clicking the appropriate options.
    • Select your microcontroller in the Configure -> Select Device menu. This area will also show you all the compatible programmers for that device.
    • Select the programmer by clicking Programmer -> Select Programmer.
      • If your programmer is plugged in, it should display an initialization routine in the output console.
      • You may also need to upgrade the firmware on it.

Your overall setup should look like this:

Now it’s time to start a new Project:

  • Click Project -> Project Wizard
  • Select your device on page 2, if it isn’t already selected
  • On page 3, select Microchip C18 Toolsuite. If any items in Toolsuite Contents have a red X, select them and click Browse. The default locations for the files are:
    1. MPASM Assembler – C:\MCC18\mpasm\mpasmwin.exe
    2. MPLINK Object Linker – C:\MCC18\bin\mplink.exe (Make sure you do not select _mplink.exe)
    3. MPLAB C18 Compiler – C:\MCC18\bin\mcc18.exe
    4. MPLIB Librarian – C:\MCC18\bin\mplib.exe
  • On page 4, click Browse and select the name and location of your new project (example: My Documents\PIC\tutorial4\tutorial4.mcp)
  • Do not add any existing files to the project since this project will be made from scratch
  • Once the project is created, you should be able to see the empty project folders in the project window

Open a file, add the header file for your PIC and save it: Click File -> New.
Add the line

#include <p18f4550.h>

with the appropriate include file for your microcontroller.

The C18 compiler provides a header file with definitions for ports and pins for each microcontroller it supports. The default directory for these files is C:\MCC18\h . For example, the 18F4550 file includes the following code:

extern volatile near unsigned char       PORTB;
extern volatile near union {
  struct {
    unsigned RB0:1;
    unsigned RB1:1;
    unsigned RB2:1;
    unsigned RB3:1;
    unsigned RB4:1;
    unsigned RB5:1;
    unsigned RB6:1;
    unsigned RB7:1;
  struct {
    unsigned INT0:1;
    unsigned INT1:1;
    unsigned INT2:1;
  struct {
    unsigned :5;
    unsigned PGM:1;
    unsigned PGC:1;
    unsigned PGD:1;
} PORTBbits;

This code shows the various ways of addressing PORT B pins. For example, they can be addressed as a byte by PORTB, or as individual pins by the union PORTBbits using PORTBbits.RB0 through PORTBbits.RB7. When set up as interrupts, pins 0-2 should be accessed as PORTBbits.INT0 through PORTBbits.INT2.

After adding the include line to the new file, it is time to save it. Click File -> Save and save it in the project folder (it will be saved as main.c for this tutorial). Then, either check “Add File to Project” at the bottom of the save screen or add this file to your project by right clicking Source Files in the Project window and clicking Add Files.

Add an empty main function to your project to make main.c look like this:

#include <p18f4550.h>

void main()


Now is a good time to try to build the project. Click Project -> Build All. In the Output window, it will say BUILD FAILED. If you scroll up, you will see that the reason for the error is:

main.c:1:Error [1027] unable to locate 'p18f4550.h'

To fix this error, the include directory for the project must be specified. To do this, click Project -> Build Options -> Project. Click the Directories tab and select “Include Search Path” from the drop-down menu. Add the include directory by clicking New, then the ellipsis. The default directory for the header files, as mentioned above, is C:\MCC18\h. Also, make sure to specify the Library Search Path (default: C:\MCC18\lib) and the Linker-Script Search Path (default: C:\MCC18\bin\LKR). Now, building should return BUILD SUCCEEDED.

Next, we will configure the microcontroller. Several very useful documents are included with C18 to facilitate the learning process. By default, these files can be found in C:\MCC18\doc. The following files are included with C18 V3.34:

  • hlpC18Lib – An overview of the MPLAB C18 library files and functions that can be included in an application. These files can be divided into 3 sections:
    • Peripherals
      • Character LCDs
      • CAN bus
      • I2C
      • SPI
      • UART
    • General
      • Character Classification (ex: isalpha(), isupper(), isprint())
      • Data Conversion (ex: atoi(), itoa(), rand())
      • Memory and String Manupulation (ex: memset(), strcpy(), memcpyram2pgm())
      • Delay (ex: Delay1TCY() – 1 cycle delay, Delay10KTCYx() – delay for multiples of 10K cycles)
      • Reset (ex: isBOR(), isMCLR() – find out cause of reset)
      • Character Output (ex: sprintf(), usart_putc())
    • Math Libraries (ex: sin(), cos(), log())
  • hlpC18ug – The technical details of the C18 compiler, including data types, pragmas, memory models, etc. This is very useful to really understand what you are doing.
  • hlpCOFFfile – Describes the format of the executable file created by the compiler
  • hlpPIC18ConfigSet – Describes the configuration settings (using #pragma config) for all supported microcontrollers. We will be looking at this file.
  • MPLAB-C18-Getting-Started_51295f – A guide to getting started with C18. A highly recommended read.
  • PIC18F Peripheral Library Help Document – Describes the peripheral library for all supported microcontrollers. To view the library details, select the appropriate family and device, then click “CLICK HERE for the Peripheral Library Support Details for this Device”

Open hlpPIC18ConfigSet.chm and find PIC18F4550 (or your respective microcontroller). This document lists all the configuration settings available for it. Right now, we will only configure the ones necessary for this tutorial to work. First and most important are the Oscillator Selection bits. Without this, the microcontroller will do nothing. To set the microcontroller to use the internal oscillator (1MHz or 250,000 instructions/second since each instruction takes 4 cycles), add the following code directly after the include directives:

#pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB 

The watchdog timer also needs to be disabled. Config values can be written one per line or separated by commas. For the sake of clarity, they will be listed on separate lines in this tutorial. To disable the WDT, add the following line:

#pragma config WDT = OFF //Disable watchdog timer

The physical setup is similar to the one in Tutorial 2:
Tutorial Setup - LED with 1KOhm resistor
5V — 1KOhm — LED — (20)

According to the 18F4550 Datasheet, pin 20 is PORT D Pin 1.

The datasheet states that each port has three registers for its operation. These registers are:

  • TRIS register (data direction register 0 – output, 1 – input)
  • PORT register(reads the levels on the pins of the device)
  • LAT register(output latch)

In other words, use the PORT register for input operations, the LAT register for output operations and the TRIS register to select between input and ouput on each individual pin. To control an LED using PORT D Pin 1, it will first be set to output using the TRIS register and then be toggled on and off using the LAT register.

A #define statement can make the code much more readable. Add these lines after the #pragma config statements:

#define LEDPin LATDbits.LATD1 //Define LEDPin as PORT D Pin 1
#define LEDTris TRISDbits.TRISD1 //Define LEDTris as TRISD Pin 1

In main, make PORT D Pin 1 an output and set it HIGH:

LEDTris = 0;//Set LED Pin data direction to OUTPUT
LEDPin = 1;//Set LED Pin

The last step is to add a loop that toggles the pin at an interval:

    LEDPin = ~LEDPin;//Toggle LED Pin
    Delay10KTCYx(25);//Delay 250K cycles (1 second at 1MHz since each instruction takes 4 cycles)

The Delay10KTCx() function and other delay functions are documented in hlpC18Lib.chm in the C18 documentation directory (see above). You will need to add the following line to the top of your file:

#include <delays.h>

Now, you should be able to test it on the microcontroller:

  • Click Project -> Build All
  • Click Programmer -> Program
  • If the above two steps were successful, Click Programmer -> Release From Reset

You should now see your LED blinking on and off about once per second. Congratulations, you have completed this tutorial!

Blinking LED using a PIC 18F4550 microcontroller

Please provide feedback in the form below!

C file:main.c

This entry was posted on Monday, November 16th, 2009 at 2:05 am and is filed under 18F4550 C Tutorial. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

There are currently 72 responses to “Tutorial 4 – “Hello World” Program in C”

Why not let us know what you think by adding your own comment! Your opinion is as valid as anyone elses, so come on... let us know what you think.

  1. 1 On April 26th, 2012, ivan said:

    thanx for sharing dude!

  2. 2 On May 8th, 2012, dave said:

    the ccode you have above has to be modified for a pic18f458; it does not run as is. get syntax errors for LEDTris and LEDPin and unrecognized error for the #pragma config FOSC line.

  3. 3 On June 11th, 2012, Kaiser said:

    Thank you very much for your tremendous tutorials. Please keep this good work up and also update your tutorials by using IDE 3. I would have suffered this internship without your great work. Thank you again

  4. 4 On June 26th, 2012, Henrique said:

    Hello masters, I am hopeless!

    I created a simply program in C# for Timer0 that only works on Proteus simulation.
    It does not work on a real PIC18F4550.
    I thought that it was some problem with my PIC board, but this is not, because it is working fine.
    My PIC board is working when I write one program in C# that uses only the code delay_us(); I know that because I see it in my real osciloscope.

    Please help.

    #use delay(clock=8000000)

    void trata_t0()
    static boolean led;
    static boolean led1;
    static int conta;

    //reiniciar o timer 0 em 131 menos a contagem que ja passou
    //se já ocorreram 125 interrupções
    if (conta == 100)
    led = !led; //inverte o led
    led1 = !led1; //inverte o led

    void main()
    { //configura o timer 0 para clock interno e prescaler dividindo por 2
    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2|RTCC_8_BIT);// sets the internal clock as source
    //habilita interrupções
    enable_interrupts(global | int_timer0);
    while(true); //espera interrupção

  5. 5 On July 10th, 2012, Rajasekaran said:

    Hey !
    Thanks and it was helpful.

    I have a doubt, whether PICkit 2 is fine with 16F877A microcontrollers? I’m planning to buy one PICkit 2 if it works good with both 18F and 16F series of controllers.

  6. 6 On August 4th, 2012, mimiza said:

    Thank you, it was a very nice tutorial

  7. 7 On August 25th, 2012, Barani said:

    I tried making the whole port to function as output.For that i used

    “#define LEDPin LATD
    #define LEDTris TRISD
    LEDTris = 0x00;
    LEDPin = 0xFF;
    LEDPin = ~LEDPin;
    Can you plz tell what’s wrong in this and if so then what is the correct code for it?

  8. 8 On September 3rd, 2012, joel said:

    thanks for the help with defining a port bit. i am converting an lcd c program from 16f684 to 18f14k50. some of the syntax is a little different going from 16fxxx to 18fxxxx code. your example #define LEDPin LATDbits.LATD1 was very helpfull. i just changed it to #define RS LATCbits.LATC5. now the compiler runs without error

  9. 9 On September 19th, 2012, talat said:

    Thanks a lot. Great explanation.

  10. 10 On October 14th, 2012, Jannis said:

    just thanks for the great work :-)

  11. 11 On January 15th, 2013, Tânia said:

    Thanks a lot!!!!!!!!!!!!!!!
    This tutorial was very helpful for me! =D

  12. 12 On January 25th, 2013, fritzowski said:

    oh man, I’ve no idea how to thank you (ok I’ll donate)
    I took this pic because off his specs….but I didn’t got it running till now, in the meanwhile I changed to arduino but now new hope came up(looking at the blinking led….. :))
    thank you for your tutorial.


  13. 13 On February 20th, 2013, Ajinkya said:

    Thank alot!
    This is a best tutorial to start.
    But i am facing the problem in
    #pragma config FOSC = INTOSCIO_EC
    The error msg is
    ”Error [1224] configuration setting ‘FOSC’ not recognized”
    Plz help

  14. 14 On March 3rd, 2013, sayali said:

    Very useful tutorial.
    Keep up the good work!! all the best.

  15. 15 On March 15th, 2013, agniteja said:

    It was a tremendous tutorial for. I enjoyed reading it and applied on my own picmicro. Pl. post up regularly … and help us to get better.

    Loads of thanks

  16. 16 On March 25th, 2013, Andy said:

    Still useful years later with PICkit 3 and 18F4515! Your tutorial was of great help setting up MPLAB and compiler and stepping through basics of how C code and this PIC interact. Simply awesome – thank you.

  17. 17 On April 17th, 2013, Varun said:

    Thanks for the tutorial.
    When will you be publishing UART (using c18) tutorial.

  18. 18 On May 6th, 2013, BOIB said:

    thanks for the tuts

  19. 19 On September 19th, 2013, viju said:

    can you send me any example using pic18f4550 cdc code to print hello in lcd using usb

  20. 20 On October 14th, 2013, Bablu Saha said:

    Thanks for helping to begin a project

  21. 21 On November 4th, 2013, Mike Richardson said:

    Very good artical. Got me started. Using 44-pin demo board shipped with PICkit3, so had to find equivalent register names (for PIC18F45K20). Otherwise works fine.
    #pragma config FOSC = INTIO7 //Internal oscillator, CLKOUT on RA6
    #pragma config WDTEN = OFF //WDog off.

    Many thanks.

  22. 22 On December 26th, 2013, anny said:

    i am using P18f4550.i m little bit confuse regarding oscillator configuration. i am using internal oscillator without USB interfacing. can anybody tell me the configuration for oscillator

Leave a Reply

  • Sponsored Links

    November 2009
    M T W T F S S
    « Dec   Jul »
  • Donate