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:
You can email me at james.boshikoopa@gmail.com
New: Testing the dsPIC33EP512GP502 (12/1/25)
PIC32 Micromite (8/1/25)
Firewing (1/10/24)
On this page you will find range of information about PIC microcontrollers with projects, tips, troubleshooting, and more.
Please note:
Some images can be downloaded from the bottom of the page for better viewing.
0x is used to denote hex values.
Development boards help ease the user into trying out different types of PIC chips as well as providing a more general introduction to microcontrollers, typically whith an on-board programmer, providing the basics to get started. This section deals with the various development boards I have come across that feature a PIC chip as the main or only microcontroller.
Please see the chipKIT page for more information about these powerful, Arduino compatible development boards.
The Firewing is an Arduino compatible development board which I got from eBay for £8.50 ($11.33), supposedly used just once. The Firewing official page can be found at:
There are 8, 16, and 32-bit versions of the Firewing depending on the PIC MCU featured. The one I got has a 32-bit RISC PIC32MX150F128B which has:
128KB flash
32KB SRAM
21 I/O in total, of which 6 are analog in capable, and 5 of which support PWM. Only some GPIO are 5V tolerant the rest are 3.3V maximum - see datasheet linked below for further information. However, there is a handy reference diagram at:
https://www.firewing.info/user-uploads/Firewing/Firewing32/firewing-pinout-r2.png
Continuing...
x2 SPI
x2 I2C
x2 UART
Internal 8MHz/32KHz oscillator
PMP (Parallel Master Port).
For more details, here is the link to the datasheet:
While the PIC32 is more powerful than the PIC24, etc., on the downside programs for it take are more space than the less powerful PICs. However, when using a compiler, the use of -O2 option for optimization (which should be enabled by default) will help reduce code size.
Although I bought the Firewing from eBay it can be bought new from:
https://www.mecanique.co.uk/shop/
Here is a direct link to the 32-bit version:
https://www.mecanique.co.uk/shop/index.php?route=product/product&product_id=82&search=firewing
The site is selling the 32-bit version for £28.80 ($38.38).
The main Arduino compatibility seems to be the Arduino Uno form factor and the ability to use 3.3V Arduino shields, additionally, the Firewing has the mounting holes and power socket in exactly the same position as an Arduino Uno but uses mini USB instead of full size USB-B as on the Arduino Uno.
A nice feature of the Firewing board is that the PIC is removable (much like on an original Arduino Uno) so it can easily be replaced if damaged, or you could use Firewing to program the PIC in the board and then put in a different circuit.
On the Firewing page there are downloads for the compiler, code samples, schematics, and much more. Because the board features a standard PIC MCU you can always use the official PIC programming hardware and software instead.
On the Firewing we find a barrel jack power connector, mini USB (J3), RX (D2)/TX(D3)/L(D4, green)/D5 (power, blue) LEDs, reset button, unpopulated USB ICSP (J4) and ICSP (J1) connectors with staggered holes (so you can fit header pins without soldering). There are also female header pins for interface and power. The board has 'Firewing', 'www.firewing.info', and 'R²' written on the board. In addition to socketed PIC, another IC of interest is the PIC18F14K50 (U5) USB 2.0 compliant PIC Microcontroller. There's also a 12MHz crystal (X1) for the PIC18F14K50 and provision for a crystal (X2) for the socketed PIC.
To test the Firewing I started by downloading the compiler from:
https://www.firewing.info/pmwiki.php?n=Firewing.Download
Which you can download by clicking the 'Download Firewing' link, after downloading and installing the Firewing app can be launched:
When I plugged the Firewing into my Surface Pro the board's power LED came on and the L LED was steadily blinking (the previously owner had supposedly only used the board once so likely they had loaded a blink test). Windows detected the board as 'Firewing Communications Port' and installed it as a USB serial device.
In the Firewing IDE you can click 'Firewing 16' (to the right of 'Compiler') to cycle between Firewing 8/16/32.
If you go to File->New will get an empty program, and if you then click on 'Build' it will prompt you to save the BASIC file. Although it successfully compiled it was unable to detect the Firewing board to program it. It seems that even if the board is installed as a COM port that doesn't mean the correct drivers were installed. You have to actually manually install the driver using the "I have a disk" procedure pointing to the folder of the USB Firewing driver: C:\Program Files (x86)\Mecanique\Firewing\USB Driver. But on Windows 10 and above you have to disable digital signature verification.
Looking online I came across this page:
http://www.firewing.info/forum/viewtopic.php?f=12&t=260
There is a download link for usbFirmware.win.10.zip, however, after downloading I was unable to extract, neither using 7-Zip nor PeaZip.
Because I didn't want to mess with disabling digital driver checks I used an Oracle VirtualBox running Windows 7. With the VM (Virtual Machine) not started and the Firewing board plugged in, in VirtualBox I clicked the Settings button, then USB from the left. I clicked the USB icon with the plus symbol and selected Mecanique Firewing Communications Port. I clicked the OK button and unplugged the board. Then I started the Windows 7 VM and after it loaded and went into the desktop I plugged the Firewing in and Windows 7 but after detecting it the driver wasn't installed. So within the VM I installed the driver manually by going to Device manager, right-clicked Firewing Communications Port, selected Update Driver Software... clicked 'Browse my computer for driver software', clicked Browse button, navigated to USB Driver folder, clicked OK button, and then Next button. Note: if prompt comes up then click 'Install this driver software anyway'. When done it said that it had successfully updated the driver software for Firewing Communications Port so I clicked the Close button.
Now I had installed the driver I opened the Firewing IDE (which has to be installed within the VM) and changed 'Firewing 16' to right of 'Compiler' to 'Firewing 32' by clicking on it.
There are a number of samples stored in their own folders at Documents\Firewing\Samples - note that the programs are written in BASIC and thus have the .bas extension. To load a sample, in the IDE either click the Open button or go to File->Open. Then navigate to a sample, one of the simplest I could find was progQA.bas in QuestionAnswer folder.
Click the Build button, which will compile and program the Firewing, during which the board's RX and TX LEDs will flicker and it will continue to run the program previously flashed (blinking L LED in my case). While compiling was very quick (and you get details of the program and variable space used) the programming took over 6 minutes - most likely slowed down by using a VM. After programming finished the L LED stopped blinking, confirming a new program had been written.
The following image shows progQA.bas opened in the IDE:
Note that the above image and the following image were taken directly from Windows 10 rather than from the VM, just to make it easier to capture the screenshots.
To see the progQA program running and interact with it you need to open up a serial connection since the program uses Console functions. While the firewing IDE does have a serial monitor, accessible via Plugin->IDE Serial Communicator, I used PuTTY. Whatever you use, you need to open a serial connection at 38400, you will then be presented with a series of questions.
In the following image the intro and questions haven't quite displayed right and are displayed twice for some reason so I pressed the reset button on the board and after a few seconds it displayed the text a third time, correctly:
Every time you open a serial connection the board appears to reset since it redisplays the opening text.
Whatever you type won't be echoed so you have to type blindly and press return/enter to submit. Rather than type the number associated with the question you have to type the complete question, for eg., 'How are you' (without quotes) and it will respond with the set answer, and if you type the same question twice it will tell you. When you enter the question you can't add a '?' or anything else to the end, but it doesn't matter what case you use.
If you want to use the Firewing IDE Serial Communicator, open it, click on 'Port Number', select whatever COM port is associated with the Firewing board and then click the Connect button. For some reason the introductory text doesn't display, but can just press the reset button on the board. The good thing about the Serial Communicator is that you can see what you're typing.
I hope this brief introduction to the Firewing has been useful, I will certainly return to it at a later date to try out more code examples and will update this section when I do.
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:
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.
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.
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.
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.
This section deals with projects that involve one or more PIC microcontrollers as the brains of the circuit, whether complete devices or for testing purposes.
When I bought a PIC32MX170F256B-I/SP out of curiosity from DigiKey I looked at an interesting use for it and came across Micromite, which supports the PIC32MX170F256B and a few other PIC32 ICs. A microcontroller (MCU) running the Micromite firmware turns it into a device that runs MMBasic, a Microsoft BASIC compatible implementation, offering a powerful and fast version of the BASIC programming language that supports floating point, integer and string variables, arrays, long variable names, and features a built-in program editor. As well as providing a feature rich version of BASIC to play around with it can be used in place of programming the MCU is a more difficult language, making MCUs more accessible.
Before we get into more detail about Micromite let's go over a bit more about the PIC32MX170F256B, firstly with the product page:
https://www.microchip.com/en-us/product/pic32mx170f256b
The site has a link to the datasheet.
A summary of the chip's features:
CPU Type:32-bit MIPS MCU
Max speed (MHz):50
Program Memory Size (KB):256
SRAM (KB):64
Operation Voltage Min.(V):2.3
Operation Voltage Max.(V):3.6
SPI:2
I2C:2
UART:2
Internal Oscillator:8 MHz, 32 KHz
Pin Count:28
2.3V to 3.6V, -40ºC to +105ºC, DC to 40 MHz
2.3V to 3.6V, -40ºC to +85ºC, DC to 50 MHz
Note: some pins are 5V tolerant, others are limited to VDD + 0.3V, see the datasheet for exact details.
As mentioned, the exact part I bought is the PIC32MX170F256B-I/SP, we can break down the end character meanings:
B=28-pin
I=industrial grade (-40°C to +85°C)
SP=SPDIP Skinny/Shrink Dual In-line Package
-I/SP part is 40MHz maximum
Back to Micromite, the official page is at:
http://geoffg.net/micromite.html
We can read that there are two main versions of Micromite:
"The standard Micromite comes in a 28 or 44-pin package, runs at a maximum speed of 48MHz and supports low cost 2.2" to 2.8" touch LCD panels. It has a focus on ease of use and low cost."
"The Micromite Plus is a more advanced version of the Micromite with double the memory and almost three times the speed (120MHz). It comes in 64 and 100-pin packages and supports a wider range of touch LCD panels up to 8". The Micromite Plus also supports SD cards for program and data storage, PS2 keyboard and advanced graphics controls including radio buttons, check boxes and on screen keyboards."
Since I intended to use the PIC32MX170F256B I went with the standard firmware, PIC32MX170F256B is the chip that is is recommended to be used, reassuringly.
In the Downloads section of the previously linked to site there are links to download manuals and the latest firmware. Note that in the Firmware Updates section it recommends to use a PICKit 3 to load firmware, which I happen to have.
It's a good idea to read ‘Getting Started with the Micromite’, which I'll be referencing from now on.
The schematic for connecting up the PIC32 is shown on page 8, which is very simple - you don't even need an external crystal. So I breadboarded the chip as per the circuit but the capacitor was of concern as it's critical to the PIC's operation, being responsible for ensuring the chip's internal 1.8V voltage regulator works. The schematic states a 47uF 16V Tantalum or 10uF 16V MLC (Multilayer Ceramic) Ceramic. This needs to be a low-ESR filter capacitor. Since I didn't have either at hand, I looked online for alternate recommendations:
https://forum.microchip.com/s/topic/a5C3l000000MQ6VEAW/t330403
"I would think the best is the 10uF electrolytic in parallel with the 0.1uF ceramic to get better high frequency decoupling."
So that's what I went with. When I later on solder up the chip I'll use a better capacitor.
Programming the chip is covered from page 9, a similar schematic is given with the PICkit 3 connected. Since the PICkit 3 can provide power it can be used to power the PIC32, more on that later.
If you do not have it already you need to download the MPLAB X development environment from Microchip:
https://www.microchip.com/en-us/tools-resources/develop/mplab-x-ide
Note: MPLAB X IDE v6.20 is the final version with support for the PICkit 3, which is the version I downloaded & installed.
I opened up MPLAB IPE (Integrated Programming Environment), set Family to 32-bit MCUs (PIC32) and Device to PIC32MX170F256B. I plugged in my PICkit 3 to my Windows 11 computer and PICkit3 appeared under the Tool drop-down. I clicked the Connect button and it detected the firmware on the PICkit 3 and downloaded the required firmware on to it but the I got error:
Target device was not found (could not detect target voltage VDD). You must connect to a target device to use PICkit 3.
I assumed the PICkit 3 would power the PIC32 but you actually have to enable that option by going into Advanced Mode (Settings), you will need to enter the password (default is microchip). You then need to click on the Power option on the left of the window, set the Voltage Level (the default 3.25 is fine) and check 'Power target circuit from a PICkit3'. As a test, I clicked the 'Blank Check' button (Operate page) and it reported it found the target device and that it was blank.
Next, I downloaded the Micromite firmware 'Firmware V5.05.05', which needed extracting, resulting in a number of files - Micromite_V5.05.05.hex is the one we need to program the PIC32 by selecting to use as Hex the file for programming in MPLAB. I clicked the Program button, the process took about 25 seconds. It reported in IPE Output window:
The following memory area(s) will be programmed:
program memory: start address = 0x1d000000, end address = 0x1d03ffff
boot config memory
configuration memory
Programming/Verify complete
2025-01-05 18:06:31 +0000 - Programming complete
*** Hold In Reset mode is enabled ***
I disconnected the PICkit and connected up a UART adapter - this is covered on page 11, with a schematic presented that's the same as the one on page 8. I used a FT232RL USB to serial adapter, which the voltage shunt set to 3.3V, which not only sets the logic level but also the VCC voltage. This meant I could power the PIC with the adapter, but the Micromite boot message will not display since I can't open a connection in PuTTY until after plugging in the adapter.
We can easily add a reset button, however: with a 10K resistor connected between /MCLR (pin 1) and +3.3V, connect a 0.1uF capacitor from pin 1 to GND (the capacitor help debounce the switch). In parallel with the capacitor connect a normally open push button switch. The cap will, pressing the switch will reset the MCU and you'll be greeted with the boot message.
After connecting up, I plugged the adapter into my computer and opened a serial connection in PuTTY (you can of course use the terminal emulator of your choice) set to the adapter COM port and speed set to 38400. As mentioned, due to the adapter powering the PIC I didn’t see the boot message, however, I pressed enter and the > prompt appeared and I was able to execute BASIC commands.
Note that BASIC commands can be entered in any case. However, for clarity they will be shown here in upper case (except in screenshots).
Not surprisingly considering the speed of the MCU and that a simple text interface is used, working with BASIC is very responsive.
By using the MEMORY command we can see there's 60K flash memory total for the BASIC program and 50K RAM total for variables. This means we get 23% of total MCU flash for our BASIC program, 78% of total RAM for variables.
Line numbers aren't needed when writing BASIC programs on the Micromite but if included they will be ignored. For example:
10 PRINT “hello”
Will execute immediately (see below) as if there was no line number but the line won't appear when you LIST.
Note: ? can be used as a shorthand for PRINT.
To create and edit a BASIC program you use the EDIT. Here I’ve written a very simple BASIC loop:
Note that although there's no need to use line numbers, labels are supported - see the manual for examples.
You can use the arrow keys to move around, and the delete and backspace keys behave as expected, at least if you have the right settings in the terminal emulator you're using. If you are using PuTTY, before opening a connection go to Terminal->Keyboard and make sure 'The Backspace key' is set to Control-? (127).
There are shortcuts shown along the bottom of the screen, adding to the ease of use of the editor. Pressing CTRL-C will terminate the currently running BASIC program or command.
However, by nature of using a serial connection it isn't a perfect screen editor like you'd get on a PC, for example. At least when using PuTTY the backspace key doesn't behave as expected (delete characters to the left of the cursor), you have to move using the arrow keys and use the delete key instead.
You can save and run with the F2 key, which also exists EDIT. LIST will show your program (but still have to use EDIT to modify) and MEMORY will show updated memory usage.
Next time you power the MCU the previously saved program will automatically be loaded but not run. Note that using NEW will not only remove the program and variables from memory but it'll also delete the program from flash.
As a simple speed test, I wrote:
FOR I=1 to 1000000:NEXT
Saved with F1, which also exits. When RUN it took about 13 seconds to complete. You can of course use RUN to execute the program after you exit EDIT.
We can control the processor clock speed with CPU, example:
CPU 5
Sets the CPU speed to 5MHz. When I ran the loop again with the slower speed it took ~1 minute 43 seconds.
I then used a higher speed:
CPU 40
And running the loop exited in about the same time as when I first ran the loop so it looks like CPU defaults to 40.
The main reason to use the CPU command is to slow down the processor to conserve power. CPU SLEEP seconds can be used to shut down the CPU to lower power draw further.
A nice feature is that we can handle I/O from within BASIC. The introduction to I/O is on page 49 of the manual. It explains that you can configure pins with:
SETPIN nn, mode
nn=physical pin number (see MCU datasheet)
mode can be one of:
AIN Analogue input.
DIN Digital input.
FIN Measure the frequency on a pin.
PIN Measure the period on a pin.
CIN Count the number of pulses on a pin.
DOUT Digital output.
Say we wanted to control an LED connected between MCU pin 14 and GND with a 1K series limiting resistor. First we set pin to digital output:
SETPIN 14, DOUT
To turn the LED on use PIN:
PIN(14) = 1
To turn off:
PIN(14) = 0
If we wanted to turn the LED on for 3 seconds we can use:
PULSE 14, 3000
Note: the duration is in milliseconds.
It is often useful to measure voltage, which is done with analog inputs. Whereas all I/O pins can be used digitally, only 10 can be used as analog in on the 28 pin PIC32. See the PIC datasheet for more information.
To set pin 2 as an analog input:
SETPIN 2, AIN
To display the analog input value use:
PRINT PIN(2)
We can connect a potentiometer (10K recommended), opposite ends to 3.3V and GND respectively, wiper to MCU pin 2. Turning the wiper should give values ranging from ~0 to ~3.3 (representing the voltage) from one end to the other.
A useful feature is that we can have our BASIC program run as soon as power is applied using:
OPTION AUTORUN ON
As a test I wrote a simple program to flash an LED connected to pin 14 ten times:
SETPIN 14, DOUT
FOR INT I=1 TO 10
PIN(14) = 1
PAUSE 1000
PIN(14) = 0
PAUSE 1000
NEXT
After saving the program I used OPTION AUTORUN ON, then power cycled (can also reset the MCU which will have the same effect).
There is a lot more you can do, Micromite is very sophisticated - you can transfer BASIC programs from a PC to Micromite, lots of configuration settings using the OPTION command, interface with an LCD, support for embedded C routines, and so on. See the manual for much more information and have fun experimenting.
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.
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.
I bought a dsPIC33EP512GP502-I/SP microcontroller (MCU) as it was unlike over PICs I had used before. For a general introduction to dsPIC33 please see:
You can find the product page at:
https://www.microchip.com/en-us/product/dspic33ep512gp502
Which has a link to the datasheet.
A summary of the chip features:
CPU Speed: 70MHz*
Program Memory Size: 512KB
RAM: 48KB
Direct Memory Access (DMA) Channels: 4
Operation Voltage:3 to 3.6V
Number of Comparators:3
ADC Modules: 1. ADC Channels: 6. ADC Resolution Max: 12. ADC Sampling Rate: 1100ksps
Number of DACs: 1. Max DAC Resolution (bits): 4
Output Compare Channels: 4
Number of CAN Modules: 1. Type of CAN module Max: CAN
Peripheral Pin Select (PPS)/Pin Muxing
*Note that the chip version I purchased is limited to 40MHz as indicated by the '-I/SP' in the full part name.
The chip has a 28 pin DIP package so it can be breadboarded or soldered easily.
As you can see the chip is very capable and coupled with the lost cost it's sure to be a benefit for those that need high speed control of devices while performing complex computations.
I had previously used a PIC32MX170F256B-I/SP (see 'PIC32 Micromite' section), which also is a 28 pin DIP chip, and has the same pin numbering for /MCLR, VSS (x2), VDD, AVSS, AVDD, VCAP, and some of the I/O pins also (there are some differences in what pins are 5V tolerant between the two PICs, however). Please read the 'PIC32 Micromite' section and associated documentation to get an idea of the minimum needed to wire up the dsPIC33EP512GP502 for programming. Page 31, 'Decoupling Capacitors', of the dsPIC33EP512GP502 datasheet and the following page also gives an idea of the minimum amount of wiring but not including the programmer.
As a quick test, I connected up the dsPIC33EP512GP502 in the same way as I had with the PIC32MX170F256B using my Pickit 3 and opened MPLAB IPE. I set the Device to dsPIC33EP512GP502 and plugged the Pickit 3 into my laptop, it then showed the Tool as the Pickit3. I clicked the Connect button and it downloaded the firmware to the Pickit 3 for the dsPIC33EP512GP502. It then said the target device wasn’t found so I did the same as I did with the PIC32. I went to Settings->Advanced Mode, clicked on Power and selected the checkbox for the Pickit 3 to power the target. Then back to Operate, I clicked the Blank Check button and it detected the dsPIC33EP512GP502 and confirmed the device was blank.
For further testing I came across:
https://predictabledesigns.com/the-beginners-guide-to-designing-with-the-dspic33-microcontroller/
Which serves as a good introduction to the dsPIC33, with the dsPIC33EP128GP502 mentioned, which is the same as dsPIC33EP512GP502 but with less RAM and less flash.
Looking at the ‘Getting Started with the Firmware’ section of the previously linked to site, it takes you through using MPLAB X and the XC16 compiler. I used MPLAB X IDE V6.20 - as I already had that installed, the images that follow will appear slightly different to those on the predictabledesigns page and may differ to your version. In MPLAB I created a new project but there was no ‘Standalone Project’ option, it would appear ‘Application Project’ is the new term for more recent versions of MPLAB. On the Select Device page I set Device to ‘dsPIC33EP512GP502’, on ‘Select Compiler’ page I clicked ‘XC16 v2.10’, and on ‘Select Project Name and Folder’ I entered a project name, and clicked the ‘Finish’ button.
I already had MPLAB Code Configurator (MCC) installed, although it required some libraries to be downloaded, which simply required the ‘Finish’ button to be clicked to download them. After that I was presented with the following:
Notice the various sections, such as Project REsources, Easy Setup, Dashboard, and Pin Manager: Package View, to name a few.
From the System Module (Project Resources->System) tab I set the clock settings to match the predictabledesigns site so that Fosc/2 was ~40MHz. ‘Enable Clock Switching’ was already checked. For ICD ‘Emulator Pin Placement’ I picked ‘Communicate on PGEC3 and PGED3’, note the chip pinout in Pin Manager: Package View doesn't update until after you change the drop-down. Below you can see some of the clock settings:
I was confused by the Pin Module as it only showed RBO and RB1 (the programming pins), I don't think it's explained well on the predictabledesigns site as they show a lot of pins available, although they only briefly mention pins. Using Pin Manager: Grid View you can lock/unlock pins and set whether they are input/output and if they are part of a specific module (GPIO/ADC/UART/etc.). When a pin is locked (indicated by the padlock icon) it appears in the Pin Module and you can adjust its attributes (Output/Analog/etc.) if needed. Any conflicts will show in the Notifications (MCC) tab so you can take action to fix the issue.
I continued reading through the predictabledesigns site which talks about compiling, programming and debugging, and in the Code Examples section there's some useful code.
My aim was to blink an LED connected to RB5 (pin 14) of the MCU, which I'll now explain how I did it.
In Device Resources I expanded ‘Timer’ and double-clicked TMR1 to add to the project, I entered 1 ms as the Timer Period.
In Pin Manager: Grid View I clicked padlock icon for RB5 output (in Pin Module section GPIO/Output row, Port B/5), and in Pin Module I set the Custom Name to IO_LED. In the Project Resources section I clicked the Generate button, which produces the necessary files to interact with the LED by providing prewritten functions.
To get to the main source file click the Projects button, expand Source Files, and double-click main.c to open it for editing. Scrolling down to main() we can see where we put our code in the while loop. However this was where I ran into issues, when I tried to do a build I got error ‘No rule to make target’. I went to Tools->Options and clicked the Embedded tab, then Build Tools. I saw that XC8 was selected, which is unsuitable for dsPIC33, which is 16-bit, so I clicked XC16, and set it as default. Now the Build was successful.
In main.c add #include <stdbool.h> before #include "mcc_generated_files/system.h", and #include "mcc_generated_files/pin_manager.h" and #include "mcc_generated_files/tmr1.h" after, so you have:
#include <stdbool.h>
#include "mcc_generated_files/system.h"
#include "mcc_generated_files/pin_manager.h"
#include "mcc_generated_files/tmr1.h"
stdbool is needed so we can use true and false even though it's C code.
In main() replace ‘// Add your application code’ with:
IO_LED_SetHigh();
delay_ms(1000);
IO_LED_SetLow();
delay_ms(1000);
The code will turn the LED on/off every second but we also need to add the delay_ms() code, taken from the predictabledesigns site, placed before main():
void delay_ms(int delay)
{
int i=0;
bool statusTimer1=0;
TMR1_Stop();
for(i=0; i<delay; i++)
{
TMR1_Start();
IFS0bits.T1IF = false; //Clear interrupt flag
while(statusTimer1 == false)
{
TMR1_Tasks_16BitOperation();
statusTimer1 = TMR1_GetElapsedThenClear();
}
TMR1_Stop();
statusTimer1 = 0;
}
}
You can see a section of the code below:
After building we can see the code takes <1% of total flash and <1% of total ram.
Next I connected my Pickit 3 to the dsPIC33EP512GP502 and then I plugged the Pickit 3 into to my computer. We need the Pickit to power the MCU which is done as follows:
In the Dashboard area bottom left click the Project Properties icon (spanner, screw and nut), click PICkit 3, and select Power from the Option Categories drop-down. Check ‘Power target circuit from PICkit3’ then click the OK button.
To program the MCU click 'Make and Program Device', in the pop-up select Pickit from the drop-down and click the OK button. After programming, you should see the LED connected to RB5 flashing.
If you want to debug click the ‘Debug Main Project’ button and you will have various debug options including Pause (looks like a typical pause icon), which will stop execution at the current instruction, which will be highlighted in main.c or other source file. You can click Continue (play button) to resume execution. While paused we can of course step through code, inspect variables, and so on. We can also set breakpoints but only while either the MCU has been stopped or paused or not being debugged (a limitation of the Pickit 3) by single-clicking the line number where we want to pause. When the instruction is reached, execution will stop at that point, which is very handy for finding errors.
However, I found that when setting a breakpoint it didn’t break where I expected (it would be an instruction after). For example, if I set a breakpoint in main() on either delay_ms(1000); it stopped at the start of delay_ms(). This could possibly be due to optmisation, however I checked in Project Properties, clicked on ‘XC16’, and saw that the Optimization level was set to ‘0’, which turns off optimization. Alternatively, the issute could be due to the skid effect:
A recommendation I found online was to put several Nop(); before the instruction you want to break on but I found that didn't help. Fortunately it's not critical to debug the blinking LED program other than to try out debugging but for more advanced programs it could be more of an issue.
You can use the ‘Finish Debugger Session’ button to stop debugging. Note that the LED connected to the MCU won't continue to flash whether you stop debugging paused or not, you need to run the program.
The next test I did was to read analog pin AN0/RA0 (pin 2) while connected to a potentiometer's wiper connection, the opposite ends connected to 3.3V and GND respectively. The analog value will be output via the MCU's UART pins so we can use a USB to UART adapter to view the values.
I built the test on top of the LED blinking project by doing the following:
Added ADC/ADC1 from Device Resources and entered ‘4’ for Conversion Clock in Hardware Settings. I checked ‘Enable Auto Sampling’.
In Pin Manager: Grid View I clicked the padlock for RA0 ANx input under ADC1. In Pin Module I set the custom name to ‘IO_ANALOG’.
Added UART/UART1 [PIC24 / dsPIC33 /PIC32MM] from Device Resources and left the default settings. I found that I did not have to check the 'Redirect Printf to UART' option in the UART settings for printf() to output to the UART.
In Pin Manager: Grid View I clicked to set RB4 as an output in the UART1 section, which becomes UART U1TX pin. I set RA4 as an input in UART1, which becomes UART U1RX pin. For this test we are only using TX but at least both TX and RX are set up ready. In Pin Module I checked ‘Start High’ for RB4 so the UART has the correct starting state.
Clicked the generate button.
To read the analog in pin I used the example analog function from predictabledesigns adapted to use the analog pin name I used:
int readADC(void)
{
int ADCval = 0;
ADC1_ChannelSelectSet(IO_ANALOG);
ADC1_SamplingStop();
while(!ADC1_IsConversionComplete(IO_ANALOG)){}
ADCval = ADC1_Channel0ConversionResultGet();
return ADCval;
}
Place readADC before main().
For ADC1_IsConversionComplete() I had to pass IO_ANALOG (I'm not sure if that was actually the correct value to use but IO_ANALOG is defined as a numerical enum), perhaps there used to be a version that didn't take an input parameter. However, the parameter is never used by ADC1_IsConversionComplete().
Note that ADC1_SamplingStop() is misleading; it actually triggers the conversion.
Add #include <stdio.h> before the other #include to add support for printf(). Add #include "mcc_generated_files/adc1.h" after the last #include.
In the while loop in main() replace the existing code with:
printf("Analog conversion start...\n");
IO_LED_SetHigh();
int ADC_in = readADC();
printf("Analog = %u\n", ADC_in);
delay_ms(250);
IO_LED_SetLow();
delay_ms(250);
Because we are still using the LED we can blink it to show that the program is running for debugging purposes.
When I did the build I got warnings about deprecated ADC functions but that is nothing to worry about.
The USB to UART adapter will need to work on 3.3V logic level and is connect as follows:
UART adapter dsPIC33
GND GND
RX RB4 (pin 11)
Next, program and run the MCU by clicking on Run Main Project button.
Open up a serial connection (I used PuTTY) set to the USB to UART adapter's COM port, speed 9600. You should see 'Analog conversion start...' message followed by 'Analog =' with the analog value, which will be dependent on the potentiometer wiper position. You should see values ranging from 0 to 1023 as you adjust the potentiometer. Note that even at a set potentiometer position the value will fluctuate slightly, which is to be expected.
If you find that PuTTY doesn't not handle newline correctly: before opening the connection, click Terminal in configuration, check 'Implicit CR in every LF' and 'Implicit LF in every CR' then open the connection (click Session).
I will be sure to do more tests on the dsPIC33EP512GP502 later on but for now this section should prove useful to those starting off with dsPIC33 MCUs.
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
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****"
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.
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.
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-2025