Frequently asked questions for Microchip
PIC 8 bit microcontroller programming
How I started microcontroller programming
Why I use PIC microcontrollers
How to start with PIC microcontrollers?
PIC16F84
PIC16F77
PIC16F877
Which development environment do I use?
First steps in PIC programming
Common programming
questions
How to assemble PIC code in MPLAB
Advanced steps in PIC programming
General
Paging - large
code considerations
High level languages
C
Debugging hints
General
RS232 communication
issues
LCD communication
issues
In case of errors
Compile errors
Page crossings
PIC History
Call it RISC...
Scientific curiosity
From I/O handling to
RISC controller
I first entered the microcontroller world with a proprietary, mask-programmed controller kit bought from Conrad Electronics, a german electronics distributor. It was a Conrad C-Control Basic kit, a 68HC05B based controller board with RS232 link and an external serial EEPROM as program memory. The user develops its application in a kind of BASIC programming language, which is afterwards translated by the development software into byte-tokens. The byte tokens are then loaded into the serial EEPROM. During execution, the controller reads these byte-tokens from the external EEPROM and interprets them using the internal, pre-programmed routines. For first contact with microcontrollers, it was a good approach, although there were some unsatisfying facts:
These reasons have lead me to change to another controller
solution. Finally, I decided to change to the Microchip PIC controllers.
The Microchip PIC microcontrollers are a convenient and cost-effective solution for a lot of home-made applications, because:
Although I use PIC microcontrollers often, I would not consider
the PIC microcontroller as high-performance RISC controller -
as claimed by the manufacturer. High-performance - compared to
what? There is no reference for comparison given...
On the other hand, I personally would implement a more sophisticated
architecture based on one instruction per oscillator cycle, i.e.
1 MIPS @ 1 MHz. This is more power-efficient and would at least
indicate that there is best use made of every clock cycle when
using a single execution pipeline. For the core, I would check
the requirements carefully and decide whether to use a two, three
or four stage pipeline. And for not loosing any performance, additional
delayed-branching would be introduced. A deeper stack for the
program counter may also be suitable, especially when serving
a lot of interrupt sources and doing prioritized interrupt handling
in software (i.e. another high-priority ISR call during a low-priority
ISR call). Finally, an ability to check the stack levels used
would also be welcome, as well as hardware-based context save
on entrance and exit of the interrupt service routine.
I started with the PIC16C84 (an early EEPROM version of today's
standard flash version 16F84).
Today, I would say, the PIC16F84 is the best-suited Microchip
RISC controller to start with:
Once you have acquired some experience in PIC programming and you are familiar with the PIC architecture, I suggest to switch to the PIC16F77 (that's what I did also). It offers a lot of peripheral hardware blocks, so that you don't have to handle this in software (e.g. RS232 transmission and reception):
You can also switch directly to the PIC16F877, which offers additional peripheral interfaces, especially if you want to connect some I²C peripheral components:
Get the latest data sheets at www.microchip.com
I started with the PICSTART Plus development programmer from Microchip in 1998, and I still use the same programmer today:
PICSTART Plus Programmer |
In-Circuit Debugger 2 (ICD2) |
This setup programs most PIC microcontrollers (PIC12xxx, PIC16xxx, PIC17xxx, PIC18xxx), and allows firmware updates whenever new PIC controllers come out. I have never experienced any issues using this commercially available programmer with the Windows operating system (Win95, Win98, WinXP). You just have to ensure that the intended RS232 port to use is in the range of Com1 to Com4.
The latest version of the PICSTART Plus programmer allows instant software-based firmware updates to the internal flash controller. See buy.microchip.com for ordering details.
PICSTART Plus Processor Upgrade Kit |
PICSTART Plus Programmer |
PICSTART Plus Programmer |
Years ago, I had to buy an extra PIC controller (UV-erasable PIC17C44JW) and had to burn the corresponding firmware to it (HEX-file supplied with MPLAB IDE). But Microchip abandoned this re-programming procedure of the 17C44JW some times ago. Today, the firmware upgrade of the programmer is performed directly from MPLAB IDE, but only if you have one of the lastest flash-based PICSTART Plus programmer, or installed the PICSTART Plus Processor Upgrade Kit (containing a PIC18F6720) in your elderly programmer (#UK003010, costs about 29.00 US-$, ordering information).
For ambitious starters, I recommend to order:
Note that with ICD2:
Please see also the latest* README text files for PICSTART Plus (17 kB) & ICD2 (32 kB)
* by 19.06.2005
|
Citing Microchip's readme.txt of PICSTART Plus programmer: "Program and read problem of PIC16F87X PIC16F87X devices are shipped with low-voltage programming enabled. PICSTART Plus programmer uses the high-voltage programming method. Some devices do not exit programming mode properly if low-voltage programming is enabled, resulting in invalid read and programming operations. Place a 10 Kohm resistor between the RB3 pin and one of the ground pins on the programming socket. Refer to the device datasheet for the pinout of the specific device." |
As first step, read the documentation of your controller, especially the memory and register architecture, the instruction set (PIC Instruction Set Quick Reference) and the I/O port section. Then try to implement a blinking LED application using the PIC16F84 and a busy loop for waiting (you can also use my assembler module m_wait.asm).
If your LEDs are blinking, you certainly want to connect your controller to your PC to exchange some data. Build a RS232 hardware setup with a MAX232 level shifter and a PIC. If you use the PIC16F84, the RS232 communication must be done by software. You can use the 'Simple RS232 interface'. Try first to burn the provided HEX-file onto the PIC16F84 to check for proper HW-setup. Once everything is working well, you can get the assembler source code and change the content according to your needs.
Question: What kind of instructions are BANK1 and BNEQ?
Answer: These are my standard macro definitions declared in the module file m_bank.asm. If you include this module file in your main program, you can make use of these instruction macros. For instance, the macro BANK1 performs a memory bank change to bank 1. Further, the macro BNEQ 0x23,LAB1 translates to 'branch on not equal w and 0x23' and performs a jump to label LAB1, if the working register w does not match the value 0x23.
Question: What kind of instructions are BNZ and SKPNZ, since they are not listed in the Instruction Set Chapter of my PIC controller?
Answer: These are 'Special Instruction Mnemonics'
listed in Table B.11 in the PIC Instruction Set Quick Reference, i.e. built-in
mini-macros of the MPLAB assembler. For instance, SKPNDC translates
as 'Skip on no digit carry' and simply assembles BTFSC
3,1.
Only declare the main assembler file as source file in the MPLAB project. For instance, this is the file PIC_Test.asm in the project PIC_Test.mcp below on the picture. It will generate a HEX-file named PIC_Test.hex when you execute 'build' or 'build all'. Ensure that the pathes to the include files exist - or remove the pathes and copy the include files to the directory of the main source.
The include files must not be listed for separate compilation under the MPLAB Project. They are just included in the main source through include statements. During assembly time (MPASM), these files are just inline expanded and treated as normal assembler code. Separate compilation is neither needed nor possible, since I've written the module code for inline compilation (and initially for simplicity) with no object or linker directives.
Of course, when project size and complexity increases, one may consider to rewrite the code to object-based sources...
MPLAB IDE |
Once the communication between the PIC controller and the PC is running successfully, I suggest to implement a visual interface on your peripheral device (the PIC controller). This can be done easiest by using a commonly available dot matrix LCD and one of my LCD assembler modules.
If more sophisticated I/O functionality is desired, you can consider to attach a standard AT keyboard (ordinary PS/2 PC keyboard) to the microcontroller. Look therefore at the AT keyboard projects.
When your code grows, you will run into the architectural issues of the PIC microcontroller. The PIC instruction set has been defined - in early days - as a natural engineering trade-off between functionality and program memory requirements. One advantage of a larger instruction word width is the increase in direct addressable space for immediate instructions, e.g. 'CALL Label' with Label resolved to a program memory location by the linker/assembler. On the contrary, larger instruction word width require more program memory, what results in larger chip area and therefore higher manufacturing costs.
The PIC16xxx microcontroller series features immediate address instructions (e.g. 'CALL' or 'GOTO'), which support 11 bit immediate values. Using 11 bits for immediate addressing, we can only address 2k words in the program memory. But what if we want to support larger memory space? One possibility to work around this limitation is to introduce a new instruction in order to jump between the different 2k memory blocks. That's why we need to deal with the upper two bits ([4:3]) of the PCLATH register. These bits cannot be altered with 'CALL' or 'GOTO' instructions, but need to be set manually before the jump.
There is quite a good discussion and elaboration of methods
to deal with paging for the PIC16xxx microcontrollers on this site.
There exist several commercial solutions to program the PIC microcontroller in C. Unfortunately, little of them are available for free.
If you know other free C compilers, you are kindly requested to email me. I will add it to the list below.
List of free C compilers (not exhaustive):
In case you have built a PIC application including serial communication (RS232), but it does not work properly, try to debug it the following way:
1. Write a simple PIC assembler program for the PIC16F84 @ 4 MHz using the module m_rs096.asm. The program keeps transmitting a dedicated character every second, e.g. something like:
LOOP SEND '@'
WAITX d'16',d'7' ; 1.045 s @ 4 MHz, extended with specific prescaler
goto LOOP
|
You may also use one of the communication test programs, commtest1.asm or commtest2.asm, which transmit constantly status messages '@' and echo on every received character.
2. Setup the HyperTerminal program (Win9x, WinXP) using the standard settings as follows:
Standard RS232 ComPort settings |
Start the HyperTerminal application using the standard settings.
It should now receive a '@' every second from the PIC microcontroller.
If not, check the MAX232 and the RS232 connectors, until you receive
the characters...
Question: I can not figure out the connection between dot matrix LCD and PIC microcontroller. Do you have a schematic?
Answer: Basically, there is a text description in the header section of each LCD assembler module file. But here is also a PDF schematic to illustrate the connection between display and controller.
Question: I have downloaded from your site the assembler module file 'm_lcd_bf.asm' for my PIC project. The LCD display I use is a 20x4 (CrystalFontz CFAH2004A-TMI-JP), but it does not work. I dont see any character and the problem is not the contrast
Answer: I've recently adapted some parts of the initialization
section of the LCD module files (longer wait delay after display
clear). I assume you have a newer type of display controller than
the traditional Hitachi HD44780 (PDF data sheet, 389 kB). In case you have
the LCD controller Samsung KS0073 (PDF
data sheet, 673 kB), you have to set the constant 'LCDTYPE'
to 0x1 in your main program. This adds specific configuration
commands of the new controller type, i.e. the extended function
set to set up the line count (PDF
data sheet, 186 kB). You may have to adapt the line count
to your KS0073-type display in the extended function set
part of the LCD initialization section of the LCD module file
(e.g. m_lcde.asm).
If this does not help, try to use longer delays for the initialization
procedure.
Below the declarations for the module file m_lcde.asm. First try the circuit with a 4 MHz crystal, later on with 20 MHz. If this does not work, you may have to adapt the initialization section to your specific display controller (latency, commands). But first try with the standard settings for PIC16F7x and 4 MHz:
LCDtris equ TRISD ; LCD data on low nibble of portD LCDport equ PORTD #define LCD_ENtris TRISE,0x00 ; EN on portE,0 #define LCD_EN PORTE,0x00 #define LCD_RStris TRISE,0x01 ; RS on portE,1 #define LCD_RS PORTE,0x01 #define LCD_RWtris TRISE,0x02 ; RW on portE,2 #define LCD_RW PORTE,0x02 CONSTANT BASE = 0x20 ; base address of user file registers #include "..\m_bank.asm" #include "..\m_wait.asm" #include "..\m_lcde.asm" |
In case of failure, ensure that you do not use the temporary
registers at BASE+0 - BASE+3 elsewhere in your code, especially
not in your interrupt service routine (ISR)! If this setup works
perfectly, you may upgrade to the more efficient LCD modules m_lcde_bf.asm
or m_lcdexbf.asm (busy flag instead of wait loop).
If you cannot compile the projects and errors like below appear, you did not specify the path to your include files correctly. Check the '#include' statements:
#include "..\m_bank.asm" #include "..\m_wait.asm" |
The errors generated by wrong '#include'-pathes look like:
|
Executing: "C:\Tools\Electronics\MPLAB_64\MCHIP_Tools\mpasmwin.exe"
/q /p16F84 "LCDx_test.asm" /l"LCDx_test.lst"
/e"LCDx_test.err" Error[101] ..\..\M_LCD.ASM 113 : ERROR: (Missing include file: m_bank.asm) Error[101] ..\..\M_LCD.ASM 116 : ERROR: (Missing include file: m_wait.asm) Error[113] ..\..\M_LCD.ASM 279 : Symbol not previously defined (LCDclk) Error[113] ..\..\M_LCD.ASM 283 : Symbol not previously defined (LCDclk) Error[122] ..\..\M_LCD.ASM 290 : Illegal opcode (WAIT) Error[122] ..\..\M_LCD.ASM 296 : Illegal opcode (LCDWAIT) Error[116] ..\..\M_LCD.ASM 184 : Address label duplicated or different in second pass (BANK0) Error[108] ..\..\M_LCD.ASM 189 : Illegal character (4) Error[113] ..\..\M_LCD.ASM 193 : Symbol not previously defined (LCDclk) Error[122] ..\..\M_LCD.ASM 194 : Illegal opcode (LCDWAIT) Error[113] ..\..\M_LCD.ASM 200 : Symbol not previously defined (LCDclk) Error[122] ..\..\M_LCD.ASM 201 : Illegal opcode (LCDWAIT) Error[113] ..\..\M_LCD.ASM 205 : Symbol not previously defined (LCDclk) Error[122] ..\..\M_LCD.ASM 206 : Illegal opcode (LCDWAIT) |
Although most of my code is below the critical size of 2k instruction
words, page crossings may occur if you extend the assembler source
code to your needs. Please read the recommendations about paging above.
Below are some interesting text snippets found on the web about
the history of Microchip PIC controllers.
Citing John Bayko (Tau), <john.bayko@sk.sympatico.ca>:
A complete version of John Bayko's interesting 'Great Microprocessors of the Past and Present' may be retrieved at http://www.sasktelwebsite.net/jbayko/cpu.html.
The roots of the PIC originated at Harvard university for a
Defense Department project, but was beaten by a simpler (and more
reliable at the time) single memory design from Princeton. Harvard
Architecture was first used in the Signetics 8x300, and was adapted
by General Instruments for use as a peripheral interface controller
(PIC) which was designed to compensate for poor I/O in its 16
bit CP1600 CPU. The microelectronics division was eventually spun
off into Arizona Microchip Technology (around 1985), with the
PIC as its main product.
The PIC has a large register set (from 25 to 192 8-bit registers,
compared to the Z-8's 144). There are up to 31 direct registers,
plus an accumulator W, though R1 to R8 also have special functions
- R2 is the PC (with implicit stack (2 to 16 level), and R5 to
R8 control I/O ports. R0 is mapped to the register R4 (FSR) points
to (similar to the ISAR in the F8, it's the only way to access
R32 or above).
The PIC16x is very simple and RISC-like (but less so than the RCA 1802 or the more recent 8-bit Atmel AVR microcontroller which is a canonical simple load-store design - 16-bit instructions, 2-stage pipeline, thirty-two 8-bit data registers (six usable as three 16-bit X, Y, and Z address registers), load/store architecture (plus data/subroutine stack)). It has only 33 fixed length 12-bit instructions, including several with a skip-on-condition flag to skip the next instruction (for loops and conditional branches), producing tight code important in embedded applications. It's marginally pipelined (2 stages - fetch and execute) - combined with single cycle execution (except for branches - 2 cycles), performance is very good for its processor catagory.
The PIC17x has more addressing modes (direct, indirect, and relative - indirect mode instructions take 2 execution cycles), more instructions (58 16-bit), more registers (232 to 454), plus up to 64K-word program space (2K to 8K on chip). The high end versions also have single cycle 8-bit unsigned multiply instructions.
The PIC16x is an interesting look at an 8 bit design made with
slightly newer design techniques than other 8 bit CPUs in this
list - around 1978 by General Instruments (the 1650, a successor
to the more general 1600). It lost out to more popular CPUs and
was later sold to Microchip Technology, which still sells it for
small embedded applications. An example of this microprocessor
is a small PC board called the BASIC Stamp, consisting of 2 ICs
- an 18-pin PIC16C56 CPU (with a BASIC interpreter in 512 word
ROM (yes, 512)) and 8-pin 256 byte serial EEPROM (also made by
Microchip) on an I/O port where user programs (about 80 tokenized
lines of BASIC) are stored.
Citing Len Umina <umina@kirk.mchip.com> from http://www.brouhaha.com/~eric/pic/faq.txt:
Actually, the PIC architecture was first integrated by Signetics for a company in San Jose (Scientific Memory Systems as I recall) using Bipolar technology and dubbed the 8X300. Prior to that, the architecture had been a scientific curiosity since its invention by Harvard University in a Defense Department funded competition that pitted Princeton against Harvard.
Princeton won the competition because the mean time between failure (MTBF) of the simpler single memory architecture was much better, albeit slower, than the Harvard submission. With the development of the transistor and IC's, the Harvard Architecture is finally coming into its own.
Microchip has made a number of enhancements to the original
architecture, and updated the functional blocks of the original
design with modern advancements that are in concert with existing
architectural processes and
enabled by the low cost of semiconductors.
Citing Alex R. Baker <alex@microchp.demon.co.uk> from http://www.brouhaha.com/~eric/pic/faq.txt:
Back in 1965, General Instruments (GI) formed a Microelectronics Division, and indeed used this division to generate some of the earliest viable EPROM and EEPROM memory architectures. As you may be aware, the GI Microelectronics Division were also responsible for a wide variety of digital and analog functions, in the AY3-xxxx and AY5-xxxx families.
GI also generated a 16 bit microprocessor, called the CP1600, in the early 70s. This was a reasonable microprocessor, but not particularly good at handling I/Os. For some very specific applications where good I/O handling was needed, GI designed a Peripheral Interface Controller (or PIC for short), in around 1975. It was designed to be very fast, since it was I/O handling for a 16 bit machine, but didn't need a huge amount of functionality, so its microcoded instruction set was small. Hopefully, you can see what's coming....yes, the architecture designed in '75 is substantially the PIC16C5x architecture today. Granted, the1975 version was manufactured in NMOS, and was only available in masked ROM versions, but still a good little uC. The market, however, didn't particularly think so, and the PIC remained designed in at a handful of large customers only.
During the early 80s, GI took a long hard look at their business, and restructured, leaving them to concentrate on their core activities, which is essentially power semiconductors. Indeed they are still doing this very successfully now. GI Microelectronics Division became GI Microelectronics Inc. (a wholly owned subsidiary), which in 85% was finally sold to venture capital investors, including the fab in Chandler, Arizona. The venture capital people took a long hard look at the products in the business, and got rid of most of it - all the AY3- and AY5- parts and a whole bunch of other stuff, leaving the core business of the PIC and the serial and parallel EEPROMs. A decision was taken to restart the new company, named Arizona Microchip Technology, with embedded control as its differentiator from the rest of the pack.
As part of this strategy, the PIC165x NMOS family was redesigned to use one of the other things that the fledgling company was good at, i.e. EPROM - the concept of the CMOS based, one-time-programmable (OTP) and eraseable EPROM program memory PIC16C5x family was born.
Last updated: 04.12.2005