PIC Microcontrollers

Introduction

The family of PIC RISC microcontrollers were first made by the company Microchip (there are now clones by other companies) back in 1976 and have since become very popular by both the electronics industry and hobbyists because they offer so much on one chip, which makes complex circuits much easier. A good example is my traffic light project (which is on this page); to create a set of traffic lights using logic and timing components alone is quite tricky, especially if you was to realistically emulate a typical traffic light sequence. But by using a PIC microcontroller, the task becomes much simpler and the number of components and the complexity of the circuit greatly drops, as the PIC does a lot of the hard work.

The PIC microcontrollers range from basic 8-bit chips to 16-bit, and 32-bit, which are much more complex devices yet even the most basic PIC's offer a lot for your money. A typical PIC contains on-board flash memory for the program code (there are one time programmable and UV erasable versions too), EEPROM for storing settings and other useful data, a section of RAM (referred to as a collection of file registers), timers, analog comparators and bi-directional input/output ports.

You may like to view this video from YouTube user Luke Briner for a general introduction to PIC microcontrollers and microcontrollers in general:

On this page you will find range of information about PIC microcontrollers with projects, tips, troubleshooting, and more.

Please note that 0x is used to denote hex values.

Boards

chipKIT

Please see the chipKIT page for more information about these powerful, Arduino compatible development boards.

Programming

A PIC microcontroller is programmed using a programmer connected to a PC with the information from a file that was produced from code written using either a low level programming language (assembly) or a high level language, such as C or BASIC. The advantage of high level programming languages is that they are much easier for beginners to learn, however, especially with the more basic PIC's, there is little space for code so using assembly has the advantage of making better use of the limited memory. Either way, the code you write gets converted to machine code which is then 'burned' to your PIC. Most programmers allow the PIC to then be tested by providing a number of switches and lights but depending on what you want the PIC to do and what testing features the programmer offers will determine how useful the programmer is for testing the PIC. You can also debug your code on your computer which will at least lets you check that your code is running as it should. MPLAB is a free PIC development IDE by Microchip which you can use for writing the PIC code, testing it and to convert to PIC code ready to be written to your PIC.

When you are happy the PIC is behaving as it should, you can then take the PIC out of the programmer and place it in your own circuit. If need be, you can put the PIC back into the programmer and update its code, perhaps to fix a bug that you have found or to change a timing value. The PIC's that use flash memory to store its code can be written to about 1000 times so that is a big bonus for flash PIC's. A good idea is to write the version number of your code on a sticker placed on the PIC along with a series of characters and numbers to reference your source code and project. Or, you could output the version number using LED's or a display (see the PIC Traffic Lights Project as an example of how you would do that).

If you do program a PIC in assembly language, there are a few things to watch as there are a limited number of instructions. While there are some very useful instructions, such as to clear or set individual bits, there are also missing some instructions you would expect to see. For example, to compare two values you have to subtract one from another and then test if the Zero flag has been set (although the development software you are using may provide additional instructions which are then converted to the individual instructions to perform the task like the one I just mentioned). Another thing to keep in mind is that there is only one working register (the W register) which is like an Accumulator register found in other processors and certain instructions make use of the W register. However, you do still have a number of general purpose registers which act as the RAM for storing your variables.

Programmers

Microchip PICkit 2 programmer

When I got a new laptop running Windows 7 64-bit I assumed that my Velleman programmer (please see the Velleman PIC programmer K8048/VM111 section) would work since I was able to program PICs using it on my old Windows 32-bit laptop. I was wrong, as even after trying different settings, the programmer wouldn't read correctly from a PIC whether through ICSP or when plugged directly into an on-board IC socket. Worse still, the PIC eventually stopped working in the target circuit.

I decided to buy a PICKit 2 PIC programmer, which from reviews I had read was actually better than the newer PICKit 3 programmer. The PICKit 2 programmer was cheaper than the Velleman programmer, much smaller (since for one thing it doesn't have the chip sockets, LEDs and switches) and since it uses USB (the Velleman programmer uses the old style serial port) it's a lot faster too.

The PICKit 2 programmer software was designed only for Windows 2000/XP but I had checked beforehand that people had got it working on Windows 7 64-bit. However, when I tried to install the software from the provided CD I got an error so I installed the PICkit 2 v2.61 software from Microchip's website:

http://www.microchip.com/pickit2

Now that the programming software was installed I connected the PICkit 2 programmer and Windows installed the USB device.

When I opened the PICkit 2 programmer software it detected the programmer. If you connect the programmer after you start the programmer software then you can go to Tools->Check Communication. The PICkit 2 programmer software  should then report that it's found the PICkit 2 device.

You can see my PICkit 2 below, connected to one of my PIC projects (PIC LCD character module driver). This was the circuit that contained the PIC that had stopped working but in seconds the PICkit 2 had it working once more. It probably took me longer to solder the lead for connecting the PICkit 2 to my PIC project than the re-programming.

The PICkit 2 device has the same pinout as the Velleman programmer but with an additional, 6th connection, called 'Auxiliary' (used for programming some types of serial EEPROMs and for PIC microcontrollers that support LVP-Low Voltage Programming). An arrow marks pin 1 on the PICkit 2 device.

I soldered a lead (see above) to go from the PICkit 2 device to my PIC target circuit connector. I used a 6 way pin header to plug into the PICkit 2 but only soldered the 5 wires I needed for the target circuit. I then connected the PICkit 2 device to the PIC target circuit and when I opened the PICkit 2 programmer software it correctly detected the PIC. I then read in the PIC's program and found it to be wrong (so somehow its program had been altered) and re-programmed it, and the PIC worked correctly as before.

The PICkit 2 device can power the PIC (and target circuit) if it draws no more than 25mA otherwise external power can be used. The PICkit 2 software gives the option to turn VDD on/off and change the voltage setting and it can also detect when external power is connected. VDD defaults to being off, most likely in case the target circuit was to draw too much current.

The only problem I've had so far with the PICkit 2 software is the ASCII view isn't as good as that of PicProg2009. Other than that it is so much better, with more features and it correctly identifies the connected PIC.

For programming, the correct VDD voltage must be set (the PICkit 2 programmer software warns that min of 4.5V is needed). It defaulted to 2.5V so I changed it to 4.5V and the PIC was programmed successfully.

While a circuit diagram was provided with the Velleman programmer as it was available in kit form, the circuit diagram for the PICkit 2 programmer can also be found with the user guide. The PICkit 2, however, is open source; the associated software has been made available by Microchip so that you can, for example, make your own version of the PICkit. Interestingly, the PICkit 2 uses a PIC internally (PIC18F2550) so it's a PIC programming a PIC!

The PICkit 2 programmer has the ability to have a PIC program downloaded to it so that a PIC can be programmed without the need of a computer; this feature is called programmer-to-go (PTG). To use PTG you will need to power the PICkit 2 programmer using the USB connection.

Velleman PIC programmer K8048/VM111

The first PIC programmer I used was the Velleman VM111 (see below) which I bought from Maplin; it comes in two forms which are the kit version in which you have to solder the components yourself and the ready made version (which is the one I got) which comes with an RS232 cable. Yes, the programmer uses the old style serial port and it is advised by Velleman to use only a real serial port on-board a computer. However, the programmer did work on my old Windows 7 32-bit laptop with a USB-to-RS232 converter as well as my desktop computer which has an on-board serial port. The PIC programmer is designed for computers running any Windows operating system from Windows 95 to Windows XP, however, the programmer works fine on my Windows Vista 32-bit desktop and my Windows 7 32-bit laptop by slowing down the speed of the programmer using the supplied software that flashes the program to the PIC (PIcProg2009).

The power supply is not supplied, which is needed for both flashing the PIC with your code and for testing the PIC while still in the programmer. An unregulated, 12V DC wall adapter rated at 300mA is what is needed for the PIC programmer and I happened to have one of those variable types with voltage settings; make sure the polarity is correct. There is no switch on the programmer to turn the power on or off but instead a switch for putting the programmer in standby, programming (or read) mode, or run mode for testing the PIC.

The PIC prgrammer supports many different types of PIC's that come in 8-pin, 14-pin, 18-pin and 28-pin sockets, with a chip socket for each type on board the programmer. You can only have one PIC in the programmer at once and you have to set the appropriate on board switch settings to connect the oscillator to the PIC. There are also four push buttons and six LED's for testing the PIC while in the programmer, although if any of them will actually be useful depends on the way you have the PIC set up (which connections are inputs and which are outputs).

The programmer also supports what is known as In-Circuit Serial Programmer (ICSP) which allows you to connect your PIC while in its own circuit to the programmer to update its code. If for example you had made your PIC project but wanted the option to be able to update the PIC's code at a later date, you can provide in the circuit of your project a connector so that it can be connected to the programmer. You can then re-program the PIC as if it were in the programmer but without having to take it out its own circuit (assuming that it is even in a chip holder). ICSP will also let you program some PICs that will not fit in the provided IC sockets on the programmer board. The cable between the programmer and your PIC circuit must not be longer than 15cm otherwise the programmer won't work.

The Velleman PIC programmer is not without its oddities; when a certain type of PIC is inserted in the chip holder of the programmer the warning light (LD9) will flash faint. According to Velleman this will do no harm to the PIC, but I can see how (like it did me) it could cause concern. Another quirk is with the programming software, PicProg2009 (see below), it will often say that the settings don't match the PIC in the programmer (even though they do). Sometimes the PicProg2009 will say there is no programmer connected and this happened to me when using an USB-to-RS232 converter so I uninstalled the converter from the device manager, unplugged the converter and when I plugged it back in again and the driver had installed I was able to program using the PicProg2009.

 For writing the PIC program I use MPLAB IDE, which can be downloaded online for free, and has many useful features including a debugger. When working with PIC's I write in assembly language, which is the PIC's native code, which gives me full control (and greatest speed) of the PIC, allows me to make full use of the available memory (the code space and RAM) and gives me an understanding of how the PIC works at low level. I then use PicProg2009 (which came with the PIC programmer-but you should download the latest version) to store my program to the PIC. However, depending on whether you want to use assembly language and certainly for beginners, you can use high level programming languages, such as C and BASIC, which then get converted to PIC machine code. These high level languages may not make the best use of the PIC's program space, which is especially important with PIC's that have little memory, but will give you a chance to use your PIC without going low level. 

Projects

PIC CompactFlash Interface Board

I bought cheaply from ebay a PIC based CompactFlash board which had no information with it but I figured at worse the cost would cover the PIC and the CompactFlash card. The board has the following features:

PIC16F877-20 microcontroller (U1). Oddly the chip is plugged into a chip holder that is in turn plugged into another chip holder (perhaps to raise the chip so it's easier to access the surrounding header pins) but it seems from my research only my version of the board has the extra chip holder.

Possibly I/O headers: J6, J2, J3, J4,J5, J9.

Various headers with shunts fitted: JP1 to JP13.

Telephone style connector J8, possibly for programming/debugging.

DC power in connector J7.

Voltage regulator (U2), 7805A, +5V.

20MHz crystal Y1.

LED1 power LED.

8MB CompactFlash  card (empty, formatted to FAT) inserted into socket J1.

The board has 'Arma design inc. NCI-2' written on the back but I couldn’t find any information online by searching for 'Arma design inc. NCI-2' or 'Arma NCI-2' but by Googling 'PIC16F877 compact flash' I came across:

https://www.mikrocontroller.net/attachment/12080/compactflashOnPicArticle.pdf

The article was written by Mark Samuels who worked at ARMA Design, and details that the board features a standard IDE header for connecting the CompactFlash card to a PC without the need for the microcontroller (for testing purposes). Additionally, ICSP and in-circuit debugger headers are provided on the board, which at the time cost $129 just for the board with the PIC (I paid £4/$5!).

At the end of the pdf it links to Armanet but the domain is down. We can view an archived version of the site:

https://web.archive.org/web/20010411031333/http://www.armanet.com/CompactFlash/

None of the links work, however.

I did find a non-pdf version of the article which also includes the source code:

http://www.massmind.org/Techref/mem/flash/cf2pic.htm

A Google search also found the CF board for sale on:

https://www.addicore.com/compactflashdevboard-p/ad412.htm

The site just calls it ‘CompactFlash Development Board’ and they still have them in stock priced Price $24.99 (as of March 2021) and a date of 2001 is mentioned. The summary of the features are:

2x25 Header to access all of the CompactFlash card pins.

All extra PIC pins brought out to headers for additional access from PIC.

Standard PIC ICD interface (6 Pin modular jack)

Power device using 7-9V power adapter.

On the site are links for:

PIC16F877 Test Code (Assembler Only)

Documentation

Schematic

Archived Circuit Cellar February 2001 Magazine Article

Note: to download the test code right-click the link and choose Save link as…

The Documentation pdf download gives brief info how to use.

The magazine article is the same pdf from the mikrocontroller.net site already mentioned.

The article mentioned earlier talks about the test code which increments a 16-bit value every time the CF card is inserted. However, to view the counter value it is suggested to use WinHex, but the software is only free to try, There is a freeware alternative (for private and commercial use) called HxD, which is what I went with. The official site is at:

https://mh-nexus.de/en/hxd/

To examine the CF card connect it to your computer and in HxD go to Tools->Open disk… Select the CF card under Logical disks and click OK. We can see sector 0 and other sectors are already filled since the card has been formatted as FAT.

I wanted to check to see if the PIC had actually been flashed with the required code so I put the chip in my MiniPro programmer, set it to PIC16F877 and read its contents which showed it wasn’t empty. However, to check if it was the correct code on the PIC I needed to build the sample code so I downloaded MPLAB v8.92 as I was not sure if newer versions of MPLAB support older PICs and I recall using V8 in the past with the same PIC so I went with that version. You can download MPLAB from:

https://www.microchip.com/development-tools/pic-and-dspic-downloads-archive

Once I had MPALB running I started a new project using PIC16F877 as the device and with the previously downloaded assembler source file; when prompted I chose Absolute. Unfortunately, when tried to build all I got Illegal character errors. which is possibly caused by multiple types of newline characters. So I removed the file from the project, added a new window (File->New) and copied and pasted the code from the previously mentioned massmind.org site. I then saved the code and added it to the project as a source file but I still got an error:

Cannot open file (Include File "c:\progra~1\mplab\P16F877.inc" not found)

Which relates to this code line:

INCLUDE "c:\progra~1\mplab\P16F877.inc"

The solution is to replace the above line with:

<P16F877.INC>

It's not a good idea to use absolute paths.

Now it built successfully. The resulting hex file was different to what was on the PIC already (so perhaps the PIC was previously used for something else?) but I burned it to the PIC using the Mini Pro (you can, of course, using any other appropriate programmer). I powered up the board (which take note has a centre positive power connector) with the CF card inserted, powered off and then put the CF card into my PC and used HxD to open the card. Note that you do not need to insert the CF card after powering on the board and isn't recommended anyway). I found that at sector 0xE0/224 (0x1C000/114688) the value was one and on repeated powering on the board with the CF card the value was increased by one each time. Although the source code says it writes the counter value to sector 256 it clearly writes to sector 224 and in the code they even use the value 0xE0 for the sector, which is 224.

PIC LCD Character Module Driver

The aim of this project is to use a PIC microcontroller (PIC16F628) to communicate with a standard character only LCD module based on the HD44780 chip. These LCD modules are found in many devices, including fax machines and alarm systems, and use a standard 14-pin interface (some have one or more additional connections for a back light) and can support up to 80 characters. These displays come in different sizes as some support displaying only a few characters, others the full amount, but another variation is in the number of lines. For example, one LCD module that supports 16 characters could display all characters on just one line but another LCD module would show them on two lines of 8 characters.

These modules are very flexible in that they can be operated in either 8-bit or 4-bit mode with the 4-bit mode offering the advantage of fewer connections to the display that are needed. When it comes to microcontrollers, such as the PIC, it may be that there are only a few control lines to interface with the display. Especially in a system where you may have lights and switches in addition to a display you soon run out of interface connections on the microcontroller. This is where the display's 4-bit mode gives such an advantage over the 8-bit mode, with a little extra work from the PIC's software (having to break up a byte into 2 4-bit nibbles).

The circuit diagram can be found below:

A PIC16F628 communicates with the LCD module using just 6 connections (D4-D7, E and RS) since the LCD module is used in 4-bit mode. Data is sent to the LCD module through D4 to D7 and E (enable) acts as a clock signal to get the LCD module to process the data. The RS (Register Select) input selects whether the data sent is an instruction or the value of a character to display. 

The LCD module is always in write mode (R/W is held low) to lower the number of connections needed between the PIC and the LCD module. Putting the LCD module in read mode is handy to do such things as check if the LCD module is too busy to accept more data. Since this circuit forces the LCD module into write mode and thus the busy flag cannot be checked the PIC's software sends data to the LCD module at a fixed speed that isn't too fast.

The PIC also detects when one of switches (SW1, SW2 and SW3) is pressed and responds by either moving to the next or previous menu option (right or left is pressed) or if OK is pressed then the menu is entered or an action takes place.

The software running on the PIC offers a number of menus so that the user can try out different modes. Not only does this show features of the LCD but the PIC also, such as, for example to display a value from the PIC's EEPROM.

Version 1.0 of the PIC software, 'LCDCharMain.asm' is at the bottom of the page for download, and is for use with MPLAB. In this version of the software there are five options; 'Timer', 'Version', 'EEPROM', 'Hex Test' and 'Turn off'. The software is designed for a two line display. The menu name is displayed on the first line and associated values are shown on the second line. To select a menu option press 'OK'.

The menu options are explained below:

Timer: a count-up from zero is displayed in decimal with a delay of 1 second between each count. Press 'OK' to exit. Note that three digits are always displayed when showing the count.

Version: the software version number is briefly displayed before you are returned to the menu options.

EEPROM: the current value stored at address zero in the EEPROM is displayed in hex. Press 'Left' to decrease the value and 'Right' to increase the value. Press 'OK' to store the value into the EEPROM at address zero and then you will be returned to the menu options.

Since you can write to the EEPROM using the programmer you can set the initial value.

Hex Test: similar to the Timer option but hex values are displayed. To exit, press the 'OK' button.

Turn off: displays a message before turning off the display and putting the PIC to sleep.

In the image that follows, you can see the soldered version of this project:

The LCD module takes up most of the space with the PIC microcontroller actually located under the display; the contrast control is also hidden by the LCD. There are three switches at the bottom for moving forward and back in the menus and for selecting an option. At the bottom right is an ICSP connector for re-programming the PIC.

PIC Traffic Lights Project

This was my first project using a PIC microcontroller and was a simple but fun way to learn how to use PIC's. The aim of this project was to simulate the traditional UK Pelican crossing traffic lights but it could be adapted for other types of traffic lights.

The circuit diagram is below:

It uses a PIC16F627 and drives the car and pedestrian LED's in response to pressing the either SW1 or SW2 to change the lights. There are two sets of lights, one for each side of the road (they are usually diagonally opposite to each other in the real life versions). However, there is no duplicate of the cars (red, amber and green) lights on one side like is the case for the real versions.

As a bonus, there were enough I/O lines to add a couple of extra features, selected using jumpers, by closing them. JP1 enables test mode which lights each LED in turn; can only enter this mode while the LED's are in their default state (that is, CARS 'G' and PED. 'R' LED's are lit).

Closing JP2 causes the version number of the PIC's software to be displayed using the LED's. The first part of the version number (before the decimal point) is output to the LED's in binary (LED1 is LSB). After a short delay, the WAIT LED lights up to represent the decimal point. After another short delay, the second part of the version number (after the decimal point) is output to the LED's in binary. As there are only 6 unique LED's there is a limit on the highest version number that can be displayed (127).

Note that JP1 has a higher priority over JP2 but while in test mode or when displaying the version number no other switches are checked.

You may be wondering about IC1's RA3 which is connected to ground via R5. It is currently unused but configured by the PIC's software as an input. One possible use could be to change it to an output and use it to drive a speaker through the use of a transistor.

The software I wrote for the PIC is attached at the bottom of this page for download and is called 'Pelican_traffic_lights.asm' and is for use with MPLAB. You will notice that in the software 'SW1' is SW1 and SW2 in the circuit; 'SW2' is JP1 in the circuit and 'SW3' is JP2 in the circuit.

Tips

Especially when you first start out with PIC microcontrollers no doubt you will stumble a number of times; I know I have. Even more so if you program a PIC in assembly language there are a range of quirks that take time to get used to.  Read the datasheet for the PIC you wish to use and learn its features so you can get a feeling of how they may be used in a project you plan to embark on. What kind of IO does the PIC have? How much program memory? How much RAM? These are the kinds of questions you need to think about and get the answers to.

I would like to stress how important it is to test your PIC program before even sending it to your PIC. Sure, with many of the PIC's you can write to them 1000 times or more but downloading the code to the PIC does take time and it's very frustrating to update your PIC and then find it won't start up at all. This is why it is so important to debug your PIC software first using an emulator such as provided by MPLAB from Microchip. Using MPLAB you can develop your PIC program and then test the code by stepping through the instructions, checking the state of your variables and other registers and simulating input to the PIC. Debugging your PIC in emulated form might not discover all errors and there are a number of limitations with MPLAB, such as not being able to simulate analogue inputs but MPLAB will allow you to find a great deal of bugs as well as test the overall functionality of your PIC code.

PIC microcontrollers treat the on-board RAM as a collection of registers which includes the general purpose registers as well as the Special Function Registers (SFR's). These registers are divided into banks, so that only a number of registers are available at any one time. It is vital then to switch to the correct bank before accessing a register but generally you will be using bank 0 most of the time. If you forget to switch to the correct bank, most likely you will end up accessing the wrong register; an emulator such as what MPLAB provides can help check for such a mistake. Something to remember is that you can switch back to bank 0 (typically the most commonly used bank) after accessing registers in other banks.

Because a typical PIC has so much built into it, a lot of its signals are multiplexed which means that a signal can function in many ways depending on a selected mode. For example, one signal may act as a reset if configured that way, but can also act as an input/output port if the software selects it to. Then, if the signal is in input/output mode, it can further be set as either an input or output signal. These considerations are very important when testing the PIC in a programmer or using the PIC in your own circuit as depending on what you want the PIC to do, you may have fewer input/output signals (for example) if you use certain features.

The PIC's have a lot of features packed into them and because of this many of the PIC connections are multiplexed, meaning that the I/O line is capable of more than one function depending on the PIC's settings; this is in addition to the ability to be configured as an input or an output. For example, depending on the setting a port line could be a digital input or an analogue input. So, keeping with this example, if that I/O line was set as an analogue input you would have one less digital input (since it's effectively two I/O port lines on one, selectable between the two). 

It is never a good idea to leave PIC I/O lines programmed as inputs floating; that is, left unconnected. If you do, the PIC could act very oddly and consume much more current than normal as well as cause problems when transferring the program to the PIC. Either program the unused I/O lines as outputs (which can be left unconnected) or program them as inputs and use a pull-up or pull-down resistor. If an I/O line is connected to OV/+V through a pull-down or pull-up resistor but the I/O connection was wrongly programmed as an output it would be protected by the pull-down/pull-up resistor. This would not be the case if the I/O line was connected directly to 0V/+V (it would probably be damaged). It's likely for this reason that when a PIC powers up its I/O connections default to inputs (and if there is a choice between analogue and digital it defaults to analogue).

It is very likely that with some PIC projects you will need to delay the program for a certain amount of time. There are a number of ways to create time delays, one of which is to use the built-in timer of the PIC which allows for accurate timing but requires a fair amount of setting up. Another way to make the PIC wait is to execute a number of instructions-either within a loop or not-that take advantage of the fact that each instruction will take up a fixed amount of time. This method is good for when you want very short delays but is dependent on the processor speed. Lastly, you could use a timer chip external which communicates with the PIC and can be checked as needed but then that uses up a number of the PIC's I/O lines.

Another useful feature of a PIC is that it can either use a built in oscillator for timing (which cuts down on the number of components needed in your circuit) or it can use external components connected to the PIC for timing. There is one thing you must watch and that is if you select to use a PIC's internal oscillator, the programmer may no longer work with that PIC (the Velleman PIC programmer K8048/VM111 is an example of a PIC programmer that has that flaw).

When writing routines for PIC's it is likely you will want to pass information to the routine, known as an input parameter, and you might also need to give back something, which is called a return value. For example, say you wanted to add two values together; you would pass the two values to add as two input parameters and the result would be given in the return value. Or, the routine might not return anything but still require an input parameter. Whichever the case, it's best to use the W register for the first input parameter and also for the first return value and then for any additional input parameters or return values you can use general purpose registers. In this way there is one less general purpose register needed and it's likely that a good number of the routines will only have one input parameter and/or one return value. For those types of routines, if they are located in another file then you won't have to make any general purpose registers global for the routine, if they only use the W register the input parameter and return value

PIC Absolute and Relocatable Code

As you program PIC's more no doubt you will build a collection of useful routines such as to work an LCD and perform mathematical functions. Likely you will want to re-use theses routines in your various projects. There is nothing stopping you from copying and pasting them as needed and this approach is good for beginners. This will result in absolute code in that you have to specify where variables and code are stored in the PIC's memory and if you do mix in routines from other files you will have to make sure there are no clashes (for example, to prevent two different named variables occupying the same memory location).

The alternative is to set up relocatable code which lets your development software (e.g., MPLAB) decide the location of your code and variables. I had great trouble getting this to work with MPLAB (and so have many others) but eventually I found a way using a guide I found online. It is well worth the effort since using relocatable code means you can more easily re-use your code and you no longer have to worry about working out the addresses for the variables.

Whereas when using MPLAB with absolute code you can make do with just the one file and quick build when it comes to relocatable code even if you have only one file you still need to create a new project (Project->New). After selecting to start a new project, make sure the target PIC (Configure->Select Device) is correct and then add the files you need (Project->Add Files to Project...). If you want to see a directory tree of your project choose View->Project.

When it comes to building your project (Project->Build All), MPLAB will prompt you whether you want absolute or relocatable code to be generated; select relocatable. Notice that on the toolbar is an option to select between Debug and Release. If you will not be using any hardware debug features (for those PIC's that support it), or when you have finished debugging your program, select the Release option. Another change is that if you go to View->1 Memory Usage Gauge it will now accurately reflect the amount data memory (PIC file registers) that will be used, as well as the program memory.

There are a number of differences when writing relocatable code compared to absolute code. To declare variables, instead of using EQU (or similar) you must use udata and res to get MPLAB to reserve space for the variables. Here is an example:

    udata

VAR_1  res 1       ;Reserve 1 memory location for variable 'VAR_1'

VAR_2  res 4       ;Reserve 4 memory locations for variable 'VAR_2'

Another difference is that you have to define the start of your code using the CODE directive.

For the main project file which will make use of other files all you need to do is add the additional files to the Project view by right-clicking Source Files and selecting Add Files... That is, at least, what I had to do since my additional files are assembler listings (.asm). I found that if I used #include the file would appear in memory but my main project listing wouldn't.

To use variables and routines stored in other files you still have to declare that they are EXTERN. I'll give an example:

(Main project listing)

PIC_Plotter.asm

EXTERN DELAY

EXTERN DCOUNT

MOVLW   D'1'

MOVWF   DCOUNT

CALL DELAY

(Additional file)

timing_1V0.asm

GLOBAL DELAY ;Delay routine using timer1 (1 second or longer)

GLOBAL DCOUNT ;Used to vary length of delay

UDATA

DCOUNT RES 1 ;Used to vary length of delay

CODE

DELAY

    MOVF DCOUNT,1 ;Move the register to itself to test for zero

    BTFSC STATUS,Z ;Exit if DCOUNT is zero

    etc.

In the timing_1V0.asm file there are two global symbols: DELAY (a routine) and DCOUNT (a variable). To use them in PIC_Plotter.asm they must be declared as external using the EXTERN directive. Then they can be used as if they were local to the main project listing.

A handy directive when working with multiple files (as well as single files) is to use the MESSG directive which will display a message in the build output. You could, for example, warn the user that a file that handles LCD output uses certain I/O connections:

MESSG "****WARNING: LCD_HD44780_DRIVER_1_0 uses RB0 to RB5****"

Troubleshooting

PIC16F877A programming issues

The PIC16F877A is an impressive chip sporting a number of special features including serial communication, a CPU compatible parallel port, 8 channel 10-bit analogue-to-digital converter, in-circuit debug mode and the ability to read and write to its own program memory. Unfortunately I had a difficult time programming the PIC16F877A and from searching online I found that I was not alone.

The K8048/VM111 PIC programmer that I use supposedly supports the PIC16F877 but since the programmer doesn't have an on-board 40-pin chip holder for the PIC16F877A, I had to do the programming using the ICSP (In-Circuit Serial Programming) method. But before I even talk about ICSP I should mention that generally the PIC micros with an 'A' on the end (such as the PIC16F877A) use a different programming technique to the non-A versions. So it's vital that both the programmer and programming software support the 'A' version of the PIC. PicProg2009 doesn't support the 'A' version so I had to try the older version of the software (Progpic2) which does support the PIC16F877A; I found the software on the CD that came with the programmer. However, the software would always fail to verify even though it appeared to program correctly.

When looking online most people suggested that the problem was cross-talk caused by long ICSP wires or even that the chip was bad. The recommendation was to put in decoupling capacitors or try another chip. I didn't have another PIC16F877A but I found that indeed a 150pF capacitor from PGD to ground reduced most programming errors.

I came across DL4YHF's WIN PIC software which can be set up to use the K8048/VM111 programmer and offered more settings than Progpic2. Using WIN PIC, it would program the PIC16F877A but fail at the verifying at the CONFIG and CONFIG-WORD stages. Yet when I set the programmer to run mode the PIC was running the program I had written for it so it had actually been programmed correctly; so it could be that Progpic2 had also programmed the PIC correctly even with the error.

It may be that the K8048/VM111 programmer is at fault and that I will have to invest in an alternative programmer but for now I can make do with what I have since it at least programs the PIC correctly even if the software thinks otherwise. It may also be that the USB-to-RS232 converter is causing problems although I can program other PIC's fine.

Problem: PicProg2009 installation error "An error occurred while trying to rename..."

When you try to install PicProg2009 you get the following error:

"An error occurred while trying to rename a file in the destination directory: MoveFile; code 32."

I got this error when trying to install PicProg2009 on my Windows 7 computer. The fix was to exclude the PicProg2009 folder from my Bullguard Internet Security 2013 software (Settings->Real Time Antivirus:File->Files/Folders. Note that I did this after the first installation failure which did at least create the PicProg2009 folder. After successfully installing another PicProg2009 folder was placed in the original PicProg2009 folder. If you have different security software then likely the setting you will need to change will be in a different place.

Problem: PIC does not work

It can be most disappointing when you have built your PIC circuit and programmed it and nothing works. You may even have trouble getting a simple PIC circuit working. Well, I'm going to go through with you a PIC project I had trouble with and what I did to fix the problem.

The PIC circuit consisted of a PIC16F628A and a 74HC595 serial-to-parallel shift register, with each of its outputs connected to a segment of a 7-segment LED display. The PIC's program was designed to send serial data to the 74HC595 so that it turned on each LED segment in turn (with a second delay) until all LED segments were on. The cycle would then repeat, with all LEDs off before each LED was lit.

The circuit was breadboarded with an ICSP lead I had soldered myself which I had checked had no shorts and only good connections, and was shorter than 15cm (the recommended length). But when I connected my PICkit to the PIC circuit there was a VPP error. However, sometimes when connecting the PICkit there was no error and I was able to program the PIC. Yet the PIC would not run the program. I tried both with batteries and a mains derived power supply and only a couple of times did the circuit work but most times it didn't. I did look online for help, especially about the VPP error in case that was linked to the problem I was having, but the causes seemed very varied.

I shortened any long wires on the breadboard and tried a different reset circuit but still the circuit wouldn't work. So I tried another PIC16F628A but got the VPP error a couple more times before it would program. I then programmed again but with updated software so that it would flash an LED connected to RA2. I removed the 74HC595 part of the circuit but when powered up the LED wouldn't light.

When I tried a different crystal the LED turned on but stayed on; it didn't flash. I connected an LED to the PIC16F628A I/O used for sending serial data to the 74HC595 and I saw it faintly flickering before turning on fully for a second. To me that seemed like it was sending the serial data and when I connected the 74HC595 again it worked. It looked like the crystal had been at fault but when I connected the original crystal it worked but sometimes didn't work. Using the alternative crystal the circuit worked every time so perhaps the original crystal was faulty or had problems with the breadboard.

But why did the test LED always stay on and not flash? Because I had made a mistake in my code. I had programmed the PIC so that it would shift out the data and then turn the test LED on before a second delay and then turn it off. The LED was turned off but as the data is shifted out at such high speed the LED was soon turned back on-too fast to see the change.

I hope that this example illustrates some of the things you can try out when trying to work out why a PIC circuit (and indeed other types of circuits) will not work. MPLAB is great for finding certain problems but some will only become apparent when you try out your program on a real PIC. In this case I had checked that the LED should flash by using MPLAB but as the simulation wasn't in real time I had made a mistake in thinking the LED would flash on a PIC running at full speed.

All content of this and related pages is copyright (c) James S. 2012-2023