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:

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.

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!

Thanks for sharing such a nice information about programing micro controller...
the code written for the pic18 microcontroller in the below post is correct, while you wrote some thing else... please have a look at the below link. ThanksHow to Program PIC18 Microcontroller

Hello, good night everyone know that I am relating to grief with a PIC16F84 on how to program in C and I can do a pulse counter to make an increase and a decrease by if they can help me a little as I can do it thanks.

I have long stopped using PIC microcontrollers and now use C# on .NET Micro Framework supported devices, but in any case, you have to copy the delay.c from the samples directory and paste it in the include directory of the compiler.

Wats up maxmus. I must say you are representing back from the days of smack. By the way in your code you used TRISB=0 to declare PORTB as output but apparently this instruction is going to be dropped by microchip so any ideas on how to replace it in c code?http://www.piclist.com/techref/microchip/tris.htm[^]

Hey Leowdeo,
What you are speaking about is the old TRIS instruction that was used in assembly programming. It is in fact no longer supported in recent PIC16 products. TRISB, TRISC etc are all C language Macros that are implemented in PIC C and MPLAB C18 compilers.

Hi.
Been quite away from PIC16s for a while. Please go to the "samples" directory and look for the "extended directory". delay.c shouldbe in there. Or just make a search inside the "samples" directory.

hello i want to make an alarm by using the c programming and i use as input the window and the front door and as output the alarm and a led but the switch tha turns off the alarm what it has to be?? please some help me..!! thnx

this is long overdue, sorry i did not configure my settings to receive mail in my inbox when a message is written here.
Just in case u were never successful, which i highly doubt, PIC.H will be found in

C:\Program Files\HI-TECH Software\PICC\PRO\9.65\include

9.65 is arbitrary depending on the version that u have installed.
hope that helps.

Hello, Maximus. I was using Wiz-C proffessional compiler to programe a PIC 18F4550 chip with C. After compiling my code, I tried to feed it into the chip with a programer, but it gave me a warning and it said that the hex file was larger than the device. I was confused, since my code was very short, and it should not be so large that could not be fixed into the chip. Any thought on that?

Hi There! Sorry i have just seen your message, been up and down with my final year tests. Now i have not used C Wiz before but i could give you a hint on what could be the possible cause of this problem. Nonetheless, i recommend you send me the code such that i can have a look.

1. Yes, the code may indeed be short, such as 5 lines of code but in those 5 lines you may be calling functions that have huge implementations! Check your modules

2. How many loops are you using in your code? Looping appears to take space as my experience has it.

3.What exactly is your program doing? Are you paying special attention to clear your flags before you start the uC?

4. Is your uC already running a multitasking kernel such as Salvo(Lite)? These are small operating systems designed to help us obatin multiple control of systems with the PIC.

5. It could even be your compiler. Though it would be a realy inefficient one i would say. Some compilers are built to have omniscient code generation ( this is basically well calculated code optimization techniques that look for redundant code and eliminate it in a good manner--to put it plainly). For example, from HI-TIDE software, their compiler PIC C Pro produces a hex file 52% smaller than the free version (PIC C Lite!)

6. Your problem could be among any of these or none whatsoever....but it would be good if i can have a look at the code.

most development systems for an embedded application have an assembler/compiler and a separate linker.
Give adequate linker commands so it generates a map file, which is a human-readable list of all
the big code and data blocks, together with their starting addresses and sizes. Studying the map
it should be easy to figure what went wrong.

1) MikroC is not from Microchip but from MikroElektronika.
And, as I know, You cant use it in MPLAB environment, nor You can use Microchip ICD2 to debug.
It is a quite low cost compiler, but you have not the source of the libraries...
Damn!

2) Microchip offer a compiler (PICC18) produced from itself in a free student version for PIC 18 series.
In this version you have a full compiler, no optimization. Anyway you have a full free compiler.
I have found it fery useful!

3) The best compiler for pic is the IAR, anyway it cost much.
No dubt about this is the best!

4) You speak about PIC16F84A. It is a milestone in microcontroller, anyway it is an old microcontroller.
You can find new microcontroller in that "range" with more power and less cost.
The first that I remember is the PIC16F630, same Flash, 4byte less RAM, 64byte more EEPROM, internal oscillator, analog comparators, ISP and more, it costs a third than a PIC16F84A. You only need a 100nF capacitor and a power source in 2,7 -> 6V range to run it...

5) I asked to a Microchip FAE why microchip hasn't a compiler for the pic16 series. It answerwd me that is because the series 16F has to be programmed in ASM, while the series 18F, which cost less and is more powerful for production can be programmed in C.

Anyway, I repeat, good article.

I also found very useful OLIMEX site, which have a low cost developer kits for many microcontrollers, not only pic.
I also suggest to anyone who wants to develop with pic to buy an ICD2 or low cost clone... it will help you more than you can imagine.

There are times when it's necessary to #include a file that contains active code, rather than just declarations. I generally use an extension of ".i" rather than ".c" or ".h" in such cases, but I'm curious what alternative approach you would suggest when it's necessary for a project to contain two nearly-identical pieces of code. For example, suppose motor1 and motor2 are structures, and I need code to process both of them. I might code such a thing as:

If reqspeed was the first thing in the structure and speed was next, the code could be optimized to "only" seven instructions, but even that best case would still represent an almost doubling of execution time for a small savings in space.

Also, incidentally, while some development systems can do a more efficient job of code placement when projects are subdivided into small files, my experience is that HiTech's compilers for the PIC work best when everything is built as one logical source file.

Secondly a question...
Are the wait/delay intervals in the examples required? If so, are they fixed specified values or does it take techie (hardware) knowledge to figure them out? What happens if you don't wait? I've seen delays like this in lots of other examples I found around the internet, and every time I tried removing the delays, it still worked. I'm asking because if I write my own code (maybe using PIC C ), how will I know where to put delays? Just curios...

I hope am getting your question right... Of course they are required if you are going to get the LED to flash on and off!! you may use the PIC C has a delay function that does not take any parameters and i think this is what you are talking about but if you want to Flash the LED at a specified interval of time ( you need this if you are working with time critical projects!), then you will have to use any of the DelayMs(int) or DelayUs(int) functions that are provided with Delay.c and Delay.h respectively.

Now the values are not specific, you decide on them (and where to pout them) yourself to suit your preferences. if you choose to use the DelayMs(int) or DelayUs(int), you can have only an integer parameter of a maximum value of 255 ms or us respectively. I chose to define my own function such that i can just specify my delay intervals in any seconds that i may want.

Sorry. I just realized what those delays are for. Actually what I meant was to ask something else. It was not specifically about the PIC controller. There are subtle timings for controller operations. I will not bother you further, as there are more suitable places for this kind of questions. Thanks.

Pumpkin Inc produce a multi-tasking kernel called Salvo. They offer a free version limited to 3 tasks and 5 events. Salvo integrates very well with Pic C Lite and MPLab, and works surprisingly well even on the PIC 16F84. You should note that this is cooperative multi-tasking, not pre-emptive; a task has to explicitly release control to the kernel.

In your code, there are two infinite for loops in two different if condition statements.
When the program starts, if RB7 is 1, the flow goes to the first infinite for loop. I do not understand how the interrupt can break out the for loop and execute the second if statement.

the two infinite for loops are executed only for the time for which their corresponding if loops are valid. Usually the PIC starts with RB7=1 (unless there is a error leakage from this pin to ground) and so long as it is in this state, the LED will flash continuously. However, on grounding RB7, its value is FORCED to zero. This terminates the validity of the first if statement and engages the second....and the LED will flash (again never ending) but with the sequence that corresponds to the second if statement. Have you tried it out? You should....its works as simply as it is written!!

Thank you for your reply. I did not test it. I just follow the logic of the program.
In the infinite for loop, it does not check the RB7 condition, so it has no way to jump out the loop.
Maybe the two "if" statements should be within a big "for" loop. So, it will check RB7's condition in each iteration.
Unless, the processor works differently....
Anyway, thank you for your reply, and I will try it out.

Hi Etc.Smith,
i saw the logic in your reply, you actually have a point. I tried using a different Programmer Board (the ones we developed ourselves) and found that i had to press the reset button to get the interrupt activated. I have thus removed the infinite for loops from the if statement blocks and used one big for loop containing the if blocks and it now works just fine on the old programmer board as well! I have emailed the updated code to the webmaster, it should be up any time from now! Thanks a lot!

Well, i remember that i tried to build a scientific calculator using C code.
I looked only sources and what you think is right, code never escapes from loop.
But watchdog timers and interrupt requests (change in values involves int) so, if program doesn't set a func explicitly to a intr, it may reset (maybe after a watchdog timer).
So, it maybe based which compiler we are using, at this code, it is not set, so it may stop on int req, or simply restart main with new values.
I am reading now, so please excuse me for misunderstanding.

"As far as the laws of mathematics refer to reality, they are not
certain; and as far as they are certain, they do not refer to reality." Albert Einstein

I want to clarify that the code you show does not appear to be an interrupt, but rather normal input.

An interrupt can be one of many sources, depending upon the pic, such as input on RB0, change of state on RB4 through RB7(good for a keypad), timer overflow(to perform tasks at a certain interval), output from a comparator, etc. Each of the c compilers has it's own syntax for handling interrupts, as these are not defined in the ansi c standard.

Interrupts need to be enabled for the specific source, then enabled globally or they won't fire at all.

Here is an example from MikroC compiler for a timer:
-----------------------------
unsigned cnt;

the input is normal...but it alters the normal operation...and therefore it is an interrupt! there are numerous ways to program interrupt signals....and in PIC C Lite, i could have as well chosen something like

I have a user manual for C-Stamp from A-Wit.
That stamp uses PIC18F6520.
In the manual, there is a chapter devoted into the event handling.
For the code here, I think it is using event polling.

What chodan says is that for an interrupt, in general, we have to setup an hardware interrupt service.
When the state of the hardware is changed, it will fire an event to the MCU.
Than the flow of the program will be switched into that interrupt service.

Much more eloquent explanation than mine...particularly the typo(if/is) in the subject line.

I appreciate the perspective of the author, and I suspect it is maybe a matter of the translation of the word interrupt. From my perspective, conditional logic within the code is not "interrupting" the normal flow of operation, but is part of the normal flow of operations that occur when that input is set.

The term interrupt is used in the context of uC programming in a more specific way than just conditional logic. The pic18, for example, allows the developer to prioritize interrupts, so that if two interrupts happen at the same moment(timer overflow at the same time as serial input, for example), one interrupt routine can be given priority over the other.

The code that you show would work on any pic, including those with no interrupt sources.

The interrupt routine has a fixed address in memory that varies by pic model, typically 0x04 on the pic16 models that I have worked with. Your routine could reside anywhere in the program space.

I respectfully suggest that the author should do a little research into pic interrupts and all the consternation that they can cause even experienced developers, and the example should be re-worked to show a true interrupt routine, or the section relabled as control of flow, something like that. I hate to see less experienced people misled by this use of the term interrupt.

Hi chodan. I also agree that it may be purely a matter of translation of the word...depending on what you define as an interrupt. Indeed, an interrupt does require the presence of some hardware action to interrupt the normal operation. but, please note that the code i provided does not entirely deviate from this circumstance. TRISB=0xF0 by definition will set the RB7(among others) port to LOGIC 1 ready to accept any external input. Under normal operation, we both see that the second if statement does not undergo execution. With RB7=0(ground), the normal operation of the uC is altered (which is the basic definition of an interrupt!). You are correct, the routine shown may reside anywhere in the program matrix.... but, at least for the PIC16 devices, it is definitely not a rule to have an interrupt(going again by our basic definition) routine in its prescribed memory address.
well, many authors nonetheless use such an approach for beginners sample code on PIC programming in C...its if and while....most of the time!

I guess you can redefine any word you want to, but the accepted definition of interrupt in this context is:
1) code that can preempt the normal execution of the main routine
2) code that resides in a specific interrupt handling address in program memory

You are not showing an interrupt here.

Ask a more experience colleage that you trust for their opinion...you are misleading people that are just beginning here and doing them a disservice.

In pic devices, interrupt routines reside in a reserved memory address and can preempt the normal flow of execution. A button pressed that is handled in the main routine is not an interrupt.

I really do appreciate the effort you are putting in here, but you will best serve other people by taking a close look at constructive criticism by more experience developers.

First of all, thanks for the article, I have renember when I used to program with JEDEC files

There's a lot of time since I do not use any of this great microcontrollers, is there a way to program a PIC by USB, I mean,

1.- a mini-device to connect the PIC to the PC to easy program it?.

2.- I am interested in a dc start-stop program for an engine, I am not sure about the best way to control it, it's a dc engine that works up to 8Vdc, may I have to use a transitor system that controls the voltage output with the PIC or can I make all with a PIC, to make sth like (pseudocode):

For this motor problem Juan, the problem is more with the current than the voltage. You will most definately need a transistor ( i usually use TIP 121 or D1250 NPN darlington transistors, they are quite cheap--abt 62 US cents here in uganda)to amplify the current. You will need to make the PIC Current flow into the base (IB) and the collector current(IC) will drive the motor. The output from the PIC16F84 is about 4.5 to 5.5 volts; there are PICs with a 3.3V output(i think?) but you can always connect an appropriate resistor to acquire your desired voltage drop.

as for the code, if you just want to start and stop the engine, its really just a matter of toggling the PIN supplying the base current! Just like we have done in the article.