Nearly all these instructions also work with
PIC16F628. Just check on Port value(s) and
first available file.
This is a directive, placed at the end of of program to tell the assembler to finish the job of assembling the instructions into .hex code. The directive is:
The end of a table can be detected in two different ways.
If a value such as FF is not used in any of the data, it can be used as an End of Table marker. The sub-routine calling the table must look for 0FFh to detect End of Table.
TableADDWF 02h,1 ;Add W to the Program Counter to create a jump. RETLW 3Fh ;0 format= gfedcba RETLW 06h ;1 RETLW 5Bh ;2 RETLW 4Fh ;3 RETLW 66h ;4 RETLW 6Dh ;5 RETLW 7Dh ;6 RETLW 07h ;7 RETLW 7Fh ;8 RETLW 6Fh ;9 RETLW 0FFh ;End of table marker
The other method is to count the number of items in a table and make sure the sub-routine calling the table doe not CALL values beyond this value.
To detect if two files are equal, they are XORed together. See XOR.
Equates assign an easy to remember label to a numeric value. This value can be a file or bit in a file.
delay1 equ 20h ;every time “delay1” is inserted into a program, the assembler will assign file 20h.
in your program:
movlw 80h movwf delay1 ;the assembler will put 80h into file 20h
The in/out pins on a 12F629 are 2,3,4,5,6 and 7.
These are GP5, GP4, GP3, GP2, GP1 and GP0
These correspond to GPIO,5 GPIO,4 GPIO,3 GPIO,2 GPIO,1 and GPIO,0 in a program.
Suppose GPIO,3 is called “switch” and GPIO,5 is called “LED” (it drives a red LED).
In the equates section of your program (at the top of your program) you can equate bit “3” of the GPIO file as “switch and bit “5” as “LED.”
The equates will appear as:
switch equ 3 or switch = 3 LED equ 5 or LED = 5
in your program:
If you get an error message when MPASM is compiling your program to a .hex file, it will not produce the .hex file.
To find the error messages, open the .lst file.
Some error messages are just a warning such as:
Message myfile.ASM 136 : Register in operand not in bank 0. Ensure that bank bits are correct.
The above is a warning that you need to select the correct bank.
You can remove the warning message by inserting the following at the top of your .asm program
ERRORLEVEL -302 ;remove messages
One of the problems with the output port of the PIC12F629/675 is making one or more of the lines HIGH or LOW and then making another of the lines either HIGH or LOW after a few uS in the program.
Theoretically you can operate on the output port with all the operations that are available to any of the files (registers) as the port is simply one of the files in the micro.
But sometimes the port fails to accept an instruction.
For instance, you can make all the output lines LOW by using:
This failed to make GP0 LOW in the Hourglass project and an extra instruction had to be added:
Detecting the value of a file or register.
movlw ;load a value into w (say 8C) subwf,0 ;subtract 8C from w to see if the result is zero (store ;the result in w so that the file is not altered. btfss 03,2 ;test the zero bit in file 03 (status). ;It will be set if value=file goto xxxx ;value in w is not = value in file goto yyyy ;value in w = value in file
This is a special file called File Select Register. It has the address 04. It is not a file like the other files in the micro but a POINTER FILE and is used in conjunction with another file called INDF.
INDF has the address 00.
INDF is not actually a file but a robot arm. It grabs the contents (or delivers contents) to a file pointed to by FSR. These are two special files (devices) that allow very powerful (low instruction) programming to be produced.
For instance, if FSR is loaded with 2C, it will tell INDF to grab (or deliver) contents to file 2C.
To do this, we need the instructions:
If we now put 8Fh into INDF, the value will actually go into file 2C.
This is called INDIRECT ADDRESSING.
The GOTO instruction causes the micro to go to the address identified by a label such as “No” or “Yes.”
BTFSS GPIO,0 ;Is button pressed? GOTO No ;No GOTO Yes ;Yes No RETLW 00 Yes MOVLW 3Fh etc
The instruction: goto $ + 2
”$” means the current address.
”+ 2” means to advance two instructions down the program.
btfss GPIO,0 goto $ + 2 ;this will end the micro to instruction y instruction x instruction y ;the micro will advance to this instruction instruction z ;the micro will never execute this instruction!!!!
To go “up” the program, the goto instruction is:
goto $ -3
goto $ -0dh
or $ -.16 (minus decimal sixteen). The instruction should be written without any gaps: $-.16
When writing a program, you must make sure the micro will get back to the “Main” routine.
If you use a “call” instructions such as:
make sure the sub-routine has:
to get the micro back to “Main.”
You cannot use the instruction:
as the “retlw 00” in the delay_1 routine will not take the micro back to “Main” as the return address has not been remembered with a “goto” instruction.
You can also define a location by writing the LABEL (in this case “Step”) and an offset - in this case +1. The micro will go to “movwf tmr2.” This has an advantage. It is easy to see, rather than writing $–4, when a large number of instructions are to be counted.
Step movlw 25 movwf tmr2 btfsc Sw2 goto newpress decfsz Sw2,f goto Step+1 retlw 00
Do not use the word “Halt” as a label, the assembler does not like it. Use Loop, Pause, Stop, Wait. See Loop and Stop.
To create a “halt” instruction:
Loop goto $ This will cause the microcontroller to keep looping the same instruction.
To halve (half - divide by two) the value of the contents of a file, it is shifted RIGHT (RRF 1A,1). The number must be an even number (it cannot have a bit in bit0).
Any mixture of binary, Hex and decimal numbers can be shown in a program.
Binary numbers are presented as: 0b’00000000’ or b’00000000’ or B’00000000’ or 00000000b or b’0100’ to indicate the lowest 4 bits.
Hex numbers are shown as: 0x2 or 0x0F (= fifteen) or 0x3C or h’ or $ ($F or $f or $3A or $0ff )
(digits)h (must begin with 0 …9) examples: 80h 3Ah 0FFh or 0ffh (do not put ffh or FFh as the compiler requires 0 to 9 at beginning)
Decimal numbers are shown as: d’250’ or decimal numbers without a prefix. They can also be written with a decimal point. examples: .250 .80 .100
To find out if a number is higher than a know value, a comparison is made. See Comparison.
To increment a file, use the instruction: INCF 2A,1. This puts the new value back into the file.
Using INCF 2A,0 puts the new value also into W!
To add two to a file, it can be incremented twice:
To double the value of a file, the contents is shifted left:
A file can be incremented until it “rolls over to zero.” Normally a file is decremented to zero and a skip occurs when it is zero. But the same effect can be produced by incrementing a file:
To increment W, use ADDLW, thus: ADDLW 01 or ADDLW 3Bh
A number of files can be addressed by a sub-routine and the information can be moved into each file or read from each file. The files must be a group.
Suppose we have 8 files and need to read the contents and output it to a display.
The files are: 21h, 22h, 23h, 24h, 25h, 26h, 27h, and 28h.
There are two special files that allow a sub-routine to be created to look at the 8 files and read the contents.
They are: INDF and FSR
The INDF file is not a real file. It is like a Robot Arm. It reaches down the list of files and picks up the contents or delivers the contents of a file to the programmer. The file it reaches is determined by the value in FSR.
FSR is loaded with the address of the file you wish to read or write.
This arrangement has an advantage. By loading FSR with a value, you can reach a file and by incrementing FSR, you can reach the next file etc.
If you load a value into INDF, you will actually load the value into the file pointed to by FSR.
If you read INDF, you will actually read the contents of the file pointed to by FSR.
You can consecutively read 8, 10 or 20 files or clear 20 files or load into 20 or more files with a simple looping sub-routine. It’s a very powerful feature.
The following instructions put a value of 8Fh into file 21h.
MOVLW 21h ;Load W with start of 8 files MOVWF 04 ;Load 21h into FSR MOVLW 8Fh ;Put 8F into W MOVWF 00 ;Put 8Fh into file 21h
The animation below shows how the information passes to the files:
Using INDF and FSR
The following instructions put a value of 8Fh into files 21h, 22h, 23h, 24h, 25h, 26h, 27h and 28h.
MOVLW 08 ;8 loops of the program MOVWF 20h ;File 20h is the decrementing file MOVLW 21h ;Load W with start of 8 files MOVWF 04 ;Load 21h into FSR MOVLW 8Fh ;Put 8F into W Loop1 MOVWF 00 ;Put 8Fh into file 21h INCF 04 ;Increment FSR to make INDF go to next file DECFSZ 20h GOTO Loop1 RETURN
The following instructions read files 21h, 22h, 23h, 24h, 25h, 26h, 27h and 28h and outputs to GPIO (file 05). Output Port 05 has only 5 lines: GP0, GP1, GP2, GP4 and GP5. GP3 is missing and this makes it difficult to display values from a file.
MOVLW 08 ;8 loops of the program MOVWF 20h ;File 20h is the decrementing file MOVLW 21h ;Load W with start of 8 files MOVWF 04 ;Load 21h into FSR Loop1 MOVF 00,0 ;Copy file 21h (or next file) into W MOVWF GPIO ;Move W to output Port GPIO CALL Delay ;Show value LEDs etc INCF 04 ;Increment FSR to make INDF go to next file DECFSZ 20h GOTO Loop1 RETURN
This is a special file called INDirect File.
INDF has the address 00.
INDF is not actually a file but a robot arm. It grabs the contents (or delivers contents) to a file pointed to by FSR.
This is used in an operation called INDIRECT ADDRESSING.
The six bits of the in/out port GPIO can be made input or output by the value of the bits in a file called TRISIO. GP3 can only be INPUT.
To make a line INPUT, the corresponding TRISIO bit must be “1.”
To make a line OUTPUT, the corresponding TRISIO bit must be “0.”
To make a line INPUT (or OUTPUT), the instructions must be placed inside BSF 03,5 and BCF 03,5.
For example, to make the lowest line of GPIO, an INPUT, the following instructions are needed:
BSF 03,5 ;Go to Bank 1 MOVLW 01 ;Load W with 0000 0001 MOVWF GPIO ;Make GP0 input BCF 03,5 ;Go to Bank 0 - the program memory area.
The other individual lines are:
movlw 02 ;Load W with 0000 0010 movwf GPIO ;Make GP1 input movlw 04 ;Load W with 0000 0100 movwf GPIO ;Make GP2 input movlw 08 ;Load W with 0000 1000 movwf GPIO ;Make GP3 input movlw 10h ;Load W with 0001 0000 movwf GPIO ;Make GP4 input movlw 20h ;Load W with 0010 0000 movwf GPIO ;Make GP5 input
To make more than one line (with a single instruction) an input, the hex values are added.
movlw 0F ;Load W with 0000 1111 movwf GPIO ;Make GP0, GP1, GP2, GP3 input movlw 12h ;Load W with 0001 0010 movwf GPIO ;Make GP1, GP4 input movlw 33h ;Load W with 0011 0011 movwf GPIO ;Make GP0, GP1, GP4, GP5 input
Port direction can be changed at any time during the running of a program. You must make sure that any input or output devices on the line will not upset the running of the program.
In this case it is best to SET or CLEAR a BIT. This involves setting or clearing an individual bit. This prevents touching any other lines.
Eg: To make the lowest line of port B an input:
bsf 03,5 ;Go to Bank 1 bsf GPIO,0 ;Make GP0 input bsf 03,5 ;Go to Bank 0 - the program memory area.
Carry out instructions using the input line, then make the line an output:
bsf 03,5 ;Go to Bank 1 bsf GPIO,0 ;Make GP0 output bsf 03,5 ;Go to Bank 0 - the program memory area.
int n_bytes or int nEmpty etc means integer.
An integer is a whole number, such as: 2, 346, -458, but 1.5 is not an integer.
You will also find INT used in a program to refer to INTerrupt, or INTCON.
This program Loops until input GPIO,0 changes state. The micro then goes to address 4, then to Interrupt sub-routine where it changes the state of a LED connected to GPIO,0. It then clears the GPIF flag and returns to Main where it Loops.
Org 0x00 ;Go to Bank 1 Goto Main ;Make GP0 output ;Go to Bank 0 - the program memory area. Org 0x04 Goto Interrupt Interrupt btfss Interrupt,gpif ;test if gpio,0 changed state retfie ;return to Main movlw b'00000001' xorwf gpio,0 ;blink LED bcf intcon,gpif ;clear gpif flag retfie ;return to Main Main bsf status,rp0 movlw b'00000001' ;make gpio,0 input movwf trisio bcf status,rp0 movlw b'00001000' ;enable port-change interrupt movwf intcon bsf intcon,gie ;enable all interrupts - bit7 Loop nop ;loops HERE until interrupt occurs goto Loop
There is no “jump” instruction, however the “jump command” is included in instructions such as
decfsz, btfsc, with the actual instruction meaning to skip or “jump over” the next instruction if the file is not zero, or the bit is not clear.
The closest instruction is: “goto”
Normally the micro advances down the program, one instruction at a time and reads each instruction as it comes to it. If you want to jump down a program, you can add a number (literal) to the Program Counter and the micro will carry out the command.
The instruction is:
Suppose you need to go to one of 5 different sub-routines. This is done by placing a value in “w:”
movlw 01, or movlw 02, movlw 03, movlw 04, movlw 05
then the instruction: addwf pcl,1
To prevent a jump beyond the 5 “goto’s, the instruction: andlw 05h is added here.
The next instructions will be:
nop ;this instruction is equal to: "movlw 00" goto sub-1 goto sub-2 goto sub-3 goto sub-4 goto sub-5
This is the name given to each sub-routine. It is placed in the first column of your program (called an assembly program).
Some names cannot be used as they are reserved by the assembler. Keep the length to less than 8 letters. Do not use ”-” or ”/” Use ”_” to separate.
Here are some examples:
Alarm Alarm_1 Beep Button Count Dec Delay Display Fast Find Flow Halt HeeHaw Inc Look Loop Main Send Show Siren Sound Sw Switch Table Table2 Table_3 Test Try Try_2 Toggle Tone Unit
This operation cannot be done directly. A number (a value) is called a LITERAL. It is loaded into W then the value in W is moved to a file. The two instructions are:
MOVLW 0FFh ;Load a value (called a Literal) (00 to 0FFh) into W MOVWF 2A ;Move the value in W to a file
There is no instruction called “look.” If a switch or button is connected to an input line such as the lowest line on GPIO, the instruction is:
BTFSS GPIO,0 ;Is button pressed? GOTO No ;No GOTO Yes ;Yes
This assumes the switch is connected to the positive rail and the input goes HIGH when the button is pressed.
This instruction also works for a signal on line GPIO,1. You must make sure line GPIO,1 is an INPUT via the SetUp routine.
The two instructions after BTFSS GPIO,1 can be “GOTO Yes”, “GOTO No” by changing the first instruction. The decision will depend on the number of instructions for the “Yes” or “No” answer, as the instruction placed directly after BTFSS GPIO,1 must be a GOTO.
BTFSC GPIO,1 ;Is button pressed? GOTO Yes ;Yes GOTO No ;No
The action of looping is carried out for a number of reasons. The micro does not have a Halt or Stop feature and must carry out instructions at all times. A loop will hold the micro in one place.
To get out, a set of instructions such as “look” is needed inside the loop. These instructions see if a button has been pressed etc. Alternatively, if the watchdog timer is SET, the micro will come out of the loop and go to location 04. The instructions to create a loop are as follows:
Loop NOP GOTO Loop
To create a “loop” instruction:
Loop goto $ This will cause the microcontroller to keep looping the same instruction.
To find out if a number is lower than a know value, a comparison is made. See Comparison.
A Macro is similar to a sub-routine. You can call it from anywhere in a program. The aim of a macro is to save lines of code.
Some assemblers have built-in macros and recognise abbreviations such as the following:
Do not use these instructions unless you know EXACTLY what you are doing.
fr = file register
For instance, we will explain the following instruction in the table below:
Branch on No Zero to addr = btfss 3, 2 goto addr. (file 3, bit 2 is the zero flag)
Test the zero flag. Skip if it is set. In other words skip if the zero flag is set, but BRANCH if it is not zero!
The normal instructions are as follows:
btfss 3,2 goto tune1 next instruction
alternately, you can use:
bnz tune1 next instruction
|addcf fr, d||Add carry to fr||btfsc 3, 0 incf f,d|
|subcf fr, d||Subtract carry from fr||btfsc 3, 0 decf fr,d|
|negf fr, d||Negate file register fr||comf fr, 1 incf fr,d|
|b addr||Branch to addr||goto adddr|
|bz addr||Branch on Zero to addr||btfsc 3, 2 goto addr|
|bnz addr||Branch on No Zero to addr||btfss 3, 2 goto addr|
|bc addr||Branch on Carry to addr||btfsc 3, 0 goto addr|
|bnc addr||Branch on No Carry to addr||btfss 3, 0 goto addr|
|skpc||Skip on Carry||btfss 3, 0|
|skpnc||Skip on No Carry||btfsc 3, 0|
|skpz||Skip on Zero||btfss 3, 2|
|skpnz||Skip on No Zero||btfsc 3, 2|
|clrz||Clear Zero flag||bcf 3, 2|
|setz||Set Zero flag||bsf 3, 2|
|clrc||Clear Carry flag||bcf 3, 0|
|setc||Set Carry flag||bsf 3, 0|
|tstf fr||Test file register fr||movf fr, f|
|decbnz fr,addr||Decrement fr, if zero branch to addr||decfsz fr goto addr|
A macro can be created to move a number (a literal) into a file, using a single instruction. This normally requires two instructions:
movlw 64h ;put 64h into W movwf 2Ch ;move 64h to file 2C
The single instruction we will create is:
movlf 64h,2Ch ;this instruction will put 64h into file 2C. (a macro must be included in the program)
To create a macro for the instruction “movlf” the following is placed at the top of your program:
movlf macro literal,file ;literal -> file movlw literal movwf file endm
When you write the instruction: movlf 4Ah,2Fh ;4A will be placed into file 2F.
The Main routine is constantly looped and generally consists of sub-routines that are CALLed.
Main CALL Switch ;Loop Main CALL Display CALL Beep GOTO Main
If you want to remove a number of bits from a file, the operation is called MASKING.
You can remove the high or low nibble (a nibble is a set of 4 bits) or any other bits. Any number from 0 - 7 can be obtained by masking (removing) bits 3,4,5,6,7, and leaving only bits 0, 1 and 2.
To mask (remove) the upper nibble, the number is ANDed with 0F. To mask the lower nibble, the number is ANDed with F0. (this is written: 0F0h in the program)
number: 1001 0111
W: 1111 0000
answer: 1001 0000
MOVLW 97h ;Put 97h into W MOVWF 2A ;Move 97h into file 2A MOVLW 0F0h ;put the "masking value" into W ANDWF 2A,1 ;AND 97h with file 2A. The result will be in file 2A.
The contents of a file can be moved to W with the following instruction:
MOVF 2A,0 The contents are actually COPIED. The original file still holds the contents.
The contents of a file can be moved to another file via the following instructions. It is firstly copied to W then W is copied to the new file:
MOVF 2A,0 ;The contents of file 2A is copied to W MOVWF 2B ;W is copied to file 2B
Simple multiplication such as multiply by 2 can be performed by the RLF instruction. Successive RLF’s will multiply by 4, 8, sixteen etc. You need to be careful as this is called a “blind” operation.
A number such as 80h (128) will not be doubled as 1000 0000 will be moved to the left and the top bit will be passed to the Carry. Only numbers up to 7F (127) can be doubled.
To multiply by 2:
RLF 2A,1 ;The contents of file 2A is doubled
To multiply any two numbers together requires a program. Since the PIC12F629 does not have any multiply function, it is carried out by successive ADDITIONS. A number from 01 to 255 can be multiplied by 01 to 255.
To multiply 75(4Bh) by 122(7A), 122 is added to a file 75 times. It needs two files to hold the answer.
CLRF 2B ;Clear the receiving file CLRF 2C ;Clear the receiving file MOVLW 7Ah ;122 MOVWF 2A,1 ;file 1A holds 122 MOVLW 4B ;75 M1 ADDWF 2B,1 ;ADD 75 to file 2B BTFSS 03,0 ;Test Carry bit in status GOTO M2 ;file. CLEAR = no carry INCF 2C,1 ; SET = carry M2 DECFSZ 2A,1 GOTO M1 RETURN
The result is a 16 bit binary number of the form: file 2C, file 2B \= 0000 0000 0000 0000
To multiply two numbers and obtain a decimal result requires a different program.
Nibble is 4 bits - each byte has two nibbles - called the Low-Nibble and High-Nibble. Here is a simple routine that takes the lower nibble and puts it in another file called LowNibble and the high nibble into a file called HighNibble:
movf Byte,w ;move the byte into w andlw 0x0F ;anding w with 0Fh will make the top 4 bits = 0 movwf LowNibble ;move w to a new file called LowNibble. 1st part finished. swapf Byte,w ;swap the high nibble with the lower nibble and put in w andlw 0x0F ;anding w with 0Fh will make the top 4 bits = 0 movwf HighNibble ;move w to a new file called HighNibble. 2nd part finished. ;The lower 4 bits will be in the 4 lower places of LowNibble ;and the 4 upper bits of Byte will be in the 4 lower places of ;HighNibble
Writing to OPTION Register:
movlw b'00000000' option
This is a pseudo instruction (also called a directive) that tells the assembler where to place the next instruction. ORG must have a value. For ORG 000, the real instruction will be placed at memory location 000.
For ORG 2Ch, the first instruction in Main will be placed at address location 2Ch as shown below:
ORG 000 ;Start of program in memory SetUp MOVLW 08 ; MOVWF TRISIO OPTION 0DFh ; - - - - - - - - - - - - - - - - - - - - ORG 2Ch ;Next following instruction will be placed at location 2Ch Main CALL Switch CALL Display CALL Beep GOTO Main
These instructions can be placed in SetUp
bsf status,rp0 ;bank 1 call 0x3ff ;get the calibration value movwf OSCCAL ;calibrate oscillator bcf status,rp0 ;bank 0
Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump. RETLW 3Fh RETLW 06h RETLW 5Bh RETLW 4Fh RETLW 66h RETLW 6Dh RETLW 7Dh RETLW 07h RETLW 7Fh RETLW 6Fh
The output port for a PIC12F629 is actually a FILE or REGISTER! It is file 05.
The 6 lines of the port are called: GP0, GP1, GP2, GP3, GP4 and GP5.
Each line can deliver approx 25mA. The maximum total current for the chip is about 150mA.
An output line can be HIGH or LOW. Each output line corresponds to a bit in the file associated with the port. When the bit is SET, the line is HIGH. When the bit is CLEAR, the line is LOW.
Before you can make a line HIGH or LOW, the file must be “configured.” This means each bit must be made an OUTPUT. This is done via the TRISIO file. This file is located at 85h - in Band 1.
Any line can be made either an input or an output at any time during the running of a program and to make a line INPUT, the corresponding bit in the TRISIO file is made “1.” To make a line OUTPUT, the corresponding bit in the TRISIO file is made”0.”
There are two ways to get to the TRISIO file. One is directly via the instruction:
MOVLW 2Bh ;Load xx10 1011 into W TRISIO ;Make GP2 and GP4 output.
The other is via the two instructions: BSF 03,5 and BCF 03,5. These instructions allow you to go to bank1 where the TRISIO file is located. It is in Bank1 and the TRISIO file is called 05.
BSF 03,5 ;Go to Bank 1 MOVLW 3Fh ;Load W with 0011 1111 MOVWF 05 ;Make all GPIO input BCF 03,5 ;Go to Bank 0 - the program memory area.
Any lines that are made output can be made HIGH or LOW.
MOVLW 16h ;Load 0001 0110 into W MOVWF GPIO ;Make GP1 and GP2 and GP4 HIGH.
Output 8 bits of a file via bit0 of GPIO:.
movlw 8 ; movwf count ; create file to hold the 8 loops Loop btfss temp,0 ; bcf GPIO,0 ;temp will be 0 so clear bit0 of gpio and send btfsc temp,0 ;temp will be set, so set bit0 of gpio and send bsf GPIO,0 ; rrf temp,f ;shift temp file so bit1 becomes bit0 call delay ; decfsz count,f ; goto Loop ;perform 8 loops