(C) 2002 .. 2005 Wouter van Ooijen (email@example.com)
Last change made at 2005 AUG 18. The latest version of this document can be found at http://www.voti.nl/swp.
Unaltered duplication is allowed. Translations require approval of the author, which will most likely be granted if the quality of the translation is adequate.
This is not a fool's guide: fools are much more fool than I am clever, and fools should not program PICs (nor anything else) anyway.
I don't accept any responsibility for errors in this text or the consequences thereof, but I appreciate constructive comments.
This document is still under construction: you will find some remarks in square brackets  where I plan to write additional text, if I ever find the time. Don't hestitate to write text yourself if you think something is missing!
So you think you want to start using PIC microcontrollers? Read on! This text will offer advice on how to proceed.
Writing this text I had to make some assumptions about you, otherwise the number of options would be even larger than it is now. So if you do not match the description below, some information might be irrelevant to you, and some recommendations might not be appropriate. Be your own judge.
This text is intended for someone who
|wants to start using PIC microcontrollers but has no prior experience in microcontrollers|
|has more time than money, but not excessively so (typical situation for a hobbyist or small-scale professional)|
|is more interested in experimenting and building prototypes than in assembling large series|
|has (at least) basic knowledge of both electronics and programming|
Note that I do not assume a master's degree in electronics or programming. But on the electronics side understanding the basic working of a resistor, capacitor, diode, LED, transistor etc., and being able to apply at least Ohm's law are mandatory. On the programming site you should have some programming experience, so terms like variable, assignment, if, while, call, goto and return ring a bell.
Starting with PICs requires you to make a lot of choices. This document tries to help you doing so, sometimes by making a strong suggestion, but always - I hope - by providing you the information you need to make the right decision for your particular situation.
If all you want is a list of pre-cooked advices don't read on, just ask on comp.arch.embedded or www.piclist.com or any other forum and you will get all possible combinations of advices, just pic the one you prefer ;)
A long, long time ago (when computer chips died when a cat came near on a dry day) General Instruments produced a chip called the PIC1650, described as a Programmable Intelligent Computer. (Check Richard Ottosen's Gizmo page, it has links to the original PIC1650 documents.) This chip is the mother of all PIC chips, functionally close to the current 16C54/16F54. It was intended as a peripheral for their CP1600 microprocessor. Maybe that is why most people think PIC stands for Peripheral Interface Controller. As far as I know Microchip has never used PIC as an abbreviation, just as PIC. And recently Microchip has started calling its PICs "PICmicro microcontrollers". Maybe they heard that PIC sounds like the Dutch word for dick and wanted to spare me the frowns from Dutch readers.
But first let's take two steps back. You think you want to start using microcontrollers? I hope you realize what you are up to. It is surprisingly easy to use a microcontroller to perform some nice tricks like flashing a LED, or even controlling a simple robot. But these simple tricks will whet your appetite for more complex applications, and then the big struggle will start. On the hardware side microcontrollers are powerful and complex chips, so you are in to some serious reading, especially of the data sheet of the chip you will be using. I know the 390 pages of an 18F4520 data sheet look intimidating, but you will have to bite that bullet some time. On the software side things can get quite complex too, especially if you want to do more than one thing at the same time. Programming is difficult, and microcontroller programming (beyond the blink-a-LED level) even more.
When all you ever want to do is blink a few LEDs, switch some relays etc. you might be better off with an environment that hides the ugly hardware details (and most of the power!) from you, like a BASIC Stamp, essentially a PIC or SX chip with a BASIC interpreter. If so, get a Stamp and put this document aside until you are in for more.
When you have decided to use a microcontroller the next step is to decide which one. This text is about PICs, but you should at least be aware that other options exist, like the Freescale (used to be Motorola) 68HC, Atmel AVR, and the 8051's and ARM's in all their varieties from various manufacturers. There are firm proponents of each of these microcontroller families (and many others), and probably for good reasons. Asking 'what chip should I choose' on an appropriate internet newsgroup will give you an idea of how religious this issue is to some people.
Criteria that you can take into account when choosing a microcontroller (family) are:
|availability (both today and in the future)|
|ease of use (as a start consider only controllers with flash memory that can be (re)programmed in-circuit)|
|quality and price of development tools|
|support from friends, neighbors, clubs, newsgroups, mailing lists|
|availability of application notes, reference designs, hobbyist web pages|
|features of the chip (IO pins, UART, A/D, D/A, counters, speed, code size, data size, etc.)|
|ease of migrating to smaller (cheaper) or larger (more capable) chips|
Personally I started with PICs and have not looked into the other ones much. Motorola's 68HC family is often used for somewhat more complex tasks than PICs, but tends to be more difficult to buy. The smaller AVR's are much like the PICs in price and performance. (Hence PIC-or-AVR debates tend to be very hot.) There are so many 8051 clones around that it is difficult to say something in general about this family. The ARM is a much more powerfull CPU than the averave PIC, AVR or 8051 (but the newer dsPICs come close), but it is not so widely used and there are not DIP versions.
If you want to hear reasons why you should choose PICs I can give you a few:
|availability! As far as I know every PIC type ever sold by Microchip is still available today (contrast this to for instance the Atmel's AVR line). Like all chip manufacturers Microchip is sometimes unable to supply the wildly varying demand, but their reputation on this aspect is very good (Motorola - now Freescale - is an example of a supplier that has a very bad reputation on this point). PICs are also available from many shops - check any electronics shop. If they sell microcontrollers at all they will most probably sell PICs - and maybe some other brands too.|
|widely used! PICs are used by a lot of people, lots of books are written about PICs, there are many many web pages, newsgroups and mailing lists about PICs.|
|extensive product line!|
If you want to hear reasons why you should not choose PICs I can give you a few too:
|mediocre architecture! The architecture of the 12/14 bit core PIC CPU is arcane and bizzare. When you are doing assembly language programmaing, or when you want to write a compiler, this can be a serious disadvantage. The 16 bit core architecture (18F's) is much better. I don't know the 24 bit dsPIC architecture very well, but it is said to be almost normal.|
|no GCC (or other free C compiler) is available!|
OK, so you have not been scared away and are firmly decided to start using PICs. May you live in interesting times, and never say I did not warn you!
So which PIC should you choose to start with? Some 10 years ago this question was easy to answer: the 16F84 (or, before that chip was available, the now discontinued 16c84). These were the only affordable flash PICs and hence THE hobbyist PICs. (EPROM based chips are either program-once or require the use of an UV-eraser.) You will still find lots of designs in electronics magazines and on the internet using these chips. The 16F84A is the slightly newer (cheaper and faster!) version.
Next came the 16F628: 18 pins like the 16F84, pin-compatible, but twice the FLASH, more RAM, more peripherals, and cheaper than the 16F84! One would expect the hobby community to make an instant switch, but that did not happen. There was (and still is) so much information on the internet about 16F84(A) that a lot of beginners still choose this chip to start with. After their start they make their own webpage, which only strengthens the position of the 16F84. In my opinion starting with a 16F84 is a bad choice on pure technical grounds, but if you found a nice introduction that features the 16F84 you might want to use it. Just be aware that you are trying to learn to drive a car on a Ford T.
Note that there are some that say that the 16F84 is still the best PIC to start with, because it is (slightly) easier to use than the later chips. This is mainly caused by the smaller code size (so code paging is not an issue) and by the lack of any analog peripherals (so there is no need to switch them off before the pins are used in digital mode). Personaly I think the added complexity of a 16F628A, 16F88, 16F630, etc is a small price to pay for the lower price and extra features.
After the 16F628 Microchip has steadily widened its offering of flash chips with types that are ever more attractive. The 16F628 was replaced by the cheaper 16F628A, the 16F648A offers twice the code size and more RAM. The 40-pin 16F877 has much more of everything, and it has smaller 16F87x cousins with less pins or less memory if you don't need its full power. The 16F87x series was replaced by the 16F87xA series (cheaper, but beware that the programming algorithm is different). The 14-pins 16F630 and 16F676 appeared, offering a very good bang-for-your-bucks. The 8-pins 12F629 and 12F675 are nice for very small projects.
The above chips (16F and 12F) are all 14-bit core chips. This refers to the properties of the computing element (CPU) in the chip. If I remember correctly the 40-pin 18F452 chip was the first 16-bit core FLASH chip. This CPU is much easier to program, and can address larger amounts of code and data than the 14-bit CPU. Think of the 18F452 as a 16F877 with a redesigned engine.
The flood has not stopped: there are lots of 18F chips (40, 28 and 18 pins DIP, even more pins in various SMD housings), and a realy hughe variety of 12F/16F chips (40, 28, 18, 14 and 8 pins, with 20 pins coming soon). Microchip is also transferring its older 12-bit core chips to flash versions, check for instance the 12F509. The latest additions are the tiny 10F chips: these are very small 6-pin SMD chips, but they are also available in 8-pin DIP (with two unused pins).
Microchip has also expanded its product line into the territory of the DSPs (Digital Signal Processors) with the dsPIC30F family. These are in my opinion intersting chips, but they are so unlike the other PICs that they should be treated as an entirely different product line.
I recently found one reason to prefer the 16F628 over any other PIC: this chip has provides a clock option where one external resistor, which carries only DC, determines the clock frequency. A lot of other PICs provide the option to determine the clock frequency with an external resistor + capacitor, but in that case both components carry AC and practical capacitor values are very small so stray capacitance can have a big influence on the frequency. With the 16F628 it is very practical to let an external potentiometer determine the speed of the PIC, which can lead to a very simple circuit.
So which chip should you choose? If that has not been decided for you by some webpage or book you want to use, or by the development tools you like, or by what you local electrnics shop has in stock, or what your wallet allows you, let's see what I can advise.
Your first impulse might be to take the cheapest chip that seems capable of what you want (the most obvious criteria are often the number of I/O pins and the availablity of peripherals like an UART or and A/D converter). If you want to follow this path I would advise you to take a chip that is at least one step 'fatter' than your original choice. That will give you some breathing room when your application expands, and some I/O pins to aid in debugging (so you could attach for instance an LCD). In fact I would advise you to take the fattest chip that still has the same architecture (CPU core), treating the 12/14 bit cores as the same. The extras will be very usefull while debugging, and the extra cost is small. If and when your application is fully debugged you can transfer to the chip you originaly had in mind. (Or just keep the fat chip. Why change a winning team?)
Some people take this reasoning to the extreme: forget all the small chips, forget the 12/14 bit cores, take a big 18F, or even a dsPIC. I agree to some extent, but if you want to do more than a few PIC projects this approach might get a little expensive, because the 18F and dsPIC families don't yet have the realy small and cheap chips you can find in the 12/14 bit families.
So my advise is: first decide which family you want to use. If you want to do a large number of projects, look low (12/14 bit core). If you need the CPU horsepower, large memories, or other goodies look high (18F, or even dsPIC). Next take a fat DIP chip within that family. Within the 12/14 bit cores that would be the 16F877A (12/14 bit core). The developents in the 16 bit cores (18F) are too fast to follow. The 18F452 used to be the king here, but it has been replaced by the 18F4520, and even larger chips are available (18F4620). I am not sufficiently experienced with these chips to advice on dsPICs, but the 30F4013 is currently the fattest 40-pin dsPIC.
If you are relatively new to electronics you might kill a few chips in your learning process. It might be a good idea to let these chips be somehat less expensive than the fat ones I advised you. For this purpose I suggest one of the 14-pins chips from the 14-bit core family. The lowly 16F630 is cheap, the 16F688 is the fattest chip in this group. The 8 and 6 pin chips are slightly cheaper, but have so few I/O pins that I would not recommend them a starters.
Ubicom sells the SX series of PIC clone. These chips are interesting because they provide MUCH more computing power than the Microchip 12/14 bit core PICs. On the downside the SX'es do not provide much peripherals (only a comparator and a timer), so you will need those MIPS to implement what the manufacturer call virtual peripherals. This is a nice and powerful concept, but IMHO not suited to a beginner. Note that the SX chips can run at one clock cycle per instruction (PICs need four clock cycles per instruction). So a 50 MHz SX is equivalent to a 200 MHz PIC. But an SX needs the equivalent of three instructions for when it changes its program counter (a PIC needs two), and the SX chips have a (somewhat enhanced) 12-bit core.
The table below compares some PICs that can be interesting.
|12F675||sdip 8||6||1k||64||128||a/d, osc||5||1.90|
|16F628||sdip 18||16||2k||224||128||d/a, uart, osc||5||3.50||3d choice|
|16F870||sdip 28||22||2k||128||64||a/d, uart||5||5.00|
|16F871||wdip 40||33||2k||128||64||a/d, uart||5||5.90|
|16F872||sdip 28||22||2k||128||64||a/d, mssp||5||4.00|
|16F873||sdip 28||22||4k||192||128||a/d, uart||5||7.00|
|16F874||wdip 40||33||4k||192||128||a/d, uart||5||7.50|
|16F876||sdip 28||22||8k||368||256||a/d, mssp||5||8.20|
|16F877||wdip 40||33||8k||368||256||a/d, mssp||5||9.50||2nd choice|
|18F242||sdip 28||34||8k||512||256||a/d, mssp||10||8.30|
|18F252||sdip 28||34||16k||1536||256||a/d, mssp||10||9.00|
|18F442||wdip 40||34||8k||512||256||a/d, mssp||10||9.00|
|18F452||wdip 40||34||16k||1536||256||a/d, mssp||10||10.00||1st choice|
|SX48||TQFP 48||36||4k||262||-||osc||50||7.40||no DIP|
|SX52||PQFP 52||40||4k||262||-||osc||50||7.40||no DIP|
The price is of course an indication only, but you should be able to get a single chip for the indicated price (excluding taxes and shipping). Both the absolute and relative prices will vary between sources.
The 12C509 is still popular for hacking pay-TV or game consoles, but its role as small and cheap PIC has been taken over by the 12F629. Note that a 12C509 can be programmed only once (OTP), so you must use an expensive 12C509JW (and an EPROM eraser) for development.
The 12F629 and 12F675 are very cheap 8-pin chips, suitable for projects that do not need the larger amount of code space, data space, I/O pins, peripherals, etc. which are present on the larger (and more expensive) chips. But I do not recommend these chips for a beginner because the code space and I/O pins of the larger chips make debugging much easier.
The 16C84 was the first re-programmable PIC. It was (and still is) featured in many designs on web pages and in magazines. The 16C84 has long been superseded by the 16F84 and the 16F84A. Except for existing designs or to use existing documentation these chips should be avoided: the 16F628 offers more memory for a lower price, in the same pinout.
The 16F628 can be considered the next-generation 16F84, because it is pin-compatible with those older chips. But note that it is not fully software compatible. The 16F628 also has a smaller cousin, the 16F627 (1k code instead of 2k, not shown in the table). The 16F627 does not seem to be an attractive chip as the prices I found were actually a little higher than for the 16F628.
With 8K code space and 34 I/O pins the 16F877 is the largest chip of the 16F87x family, The 16F876 comes in a smaller package with less (IO) pins. It is about the same price as a 16F877, so it is interesting only when the larger package of the 16F877 is a problem. The 16F873 and 16F874 have less resources and use a more cumbersome RAM address mapping to be compatible with older (non-flash) PICs. The 16F870 and 16F871 have even less resources but use the same RAM addressing as the 16F877. Note that the 16F877 and 16F876 both have a UART (for asynchronous serial communication) and an MSSP (for SPI and I2C), while the smaller chips have only a UART. The 16F872 is a 16F870 but with an MSSP instead of a UART.
The 18F chips are new family of PICs, with an instruction set that is much improved over the 16F chips, with more peripherals, and more code and data space. Yet the price of the 18F chips is only marginally higher than the comparable 16F87x chips. There are variations of the 18F chips (not shown in the table) that have an integrated CAN controller - nice when you want to create a network of PIC chips.
If you can't make sense of the Microchip part numbering you are not the only one. These are the only patterns that I have found:
|The prefix 12 is for chips with 8 pins.|
|The prefix 16 is for 12-bit and 14-bit core chips with more than 8 pins.|
|The prefix 18 is for 16-bit core chips.|
|Next the letter C is for EPROM (OTP or windowed) chips, except for the 16C84 that has EEPROM, which is (for a user) almost the same as flash.|
|The letter F is for flash chips.|
|Windowed EPROM chips have a JW suffix.|
For some of the chips mentioned in the table Microchip has released improved versions, identified by appending an A to the type. Such A chips are in most aspects identical to their non-A predecessors (but it does not harm to check the data sheets or the 'migration' document), except that the programming algorithm often changed. Hence you can buy and use an A chip if it is available (they are often slightly cheaper), but check that your programmer explicitly supports the A version. Note: The 16F84A uses the same programming algorithm as the 16F84, but the A chip can run at up to 20 MHz, the non-A only up to 10 MHz.
So what chip should you choose to start with? As said before, first check which chips you can actually buy. Then consider whether you want to use an existing design or other document. In that case the choice has been narrowed down for you. If you already have a programmer, check which chips it supports. For the choice I recommend that you take the most powerful chip that still fulfills the above constraints. The 18F452 (the largest chip of the 18F family) would be the first choice, the 16F877 (the largest chip of the 16F87x family) the next, and the 16F628 the last.
Once you have acquired some experience with your first PIC, and you have a nice project debugged and running, it might be the right time to fit it into a cheaper PIC.
A discussion about choosing a microcontroller might create a lively discussion on the appropriate newsgroups, but the next choice is sure to raise an outright flame war: which programming language should you use? I will not attempt to answer this question for you (the answer depends on too many factors), I will just give some criteria and present some alternatives.
Criteria that can be taken into account when choosing a language:
|which languages do you know (but beware that C for a microcontroller might not exactly be the ANSI-C you are used to on a desktop system)|
|price of the tool|
|quality of the tool|
|quality of the tool documentation|
|support for the tool (vendor, mailing list, newsgroups)|
|ease of writing (a high level language is definitely easier to write in than assembler)|
|availability of useful libraries|
|effective use of the microcontrollers resources|
The last issue (effective use of resources) can start a flame war on its own: the famous C-versus-assembler war (for C you can substitute your own favorite language). As often in such a case the answer depends a lot on the application. My opinion is:
|An assembler programmer can, given sufficient time, always make his program smaller, faster, etc. than a programmer that uses C or another high level language.|
|Given insufficient time the reverse is true. (If you are a professional programmer: When was the last time you were given enough time to write an application? If so you are probably in an industry where the size of a production run is measured in the thousands, if not more.)|
My conclusion is that for a product that will be made in large numbers assembler should be used and for a a product that is produces in smaller numbers a high level language. But that leaves the question open how large or small the series must be, and it leaves a large gray area. A good middle road is often to use a high level language for most of your code and inline assembly for the parts that are very time- or timing-critical.
Microchip provides MPLAB, a free assembler programming environment. Even when you do not want to use assembler you should get MPLAB, if only for the build-in simulator.Various companies sell C compilers for PICs. The prices range from moderate (below $100) to out-of-the-question (at least for a hobbyist: around $1000). I have not used any of these compilers extensively, so I cannot make a recommendation.
Before you start asking around: no, there is no GCC port for PICs, and it is not likely that one will ever exist. The assumptions made by GCC about the target CPU architecture are reasonable for almost all CPU's that can be found in the world (including AVR, 8051 and 68HC microcontrollers), but definitely not for PICs. There is at least one attempt to create a free C compiler for PICs (based on SDCC), but at this moment (2002) no useable product is available.
High-Tech C provides PICC-Lite, a free demo version of their compiler. PICC-Lite targets an number of 16F chips, some with limitations. Check the Hi-Tech website for the most recent information.
BKD provides a free demo version for their CC5X, which can generate up to 1K instructions for all PIC types. This might be interesting to hobbyists, but be aware that CC5X is not exactly an ANSI-C compiler.
Bytecraft provides a demo version of their C compiler. This demo produces only a listing, so you can not use it to translate an application, but it might be useful to see how C constructs are translated to PIC assembly.
I provide the Jal compiler. Jal looks more like Pascal or Ada than C. I think Jal is a very good tool to start (and continue!) using PIC microcontrollers, but you can hardly expect me to be objective about my own creation.
So, which language should you choose? Sorry, I can't decide this one for you. Like for all choices, if you have an individual or group near you that can help you, it is not a bad choice to select the same tools. Otherwise the right choice depends a lot on your programming experience. If you have experience in a single language, you might select a PIC language that resembles it. If you don't have prior programming experience: There are people who advice assembler as the best choice to start programming, but personally I would definitely suggest a High Level Language. Or even better: forget PICs for a while and start programming on a PC, using the parallel port to interface to 'the real world'.
For those of you who take it all to seriously: a question on the PICLIST from Christopher Gill and the answer from Wagner Lipnharski.
I have been using PICs since last June programming in assembler, I am now looking a using the C language. What are the advantages/disadvantages of C over the assembly language. Am I right in thinking that there are built in 'modules' for division, multiplication etc. Are there any good online tutorials on programming in C for complete beginers?
For most PICLISTers Christopher's question would be an open invitation to start the Nth C-versus assembler war, but Wagner took a more original approach:
First you know nothing;|
YOU ARE HAPPY
You first learn about the chip:
YOU LEARN AND USE ASSEMBLY
You first find out there is an easier way, so you can spare some time to watch TV:
YOU LEARN AND USE C
You first find out there is a simpler way, so you can spare all the time in TV, cars, girls, bars, traveling, yatch, relaxing, etc:
YOU HIRE SOMEBODY ELSE TO WRITE THE CODE.
You first find out your money is going fast, so you decided to do some work:
YOU LEARN AND USE JAL
You first find out your money is going real fast, you need to do all the work and save some code space:
YOU RETURN TO WRITE IN C.
You first find out it is not bad to dedicate time, by the way, writing code is a kind of hobby, so stop watching TV and leave girls alone:
YOU RETURN TO WRITE IN ASSEMBLY.
You first find out happines is all around:
YOU LEARN ABOUT AVRs
You first find out you were happy and didn't know.
YOU REMOVE WinXP AND REINSTALL WIN98SE.
You first find out life is a misery, and you want paradise right now.
YOU REMOVE Win98SE AND INSTALL DOS6.
Now, what was your question up there?
This is yet another issue that can start a flame war, partly because there are so many options:
|There are flash and EPROM PICs.|
|There are 2 different ways to program a PIC: serial (used by nearly all PICs), and parallel (used only by some older non-flash types),|
|2 different ways to put a PIC in programming mode (HVP and LVP),|
|one alternative to an external programmer (self-programming using a bootloader),|
|at least two ways to interface to your PC: serial and parallel, and USB is emerging as a third option (and Ethernet probably will be coming soon),|
|in-circuit and ex-circuit programmers,|
|production programmers and prototype programmers.|
|you can either build your own programmer or buy one.|
|The SX PIC clones are programmed in an entirely different way.|
When you start using PICs you should use only flash-based PICs, and you should probly never consider a non-FLASH PIC. Flash PICs can be re-programmed quickly, if preferrably without taking them from the circuit. The programming time depends (among other things) on the size of the program, but even the largest chips can be programmed in about 30 seconds. EPROM-based PICs come in two versions: cheap OTPs (One Time Programmable) chips for production, and more expensive windowed (/JW) chips that can be erased using a UV EPROM eraser. Development using windowed chips is slow and tedious: erasing requires that the chip is removed from the circuit, put in the eraser, and erasing can take 20 minutes. Then you have to put the chip back in the target circuit and hope that you still know what you were trying to do. A professional can invest in a set of windowed chips and an eraser that can erase the whole set in one go, but for a hobbyist the high price of windowed chips makes this unattractive.
A PIC programmer puts the target PIC in programming mode and then uses the programming interface pins to enter the program into the target. The PICs that are interesting to hobbyists use two pins (RB6 and RB7) to enter the program into the PIC (serial programming). Some older PICs used a lot of pins to enter the program (parallel programming). Nearly all affordable programmer designs support serial programming only.
There are two ways to put a PIC into programming mode:
|a high voltage (around 14V) on the MCLR pin, this is called HVP (High Voltage Programming)|
|a logical one on the LVP enable pin (RB3 or RB4) during a reset (Low Voltage Programming)|
All PICs support HVP, only a few support LVP. Most of the newer PICs with at least 18 pins (16F62x, 16F87x, 18F, 30F) support LVP (but note that the 6, 8 and 14 pins chips, and the older 16C84, 16F84 and 16F84A do not).
LVP is both a blessing and a curse. The blessing is that it can be used with very simple programmer hardware and a single 5V supply. A typical LVP programmer uses one HCT buffer IC and interfaces to the parallel port. The curse is that the LVP enable pin (RB3, RB4 or RB5, depending on the particular PIC) is dedicated to the LVP enable function and can not be used by the application. For a new design this would not be a big issue (A 40-pin chip like an 16F877 or 18F452 has 33 IO pins, which is more than adequate for most applications) if the pin was not in the middle of an 8-bit port (port B), which is the only full 8-bit port available on PICs with 18 or less pins. And for existing designs LVP is not possible when the LVP pin is used in the design. LVP can be disabled by changing a particular bit in the PICs configuration word. This bit can only be changed using HVP programming. A freshly bought chip has LVP enabled. Personally I do not use LVP.
Within the HVP programming a distinction can be made between the flash PICs and the (older) EPROM PICs. The EPROM PICs use the high voltage to power the EPROM writing, so the high voltage must be able to deliver a substantial current. Flash PICs use the high voltage only to enable the writing (a high voltage source is generated internally), so the high voltage can have a high impedance (needs to supply only a very low current). Hence some HVP programmers (like my Wisp628, and most serial-port powered programmers) can handle flash PICs, but not EPROM PICs.
Microchip makes a distinction between a production programmer and a prototype programmer. A production programmer must be able to verify the correct programming (by reading the code back) at the low and high extreme of the Vcc expected in the application. This is supposed to catch the occasional PIC that is not programmed (or erased) perfectly. I have heard that such imperfect programming occurs maybe one in a thousand cases. Hence the production/prototype distinction between is not very important for hobbyists and for development, but for production it is a small price to pay to avoid an occasional problem.
In a pinch you can use most prototype programmers for an occasional production programming by using a variable power supply, manually setting the power supply to the expected extremes and verifying the correct programming.
Some of the newest PICs (16F87x) can program themselves. This makes it possible to eliminate the need for a programmer: the PC communicates with a small program in the target chip, this so-called bootloader writes the application in the (remainder of) the targets memory and starts the application. No high voltage required, no dedicated LVP pin. But there are - of course - some disadvantages too:
|you must program the bootloader into the chip before you can use it|
|the bootloader takes away some memory (typically 256 instructions)|
|some hardware is required to interface the chip to the PC, and this interfacing uses PIC pins|
|at reset there must be some way to choose between starting the application or starting the bootloader|
|an application can be incompatible with a bootloader (for instance because the application insists on using the same code space)|
Most bootloader communicate using the PICs UART and the serial port of the PC. These bootloaders are small (256 instructions), but use the two hardwired UART pins (RC6 and RC7) that might be needed by the application for other purposes.
My WLoader bootloader uses programmed (bit-banged) serial communication via a single pin (RE3) which is less likely to be required for other purposes (and can be changed easily). The disadvantage is that WLoader is much larger (1k instructions).
Programmers (including bootloaders) must interface to a PC. Typically a parallel or serial port is used. There is no big advantage in using either one except for the availability of a free port on your PC.
On the PC software is required to drive the programmer. Most programmer software accesses the serial or parallel port directly, which is not possible or very slow under some windows versions (NT, XP).
There are lots of so-called 'zero parts' serial port programmers that are not actually zero parts but can consist of nothing more than single resistor. These HVP flash-only programmers use the RS-232 levels on the serial port directly to program the target PIC. This can work, and when it does it is surely an easy way to program your first PIC (for instance to put a bootloader or Wisp628 firmware in it). These programmers use the RS-232 signals directly to put the chip into programming mode. This requires about 14V, provided by two RS-232 signals. Most serial ports provide -5 .. +12 (because those voltages are available from a standard PC power supply), but laptops for instance often provide much less. The RS-232 specification requires at least -5.. +5 Volt, which is not enough to put the PIC into programming mode. The PC software for these programmers often use the serial port hardware directly. This is no longer possible on recent Windows versions, so a special driver must be used or the software must be configured to use Windows calls (if that is possible).
The SX chips can not be programmed using a PIC programmer. There are very few (free) SX programmer designs on the web.
So what programmer should you build or buy? When you are not sure how serious your involvement with PICs will be I suggest that you start with a 16F877 or 18F452 and a bootloader. You can either
|find someone who can program a bootloader into the PIC for you|
|build a 'zero-parts' serial port programmer and use it to program a bootloader into a PIC|
|buy yourself a 16F877 from me with WLoader.|
If you have little money and a lot of time you could try one of the almost-no-components serial or parallel port programmers. But when your time is worth anything to you I would recommend to skip this step. As a compromise you could give one of these simple designs a try, but be prepared to discard it when you can't get it to work.
I definitely recommend selecting one a programmer that communicates with your PC in a 'normal' way (hence not serial or parallel port 'bit banging' programmer). These programmers can be recognised from the fact that they contain a PIC (or maybe another microcontroller). The disadvantage is that you can't build such a programmer from unprogrammed components, but you can buy a kit, a pre-programmed chip, have someone program a chip for you, or program one using a more primitive programmer.
A also recommed to select a programmer that can do HVP in-circuit programming and allows to program and run the application without touching the hardware (no switch etc.), but this still leaves a lot of choices. My favorite is of course my own Wisp628 programmer, mainly because it allows you to talk to your application over the same serial line you used for programming. Compareable programmers are the EasyISP, the WARP programmers, some of the DIY/Kitsrus programmers, and the recent programmers from Mircochip (ICD, ICD2, PicKit1, PicKit2, Baseline Flash Programmer).
You might think that a programmer must have a ZIF socket so you can insert your PIC, program it, take it out, and put it into your application. Unless you are going to do series production I think this is a mistake. You will spend most of your time debugging your application, which means programming and reprogramming your PIC again and again. This will wear out the PICs pins, and sooner or later you will insert the PIC backwards or break a pin. Or do you plan to have a ZIF socket in your target system too? The alternative is in-circuit programming (ICSP): leave the PIC in the target system, connect the programmer, and you can program and run without even touching the hardware.
If you want to invest in something fancy consider a good DIP clip and connect your programmer to it. Unfortunately you will probably need different clips for 40, 28, 18 and 14/8 pins chips. The 14/8 pin chips have the same pinout for the relevant pins, so you can use one clip for both. Clips for SMD do exist, but they are higher prices and less easy to find than DIP clips. The SMD exquivalents of ZIF sockets (they are called clamshell sockets) do exist but they are horrendously expensive.
Now where can you buy the PIC chip of your choice? If you are a lucky guy your local electronics shop might have them in stock. For the rest of us mail order will probably be the only alternative. Most big mail-order companies carry a long list of PICs and there are lots of small-scale web shops that sell PICs (mine for instance). Microchip also sells its products directly via buy.microchip.com at good prices, but beware that shipping costs are added. At the end of this document you can find some links.
There are actually a number of variations of each PIC: different temperature ranges, packages, maximum clock, low power version, etc. For hobbyists I recommend the standard (commercial) temperature range, DIP (or 28 pin skinny DIP) package, standard power (low power chips have a lower maximum clock), and the maximum clock frequency (4 MHz versions are a little bit cheaper but the difference is too small to be interesting). The clock frequency is omitted for chips that are only available in the full-speed version. Hence for a 16F877 the full designation is 16F877-20/P, for an 28 pin PIC the designation is for instance 16F876-20/SP (SP = Skinny diP).
A PIC has a number of clock options. For most PICs the options are:
|HS: high-speed crystal (4 .. 20 MHz)|
|XT: medium-speed crystal (200 kHz .. 4 MHz)|
|LP: low-power 32768 Hz .. 200 kHz watch-style crystal|
|RC: (external) capacitor + resistor|
Instead of a crystal a (cheaper) ceramic resonator can be used. The HS, XT or LP options can also be used with an externally generated clock, connected to OSC1. Note that for a 4 MHz crystal either the XT or HS setting can be used.
When a crystal or resonator is used two capacitors are required, from each of the OSC pins to GND. The value depends on the frequency. I use 20 pF for 4, 10, and 20 MHz. 3-pin resonators have build-in capacitors. It is advised to keep the leads from these capacitors to the GND pin short. (This makes me wonder why Microchip has on most PICs placed the OSC pins next to the VCC, and the GND on the other side.)
Some PICs have other clock options:
|The 16F62x, 12Fxxx 12C509 provide an INTRC mode that generates an internal clock of approximately 4 MHz. One or both of the pins that are normally used for the crystal can be configured for IO. This is especially important on the 8-pin chips which would - when an external crystal and reset were used - have only 4 IO pins left.|
|The 16F628 has an ER mode where an external resistor and an internal capacitor determine the clock. This mode has the big advantage over the RC mode that the external resistor carries only a DC current, so long leads can be used (for instance to a front-mounted potentiometer) without problems.|
|The 18Fxxx chips provide a PLL setting which generates an internal clock of four times the external (crystal controlled) clock. This can be used to get a 40 MHz internal clock, with only a 10 MHz crystal (note: A 40 MHz crystal is not supported).|
The internal and external RC clocks have an (in) accuracy of a few %. This is adequate for flash-a-LED applications, but either not or just barely for more timing-critical things like asynchronous serial communication.
When you build an existing design you have no choice but to follow its choice of clocking, but for your own first experiment you could use a 'low cost' clock: INTRC for a 16F628 (4 MHz), RC for a 16F87x (100pF, 10k => 0.877 MHz). Note that the RC characterization data (relation between RC values and frequency) for the 16F877 is not in the 16F877 data sheet but in section 31.3.3 of the midrange reference manual. But immediately after the 'first step' I recommend to use a crystal, and maybe use other clock options later when this fits the design better. Using the 8-pin 12C509 and 12Fxxx with an external crystal makes sense only when the remaining 4 IO pins are sufficient, and the increased accuracy of a crystal over the internal oscillator is required (or the full speed of 20 MHz is needed).
So now you have a PIC and a programmer, and you have selected a programming language. It is time to build a target circuit. When you are the bold type you could warm up your soldering iron, to build your first target circuit on perfboard or even on a home-made PCB. But if you are like me you will make some mistakes and you will want to be able to make quick modifications, so I suggest to use a solderless breadboard.
A solderless breadboard is a piece of plastic with a large number of holes in which you can plug your components. Beneath the holes are metal springs that secure the leads of the components and connect them together. The breadboards that I use most often consist of a mid-section where you put the components and two double power strips on both sides of the mid-section. In the mid-section the strings are connected vertically, in the power strips horizontally (see picture). Beware that the power strips often (but not always) have a break in the middle, and that the top and bottom power strips are not connected.
I prepare my breadboards like shown below:
|the breaks in the power strips are bridged|
|the top and bottom power strips are connected|
|a diode will short an accidentally reversed power|
|a LED shows the presence of power|
|a few capacitors (2x 100uF, 2x 0.1uF) provide power decoupling|
You will need some power for your circuit, preferably a stable +5 Volt. If you don't have a real power supply I recommend using a wall-wart (a big line plug with a transformer) plus an 7805. The circuit is dead simple (see below) and will work for all wall-warts that provide either 8 .. 24 Volt AC or 12 .. 32 Volt DC. A 7805 is both short-circuit and thermally protected, so it is difficult to damage. If you want to draw substantial current from this circuit you should use a wall wart with a lower output voltage, and put a big heat sink on the 7805.
Other options to obtain power are:
|a PC game port or USB port (your PC might be damaged when you draw too much current!)|
|a 9 Volt battery + an 7805 (be sure to disconnect the battery between experiments, otherwise the 7805 will drain the battery quickly)|
|a 4.5 Volt battery (not for the 16F84 - the one without A -, and at most at 10 MHz, preferably at 4 MHz or lower)|
When you program your PICs using a High Level language the compiler will isolate you from most details of the PIC architecture, but some details will shine through. So even when you use a compiler it is still a good idea to have some knowledge of the PIC architecture, if only to know what kind of constructs can be translated compactly to PIC instructions and which can't.
The PIC architecture is a bit peculiar, even (or especially) for people who are familiar with more mainstream architectures.
The PIC uses a Harvard architecture, which means that the code and data spaces are completely separate. Most other CPU's use the VonNeuman architecture, where code and data share a common address range. On a PIC code address 0 and data address 0 have nothing to do with each other, and can even address a different number of bits. The addressable element in the PIC data space is a byte (8 bits), the addressable element in the PIC code space is the instruction, which is 12 bits on the 12-bit cores (for instance the 12C509), 14 bit on the 14-bit cores (16x84, 16F628, 16F87x), and 16 bit on the 16-bit cores (18Fxxx).
A frequently asked question is 'how can I read (or write) the instruction at address X?'. For 12-bit and most 14-bit core PICs the answer is simple: you can't. The 16F87x and 18Fxxx PICs have a special procedure (using registers mapped in the data space) to read from and even write to the code space. On the SX reading the code space is possible with a similar mechanism, but writing is not.
On the 12-bit and 14-bit core PICs the control instructions that specify a new code location (goto and call) contain only a limited number of bits for this new location. On the PICs that have a code space that is larger than this number of bits can specify (512 instructions on the 12-bit cores, 2048 instructions on the 14-bit cores) a called code is used to get the remaining (higher) bits. The essence is that a few bits are taken from a fixed location (in the status register). Before a goto or call you must make sure that these bits are set appropriately, or your goto/call will lead your program to an unexpected location (often referred to as never-never land). The table below shows how the target address is constructed. The colons (:) mean that the various bits are concatenated. Note that there are three different cases: goto, call and modification of PCL (explained later).
|12-bit core and SX||14-bit core|
|new location after a goto||
[2/3 bits from status register]|
: [9 bits from instruction]
[3 bits from PCH]|
: [11 bits from instruction]
|new location after a call||
[2/3 bits from status register]|
: [one 0 bit]
: [8 bits from instruction]
[3 bits from PCH]|
: [11 bits from instruction]
|new location after modification of PCL||
[3 bits from status register]|
: [one 0 bit]
: [8 (modified) PCL bits]
[5 bits from PCH]|
: [8 (modified) PCL bits]
A 12-bit core PIC has up to 2 page selection bits in STATUS, an SX up to 3 (the exact number depends on the amount of code space in the particular chip).
Note one strange detail: on the 12-bit core (and SX) one bit of the new code address after a call or modification of PCL is always 0. This means that only half the code space is accessible for these actions, and the accessible and inaccessible regions alternate. This complicates jump tables, value tables and subroutine calls.
From the table you can read that:
|As long as your program uses only the first 256 instructions you don't have to worry about code paging at all.|
|For the 14-bit cores, and when you don't touch the PCL, you don't have to worry about code paging when your program uses only the first 2k (2048) instructions. 14-bit core PICs with 2k code or less include 16x84, 16F62x, 16F870, 16F871, and 16F872.|
Turning this logic around: when you have just added a small amount of code to a perfectly working program and it suddenly starts acting weird if might be a good idea to check whether the size of your code has crossed a 'magic border' and you must start paying attention to code paging.
When the size of your code increases above the no-worries limit the simple way to keep your program working for jumps and calls is to set the page bits before each (attempted) jump or call. MPASM provides the pagesel macro to do this. The SX chips have a special page instruction that sets the page selection bits. Note that for a conditional jump or call the pagesel (or page) must be put before the skip:
pagesel destination ; set page bits for 'destination' skpnz ; skip if not zero goto destination ; jump
The GOTO and CALL instructions on the 16-bit cores use two 16-bit 'instructions' to specify a 20 bit target address, so there is no need for code paging. There are also relative call and jump (branch) instructions that provide an 8 or 11 bit offset.
The PIC documentation calls the data space 'file registers'. You could interpret this as stating that the data RAM (file) and special purpose hardware (registers) are mapped in the same address space.
Just like the code space the PIC data space is larger than can be specified in an instruction. The same trick as for the code space is used: some bits of the effective address are taken from a fixed location, and the programmer must make sure that those bits are set appropriately, but in this case the mechanism is called register file banking. The table below shows how the effective data address is constructed.
Indirect addressing is used when an address must be calculated at run time. The calculated address is placed in dedicated special function registers, and another special function register can now be used as if it were the addressed memory location.
|12-bit core and SX||14-bit core||16-bit core|
|effective direct (instruction-specified) address||
[2/3 bits from status register]|
: [5 bits from instruction]
[3 bits from status register]|
: [7 bits from instruction]
[4 bits from BSR]|
: [9 bits from instruction]
|effective indirect (FSR) address||[7/8 bits from FSR]||
[1 bits from STATUS]|
: [8 bits from FSR]
|three FSRnH : FSRnL register pairs|
The SX48/52 use a somewhat different data addressing scheme. As I have no experience with these chips so I won't attempt to describe it.
The data addressing scheme shown so far has a big problem: to move data from one bank to another a LOT of bank selection instructions must be used. To reduce this problem some addresses 'map to' the corresponding address in bank 0 (or sometimes to another bank). Another way to say the same thing is that some registers appear at more than one address. The registers that map to all banks are called shared. The shared data RAM is very convenient for the assembler programmer, but there are only a very limited amount of it (typically 8 address on the 12-bit cores and 16 addresses on the 14-bit cores, and some PICs have no shared RAM at all).
The 16-bit core PICs uses the same mechanism but the data sheet describes it differently: one bit from the address provided by the instruction selects either the bank selected by the BSR, or a fixed bank that contains 256 RAM locations and 256 special function registers (on most 16-bit core PICs this includes all relevant special function registers).
When your program does not use too much data the most convenient data banking strategy is to keep the bank selection bits pointing to bank 0, only changing these bits when you must access a (probably special function) register in another bank, and then set the bank bits back immediately afterwards. Use the RAM in the higher data banks (mostly or only) using indirect addressing. MPASM provides the banksel macro to set the bank bits. The bankisel macro sets the bank bits for indirect addressing. To use this macro you must make sure that the whole data array that you are going to access is within one bank.
The PICs data memory banking with fragmented pieces of RAM makes accessing an array that is larger than the amount of contiguous RAM very tedious. For each access you will have to translate the array index to the correct bank bits and the address within the bank, and the irregular layout of the banks make it impossible to do this with just a few instructions.
The 12-bit and 14-bit core PICs have a primitive stack that is used for just one purpose: saving and storing (code) return addresses. The 12-bit cores have a 2-level stack, the 14-bit cores have an 8-level stack. The SX, which is in most aspects a clone of the 12-bit PICs, can be configured to have a 2-level stack (for maximum compatibility) or an 8-level stack (much more useful). For pushing the stack behaves like an N-entry book shelve: when you push a new address onto the stack (let's say at the left end), the oldest address (at the right end) falls off and is lost forever. For popping there appears to be a copying machine at the right end: when you take (pop) the leftmost book from the shelve the rightmost book is duplicated. Hence there are always exactly N addresses in the stack.
The 16-bit core PICs have a 32-entry stack that can be read from and written to. This means that these chips can support a real (preemptive, non-cooperative) multi tasking kernel, which is not possible on the 12-bit and 14-bit PICs.
Some stack-related FAQs:
|How can I clear the stack? There are clever methods to do so, but unless you are doing something very very clever there is no need to initialize or clear the stack. And if you are doing something that clever you will find clearing the stack a triviality.|
Is it bad to overflow the stack?
No. But it is bad to underflow the stack, because that means that you are (probably) returning to somewhere you did not intend to return to. In most cases overflowing the stack will mean that you will underflow it later, but not always. Suppose you have a main program that calls a function, and the function will never return because it loops forever. The return address of that call will never be used, so no harm is done when it is lost. In assembler you could of course have used a jump instead of a call, but in a high level language that is probably not possible.
Can I use the N stack levels for call/return?
On the 14-bit cores the stack is used for call/return AND for interrupts, so when you use interrupts only N-1 levels are available for call/retrurn. On the 12-bit cores there is no interrupt, so the 2 stack levels are available for call/return. On the SX there is a dedicated location for storing the interrupt return address, so the 2 or 8 stack levels are available for call/return, whether interrupts are used or not. On the 16-bit cores the stack is accessible, so you could enlarge the stack by saving and restoring stack entries.
How can I push/pop data?
You can't. Parameters must be passed to subroutines in RAM. On the 16-bit core PICs you can push and pop data, but using this mechanism to pass parameters is not effective.
How do I know that my program does not overflow the stack?
Most high level languages will warn you. You can use the simulator build into MPLAB to run your program. Or you can just use your own intelligence: construct the call tree of your program, which is a good idea anyway.
My program overflows the stack. What can I do?
First make a call tree of your program to find out the problem area(s). Now determine if the problem is real (see explanation about never-returning functions). If there are real problems you could
- change your program structure to use less call levels
- inline some subroutines
- use goto/goto instead of call/return for subroutines that are called only once
When this does not help there is the advanced trick of the computed return:
- before the call set a variable to indicate the return point
- use a goto instead of a call
- instead of the return use a computed goto or one or more if's to jump to the correct return point
When you don't understand this very short description you should probably not use this technique. Note that some compilers will use this technique automagically.
Once you have mastered the paging and banking the actual PIC instruction set is very simple to understand. The processor is byte (8 bit at a time) oriented. There is one special register, called the W register.
The diadic (two-operand) arithmetic instructions have two forms. The first form operates on a memory location specified in the instruction, use the W register as second operand, and can store the result either in the memory location or in W. The second form operates on an 8-bit constant, uses the W register as second operand, and stores the result in the W register. The arithmetic operations that can be done in both forms are add, subtract, and, or and xor. Note that W is the second operand, not the first. This makes a difference for subtraction only, but has confused many people.
There is a status register that reflects the zero, carry and digit-carry status of the last calculation. Add and subtract affect all three flags. Rotate involves the carry bit. The others affect only the zero flag, except swap nibbles which affects no flag at all. For subtracting the carry flag is set when no carry occurs and cleared when a carry occurs, so it is often referred to as the carry - /borrow flag: carry refers to the carry for addition, /borrow refers to the negated (the /) borrow for subtraction.
In the tables a represents an address, [ a ] the (byte) content of that address, n a (byte) literal, b a 3-bit literal (a bit number, 0..7), and X : b represents bit b of X.
|W := [ a ] op W||[ a ] := [ a ] op W||W = n op W|
|add||ADDWF a, W||ADDWF a, F||ADDLW n||affects Z, C, DC|
|subtract||SUBWF a, W||SUBWF a, F||SUBLW n||affects Z, C, DC|
|and||ANDWF a, W||ANDWF a, F||ANDLW n||affects Z|
|or||IORWF a, W||IORWF a, F||IORLW n||affects Z|
|xor||XORWF a, W||XORWF a, F||XORLW n||affects Z|
Monadic (one-operand) calculations can only be done in the first form: increment, decrement, rotate left, rotate right, swap nibbles, and (!) move.
|W := f( [ a ] )||[ a ] = f( [ a ] )|
|increment||INCF a, W||INCF a, F||affects Z|
|decrement||DECF a, W||DECF a, F||affects Z|
|rotate right||RRF a, W||RRF a, F||involves C|
|rotate left||RLF a, W||RLF a, F||involves C|
|swap nibbles||SWAPF a, W||SWAPF a, F||affects no flags|
|move||MOVF a, W||MOVF a, F||affects Z|
There is an instruction that loads the W register with a literal, and an instruction that saves the W register to a memory location. These instructions do not affect the flags. The instruction that loads the W register from a memory location has already been listed as an arithmetic instruction instruction: it affects the zero flag, and its destination can be either the W registers or (!) the memory location.
|W := n||MOVLW n||-|
|[ a ] := W||MOVWF a||-|
|W := [ a ]||MOVF a, W||affects Z|
There are instructions that clear the W register or a memory location. Both set the zero flag.
|W := 0||CLRW||sets Z|
|[ a ] := 0||CLRF a||sets Z|
There are bit set and bit clear instructions set or clear a single bit in a memory location. Note that both the memory location and the affected bit within the memory location are encoded in the instruction. For the memory location indirect addressing can be used to affect a calculated address, but there is no one-instruction way to affect a calculated bit within a byte.
|[ a ] . b = 1||BSF a, b|
|[ a ] . b = 0||BCF a, b|
There are bit-test-and-skip instructions that skip the next instruction when a single bit in a memory location is either clear or set. A strange omission is that the W register is not memory-mapped, so testing a bit in the result that is in W is more complicated than testing a bit somewhere in memory. The status register is memory-mapped (and mapped into all banks) so the bit-test-and-skip instructions can use the status flags. As for the bit set and clear instructions both the address and the bit are constants encoded in the instruction.
|skip next instruction when bit N at address A is set||BTFSS A, N|
|skip next instruction when bit N at address A is clear||BTFSC A, N|
There are special increment and decrement instructions that look a lot like the increment and decrement already described, but these forms do not affect the zero flag, but skip the next instruction when the result is zero.
|skip next instruction when bit N at address A is set||BTFSS A, N|
|skip next instruction when bit N at address A is clear||BTFSC A, N|
[ A ] := [ A ] - 1 or|
W := [ A ] - 1
skip next instruction when result is 0
DECFSZ a, F
DECFSZ a, W
[ A ] := [ A ] + 1 or|
W := [ A ] + 1
skip next instruction when result is 0
INCFSZ a, F
INCFSZ a, W
For control there are unconditional goto and call instructions, and a return to terminate a call. These can be combined with a bit-test-and-skip instruction to create conditional flow of control.[ goto call return retlw sleep crlwdt retfie mpasm specials skpz skpnz ]
The PIC instruction set itself does not support indirection (the use of a calculated address). Instead two memory mapped registers are used: the FSR register acts as pointer, the INDF 'register' acts as if it were the registers who's address is currently in FSR. This is roughly equivalent to indirection as it is available on other architectures, but with only a single pointer register.
The instruction set has some funny irregularities, that can either be seen as annoying design mistakes or as opportunities to write clever code. The add and subtract instructions do not take the carry into account, so multi-byte arithmetic is cumbersome (but there is no carry to worry about when adding or subtracting the first - or only - byte).
The 12-bit core lacks a few instructions compared to the 14-bit core:
|There is no return instruction, only a return-and-load-W.|
|There are no interrupts, so there is no return-from-interrupt.|
|There are no literal forms of add and subtract.|
The PIC instruction set can both be effective and powerful, resulting in very compact and fast code, or cumbersome and deficient, resulting in bloated and slow code. It all depends. The PIC instruction set is very good at the bit-manipulations and byte-sized arithmetic that are typical for small controller applications. The problems arrive when either multi-byte arithmetic is needed or the code and/or data is so large that the paging and banking gets in the way. This typically happens when more complex calculations or larger data sets (both comparatively speaking) are required. The use of a compiler will often shield you from the ugly details, but it can not hide the large amounts of code required to do things that can be done with much less code on more mainstream architectures. On the other hand good compilers will take advantage of the power of the PIC instruction set for simple operations.
To illustrate the weak side of the PIC architecture imagine an application that requires random access to a 120-byte array. There are PICs that have 120 and more bytes of RAM data, but this is spread over four memory banks, none of which contains 120 bytes of data. So the data access routine has to figure out, for each byte, in which bank the byte is, set the banking bits appropriately, and to the address according to the starting address of the data fragment in that bank. Store the adjusted address in FSR and the byte can be accessed in INDF. But to access the next random byte this whole procedure has to be done again. Contrast this with the very simple way in which a small array that fits in one bank can be accessed: set the bank bits, add the start address of the array within the bank and the index, move the result to FSR and use the byte in INDF. To access the next byte just change the FSR accordingly.
When you argue that you will use C and be shielded from these details you might be in for an unpleasant surprise: most compilers do not support arrays spread over multiple banks (some don't even support banking at all), and those who do will still produce the same large code that you would produce by hand, slowing down your application.
My conclusion about the PIC architecture is that for PICs the relation between 'application complexity' and 'engineering effort' is much less smooth than for more regular architectures (especially due to paging and banking). This means that PICs will often do well (read: as good as or better than other architecture) for smaller applications, but do not so well (read: worse than other architectures) for larger applications. But a lot of experience is needed to rate an application's complexity before applying this rule, it is certainly not just the amount of code, data or MIPSs.[ FSR maps? ] [need more on 18F instruction set]
Your first application should definitely be a blinking LED (the microcontroller equivalent of 'hello world'). When the LED blinks you have proof that your programmer and target circuit work OK. This blink-a-LED is also your fall-back when nothing seems to work and you start suspecting the PIC, the clock input, your power supply, programmer etc, your sanity, etc.
Blink-A-LED programs for the flash PICs that I have are available on my Wisp628 page.
In magazines and on the internet you can find lots of designs that use the now obsolete 16c84, 16F84 or 16F84a. At the moment you can still buy a 16F84a, but the fact that this chip is now more expensive than the more capable 16F628 is a clear indication that it is nearing its retirement. So you might find yourself facing the task of porting an existing 16x84 design to the 16F628. This requires some modifications and re-compilation or assembly of the program. Here we deal only with code written in assembler, which will be the most common case.
The programming model of the 16F628 is in most aspects upwards compatible to the 16x84 (more program memory, more RAM data memory, more EEPROM data memory, more clock options, more I/O options). The differences between the 16x84's and the 16F628 that must be taken into account are:
|The Vcc range for 16F628 stops at 5.5 Volt, while older PICs could handle up to 6.0 Volt. When the circuit really requires working above 5.5 Volt you will have to adapt the circuit or stick with the original PIC. My original Wisp programmer is an example of such a problematic circuit: it varies the Vcc of the PIC over a range that includes 6.0 Volt. Bad luck, moving to a 16F628 requires a redesign.|
|A topic that is a bit fuzzy in the PIC data sheets is the maximum positive voltage that RA4 (open collector) can tolerate. For old PICs this parameter is not documented, but I heard from a Microchip guy that it could handle up to around 15 Volt. The 16F628 data sheet mentions 14 Volt as absolute maximum, 8.5 Volt operational. I am not sure whether this is a difference between 16x84's and the 16F628 or just a (conservative) documentation update, but be aware that there could be a problem.|
|The configuration options (configuration fuses word) is very different for 16x84 and 16F628. In most cases the configuration word is specified as the sum of a set of pre-defined constant, so re-assembling for a 16F628 will produce a correct configuration. But when the configuration word is specified as a literal you will have to unravel it to its symbolic components.|
|The address of the special function registers on the 16x84 and the 16F628 are quite different. When the program uses the symbolic names defined in the standard include files this will be taken care off automatically, but when the SFR addresses are coded explicitly you will have to do the translation by hand (and it might be a good idea to translate to the symbolic names). Note that on a 16x84 almost all interesting SFRs are in bank 0 (so you can almost ignore banking), but on a 16F628 the EEPROM access SFRs are in bank 1. Apart from that all the SFRs on the x84 are in the same banks on the 628, but not that a 16F628 has many more SFRs and hence the GPRs (RAM) start at a different (higher) address.|
On a 16f628 the reset condition for port A is analog mode, which does
not exist on a 16x84. To make port A behave as on a 16x84 insert the following code:
OTP / Windowed PICs
|Some PICs (12C509, 12Fxxx) have a calibration value in the highest code location. When the internal RC oscillator is used (which will often be the case) this constant (actually a movlw instruction) is used to get the best possible accuracy of the clock. A windowed PIC has the calibration constant stored at the same location, but erasing the chip will also erase this constant. Use a programmer to read the calibration value and write it down, the bottom of the chip might be a good location.|
|The code protection of OTP PICs is controlled by an EPROM cell, just like the executable code. To prevent erasing the code protection bit before the code itself is fully erased Microchip has assured that this bit is either not erasable or very hard to erase. So when the code protection bit of a windowed PIC is set you are either one windowed PIC down, or it will have to stay in the eraser for a very long time. Advice: never enable code protection while developing!|
|Light through the window of a windowed (/JW) PIC can affect the (initial) state of the PICs RAM. This can cause differences in behavior between the windowed (development) and OTP (production) PICs. Advice: cover the window with something that is REALLY opaque, and/or make sure you initialize all variables.|
|Most PIC IO pins can be used either as input or as output, and when used as output can both source and sink current. But some pins can be used only as input, for instance MCLR on a 16F628 configured for internal reset, and some pins can only sink current (open collector / open drain), this is the case with RA4 on most PICs.|
|On PICs that support LVP programming the LVP pin should be tied to Gnd during HVP programming, even when LVP is disabled. Whether HVP will fail when this is not done is unsure and seems to depend both on the PIC type and on the revision, but the safest bet is to tie LVP down. Note that a different pin is used for LVP on the 16F628 (RB4), 16F87x (RB3) and the 18fxxx (RB5). When LVP is enabled the LVP pin must of course always be tied low during normal operation of the PIC.|
|On 14-bit core chips that have analog capabilities the pins that can have an analog function default to that analog function. This is not a coincidence: when a digital IO pin is tied to a voltage somewhere between high and low this can cause the internal circuits to drawn much more current than when IO pin levels are well-defined. A digital signal on an analog pin is no problem, but the reverse is, so the pins default to analog. But this means that for digital use such pins must first be configured for digital use! This applies especially to port a on the 16F628 and 16F87x.|
|Contrary to the analog functions, which are generally enabled by default, most digital special IO functions (UART, I2C, PWM etc) must be enabled before they can be used, and often the pin must also be configured for the appropriate direction. When using a special digital function it is advised to read both the section on those functions, and the section on the IO port and pin.|
|For some purposes (I2C for instance) open-collector (or open-drain) IO pins are needed. Most PICs have one such pin (RA4), but other pins can be used in this mode by writing a 0 to the pin itself and then writing the desired IO state to the tris (direction) register. A 0 in the tris register happens to set the bit to output, so writing to the tris mimics writing to an open-collector output pin.|
|A 16F628 does not have an A/D converter, but when all you want is to control the speed of an application you can use the ER (external resistor) clock configuration and use a potentiometer. The data sheets do not specify the relationship between the resistor value and the clock frequency, but measurements indicate that 10k gives around 8 MHz, dropping roughly linearly to 80 kHz for 2M.|
|Some PIC data sheets mention a TRIS instruction and warn that this instruction 'should not be used for compatibility with future products'. Although not using the TRIS instruction might be a good idea when you want maximum portability, it is a useful instruction (it can avoid some bank switching), it is still supported on most 14-bit core flash PICs (it even works on th 16F87x which do not document it), and it will of course continue to be supported on all PIC types that currently support it. So decide for yourself whether to use or avoid it.|
|PIC IO pins have a primitive protection, consisting of diodes to Vcc and Gnd. These diodes are certainly not meant to carry significant current, and it is a continuing debate whether they are designed to carry any current at all during normal operation of the chip. A funny consequence of these diodes is that when the power to a PIC is removed but one of its inputs is still high, it will be powered via the protection diode! This is not a guaranteed operation, but it can ruin an attempt to reset the PIC by removing the power.|
PICs use a funny IO architecture where a reading of a pin always returns
the current external level of the pin, which can be different from
the last value written to a pin, even when the pin is set as output, for
- PIC instructions execute in a pipeline, and for IO pins the read part of the next instruction takes place before the writing of the previous instruction.
- the load on the pin can be too high for it to reach its 'desired' level. This can easily happen (for a short time) when the load is capacitive.
All PIC byte instructions that modify some bits in a byte are read-modify-write instructions, so when two consecutive BCF (bit clear) instructions on an IO port are executed the second instruction can ruin the effect of the first because of the first reason. Actually a BCF instruction (and a lot of other instructions, like INCF) on a port can ruin any previous setting of that port because of the second reason! It should be noted that the first reason occurs far more often and can be avoided by placing a NOP or another instruction between any two read-modify-write instructions on the same IO port. But to really avoid all problems it is advised to allocate a separate register, do manipulations on that register, and copy it to the port register after each change (shadow register).
|Microchip calls the (only) IO port of the 8-pin PICs GP (General Purpose). For consistency with other PICs it might be easier to think of this port as port b.|
|12-bit core PICs (for instance 12C509) do not have a RET instruction. Yet the assembler accepts the RET mnemonic, and translates it as 'RETLW 0', which clears the W register. This can be an unpleasant surprise to a programmer who is used to a 14-bit core, where the W register can be used to return a calculated value.|
|Most instructions that operate on a file register can leave the result either in the same file register or in the W register. This is indicated by ',f' or ',w'. But actually f and w are just pre-defined constants, so the assembler accepts strange things like 'INCF w,w' which is interpreted as 'INCF 0,W'. When the ',f' or ',w' is omitted the assembler uses a default. I always forget what it is, so it is advised always to specify the target.|
|A radix (base) of a literal without an explicit radix specification is determined by an assembler option! Hence the only way to make sure that someone else can assemble your program (and get the same result) is to specify an explicit radix for each literal. To make sure that you have done so you could assemble with both (hex and decimal) defaults and check that the produced .hex file is the same.|
Some things that appear to be PIC assembler instructions are actually macro's that
can generate a number of instructions, not necessarily one. Funny things will
happen when you try to skip such a macro-instruction: when it has
generated more than one instruction you will skip only the first, when it has generated
zero instructions you will skip the next instruction!
[list those multi-instruction macro's]
The information about a particular chip is spread over a number of documents:
|The data sheet electrical characteristics contains a section called absolute maximum ratings. These figures indicate the circumstances which a chip will survive. Don't interpret these absolute maximum ratings as normal operating conditions.|
|The electrical characteristics document the circumstances for which the chip is guaranteed to work. This does not mean that it necessarily won't work when one or more of these characteristics are violated, just that the manufacturer does not guarantee it. For an one-off hobby project you could exceed some characteristics, test your circuit, find it working, and use it. For a very large production run you could do the same, but with much more testing. In between these extremes I would advice you to keep well within all characteristics.|
|Most PICs are sold in two speed grades: the maximum speed (currently often -20 for 20 MHz), and a 'lower grade', often -04 for 4 MHz. The 4 MHz version is often a bit cheaper. These two grades of PICs are made in the same process, using the same design, so one could reason that having two grades is just a marketing trick. All people I have heard of that have tried to run a -04 at the higher clock speed have reported success. On the other hand none of them can have applied the same tests Microchip will do on their chips (which alone might account for the price difference). So on the question 'can I use my 16F628-04 at 20 MHz': if you are a hobbyist: you are free to do so, and the chance that it will work OK (especially at 5.0 Volt Vcc and room temperature) is very high. There are reports of successful PIC over-clocking by a factor of almost 2 (a 16F84-10 at 18 MHz). But using a -04 at 20 MHz is still operating outside the guaranteed parameters, so for a professional product it should probably be avoided.|
|Put a 0.1 uF decoupling capacitor near the power connections of each chip, and a 100 uF (or 1000 uF when larger currents are to be expected) on the breadboard. These capacitors might not always be needed, but it is a waste (even for a hobbyist) to spend days tracking down a problem caused by insufficient power decoupling.|
|I put all my chips in a 'turned' chip socket to avoid breaking the chips flimsy legs. Some people have reported that when such a combo is put in a breadboard or (straight-pin) socket that board or socket can no longer reliably accept normal chips.|
|PICs are fairly robust against mistreatment, but I killed a few by applying the power in reverse. To protect me against this mistake I put a 1N400x 'fools diode' between the power lines, and I always use a 7805-based power supply.|
|Like everything in the real world code protection on PICs is not absolute. The old 16c84 was used widely in pay-TV stations, so it was a favorite target for hacking and receipts for defeating its code protection were circulating on the web. The newer PICs are reported to be invulnerable to these (rather simple) attacks, but undoubtedly other attacks exists. There are even companies that offer to retrieve the code from any protected PIC, but such services are not cheap and often require more than one PIC. The best (and probably only) way to protect your code from piracy is to make sure that it is not worth the effort by keeping your price low.|
|A surprisingly common mistake made by PIC beginners is to enable the watchdog. This will let the program run for a short time, then the watchdog will trigger and the chip resets. When the program is 'blink-a-LED' it might even seem to work correctly, although the blinking will probably be irregular and/or at an unexpected frequency. Note that the configuration setting (which contains the watchdog enable bit) should be specified in the source (assembler, C, Jal, ...) and that the programmer should load this setting. But some programmers ignore this setting and require the user to set the configuration in the programmer software.|
|When permanent (internal or external EEPROM) storage is used care should be taken that the data is not corrupted in a low Vcc (brownout) situation, which will often occur when power is removed and the voltage on the main capacitor falls slowly. The remedy to this problem is a brown-out protection, either internally or externally. The newer PICs have an internal brown-out protection (but it must be enabled in the configuration!). Brownout protection should also be used when it is for other reasons unacceptable that the PIC might behave erratically during power up and/or power down.|
PICs are generally quite sturdy and can still be functional after a lot of punishment.
There is a story of a windowed PIC that glowed softly due to a high current but worked
OK after the current was removed. But two things that can easily destroy a PIC are:
+---+--+---+ VCC |1 +--+ 8| GND OSC1,X1,GP5 |2 7| GP0,CIN+,PGD OSC2,X1,GP5 |3 6| GP1,CIN-,PGC VPP,/MCLR,GP3 |4 5| GP2,T0CKI,INT,COUT +----------+ 12Cxxx, 12Fxxx
+----------+ VPP,/MCLR,GP3 |4 5| GP2,T0CKI,INT,COUT OSC2,X1,GP5 |3 6| GP1,CIN-,PGC OSC1,X1,GP5 |2 7| GP0,CIN+,PGD VCC |1 8| GND +----------+ 12Cxxx, 12Fxxx bottom
+---+--+---+ Vref,AN2,RA2 |1 +--+ 18| RA1,AN1 CMP1,AN3,RA3 |2 17| RA0,AN0 CMP2,TOCKI,RA4 |3 16| RA7,OSC1,CLKIN VPP,/MCLR,RA5 |4 15| RA6,OSC2,CLKOUT GND |5 14| VCC INT,RB0 |6 13| RB7,T1OSI,PGD RX,DT,RB1 |7 12| RB6,T1OSO,T1CKI,PGC TX,CK,RB2 |8 11| RB5 CCP1,RB3 |9 10| RB4,(LVP 16F628) +----------+ 16x84(A), 16F62x
+----------+ CCP1,RB3 |9 10| RB4,(LVP 16F628) TX,CK,RB2 |8 11| RB5 RX,DT,RB1 |7 12| RB6,T1OSO,T1CKI,PGC INT,RB0 |6 13| RB7,T1OSI,PGD GND |5 14| VCC VPP,/MCLR,RA5 |4 15| RA6,OSC2,CLKOUT CMP2,TOCKI,RA4 |3 16| RA7,OSC1,CLKIN CMP1,AN3,RA3 |2 17| RA0,AN0 Vref,AN2,RA2 |1 18| RA1,AN1 +----------+ 16x84(A), 16F62x bottom
+---+--+---+ VPP,/MCLR |1 +--+ 28| RB7,PGD AN0,RA0 |2 27| RB6,PGC AN1,RA1 |3 26| RB5,(LVP 18F) Vref-,AN2,RA2 |4 25| RB4 Vref+,AN3,RA3 |5 24| RB3,(LVP 16F) TOCKI,RA4 |6 23| RB2 /SS,AN4,RA5 |7 22| RB1 GND |8 21| RB0,INT CLKIN,OSC1 |9 20| VCC CLKOUT,OSC2 |10 19| GND T1CKI,T1OSO,RC0 |11 18| RC7,RX,DT CCP2,T1OSI,RC1 |12 17| RC6,TX,CK CCP1,RC2 |13 16| RC5,SDO SCK,SCL,RC3 |14 15| RC4,SDI,SDA +----------+ 16F870, 16F872, 16F876 18F242, 18F252
+----------+ SCK,SCL,RC3 |14 15| RC4,SDI,SDA CCP1,RC2 |13 16| RC5,SDO CCP2,T1OSI,RC1 |12 17| RC6,TX,CK T1CKI,T1OSO,RC0 |11 18| RC7,RX,DT CLKOUT,OSC2 |10 19| GND CLKIN,OSC1 |9 20| VCC GND |8 21| RB0,INT /SS,AN4,RA5 |7 22| RB1 TOCKI,RA4 |6 23| RB2 Vref+,AN3,RA3 |5 24| RB3,(LVP 16F) Vref-,AN2,RA2 |4 25| RB4 AN1,RA1 |3 26| RB5,(LVP 18F) AN0,RA0 |2 27| RB6,PGC VPP,/MCLR |1 28| RB7,PGD +----------+ 16F870, 16F872, 16F876 18F242, 18F252 bottom
+-----+--+-----+ VPP,/RST |1 +--+ 40| RB7,PGD AN0,RA0 |2 39| RB6,PGC AN1,RA1 |3 38| RB5,(LVP 18F) AN2,Vref-,RA2 |4 37| RB4 AN3,Vref+,RA3 |5 36| RB3,(LVP 16F) T0CKI,RA4 |6 35| RB2 /SS,AN4,RA5 |7 34| RB1 /RD,AN5,RE0 |8 33| RB0,INT /WR,AN6,RE1 |9 32| VCC /CS,AN7,RE2 |10 31| GND VCC |11 30| RD7 GND |12 29| RD6 CLKIN,OSC1 |13 28| RD5 CLKOUT,OSC2 |14 27| RD4 T1CKI,T1OSO,RC0 |15 26| RC7,RX,DT CCP2,T1OSI,RC1 |16 25| RC6,TX,CK CCP1,RC2 |17 24| RC5,SDO SCK,SCL,RC3 |18 23| RC4,SDI,SDA RD0 |19 22| RD3 RD1 |20 21| RD2 +--------------+ 16F871, 16F877, 18F252, 18F452
+--------------+ RD1 |20 21| RD2 RD0 |19 22| RD3 SCK,SCL,RC3 |18 23| RC4,SDI,SDA CCP1,RC2 |17 24| RC5,SDO CCP2,T1OSI,RC1 |16 25| RC6,TX,CK T1CKI,T1OSO,RC0 |15 26| RC7,RX,DT CLKOUT,OSC2 |14 27| RD4 CLKIN,OSC1 |13 28| RD5 GND |12 29| RD6 VCC |11 30| RD7 /CS,AN7,RE2 |10 31| GND /WR,AN6,RE1 |9 32| VCC /RD,AN5,RE0 |8 33| RB0,INT /SS,AN4,RA5 |7 34| RB1 T0CKI,RA4 |6 35| RB2 AN3,Vref+,RA3 |5 36| RB3,(LVP 16F) AN2,Vref-,RA2 |4 37| RB4 AN1,RA1 |3 38| RB5,(LVP 18F) AN0,RA0 |2 39| RB6,PGC VPP,/RST |1 40| RB7,PGD +--------------+ 16F871, 16F877, 18F252, 18F452 bottom
|Google: definitely my best friend on the web|
|Findchips: Looking for the availability and/or price of a chip? Try Findchips!|
|Chipdir: van Ganswijk's Chipdir|
Manufacturers of microcontrollers and other hardware (to get the data sheets):
|Microchip: PIC microcontrollers (12F675, 16F628, 16F877, 18F452, midrange reference manual (pdf))|
|Ubicom: very fast PIC clones|
|Atmel: AVR and 8051 microcontrollers|
|Motorola: 68HC microcontrollers|
|Philips: 8051 microcontrollers, I2C peripherals, also a good site for TTL data sheets|
|Parallax: BASIC Stamps|
|Dallas / Maxim: MAX232 serial interface chip, Dallas 1-wire peripherals|
|National Semiconductor: LMxxx temperature sensors|
|Microchip: MPLAB, a free integrated assembly development environment.|
|gputils: GPL PIC assembler development tools|
|C2C: Pavel has sold his compilers to Kanda, but some free versions can still be downloaded from this page|
|Optama PIC/SX C compiler: $199, this seems to be the Kanda version of C2C|
|FED C: UKP 60|
|CC5X a compiler that is described both as 'efficient' and as 'a bit special', a free version is available that generates up to 1K code|
|Hi-Tech C compiler: $850, but a free 21 day demo is available|
|Hi-Tech PICC Lite: free, targets a number of 16F types.|
|CCS C compilers: different compilers for the 12 and 14 bit PICs, $99 each|
|Byte Craft MPC: the 'professional' PIC C compiler with matching price, a free demo is available which produces only a listing file|
|MediumC PIC-C compiler: source of a primitive C compiler, interesting for a compiler writer only|
Other compilers and interpreters:
|Jal: my own PIC language and compiler, free|
|MEL basic compilers: 'professional' compilers with a ditto price ($100, $250)|
|Oshonsoft: Basic / assembler IDE with simulator, time-limited trial version, reasonable prices|
|XCSB basic compiler: has a LITE version available free of charge for personal non-commercial use.|
|Ralf Pagel's PIC-BASIC: EUR 45, which seems rather expensive to me|
|Zoran Ristic'spascal demo|
|Basic18 for 18F chips, gerenates 1500 instructions without registration|
|BS-1/4: basic interpreter for very small programs only, free for personal use|
|Myke Predko's PredBASIC87x Interpreter : a basic interpreter for the 16F877, free|
|Pascalite: a Pascal development system for PICs, they charge per target|
|Microchip's MPLAB contains a simulator|
Where to buy PICs etc:
|Voti web shop: my very own PIC shop (buy a 16F877 with WLoader!)|
|P.H.Anderson: PICs and much more|
|R.T.Nollet: SX PIC clones, BASIC Stamps|
|Dontronics: PICs, SIMMstick boards, programmers|
|Crownhill: PICs and more|
|Digi-Key: wide range of components, including PICs|
|Mouser Electronics: wide range of components|
|Arrow: smaller range of components, but often cheaper than Digi_Key or Mouser|
|Allied Electronics: another mail-order shop|
|Jameco: and yet another mail-order shop|
|PMB Electronics: webshop for PICs and other electronics, New Zeeland|
Where to get answers for your PIC questions:
|piclist: THE forum for PIC users, heavy traffic (~ 100 posts/day), lots of noise, but also the source for good answers (to good questions only..)|
|PIC at techref: lots of links, tricks, etc.|
|the newsgroup comp.arch.embedded (or try the mailgate archive)|
Software for the typical port-wiggeling tupe of programmer:
|Bonny Gijzen's ic-prog|
|dspicprg and dspicdmp|
Some free programmer designs:
|Trivial 16F87X LVP programmer: a typical parallel port LVP programmer|
|JDM PIC-Programmer 2: simple serial port programmers, the simples uses just one resistor|
|Stef Mientki's USB programmer|
|Fluffy and Fluffy2: the only free SX programmer designs that I know of|
|The pocket programmer: not a simple design, but it can work stand alone (without a PC), and do production programming (variable VCC verification).|
|ic-prog: software that drives lots of programmers, the site also provides lots of programmer schematics|
|PonyProg serial device programmer: like ic-prog: software that drives lots of programmers|
|Wisp628: my in-circuit flash PIC programmer (also available as kit|
|WLoader: my 16F87x bootloader (with links to other bootloaders)|
Some commercial programmers:
|PICSTART Plus: the 'official' Microchip development programmer. Not cheap, but well integrated into MPLAB and updates are made available to support new chips. Can be used to do in-circuit programming, but this can give problems. See picp for a Linux command-line interface.|
|Microchip's MPLAB ICD: for the 16F87x chips only, but much cheaper than PICSTART, and supports in-circuit debugging.|
|PICALL: programs a wide range of PICs (including those that require parallel programming), but also SX and Atmel AVR. The design is free, but you must buy the kit (~ $70) to get the preprogrammed chip.|
|WARP-13 (on PHA's pages): ~ $99, MPLAB compatible, programs PICs and Atmel AVRs.|
|Olimex: sells some cheap programmer kits, for instance the PicStart+ compatible PIC-MPC|
Other introduction pages:
|Guide to use the PIC is a (translated) japanese PIC introduction page, with a good explanation of the 14-bit core architecture and instruction set.|
|Bubblesoftonline: a PICmicro®MCU teaching package.|
|Fred Stevens' book (pdf) "Getting started with PIC microcontrollers" "Getting started with PIC microcontrollers": a bit outdated, actually just an introduction to using the 16F84|
Other things I found useful:
|CadSoft's Eagle circuit / PCB editor has a free version for limited size boards|
|PFE (Programmers File Editor) is a free text editor, often used by programmers (including me)|
|"the Art of Electronics" by Paul Horowitz and Winfield Hill (Second Edition, 1988, ISBN 0-521-37095-7) is sort of a bible among electronics enthusiasts|
|Jones on Stepping Motors is the first document to read when you want to start using stepper motors|
|Richard Ottosen's Gizmo page has links to the original PIC1650 documents.|
|Peer Ouwehand's HD44780 LCD page|