Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C

Programming the PIC Microcontroller in C using PIC C Lite

4.91/5 (18 votes)
16 Jan 2009GPL35 min read 2   3.6K  
In this article, I will show you how to program a PIC16F84 using C.

Introduction

Programming microcontrollers using assembly language is very frustrating and cumbersome, not to mention archaic. As time goes by, developers have started building compilers for high level languages, targeted specifically for microcontrollers. I use PICs personally, and there is quite a lot of resources for them. Even good basic compilers like MBasic exist, but I hate BASIC, so I won't even talk about it! I have tried building applications for the PIC16F84, a very popular microcontroller, with various compilers like CC5X, SDCC (this is Open Source), and PIC C from HiTech software. I have not yet used mikroC from Microchip, because I do not use higher PICs. Each of these has its own strong points and weak ones, but by far, the best compiler I would recommend is PIC C. There is a free Lite version from HiTech Software, and as expected, I would not expect anything less from a company that has its aim at specifically developing C compilers for PIC microcontrollers.

Background

As usual, for any beginner of any type of coding, there must always be that first "hello world" application! In microcontroller programming, this is most definitely flashing an LED on and off. We shall do this now.

I am using the HI-TIDE Integrated Development Environment with PIC C Pro (45 day trial). You can use PIC C Lite as well (it will produce a larger hex file because it does not have omniscient code generation). What's more? PIC C Lite easily integrates into Microchips MPLAB...so there you go...you have two free products.

SDCC has an IDE called DevMic (I think it's written in Delphi just like DevC++; they are so similar), and both are Open Source. But, let's reserve SDCC for some other time...I wouldn't say it's better for a beginner.

So, let's get some Zzzzt zzzt as the old CodeProject saying goes!!

The <htc.h> and <pic.h> contain standard definitions, and are never to be left out of any source file you are working with. Since we want the LED to delay a bit, we shall use a function DelayMs(int); this function only takes values up to 255. This number indicates the number of milliseconds for which you want the LED to be on or off. Furthermore, you will have to declare which port, or more specifically, which pins are outputs and which ones are inputs. PortB has 8 ports from RB0-RB7, and is bidirectional (any pin can be an input or an output). PortA has pins from RA0-RA5, and is also bidirectional. However, only RB4 to RB7 can be configured as interrupts. We shall see later what an interrupt is. Your code should look like this in the editor:

#include <htc.h>
#include <pic.h>
#include <delay.c>

main()
{
    TRISB=0; // declare portb as outpot
    
    for(;;)  // do forever
    {
        RB0=1;    // LED ON
        DelayMs(250);  // delay for 0.25 seconds
        RB0=0;      // LED OFF
        DelayMs(250);
    }
}

Get the formed HEX file and load it into the microcontroller (I am assuming you know how to do this). Please remember that we are using a PIC16F84. If you are using another type, then you will have to specify this detail when making your project. HI TIDE even enables you to adapt your source code for any type of PIC anytime, even as you work with your project.

The PIC has a maximum source current of 25mA (I have measured currents of up to 26.3mA some times), and this is enough to drive LEDs directly. So, if you connect your LED to the RB0 pin and ground, you should see it flashing at a quarter of a second. Please remember that an LED is a p-n junction, so you must have your connection right (in short, if one orientation doesn't work, the second should!!!).

Interfering with normal operation

Always, in microprocessors and microcontrollers, we want the device to control multiple things, and react differently according to different situations. In other words, let there be sequence1 in a normal operation; when such and such a thing happens, activate sequence2. Normally, this would be called an “interrupt sequence”, but to avoid criticism from more experienced programmers (interrupt sequences must reside in their own code space within the program, and directly cause the execution of the main routine to change), let us just call it “interfering with normal operation”!

There are two ways to do this in C. One is to use if statements, and another is to use a while statement. I hate while loops, so we shall stick to "if".

We are going to modify our code a little, and even add an extra function so that we can specify our "delay" in decimals of seconds instead of being limited to milliseconds (moreover 255!).

So, let us create another project in HITIDE or MPLAB, and insert this code. It is called Interrupt.c in my uploaded source code.

#include <htc.h>
#include <pic.h>
#include <delay.c>

int j;// general global variables I will use

void Wait_These_Seconds(float s)// only to 3 decimals
{
    int milli_Equiv;  // milli second equivalent integer
    milli_Equiv=1000*s;
    for(j=1;j<=milli_Equiv;j++)
    {
        DelayMs(1);
    }
} 
   
main()
{
    TRISB=0xF0; // RB4:RB7 are input ; 11110000 in binary
    for(;;)
    {
 
        if(RB7==1)
        {
            RB0=1;    // LED ON
            Wait_These_Seconds(1.8);  // delay for 1.8 seconds
            RB0=0;      // LED OFF
            Wait_These_Seconds(0.9);
         }
     
        if(RB7==0)  // interrupt is connecting RB7 to ground
        {
            RB0=1;    // LED ON
            Wait_These_Seconds(0.7);  // delay for 0.7 seconds
            RB0=0;      // LED OFF
            Wait_These_Seconds(0.1);
        }
    }
}

I recommend that you learn how to convert from hexadecimal to binary and vice versa. You need it if you are going to work with PICs in C. What we have done now is:

  • We have configured pins RB4 to RB7 to accept inputs, and thus interrupts, since they are the only pins that can do that, and
  • we have RB7 as our interrupt pin. In normal operations, RB7=1. Our interrupt action shall be to ground RB7 and force it to zeroes (the hardware always prevails over the software!).

So, build the project, and program the PIC. It should be going on for about 2 (1.8 to be precise) seconds, then off for about a second. Now, connect a wire to RB7 and pin it to the ground. The sequence will change, and the LED will be flashing faster, being on for 0.7 seconds, and off for only a tenth of a second. We have successfully programmed the interrupt!

What's more?

Want to instead flash a big bulb or a DC motor? I will tell you how if you let me know! We just have to amplify the current and use a transistor!

Any questions and troubleshooting are welcome.

I will write more articles on how to build complex algorithms for things like decorative lights, simultaneous LED flashing at different time intervals, and much more!

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)