PIC Beginners Guide

Embed Size (px)

Citation preview

  • 8/3/2019 PIC Beginners Guide

    1/31

    Understanding & Programming thePIC16C84

    A beginner's tutorial

    Jim BrownBSc(Eng), HDipEdAd, GDE (Wits)RTF --> HTML Translation by: Dan Creagan

    Minor amendments by: Joe da Silva

    Contents at a Glance

    Contents at a Glance

    Contents

    List of Programs

    Introduction

    Introducing the PIC'84

    The Instruction Set

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 1/31

  • 8/3/2019 PIC Beginners Guide

    2/31

    Interrupts on the '84

    Timers on the '84

    Using the EEPROM data memory

    Appendix: Program listings

    Contents

    Contents at a Glance

    Contents

    List of Programs

    Introduction

    Background

    What you need

    What you should know

    Introducing the PIC'84

    Architecture

    Instruction Set

    A simple PIC'84 program

    Using MPLAB to debug the program

    Pause to reflect

    The Instruction Set

    Instruction format

    The STATUS register

    1: Move instructions

    MOVF f,d (Move f, PIC p58)

    MOVWF f (Move W to f, PIC p58)

    MOVLW k (Move literal to W, PIC p58)

    2: Clear instructions

    CLRF f (Clear f, PIC p55)

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 2/31

  • 8/3/2019 PIC Beginners Guide

    3/31

    CLRW (Clear W, PIC p55)

    3: Arithmetic ins tructions

    ADDWF f,d (Add W & f, PIC p53)

    SUBWF f,d (Subtract W from f, PIC p61)

    ADDLW k (Add literal & W, PIC p53)

    SUBLW k (Subtract W from literal, PIC p61)

    4: Logical functions

    ANDWF f,d (AND W with f, PIC p53)

    IORWF f,d (Inclusive OR W with f, PIC p58)

    XORWF f,d (Exclusive OR W with f, PIC p62)

    ANDLW k (AND literal with W, PIC p53)

    IORLW k (Inclusive OR literal with W, PIC p57)

    XORLW k (Exclusive OR literal with W, PIC p62)

    COMF f,d (Complement f, PIC p56)

    5: Decrementing & Incrementing

    DEC f,d (Decrement f, PIC p56)

    INC f,d (Increment f, PIC 57)

    6: Bit setting & clearing

    BCF f,b (Bit clear f, PIC p54)

    BSF f,b (Bit set f, PIC p54)

    7: Program control

    GOTO k (Go to address, PIC p57)

    CALL k (Call subroutine, PIC p55)

    RETURN (Return from subroutine, PIC p60)

    RETLW k (Return with literal in W, PIC p59)

    RETFIE (Return from Interrupt, PIC p59)

    8: Skipping instructions

    DECFSZ f,d (Decrement f, skip if 0, PIC p56)

    INCFSZ f,d (Increment f, skip if 0, PIC p57)

    BTFSC f,b (Bit test f, skip if clear, PIC p54)

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 3/31

  • 8/3/2019 PIC Beginners Guide

    4/31

    BTFSS f,b (Bit test f, skip if set, PIC p55)

    9: Rotations & Swap

    RRF f,d (Rotate right f thru carry, PIC p60)

    RLF f,d (Rotate left f thru carry, PIC p60)

    SWAPF f,d (Swap nybbles in f, PIC p62)

    10: Sleep & Watchdog Timer

    SLEEP (Sleep, PIC p60)

    CLRWDT (Clear watchdog timer, PIC p56)

    11: Miscellaneous

    NOP (No operation, PIC p59)

    OPTION (Not recommended)

    TRIS (Not recommended)

    Pause to reflect

    Interrupts on the '84

    What's an interrupt?

    Types of Interrupt and the INTCON register

    Servicing an Interrupt

    Timers on the '84

    The basic idea

    The TIMER0 module

    Using the timer's overflow

    Using the EEPROM data memory

    Appendix: Program listings

    List of Programs

    Program 1: simple.asm

    Program 2: moves.asm

    Program 3: clears.asm

    Program 4: arith.as m

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 4/31

  • 8/3/2019 PIC Beginners Guide

    5/31

    Program 5: inter1.asm

    Program 6: inter2.asm

    Program 7: inter3.asm

    Program 8: time0.asm

    IntroductionBackground

    When I first started looking into programming the PIC'84, I was daunted by what I saw as the complexity of the thing. After

    all, I was only get ting into this for a hobby - not as a control engineer. I had had some experience years before with Zilog's

    Z80, so I knew what registers, op-codes and so on were, but was still a little perplexed. The PIC'84 data sheet from

    Microchip is quite a technical document, and the MPASM manual is a reference. Neither of these documents served me as a

    tutorial, which is what I needed. So this manual is quite s imply my idea of a tutorial for programming the PIC'84, covering

    both the '84's instruction set and some MPASM directives. Along the way, it covers the '84 itself, in terms of registers, pins

    and so on.

    By the end of working through this material you will notbe a fully-fledged '84 expert. But youwill be quite comfortable with

    the device, even though you won't necessarily have touched one!

    What you need

    First, you need a copy of this guide. Preferably your own copy, so you can scribble in it to your

    heart's content. Feel free to make as many copies of this as you wish - it's 'freeware'.

    Second, you need to have some of Microchip's documentation. As a minimum, you'll need the

    PIC'84 data sheet (preferably DS30445B, file '16c84_96.pdf'). This contains all the real info you

    will need on the chip itself. I refer to this from time to time: there's no point my trying to duplicate

    the detail of the info, or the diagrams. You should also have the MPASM User Guide, which is

    available from Microchip's website, at http://www.microchip.com, or from their annual CD

    'Microchip Technical Library'. I refer to these thus: [PIC] or [MPASM] with a page, figure or table

    number; for instance [PIC figure 4.1] or [MPASM table 6].

    Youcouldwork through the material with just the above, but you will get a lot more out of it by

    being able to experiment. So, thirdly, load a copy of MPLAB (for Windows) onto your PC. This is

    their Interactive Development Environment (IDE), and it contains an editor, assembler and a

    simulator. Here, you can create your source code (editor), produce the executable code (assembler)and then run it on your PC (simulator). In the simulator, you can watch the program running,

    keeping an eye on the registers and even simulate events like externally caused changes to the I/O

    pins. You really should get this, and it's also available as above. Work through its tutorial before

    you start this book, at least so you can find your way around it.

    That's all youneed, but there's lots more you mightlike. Not least, is a PIC'84 chip and some kind

    of PC based programmer. I haven't covered the physical use of it in here, but might in a future

    volume. But there are many sources of info for that. I also found it handy to have a calculator that

    works in decimal, hex and binary for conversions: there's one in Windows which you just need to

    switch to scientific mode.

    Of extreme help - perhaps in the longer run - are Microchip's Application Notes (ANs). These are

    available from them, and a handy source is the CD-ROM mentioned above. These notes cover all

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 5/31

  • 8/3/2019 PIC Beginners Guide

    6/31

    sorts of uses of the PICs, with many helpful insights into real-world use. The ANs are in Adobe's

    .pdf format: using Adobe Acrobat you can search through the ANs looking for terms like 'motor' or

    'serial' and read the ANs appropriate to your needs.

    One of the notes, AN585 on real-time operating systems for the PIC, refers toReal time

    programming - Neglected topics.I urge you to get your hands on a copy - it is a fascinating tutorial

    on the whole subject of interrupts, closed-loop control, and the like.

    What you should know

    It's not really for me to say what you should know: I don't know who you are or what you do . But, I guess you'll find it

    easier going if you do unders tand (or can find out about) basic computer terminology like bits, bytes & EEPROM and

    concepts like binary and hex. Of course, if you're using the simulator on your PC, you must feel comfortable with your PC

    and Windows, and have played with the IDE tutorial.

    I certainly don't expect that you have any PIC84 knowledge - this tutorial is aimed at the absolute neophyte.

    Introducing the PIC'84

    Architecture

    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 process or and

    registers.

    1: The PIC'84 has an 8-bit processor, and that 's all we need to know about it!

    2: The 51 registers are the processor's internal working storage. Referring to [PIC figure 4-2], you'll see that some of

    these have names (STATUS, PORTB etc): these have special functions and we'll 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, and

    we can consider these as ours (as opposed to the processor's 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.

    You'll see from [PIC fig 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

    table 9.2] and you'll see that each is 14 bits long. For instance, ADDLW is 11 111X kkkk kkkk : don't worry about

    what this means, just count it! We'll be using this memory extensively later on.

    4: It has 64 bytes data memory, which is used for storage of, for ins tance, calibration values. We'll look at the use of

    this EEPROM memory las t 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

    program's normal flow and cause some special treatment. We'll examine the '84's interrupt techniques later.

    6: The use of theI/O pins is key to the us e 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 we'll be us ing them later.

    Instruction Set

    There are 35 instructions in the PIC84 instruction set; all are 14 bits long, and cons ist 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

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 6/31

  • 8/3/2019 PIC Beginners Guide

    7/31

    groups: byte-oriented, b it-oriented and literal & control. Later on we will use each and every one of thes e operations , firstly

    individually (usually trivially) and secondly with others in more meaningful scenarios.

    For now, let's look at one of the instructions. Concentrate more on theformatthereof, rather than thefunction which we'll

    see closely later. I've chosen the instruction ADDWF - see [PIC table 9.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 you'll see this sort of look in many other instructions.

    This is an appropriate time to introduce the working register: this is a s pecial 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 isn't 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 (stands forfile register). So, we would code theinstruction as:

    ADDWF 3Ch,d

    Well, not quite - what's the 'd' for? It is the des tination of the result, and you'll 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

    Let's get on with actually writing a simple program . . . .

    A simple PIC'84 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; I'll walk you through it line by line.

    Program 1: simple . asm

    ;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, it's much clearer

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 7/31

  • 8/3/2019 PIC Beginners Guide

    8/31

    my_reg_1 equ H'10' ;position my 2 registers in file

    my_reg_2 equ H'15' ; map at h'10' & H'15'

    ;***************** 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 H'08' ;put value H'08' 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

    Let's examine this sample program. You should verify the following by finding each directive or instruction in the

    appropriate Microchip book:

    Anything after a ';' is a comment. Every programming book in the world recommends comments to explain what's

    going on (at least to others , if not to yourself!).

    In the part called 'setup', we meet three assembler directives:

    processortells the assembler which model of Microchip the program is for. If this is incorrect, then

    you might use an instruction in the code, for a processor which doesn 't support that instruction and an

    assembly error will result.

    orgtells the assembler where to s tart putting the code in program memory. From the memory map [PIC

    figure 4.1], you can see that you s hould at least put your program beyond 0004h.equis an equivalence. It s imply means that the items on either side ofequmean the same thing. For

    instance, the ADDWFinstruction expects a 0 or 1 in the 'd' place: by equating a 'w' with a '0', it means we can

    use the 'w' in the instruction rather than '0'. This is eas ier to remember during coding, and to read later.

    Similarly, by equatingmy_reg_1with 10h, every time I want to refer to register 10h, I can more easily refer

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 8/31

  • 8/3/2019 PIC Beginners Guide

    9/31

    to it by its meaningful, more eas ily remembered, name.

    In the part called 'program', we meet a number of '84 instructions . Check the full descriptions in [PIC] if you like; we'll be

    looking at them later, anyway.

    MOVLW k[PIC page 58] causes the value k (eg 08h) to be put into the working register.

    MOVWF f[PIC page 58] copies the contents of W into register f. Note thatmovwfis s trictly a misnomer,

    since this is really a copy (W is not cleared), not a move (in which W would be emptied). Note too,

    Microchip's convention in [PIC] by comparingmovlwand movwf: in describing the operation, the

    parenthes es () mean 'the contents of'. Thus k(W) means the value k becomes the contents of W; (W)

    (f) means that the contents of W become the contents of f. Lastly, be sure you understand the use of the

    equconcept with respect to registers. The 'f' inMOVWF frefers to a register; [PIC figure 4-2] shows that

    registers have hex address es and we would expect the instruction to readMOVWF 10hfor instance.

    Equating my_reg_1 with 10h, means I can writeMOVWF my_reg_1with the same result.

    ADDWF f,dand SUBWF f,d[PIC pages 53 & 61] respectively perform the arithmetic addition &

    subtraction on the contents of W and f. Note the use of the equivalencies here too; we can refer to

    my_reg_1 as before, and also replace the allowed values of d (ie, 0 &1) with w & f respectively. Hence we

    can writeADDWF my_reg_1,fin place ofADDWF 10h,1.

    Let's assemble and run this program . . .

    Using MPLAB to debug the program

    This is a three s tep 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. I'll ass ume you have and do,

    and so we can move to the s imulation.

    With sample.asm successfully assembled, and the editor being the only window open in MPLAB, single-step through the

    program (the foots tep icon). Not too helpful - you see each line of the program being highlighted as it is activated, but that's

    it.

    So, let's start to use a few of the simulator's other facilities. I sugges t you open the following other windows in MPLAB.

    They all serve similar purposes - namely to see what's 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. Asyou s tep 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

    there's 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 b inary.

    Window > New Watch Window

    This is your custom window into the registers, and it allows you to select which registers you want to monitor. Allregisters are available to choos e, 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. You'll see the contents of the register displayed in the window. To add other

    registers you can either click in the watch window's top-left-corner icon, and then choose Add Watch; or just press

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 9/31

  • 8/3/2019 PIC Beginners Guide

    10/31

    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 ofwarning . . . 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 equdirectives in your code,

    which is great. However, in our example, we have also usedw equ 0andf equ 1although these are notintended as register names. However, they s till appear in the list of poss ibilities. So what's the problem - just don't

    choose them you say. But don't 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 theequ. Using either of them, causes a symbol notfounderror in your watch table, meaning that you cannot monitor the working register if you have declared aw

    equin your code. Try it yourself, then comment the offending line out with a ;, re-assemble and try again. Now youcan use the working register in the watch.

    With these three windows, s tep through your program: you've now got some insight into what's going on. Satisfy yourself

    that all is working to plan.

    Pause to reflect

    Where s hall we go from here? Well, where are we now? We've looked at the architecture and instruction set briefly; we've

    created a simple program and examined the code to get the feel of it; we've edited & assembled this program; and we'veseen some of the simulator's 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 s tuff before going on to the instructions, but I found this the better way.

    The Instruction Set

    Microchip present full details of the instruction set in [PIC, section 9, page 51 on]. They group these into 3 categories which

    I don't find particularly useful. These are Byte- and Bit-oriented and Literal / Control operations. I have taken the view of

    grouping them into what we use each command for, such as performing arithmetic. Page 52 in [PIC] gives a one-page

    summary of the commands ; I made a copy of this page loose from the data sheet, for easy reference. A windows help file is

    available on the Internet from Trisys Inc: I found this very useful. It contains details - similar to those in [PIC] - on the

    instruction set and the special function registers. It's a normal windows help file, with the expected hypertext links &

    searches.

    For each instruction, I have explained the operation as described in [PIC], and have expanded on [PIC]'s explanations where

    appropriate. (For instance, I have explained what an inclusive oractually is in IORWF.) Perhaps more importantly, I have

    suggested exercises to us e the instructions as presented, with a poss ible solution given in the Appendix. The exercises

    suggested are quite trivial, but will afford you the opportunity to use each instruction, and also practice using the s imulator.

    Remember to use things like the watch window to see what's going on as you step your program: keep an eye on registers

    you decide to use, as well as W and STATUS.

    Instruction format

    Microchip's grouping does keep instructions of s imilar format together. The instructions look like th is:

    byte_command f,d

    where f is the file register designation and d is the des tination; if d=0, the result goes to the working register, w; if

    d=1, the result goes to register f

    bit_command f,b

    where f is the file register, and b is the bit therein; bits are numbered from 0 on the right, to 7 on the left. In the text, a

    bit is written as FILE_REG, for instance INTCON means bit no 4 in the intcon register at 0B

    other_command k

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 10/31

  • 8/3/2019 PIC Beginners Guide

    11/31

    where k is an 8-bit constant or literal.

    The STATUS register

    The '84 implements a STATUS register at 03h, which contains the arithmetic status of the arithmetic & logic unit; see [PIC

    fig 4-3]. Have a glance down the 'Status Affected' column of [PIC table 9-2], and you will see that many '84 instructions

    affect certain parts of STATUS. Many instructions affect STATUS, Z - the Zero flag, which gets set if the result of an

    operation was zero. Certain operations affect the carry bits: STATUS, C - the Carry bit, is set if a carry out occurs from

    the left-mos t bit in the result; STATUS, DC - the Digit Carry bit, is set if there is a carry between the hex digits (ie, from

    the right hand nybble (bit 3) to the left hand nybble (bit 4). Two commands affect STATUS, the Power Down bit PD, and

    STATUS, the Time Out bit TO.

    1: Move instructions

    We have met some of these instructions, which do nothing other than put things in registers.

    MOVF f,d (Move f, PIC p58)

    (f)(dest)

    MOVWF f (Move W to f, PIC p58)

    (w)(f)

    MOVLW k (Move literal to W, PIC p58)

    k(W)

    Exercise: Write a program to us e these commands to (for ins tance) put something into W, move it from there to anotherregister, put something else into W, and then move the original thing back to W. See moves.asm.

    2: Clear instructions

    These 2 commands clear a register.

    CLRF f (Clear f, PIC p55)

    00h(f)

    CLRW (Clear W, PIC p55)

    00h(W)

    Exercise: Expand the above program to clear registers at the end. See clears.asm .

    3: Arithmetic instructions

    Performing arithmetic is pretty important: that's why computers are called computers after all. The '84 can only add and

    subtract though.

    Arithmetic occurs either between W and an f register:

    ADDWF f,d (Add W & f, PIC p53)

    (W)+(f)(dest)

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 11/31

  • 8/3/2019 PIC Beginners Guide

    12/31

    SUBWF f,d (Subtract W from f, PIC p61)

    (f)-(W)(dest)

    or between W and a literal:

    ADDLW k (Add literal & W, PIC p53)

    (W)+k(W)

    SUBLW k (Subtract W from literal, PIC p61)

    k-(W)(W), [PIC p61]

    Exercise: Use thes e and previous commands to load some registers and W, and do some adding and subtracting. Keep a

    close eye on the carry bit and on the zero bit in the status register. See arith.asm.

    Technical aside:You may see in [PIC] that subtraction is performed using the 2's complement method. Que? I hear you

    ask. This is the normal way that subtraction occurs in binary. I'll explain, then look at an example. Express both numbers in

    binary. Leave the number from which you are taking away, unchanged. Form the 2's complement of the one which is being

    taken away thus : change all 0s to 1s and all 1s to 0s (this is the complement), add 1 to the right hand digit, carrying to the

    left as necess ary. Now add the result to the unchanged other number. Discard the carry at the left, if there is one. That's the

    answer. Let's check . .

    We want to subtract 20 from 27 - we should get 7. Proceed as follows:

    Convert to binary:2711011 . . . . x

    2010100 . . . . y

    Make 2's complement of y: complement:01011

    add 1:01100 . . . . z

    Add x and z: +11011 . . . . x

    (1) 00111 = 7 QED.

    The 1 in brackets is the carry, which gets discarded.

    4: Logical functions

    At this stage, before we examine the logical functions provided by the '84, we'll discuss what logical functions are. Cons ider

    for the time being an electronic device of some description, with 3 wires attached. Let's say that 2 wires are inputs , and that

    what gets output on the 3rd

    wire depends on the inputs. Further, we'll say that this is a digital device, so that the 3 wires can

    only have binary values of 1 & 0.

    What relationships can exist, then, between the 2 inputs and the output? The input combinations are easy: if wire/pin 1 can

    be 0 or 1, and so can pin 2, then the combinations are 00, 01, 10 & 11. What about pin 3: perhaps it must be a 1 if and only if

    the inputs are both 1 (ie 11); or perhaps a 1 if either or both inputs is 1 (ie 01, 10, 11). Or whatever!

    The basic relationships are known as andand or; andmeans both inputs while ormeans either or both. Most explanations

    of this resort to the s o called truth table, which I have drawn below for the following logical operations: and, or, xor, nand,nor. I'll explain them once you've had a look at the table.

    Inputs A B A AND B A OR B A XOR B A NAND B A NOR B

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 12/31

  • 8/3/2019 PIC Beginners Guide

    13/31

    both either, both either, not both not both neither, notboth

    00 0 0 0 1 1

    01 0 1 1 1 0

    10 0 1 1 1 0

    11 1 1 0 0 0

    The function andmeans that the result is 1 only when both inputs are 1. The ormeans that either input may be a 1 for

    output to be 1, but so may both. The functionxormeans exclusive or, and means that either input as 1 will cause a 1 to be

    output, and specifically excludes the s ituation where both inputs are 1. Lastly, the nandand norare the negations ofand

    and orrespectively: compare the columns and you'll see what this means.

    By the way, the orfunction (as opposed to thexorfunction) is sometimes known as the inclusive or (ior). The '84 in fact

    uses th is term.

    The '84 provides a number of logical operations which act on 2, 8-bit values; these values are compared bit for bit. Forexample - without yet looking at an '84 instruction - consider the anding (is there such a word?) of the numbers H'5F'

    (equivalent to D'95' and B'01011111') and H'A3' (which is D'163' and B'10100011'); resulting in H'03' (which is D'3' or

    B'00000011').

    5F: 01011111

    A3: 10100011

    and: 00000011

    Clearly, only in the rightmost 2 pos itions is the andsatisfied, resulting in 1s there and 0s elsewhere. You should check this

    on the calculator in Windows, which has logical functions built in.

    So, let's move to the instructions as provided by the '84.

    Comparison occurs either between W and an f register:

    ANDWF f,d (AND W with f, PIC p53)

    W. .and. (f)(dest)

    IORWF f,d (Inclusive OR W with f, PIC p58)

    W. .or. (f)(dest)

    XORWF f,d (Exclusive OR W with f, PIC p62)

    W. .xor. (f)(dest)

    or between W and a literal:

    ANDLW k (AND literal with W, PIC p53)

    W. .and. k(W)

    IORLW k (Inclusive OR literal with W, PIC p57)

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 13/31

  • 8/3/2019 PIC Beginners Guide

    14/31

    W. .or. k(W)

    XORLW k (Exclusive OR literal with W, PIC p62)

    W. .xor. k(W)

    Lastly, you may have noted that the '84 doesn't provide nandor norfunctions. Rather, it provides the means of

    complementing (negating) a register; this means to nandyou must first andand then com:

    COMF f,d (Complement f, PIC p56)

    complement of (f)(dest)

    Exercise: I suggest 2 things here. First , using Windows' calculator, verify the results of the examples in [PIC] with each o f

    the above: this will ensure that you understand the concepts. Then, write an as sembler program to verify the '84

    instructions, by loading the appropriate registers, performing the actions , then checking the results. See logic.asm.

    5: Decrementing & Incrementing

    Two s imple instructions can decrement or increment the contents of a register, thus:

    DEC f,d (Decrement f, PIC p56)

    (f)-1(dest)

    INC f,d (Increment f, PIC 57)

    (f)+1(dest)

    Exercise: In a program, perhaps by adding to one of the previous ones in which you do some arithmetic or some logic, check

    out that these commands do work. Keep an eye on the Zero flag, which is set if either command causes the register inquestion to go to zero: we'll rely on this fact in 2 more commands later. See dec_int.asm

    6: Bit setting & clearing

    Using the following 2 commands , you can set or clear any bit b in register f. But why would we want to? Two reasons come

    to mind:

    First, as an example, the register in question might be a port controlling some external equipment. Each bit could

    be switching a different device: a motor, a light or whatever. Setting and clearing each bit switches each device on or

    off.

    Second, as we'll see in 8. below, we can use the fact that a bit is set or clear to skip instructions in our program.

    Being able to set or clear any bit gives us the ability to control this process.

    BCF f,b (Bit clear f, PIC p54)

    0(f)

    BSF f,b (Bit set f, PIC p54)

    1(f)

    We read thes e two operations as "0 (or 1) becomes the content of bit 'b' in register 'f'".

    Exercise: Sprinkle these commands into any of the programs above, and watch the changes to individual bits in your watch

    window. See bits.asm

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 14/31

  • 8/3/2019 PIC Beginners Guide

    15/31

    7: Program control

    For many reasons, we need to control the flow through our program. Normally, flow proceeds linearly from the top; often

    this is not suitable.

    Firstly, we often need to loop through certain instructions: we might have a system in which one process is a continuous

    one. This might be the control of a bucket conveyor which continuous ly adds ingredients to a vat. Here, when a bucketful

    is added, we take it from the top and go through the same steps again, adding more on each pass .

    Second, there may be part of our program which is useful in many other parts. Rather than repeating this code in manyplaces, we separate the piece we like from the rest of the code; then we merely call it in as often as we like, from wherever.

    The reusab le piece is called a subroutine. The subroutine returns control to the point from which it was called when it's

    finished.

    Let's look at looping first:

    GOTO k (Go to address, PIC p57)

    k(PC)

    This instruction literally 'goes to k', which it does this by loading the address of k into the program counter, PC. In order touse goto you s hould s tart the line to which you want to go, with a label. Then you goto label. See [MPASM p15] for rules

    on labels.

    Exercise: Modify one of the programs you have already written. You could put a label near the top, and a goto later on. As

    you step, you'll see from the highlighted line that your program loops through the s ame part again and again. Look at the

    program counter (pcl) in a watch window and you'll verify this. See goto.asm

    Now we shall examine subroutines . We need to understand the concept of the stackfirst . Look at [PIC figure 4-1] and you'll

    see a connection between the program counter and the s tack. The stack - which has 8 levels in the '84 - is the repository of

    where the PC was before the subroutine was invoked. This is so that the program can go back to take up where it left off

    when the subroutine is finished.Strictly speaking, the stack is loaded with the address of the instruction immediately afterthe one doing the sending; otherwise it would keep on going back and performing the instruction it had done earlier - we

    really want the next one. We refer to loading the stack aspushing and taking a value off later aspopping. The stack is only

    accessible at the top: it's like a pile of plates in one of those hoppers in a restaurant. The top of the stack is abbreviated as

    TOS.

    There are 2 instructions ass ociated with any subroutine - one to s end the program off to it, the other to bring it back:

    CALL k (Call subroutine, PIC p55)

    (PC)+1TOS, k(PC)

    The call to a subroutine pushes the current PC+1 onto the stack, then changes the PC to the address k. This results in

    program flow jumping to the s ubroutine, but the address to come back to later is safely ensconced on the stack for later

    retrieval.

    RETURN (Return from subroutine, PIC p60)

    TOS(PC)

    Return is the last instruction in the subroutine itself. The return instruction pops the stack, and so the program resumes in

    the right place. Think about the depth of the stack: it means that calls can be nested, and flow will be correct as long as the

    calls are matched by returns. Consider the following, which is OK:

    CALL . . . . . push 1st

    address

    CALL. . . . push 2nd

    address

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 15/31

  • 8/3/2019 PIC Beginners Guide

    16/31

    RETURN. . . pop 2nd

    address

    RETURN. . . . . pop 1st

    address.

    But we don't want this, which is not OK:

    CALL . . . . push 1st

    address

    CALL . . . push 2nd address

    RETURN . . . . pop 1st

    address

    RETURN . . . pop 2nd

    address.

    As an alternative to the vanilla-flavoured return, you can bring a value back with you, thus :

    RETLWk (Return with literal in W, PIC p59)

    k(W), TOS(PC)

    This is the normal return, with the k(W) added.

    Exercise: Write a program to execute s ome code - anything you like - and then branch to a subroutine to do something else.

    Check that you return correctly. Use both types of return.

    Problems? You probably had a little difficulty wondering where to put the subroutine in the source. How do you s top the

    subroutine being run by mistake? Because wherever you put it - either above or below the main part of the program, the

    program's natural flow will go through the subroutine, which is called subby here. If the stack is empty , this causes a stack

    underflow error, as when the subroutine's return is encountered before a call has been made. If the s tack has indeed been

    pushed by some other event - like an interrupt - then the return would be honoured but incorrectly.

    ;example 1 ;example 2

    . .

    . .

    label subby call subby

    . subby code here .

    . and here .

    return label subby

    . . subby code here

    . . and here

    call subby return

    . .

    . .

    The way around this seems to be to proceed more or less as example 1, with the subroutines at the top. But, down below

    where the main part of the program is, have a label like start; above the subroutines, have a goto startto hop over them in

    the normal course of things. When a subroutine is called, the program shoots to the top: one subroutine will not flow into

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 16/31

  • 8/3/2019 PIC Beginners Guide

    17/31

    another, because the return will take care of this. Thus:

    goto start

    label subby1

    .

    return

    label subby2

    .

    return

    start

    .

    .

    call subby2

    .

    call subby1

    .

    . etc

    See subby.asm

    Associated with these last 2 commands is another type of return, which is to do with interrupts. We

    will look at interrupts later, but for completeness I've put the return from interrupt here:

    RETFIE (Return from Interrupt, PIC p59)

    TOS(PC), 1GIE

    When an interrupt occurs, the PC is pushed to the stack like with a subroutine call, so retfie pops it back out. Also, though,

    the occurrence of an interrupt disable further interrupts: one doesn 't want interrupts interrupted after all. What happened

    was, that the interrupt caused the global interrupt enable flag, GIE (INTCON) to be set to 0. Returning from an interrupt

    means that further interrupts s hould be allowed, hence retfie sets GIE back to 1.

    8: Skipping instructions

    There are 4 ins tructions which allow you to s kip over the next instruction. I'll explain this before we look at the commands

    themselves.

    In the conveyor example above, we don't want the vat to overflow, so let's have a level sensor in the vat (just like the ball-

    valve in the loo) which switches on when the vat is full. The conveyor is running, adding buckets ful; the program needs to

    monitor the switch, and when the vat is full (the switch closes) the program switches off the conveyor and starts some

    other part of the process , perhaps the mixer. This process is shown below: the dots show some or other process happeningbefore and after the part of interest. I've used line numbers for ease of reference. This is notin '84 assembler!

    .

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 17/31

  • 8/3/2019 PIC Beginners Guide

    18/31

    line # 40: start conveyor

    .

    .

    line # 63: is the level sensor switch set?

    line # 64: no - go back to line # 63 and look again

    line # 65: yes - stop the conveyor

    line # 66: start the mixer and carry on

    .

    .

    In this example, we need to skip line 64 when the vat is full. When the vat still has room, this code will cause more ingredientto be added; the conveyor will stop and the mixer will start when the vat full sensor has switched on.

    Now we can look at the commands which do this skipping in the '84:

    DECFSZ f,d (Decrement f, skip if 0, PIC p56)

    (f)-1(dest), skip if result = 0

    INCFSZ f,d (Increment f, skip if 0, PIC p57)

    (f)+1(dest), skip if result = 0

    The above commands are based on the decfand incfcommands seen earlier: the sz part means 'skip if zero'.

    Exercise: Verify these 2 instructions by loading a start value into a register called 'count ' or something. Then use either

    instruction to change it, looping through this block of code. Check that the instruction following the decfsz or incfsz

    (probably a goto, to caus e the looping) is skipped or not, as appropriate. (This approach would work if the conveyor had to

    add say 10 bucketsful, rather than wait for a sensor.) See skip.asm.

    BTFSC f,b (Bit test f, skip if clear, PIC p54)

    skip if (f)=0

    BTFSS f,b (Bit test f, skip if set, PIC p55)

    skip if (f)=1

    Read thes e instructions as 'bit test f, skip if clear/set".

    These commands could be used to check the vat full sensor mentioned above. The bit to be tes ted would be the bit of a

    port on the '84: it would be set or cleared by the sensor from time to time.

    Exercise: Write a program with a block of code to loop through. These can be just abou t any instructions, and will simulate

    the conveyor as nonsense. Have a btfss at the bottom, followed by a goto back to the top. Have some more code then,which simulates the mixer coming on. The btfss will need to refer to one of the '84's I/O ports as its f (H'05' or H'06' for porta

    & b respectively), and you can use any bit 0-4 on porta, 0-7 on portb you wish. You should have another goto right at the

    bottom, to make a sort of outer loop back to the top - this might not be too real-life, but you'll want the whole program to

    loop to tes t what happens when the pin changes. See bits.asm

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 18/31

  • 8/3/2019 PIC Beginners Guide

    19/31

    But how do we get the pin to change its state, simulating the vat full sensor? There's an eas y way of doing this in MPLAB's

    simulator. Go Debug > Simulator stimulus > Asynchronous stimulus; you'll get a table of Stim0 to Stim12 buttons. Right

    click on any one, perhaps Stim7, and click Assign pin. Double click on the pin you've elected to use as the s ensor, perhaps

    it was RA3, say. Stim7 then changes to RA3 . Now right click on the button again: you can choose to pulse, make low, make

    high or toggle the pin. Here, we would want to toggle the pin, since the vat sensor will be changing from time to time

    probably, as it empties and fills.

    Now we're all set to tes t. Step through your program. Depending on the initial state of the pin, which [PIC table 4-1] says is

    unknown at power up, the program will loop or not. (At the inner loop, that is; it will always go back to the top from the very

    bottom, for testing purposes.) Any time you like, left click on your chosen Stim button, now known as RA3 or whatever. (Ifyou have the port showing in a watch window, you'll see the pin change state at the next instruction boundary.) In any

    case, next time the program gets to the btfss step, it should behave differently, since we've toggled the pin and so the btfss

    should get a different answer.

    9: Rotations & Swap

    Three instructions allow you to manipulate the bits within a register. Of these, two slide the bits to the right or left (through

    the carry bit), the third switches the register's two nybbles over.

    RRF f,d (Rotate right f thru carry, PIC p60)

    Each bit in the f register is moved 1 to the right; the one that falls o ff the right is circled round to the carry, and the

    carry moves in from the left.

    RLF f,d (Rotate left f thru carry, PIC p60)

    Each bit in the f register is moved 1 to the left; the one that falls off the left moved into the carry, and the carry is

    circled round to the right.

    SWAPF f,d (Swap nybbles in f, PIC p62)

    (f

  • 8/3/2019 PIC Beginners Guide

    20/31

    OPTION (Not recommended)

    TRIS (Not recommended)

    Pause to reflect

    We have now met each '84 ins truction, with the necessary background if appropriate, and us ed them in simple programs.

    Now, we'll move on to explore two important areas of the PIC'84: interrupts and timers. It is these two areas which move the

    '84 into the real world.

    Interrupts on the '84

    What's an interrupt?

    Put simply, it's exactly what it says: a means of getting the computer's attention. Refer to the conveyor/mixer scenario

    mentioned earlier (p17), where we saw the following snippet of 'pseudocode':

    .

    line # 40: start conveyor

    .

    .

    line # 63: is the level sensor switch set yet?

    line # 64: no - go back to line # 63 and look again

    line # 65: yes - stop the conveyor, then

    line # 66: start the mixer and carry on

    .

    .

    Here, the program will loop around line 63 and 64 for ever if necess ary, waiting for the vat to fill up. That's OK, the program's

    job is to run the process! Well, true, but it's wasteful. It might take a few seconds, minutes or hours to fill the vat; we couldhave the program doing something useful while it's waiting. But if the program's off somewhere else - doing the payroll? -

    and the switch closes, how will the program know? It's not looking.

    Same way as you get someone's attent ion when you come to visit. They're not standing looking out the front door all day,

    they're going about their daily bus iness ; your knock on the door interrupts this, and they come to the door.

    Our program would look something like this:

    .

    line # 40: switch on the conveyor

    .

    line # 50: do some payroll work

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 20/31

  • 8/3/2019 PIC Beginners Guide

    21/31

    line # 51: and some more, and stay up here until interrupted

    .

    .

    .

    line # 60: only come here when interrupted

    line # 61: stop the conveyor

    line # 62: switch on the mixer

    line # 63: go back to where you were when you got sent here

    Now, the program spends most of its time in the payroll section, not looking at the s witch in the vat. When the switch

    closes , the hardware takes care of things: the switch is connected to the computer by the interrupt request line (IRQ), and

    program control is passed to a predetermined point. That point is line # 60 in the example above, and what happens at line

    60 is up to the program/mer.

    Notice something crucial here: once the interrupt has been taken care of, control must go back to where it was earlier. Not

    only that, but the state of the sys tem must be put back: if any registers were changed while handling the interrupt, they

    must be restored. We'll look into this later.

    Now we know what an interrupt is in concept, we can look at how the '84 allows for this notion.

    Types of Interrupt and the INTCON register

    The '84 has 4 different types of interrupt [PIC p44]:

    an external interrupt on pin 6, aka RB0

    a change on any of pins 10-13, aka RB4-7

    a timer overflow

    an EEPROM write complete.

    (Of these 4 types, the first one is the kind we'd use in the above conveyor/payroll program.)

    In order to allow interrupts, and to determine the source thereof, the processor uses the INTCON register (0Bh) whosecontents are detailed in [PIC table 4-5], and which I'll explain here. Each bit serves a specific purpose, and interrupts work

    according to the value (set or clear) of the various bits.

    Firstly, interrupts as a whole may be enabled or disabled by INTCON, the GIE (Global Interrupt Enable) bit. If this bit is

    clear, then no interrupts may occur: this is the power-up value by the way. Also, if an interrupt occurs, then GIE is cleared

    to prevent the interrupt being interrupted; returning from the interrupt with the retfie instruction re-enables interrupts .

    Second, each of the interrupt types must be enabled with its own bit in INTCON, before it can be used:

    external interrupt on pin 6: INTCON, the INTE bit

    change on any of pins 10-13: INTCON, the RBIE bit

    timer overflow: INTCON, the T0IE bit

    EEPROM write complete: INTCON, the EEIE bit.

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 21/31

  • 8/3/2019 PIC Beginners Guide

    22/31

    Third, when interrupts occur, certain bits (known as interrupt flags)are set so that we may determine the source of the

    interrupt:

    external interrupt on pin 6: INTCON, the INTF bit

    change on any of pins 10-13: INTCON, the RBIF bit

    timer overflow: INTCON, the T0IF bit.

    Why do we need to know the s ource? Well, depending on the type of interrupt, we will take different action: checking theappropriate bit tells us which interrupt it is. Note that the interrupt flags always get set when there's an interrupt, regardless

    of the state of the corresponding enable bit.

    Servicing an Interrupt

    In the conveyor/payroll example above, there must be a means of sending the program to the right place to sort out the

    interrupt; line 60 in the example. How does the processor know where to go? In the PIC84, all interrupts are sent to 0004h:

    in the parlance of microprocessors, this point is the interrupt vector, and the program is said to vectorthere. At the vector,

    we must make sure that we provide whatever code is necess ary to take care of the problem.

    A crucial point is that we might need to save the status of the machine as it was before interruption, before we service the

    interrupt. Clearly, the activities undertaken during servicing could change such things as the W & STATUS registers; we

    would need these restored after handling the interrupt, in order that our other work may resume. The '84 only saves the PC

    to the stack (PC+1, actually), and it's up to us to ensure we save and restore anything else we need!

    Let's walk through a scenario in pseudocode, without yet looking at the '84 code. Foster sugges ts 3 parts to a program

    which must handle simple interrupts: an initialize section, where in our case we'll enable the interrupts; a main section,

    where the bulk of the time is s pent (doing the payroll, or whatever) and the handlerpart where the interrupt is taken care of.

    Initialize:

    set GIE, INTCON, to enable interrupts

    set INTE, INTCON, to enable pin 6 interrupt

    Handler:

    save the status of the machine; probably W & STATUS

    check interrupt flags for source; INTF, RBIF, T0IF

    branch to the correct 'sub-handler' for the interrupt type (we've only

    set INTE, though)do whatever is required for the interrupt

    restore the status

    return

    Main:

    do the payroll calculations

    Exercise:Start slowly with interrupts - this can get quite hairy. Write a program to provide the

    absolute minimum interrupt ability: enable them, have an interrupt service routine that does little ifanything other than re-enable interrupt and then return, and a main part that merely loops through

    some meaningless code waiting for an interrupt. You need not save the status of the machine, nor

    check for the type of interrupt at this stage. In order to see this program working properly in the

    simulator, I suggest using the interrupt on change in port b, using the asynchronous stimulus

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 22/31

  • 8/3/2019 PIC Beginners Guide

    23/31

    technique discussed before. Use a toggle on the pin to effect the change: while the program is

    looping in the main section, toggle the pin and check that the interrupt occurs when you next step

    the program. While the program is then in the isr, toggle the pin again: if it's all working, the pin

    change willnotcause an interrupt, because GIE will have been cleared. See inter1.asm.

    Exercise: Now add to the program, to save the state of the machine at the interrupt. To test this,

    make sure you load W (say) in the main part, then change it in the ISR, and check that it gets

    restored properly. Hint: see [PIC p46, example 8-1]. See inter2.asm

    Exercise: Finally, allow for more than 1 kind of interrupt - change on one of portb pin 4:7 as well as

    an interrupt on the rb0/int pin. Now, you'll need to determine the kind of interrupt, and handle it

    accordingly. See inter3.asm.

    Timers on the '84

    The basic idea

    The basic idea, is that we will want to use our '84 to time something. Time, that is, in the way we would use a wall clock: we

    might switch on our fish-tank lights for ins tance, or close the curtains at 18h00 each night. But there's no clock in the '84: no

    clock in the wall clock sense anyway.

    What there is though, is a simple relationship between the carrying out of instructions and the s peed with which the

    process or ticks away. The book tells us [PIC p1] that an instruction completes in 1 cycle, namely 400ns when the process or

    is being clocked at 10MHz.

    Let's verify this, and introduce a handy feature of MPLAB at the same time: the Stopwatch. In MPLAB prepare to run any

    of the programs you have written up to now. Open the s topwatch by going Window > Stopwatch. You'll see a simple

    window, containing 3 important pieces of information: the number ofsteps completed in what time, and at whatfrequency.

    Check that the frequency is set to 10MHz for now, clickzero and s tep your program once. You should see that you

    progress to 1 cycle in 400ns. (Unless this was coincidentally a program branch, which is a 2-cycle instruction.) Experiment

    with various frequencies; for instance 400ns becomes 40ns at 100MHz, or 800ns at 5MHz.

    So, we have the glimmerings of a wall clock type of timer here - we know how much time has pas sed if we know how many

    steps have occurred. Enter Timer0 . . .

    The TIMER0 module

    The PIC'84 timer, TIMER0, works on the bas is that each time an ins truction cycle occurs , a certain interval of time has

    elapsed. When TIMER0 is running, its register (TMR0) is incremented each cycle; each 400ns if the clock is a 10MHz one.

    Therefore, the value of TMR0 represents the 'time' in 400ns steps. But TMR0, like all registers, is an 8-bit one and can thus

    only count as high as FF: that means time only goes as far as 255 x 400ns = 102000ns or about 100s which is not too long.Cast your mind back to the discus sion of interrupts earlier, where we said that one of the interrupt types was a timer

    overflow interrupt: that means that the TMR0 register has gone over the top at FF and back to 00. That means the interrupt

    occurs every 100s of real time. It's up to us to do s omething with this interrupt, which probably means incrementing aregister of our own, clockedsay: every time clockedgets to a certain value, that means 1 second of real time, and we'd

    probably then go off and increment another register, perhaps seconds

    Let's walk through the process , then, of simply getting TIMER0 going, using the initialize, handler, main interrupttechnique used earlier.

    Initialize: set GIE, INTCON, to enable interrupts

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 23/31

  • 8/3/2019 PIC Beginners Guide

    24/31

    set T0IE, INTCON, to enable timer interrupt

    clear T0CS, OPTION, to enable timer - see [PIC 6.0]

    set PSA, OPTION, to keep prescaler out of this

    Handler: increment 'clocked', our overflow counter

    Main: have some trivial loop to keep the program going

    Exercise:Write a program to implement the above simple timer, bearing in mind we won't be doing

    anything with the timer overflows other than clicking them inclocked.Check the program in the

    simulator, having visible any registers you think you should monitor, also the stopwatch. Before

    you start, you'll need to figure out how to access theoption register, which is not quite as simple as

    accessing saystatus. I've explained it below. See time0.asm.

    Accessing registers in Bank1: You'll have noticed in [PIC fig 4-2, p12] that some registers like

    optionare in what they refer to as Bank1, as opposed to Bank 0. Others, like statusare in both

    Banks. What this means in practical terms, is that these Bank 1 registers are not normally

    available, because our default sphere of operations is Bank 0. We use thestatusregister to effect a

    switch between banks, with RP0 & RP1 (STATUS & ) doing the trick. This simply means

    that we must set RP1 to go to Bank1 and clear it to return. For those registers which are in both

    banks, you can of course access them no matter where you are, but remember the register has 2

    different addresses:statusis known as h'03' and h'83'.

    Using the timer's overflow

    Now we can probably see the wood through the trees: we have a register clocked which is updating whenever the timer

    overflows. That's roughly every 100s. Being an 8-bit register itself, clocked can of course only count to 255, and so it will

    overflow at 255 x 100s which is 2.55 x 10-2 seconds. We'll need to count thes e overflows too, into say clocked2. Now,we're getting closer to the actual second, which is what we're heading for: how high do we need to count in clocked2 to

    reach 1 second? Incrementing every .0255 seconds there are roughly 39 increments in a second , so this means, finally, we

    can count real-time seconds by incrementing another register, perhaps SECONDS, every 39 steps . To get to minutes and

    hours, we can simply overflow SECONDS into MINUTES at 60 seconds and MINUTES into HOURS every 60 minutes .

    Exercise: Create a program to implement the above, at least as far as the SECONDS register.

    Using the EEPROM data memory

    Appendix: Program listings

    The following programs are intended as illustrative of the use of the commands discussed. They are certainly trivial, and

    probably not paragons of programming technique! In each, I have added a section calledsimulator: this section is asuggestion for things you might like to do during the simulation of your program. For instance, you might need to have a

    watchwindow open showing the W register and portb, as well as having the stackopen too. Of course, it's up to you how

    you design and code these programs, and how you experiment with them in the simulator.

    Program 1: simple.asm

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 24/31

  • 8/3/2019 PIC Beginners Guide

    25/31

    See above (A simple PIC'84 program)

    Program 2: moves.asm

    ;moves.asm to show how MOVF, MOVWF & MOVLW work

    ;*********************************** simulator ***

    ;watch window: reg1, w, pcl

    ;*********************************** setup ***

    processor 16c84

    reg1 equ h'10'

    ;*********************************** program ***

    start: movlw h'05' ;load w

    movwf reg1 ;move (w) to reg1

    movlw h'82' ;change w

    movf reg1,0 ;restore w

    end

    Program 3: clears.asm

    ;clears.asm to show how clrf & clrw work

    ;based on moves.asm

    ;*********************************** simulator

    ;watch window: reg1, w, pcl

    ;*********************************** setup

    processor 16c84

    reg1 equ h'10'

    ;*********************************** program

    start: movlw h'05' ;load w

    movwf reg1 ;move (w) to reg1

    movlw h'82' ;change w

    movf reg1,0 ;restore w

    clear: clrf reg1 ;clear reg1

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 25/31

  • 8/3/2019 PIC Beginners Guide

    26/31

    clrw ;clear w

    end

    Program 4: arith.asm

    ;arith.asm to show using ADDWF, SUBWF, ADDLW, SUBLW

    ;************************************* simulator

    ;watch window: reg1,reg2,status,w,pcl

    ;************************************* setup

    processor 16c84

    reg1 equ h'10'

    reg2 equ h'12'

    ;************************************* program

    loads: movlw d'20' ;load w

    movwf reg1 ;load reg1

    movlw d'80' ;load w anew

    movwf reg2 ;load reg2

    arith: addlw d'05' ;add d'05' to w

    sublw d'100' ;sub w from d'100'

    addwf reg1,1 ;add w to reg1, into reg1

    subwf reg2,1 ;sub w from reg2, into reg2

    end

    Program 5: inter1.asm

    ;inter1.asm is a simple interrupt handler -

    ; it does not save the state of the machine

    ; nor does it determine the kind of interrupt.

    ;

    ;*********************************************simulator

    ;watch window: intcon, pcl

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 26/31

  • 8/3/2019 PIC Beginners Guide

    27/31

    ;stack: have this open too - see the return address come & go

    ;asynch stimulus: have a toggle on rb4

    ;********************************************* setup

    processor 16c84

    movlw h'0'

    movwf h'0b' ;clear intcon

    goto main ;hop over the isr

    ;********************************************** isr start

    isr: org h'0004' ;interrupts always vector to here

    nop ;here we actually do the stuff

    nop ; of the interrupt

    bcf h'0b',0 ;clear int before going back

    retfie ;this re-sets intcon gie

    ;*********************************************** isr ends

    ;

    ;*********************************************** main start

    main: org h'0020' ; leave enough room for the isr!

    bsf h'0b',7 ; set global int enable

    bsf h'0b',3 ; set change on b int enable

    payrol: nop ; loop here until interrupted,

    nop ; doing payroll stuff

    goto payrol ;

    nop

    nop

    end

    Program 6: inter2.asm

    ;inter2.asm does save the state of the machine

    ; but does not determine the kind of interrupt.

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 27/31

  • 8/3/2019 PIC Beginners Guide

    28/31

    ;

    ;****************************************************simulator

    ;watch window: intcon, pcl, portb, w, w_saved

    ;stack: have this open too - see the return address come & go

    ;asynch stimulus: have a toggle on rb4

    ;**************************************************** setup

    processor 16c84

    w_saved equ h'10' ;a place to keep w

    movlw h'0'

    movwf h'0b' ;clear intcon

    goto main ;hop over the isr at the beginning

    ;**************************************************** isr start

    isr: org h'0004' ;interrupts always vector to here

    movwf w_saved ;save w as it was in main

    movlw h'65' ;do something to change w

    nop ;do more isr stuff

    ;now, restore w: there is

    ; no "movfw" - 2 swapf's seems to be

    ; the way to do this....

    swapf w_saved,1 ; first, swap w_saved into itself

    swapf w_saved,0 ; then, swap it into w

    bcf h'0b',0 ;clear int on b before going back

    retfie this re-sets intcon gie

    ;***************************************************** isr ends

    ;

    ;****************************************************** main start

    main: org h'0020' ; leave room for the isr!

    bsf h'0b',7 ; set global int enable

    bsf h'0b',3 ; set change on b int enable

    payrol: nop ; loop here until interrupted,

    nop ; doing payroll stuff

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 28/31

  • 8/3/2019 PIC Beginners Guide

    29/31

    movlw h'0f' ; simulate a calc by loading w

    goto payrol ;

    nop

    nop

    end

    Program 7: inter3.asm

    ;inter3.asm saves the state of the machine

    ; and determines the kind of interrupt.

    ;

    ;**************************************************simulator

    ;watch window: intcon, pcl, portb, w_saved, w

    ;stack: have this open too - see the return address come & go

    ;asynch stimulus: have a toggle on rb4(for rbi) and rb0(int)

    ;************************************************* setup

    processor 16c84

    w_saved equ h'10' ;a place to keep w

    movlw h'0'

    movwf h'0b' ;clear intcon

    goto main ;hop over the isr at the beginning

    ;*************************************************** isr start

    isr: org h'0004' ;interrupts always vector to here

    movwf w_saved ;save w as it was in main

    ;find out what kind of interrupt

    btfsc h'0b',0 ; is it an rbi?

    call _rbi ; yes - call the rbi 'sub-handler'

    btfsc h'0b',1 ; is it an int?

    call _int ; yes - call the int 'sub-handler'

    ;end up here after sub-handler

    ;now, restore w

    swapf w_saved,1 ; first, swap w_saved into itself

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 29/31

  • 8/3/2019 PIC Beginners Guide

    30/31

    swapf w_saved,0 ; then, swap it into w

    bcf h'0b',0 ;clear rbif before going back

    bcf h'0b',1 ;clear intf before going back

    retfie ; this re-sets intcon gie

    _rbi: movlw h'65' ;do something to change w

    return

    _int: movlw h'24' ;do something different to w

    return

    ;***************************************************** isr ends

    ;

    ;**************************************************** main start

    main: org h'0020' ; leave room for the isr!

    bsf h'0b',7 ; set global int enable

    bsf h'0b',3 ; set change on b int enable

    bsf h'0b',4 ; set ext int on pin6 enable

    ; we've got 2 types of int!

    payrol: nop ; loop here until interrupted,

    nop ; doing payroll stuff

    movlw h'0f' ;simulate a calc by loading w

    goto payrol ;

    nop

    nop

    end

    Program 8: time0.asm

    ;time0.asm to see how timer0 works

    ;

    ;************************************ setup

    processor 16c84

    STATUS EQU H'03'

    05-10-2011 PIC beginners guide

    linuxfromscratch.dk//pic-guide.html 30/31

  • 8/3/2019 PIC Beginners Guide

    31/31

    OPTIO EQU H'81'

    tmr0 EQU H'01'

    BANK_ EQU H'05'

    T0CS EQU H'05'

    PSA EQU H'03'

    clocked equ h'10'

    INTCON equ h'0B'

    T0IE equ h'05'

    GIE EQU H'07'

    goto top

    ;************************************ isr

    isr: ORG h'0004'

    incf clocked ;clocked is the 'wall clock'

    BCF INTCON,2

    retfie

    ;************************************ program

    top: org h'0010'

    clrf tmr0 ;clear the tmr0 register

    clrf clocked

    mode: bsf STATUS,BANK_ ;switch to page 1

    bcf OPTIO,T0CS ;go from counter to timer

    bsf OPTIO,PSA ;no prescaler yet

    bsf INTCON,GIE

    bsf INTCON,T0IE

    loop: nop

    nop

    goto loop

    END

    05-10-2011 PIC beginners guide