A microcontroller such as the 84 is- by its nature- a complete computer on a chip. It has 1: a processor and 2: registers, as well as 3: program and 4: data memory. This makes it different from mere CPUs which have only the processor and registers.
1: The PIC84 has an 8-bit processor, and thats all we need to know about it!
2: The 58 registers are the processors internal working storage. Referring to [PIC figure 4-2 The page, figure, and table numbers reffered to here come from an older version of the '84 datasheet which is available at http://www.piclist.com/images/piclist/30445B.PDF the current datasheet for the modern version of the '84 is available at microchip.com], youll see that some of these have names (STATUS, PORTB etc): these have special functions and well examine them later. PORTA, for instance, contains the contents of one of the I/O ports, namely port A. There are 36 general purpose registers [now 68 in the 16F84A], and we can consider these as ours (as opposed to the processors special ones) and use them as our scratch pad.
3: The 84 has 1K x 14 program memory: that means there are 1024 program locations, and each is 14 bits wide. Youll see from [PIC fig 3.4.1] that the memory goes from 0000h to 03FFh: 03FFhex is 1023 in decimal so there are 1024 locations including 0000. The 14 bits wide part comes from the length of each instruction: look at any one in [PIC section 4.2] and youll see that each is 14 bits long. For instance, ADDLW is 11 111X kkkk kkkk : dont worry about what this means, just count it! Well be using this memory extensively later on.
4: It has 64 bytes data memory, which is used for storage of, for instance, calibration values. Well look at the use of this EEPROM memory last in this booklet.
In addition, the device includes 5: four types of interrupt and 6: 13 I/O pins.
5: Interrupts are means of something preempting the program. A button press by an operator, could interrupt the programs normal flow and cause some special treatment. Well examine the 84s interrupt techniques later.
6: The use of the I/O pins is key to the use of a device like the 84, since any process consists of 3 parts- the input to the process, the process itself, and the output. The 84 has 13 pins configured as 2 ports: port A comprises 5 pins and port B has 8; and well be using them later.
There are 35 instructions in the PIC84 instruction set; all are 14 bits long, and consist of an opcode and operand/s. Basically, the opcode specifies what to do and the operand/s specify how or where. These instructions are split into 3 groups: byte-oriented, bit-oriented and literal & control. Later on we will use each and every one of these operations, firstly individually (usually trivially) and secondly with others in more meaningful scenarios.
For now, lets look at one of the instructions. Concentrate more on the format thereof, rather than the function which well see closely later. Ive chosen the instruction ADDWF- see [PIC table 4.2]. In this tutorial, I have adopted the Courier font below for all coding examples. The syntax of this instruction is:
ADDWF f,d
and youll see this sort of look in many other instructions.
This is an appropriate time to introduce the working register: this is a special register (over and above those already mentioned) known as the W register, and it is where the arithmetic and logic unit (ALU) does the maths. Any instruction with the W in the name acts on the working register. Generally, some other register is known as F in these commands. So- almost intuitively- we can understand that the command ADDWF adds the working register to register F. But where is register F?
Have a look at [PIC fig 4-2]: each register (other than W, that is, which isnt in the figure since it is a special one) is given a hexadecimal address. For instance, PORTA is 05h, TRISA is 85h and we could use one of the 36 GP registers between 0Ch and 2Fh like 3Ch. The f in the command is a place holder for the actual address of the register F; remember there is no register F as such- it is a generic name for some register or other. So, we would code the instruction as:
ADDWF 3Ch,d
Well, not quite- whats the d for? It is the destination of the result, and youll see this in many operations. Depending on our needs at the time, we need to choose to put the result either back into the working register or register F itself. [PIC page 51] explains that d may be 1 or 0: a 0 causes the result to go to W, and a 1 puts it in F. Finally, therefore, this command could be either of the following, depending on our needs:
ADDWF 3Ch,0 ; adds W to reg 3C, result to W
ADDWF 3Ch,1 ; adds W to reg 3C, result to 3C
Lets get on with actually writing a simple program . . . .
This sample program serves a number of purposes. Apart from showing how to use a few instructions, it also introduces a couple of the assembler concepts and will also show some simple simulator techniques. The program, simple.asm is presented below; Ill walk you through it line by line.
"...tried to build it i got a cannot find .hex message when i looked closer 3 lines needed altering H'10' H'15' and H'08' needed changing to 0010h 0015h and 0008h then it worked perfectly"
;simple.asm ;to demonstrate the look & feel of a program ; and introduce some instructions & directives ;***************** setup ******************************* processor 16C84 ;processor type org 0010h ;origin of program in memory w equ 0 ;in byte instructions, use w & f f equ 1 ;instead of 0 & 1, its much clearer my_reg_1 equ H10 ;position my 2 registers in file my_reg_2 equ H15 ; map at h10 &H15 ;***************** program ****************************** ;all we're going to do, is load the accum (reg w) with ; some values and play around with some arithmetic in w ; and my_reg_1&2 movlw H08 ;put value H08 into w register movwf my_reg_1 ;move contents of w to my_reg_1 ; note- same as movwf 10h, since ; my_reg_1 and 10h are same thing movlw 32h ;put 32h into w reg addwf my_reg_1,f ;add contents of w to that of my_reg_1 ; answer goes into my_reg_1, due to f movlw 92h ;put value 92h into w register movwf my_reg_2 ;move contents of w to my_reg_2 ; note- same as movwf 15h, since ; my_reg_2 and 15h are same thing movlw 26h ;put 26h into w reg subwf my_reg_2,w ;subtr w from my_reg_2 ; answer goes into w end
Lets examine this sample program. You should verify the following by finding each directive or instruction in the appropriate Microchip book:
In the part called program, we meet a number of 84 instructions. Check the full descriptions in [PIC] if you like; well be looking at them later, anyway.
Lets assemble and run this program . . .
Using MPLAB to debug the program
This is a three step process: edit the source code, assemble it, and then run the simulator to see what happens. If you worked through the MPLAB tutorial, you will already know about the editing and assembling. Ill assume you have and do, and so we can move to the simulation.
With sample .asm successfully assembled, and the editor being the only window open in MPLAB, single-step through the program (the footstep icon). Not too helpful- you see each line of the program being highlighted as it is activated, but thats it.
So, lets start to use a few of the simulators other facilities. I suggest you open the following other windows in MPLAB. They all serve similar purposes- namely to see whats happening in the registers- but all implement differently. I found it useful to have them all open at once, to compare the implementations:
Window > File Register
This window lists the contents of all file registers from 00 to 2F- ie, it does not show those in the region 80 to 8B. As you step through the program, you will be able to see the hex contents of registers 10h and 15h change. Note that any register whose contents have just changed is shown in red- this goes back to blue on the next step (unless theres another change of course).
Window > Special Function Registers
Here you can see the SFRs by name, rather than location which is what the previous window shows. The contents are shown in decimal, hex and binary.
Window > New Watch Window
This is your custom window into the registers, and it allows you to select which registers you want to monitor. All registers are available to choose, both SFRs and GPRs. When you choose New Watch Window, you are prompted with an input box and a down arrow. Click the arrow, and a list of all available registers appears: choose the one you want (eg, my_reg_1) and then OK. Youll see the contents of the register displayed in the window. To add other registers you can either click in the watch windows top-left-corner icon, and then choose Add Watch; or just press the Insert key (while the watch window is selected). You can save oft used combinations as .wat files, and then load them back later with Window > Load Watch Window.
A word of warning . . . Where did the list of register names to select from, come from? The SFRs are obvious: the MPLAB knows about them anyway. The others, like my_reg_1&2, come from the equ directives in your code, which is great. However, in our example, we have also used w equ 0 and f equ 1 although these are not intended as register names. However, they still appear in the list of possibilities. So whats the problem- just dont choose them you say. But dont forget that w is a register: so now there are 2 w entries in the list, one was there all along (the working register), and we caused the other with the equ. Using either of them, causes a symbol not found error in your watch table, meaning that you cannot monitor the working register if you have declared a w equ in your code. Try it yourself, then comment the offending line out with a ;, re-assemble and try again. Now you can use the working register in the watch.
With these three windows, step through your program: youve now got some insight into whats going on. Satisfy yourself that all is working to plan.
Where shall we go from here? Well, where are we now? Weve looked at the architecture and instruction set briefly; weve created a simple program and examined the code to get the feel of it; weve edited & assembled this program; and weve seen some of the simulators facilities.
I think we should move on to look more fully at the instruction set. I know that [PIC] covers all the registers, flags, interrupts, timers and stuff before going on to the instructions, but I found this the better way.
Questions: