See more projects using micros:
Library of Sub-routines “Cut and Paste”
Here are lots of helpful hints to get you started in programming. Programming is easy if you follow our suggestion of taking a program from the list of projects and modifying it slightly by changing one or two instructions at a time.
It’s a lot more tricky writing a program from the start. And we don’t advise this AT ALL.
But if you want to find out about some of the “tricky things” in a program, here is a list of 100 Helpful Hints.
Don’t forget to see our Library of routines: A-E E-P P-Z It covers lots of things.
The numbers in your program can be written in binary, decimal or hex.
Here is how to write them:
;Binary numbers are shown as b’00000000’ or b’11110001’
;Decimal number are shown as: .10 .255 or d’10’ - note the decimal point.
;Hex numbers are shown as: 0Ch, 0ffh, 0x2F, 0x20, 0x0ff - “0” must be placed before any letter as 0xff will not be read correctly.
You can use a mixture of all three providing you keep to the correct formatting.
Or you can specify the way numbers are to be interpreted by the compiler by adding:
radix binary
radix dec (a number such as 20 will be treated as a decimal).
radix hex
A simpler way to list all the names for the files is to use cblock. A program inside the compiler takes each name and allocates a file, starting at 20h:
cblock 0x20 (block of constants) delA loops display jump tLOW tHIGH tREC endc
cblock is very easy to use. You can add or remove names without having to allocate file numbers.
The CALL instruction for a PIC12F629 accesses ALL MEMORY.Using the:
call sub-routine
instruction will send the micro to another address such as a sub-routine and if the sub-routine contains the instruction:
retlw 00
the micro will go to the next instruction after the call instruction.
If you use
goto sub-routine
the micro will go to the sub-routine but when it sees the
retlw 00
instruction, it will go to a previous call.
When writing a program, the layout must be in columns so that the assembler will know how to interpret each item. This layout is called a TEMPLATE and the program is saved as .asm (assembly program)
The first column contains Labels.
The second column contains Directives (such as equ, end) and Mnemonics (instructions)
The third column contains Operands, and
The fourth column contains Comments (such as ;output HIGH ;test zero bit)
Pink – Labels Blue – Directives Black – Mnemonics Red – Operands Green - Comments
del1 equ 0x20 ;store del1 in file 20 hex movlw 0x34 ;load w with 34 hex loop movwf del1 addwf del1,w goto loop sleep end
During the running of a program you may want to decrement a file to create a delay.
The file is called a temporary storage and a set of files from 20h to 5Fh is available in the PIC chips we are promoting.
At the beginning of a program, each file that you want to decrement, or store a number of loops, or hold a value for displaying later, or hold the jump value for a table, is given a name such as: delA, loops, display, jump. These files are sometimes called Variables.
Each name is then allocated a file, starting at 20h, 21h, 22h, etc.
delA equ 20h loops equ 21h display equ 22h jump equ 23h
The instruction:
goto $+1
sends the micro to the next instruction but takes 2uS. (A nop instruction takes 1uS)
The instruction:
goto $-1
sends the micro to the previous instruction. This can create an endless loop!
The instruction:
goto $
creates a halt as $ represents the current address.
You can also use this terminology to go to an instruction before a sub-routine, such as:
goto delay-1
This sends the micro to the line before the delay sub-routine. This allows you to use the delay sub-routine for different timings. The line before the label: “delay” has a load-value of 3Fh and this can be used in the sub-routine. Or you can preload a value into w and go to the sub-routine at the actual label: delay.
This is how the delay sub-routine is structured:
movlw 3Fh delay movwf temp decfsz temp,w ;the decremented value of temp is placed in w goto delay retlw 00
Normally we use the instruction decfsz temp,f
where the temp file holds the decremented value. But to create a multiple input delay sub-routine we need to use: decfsz temp,w
and the previous instruction: movwf temp
to put the decremented value into temp.
To use the load value 3Fh
, use the instruction: call delay-1
To load temp with any other value, use the instructions:
movlw xxh call delay
Some of the latest PIC chips have part numbers such as dsPIC30F1010. These are classified as Digital Signal Controller chips as they have the capability of processing digital signals and contain a fully implemented digital signal processor (DSP).
The IN/OUT port on a PIC12F629 is file 05h. This port corresponds to pins 7, 6, 5, 4, 3, and 2 for GP0, GP1, GP2, GP3 GP4 and GP5.Remember: GPIO,3 (GP3) (pin 4) is an INPUT-ONLY pin.
When writing a program, use GPIO,0 GPIO,1 GPIO,2 GPIO,3 GPIO,4 GPIO,5 in your program and the compiler will do the rest. (GPIO = General Purpose Input/Output).
For instance, If you want to SET (make HIGH) pin 7, you must do two things:
bsf status, rp0 ;bank 1 movlw b'xxxxxxx0' ;(x= don't care = does not matter) movwf TRISIO ;the lowest bit will be an OUTPUT bcf status, rp0 ;bank 0
Do not set more than one bit at a time in the GPIO (in/out) port. The actual setting of a bit is very complex. The micro reads the value of the bit, modifies it, then writes the new value and the pin may be connected to a capacitor that take time to charge or allow the voltage on the pin to change and somewhere along the line, the result is not transferred to the result and the state of the pin does not change. To avoid this problem, do not create two instructions such as:
bsf GPIO,0 bsf GPIO,2
If you need to clear or set two or more output lines, perform the operation via a single instruction:
movlw b'xxxxx1x1' movwf GPIO
or perform: bsf GPIO,0 bsf GPIO,2 with other instructions between.
If you must perform the two operation in quick succession, you need to know the state of all the outputs and include this in the value you are going to load into GPIO via movlw b’xxxxxxxx’ etc.
As can be seen from the above, the six lower bits of file 05 are connected to 6 pins of the chip and these connect the microprocessor to the outside world. This file is like all the other files (from 20h to 5F - 64 files) as it can be operated-upon (incremented, decremented, shifted left or right, plus other operations). The only difference is the contents of file 05 can be exported to the outside world and the outside world can influence the file. When any of the bits of file 05 are configured as “out,” the value of the bit will make the corresponding pin of the chip either HIGH or LOW. When it is “set” (=1), the pin will be HIGH. When it is “clear” (=0), the pin will be LOW.
If you only want to change 2 or more bits and do not know the state of the other bits, you can use the following instructions. Only bits 0 and 4 will be toggled:
movlw b'0001 0001 ;only bits 0 and 4 will be toggled xorwf gpio,f
To set 2 or more bits:
movlw b'0001 0001 ;only bits 0 and 4 will be set iorwf gpio,f
A MACRO is a piece of code that “gets inserted” into your program, by a program called an assembler, during the time when the program is ASSEMBLED. You only have to write a particular macro once, and it may be inserted 6 times into your program. Each macro must have an specific name (called a LABEL), so the assembler can find it.
I do not use Macros. They involve extra thinking and can take up extra space in your program.
But you will find some programmers use them and you need to know how they work.
A macro is like a sub-routine. It is written once and can be used many times in a program.
A macro has a LABEL just like any sub-routine. When you want to use a macro, the name of the macro is written on a new line in your program and the assembler adds the instruction(s) in the macro at the location where you have written the name of the macro. If the macro consists of 5 lines and it is used 6 times, a total of 30 instructions will be added to your program.
The macro will be deleted from the assembled program and only the contents of the macro will appear 6 times.
The advantage of a macro is the slightly faster execution of the program as the microcontroller does not have to execute a call and return. The disadvantage is the extra lines of code.
The reason for this article is to explain how a MACRO is prepared and the terms used.
The first line of a macro contains three terms:
LABEL macro PARAMETERS
LABEL can be any set of letters or numbers (some words cannot be used as they are used by the assembler and a label cannot begin with a number. Use ”_” or ”.” if numbers are required.
macro tells the assembler that a macro is the next item in the program.
PARAMETERS - a list of the files to be used with a comma between each.
Any number of lines of code can now be written. These will be any of the 33 PIC instructions.
The macro ends with:
endm ;end of macro
Example:
count macro Switch incf Switch,1 ;increment the Switch file btfss Switch,6 ;test bit 6 in the switch file and if it is "1," miss next instruction goto $+2 ;go to endm ($+0 is this instruction, $+1 is next instruction) decf Switch,1 ;decrement the Switch file and leave the result in the file. endm ;end of macro
Pin 4 can be configured as an “Input line” (GP3) OR “Master Clear.”
To configure Pin 4 as MCLR (also written as /MCLR or /MCLRE ) the configuration bit setting is: _MCLRE_ON
When this pin is configured as /MCLRE, the pin resets the chip when it is taken LOW. But why waste a pin? Use the pin as an INPUT!
To configure Pin 4 as GP3, the configuration bit setting is: _MCLRE_OFF
This instruction tells the PIC to use its internal MCLR circuitry (to keep /MCLRE high), and leaves pin 4 free as an Input line. Note: MCLR pin (GP3) is INPUT ONLY.
Microchip ICD programmer is sold in a round plastic case. If you have one of these and use long leads between the programmer and the chip you are “burning,” add a 2k2 resistor to the clock line and 0v rail and a 2k2 to the data line and 0v rail to makes these lines LOW IMPEDANCE. We had enormous trouble programming a chip due to cross-talk between these two lines.
IDE stands for Integrated Development Environment and is part of MPLAB. MPLAB has two parts and the section we use is MPASM. The other section allows you to load your program into a window and look at how each register (file) is loaded or is currently holding bits (0’s and 1’s). It also has a single-stepping feature that increments thorough your program and lets you see what is happening. But this program is very complex and will cause lots of headaches, to get it up-and-running. We have kept things simple by showing you routines that work and you simple copy-and-paste.
Numbers can be multiplied by 2 by shifting the file left with the instruction rlf total,f Before this instruction it is wise to clear the carry bit: clrc
Numbers can be divided by 2 by shifting the file right with the instruction rrf total,f Before this instruction you must clear the carry bit: clrc
You can also create a value of 0.75 by using the following instructions.
Suppose you have a file called loops and you want to reduce it to 75%:
;you have a file called loops clrc ;clear carry before shifting rrf loops,f ;halve the value of loops clrc rrf loops,w ;halve the value of loops again and put into w addwf loops,w ;to get 0.75 of original
Calibration of the oscillator is only necessary when you need precise timing, as for serial communication. In most cases you will not have to worry about this.
To use the factory calibration value:
SetUp org 0x00 bsf status, rp0 ;bank 1 call 0x3FF ;retrieve factory calibration value movwf OSCCAL ;update register with factory cal value bcf status, rp0 ;bank 0
The oscillation calibration value can be changed from the value supplied in the chip by adding the following instructions to the end of your program, (BEFORE the “end” instruction of the program).
;**************************************************************** ;* OSCCAL calibration value * ;**************************************************************** org 0x3ff retlw 0x20 END
During the programming of the chip, the above instruction will cause the burner to go to location 3FF and insert the value 20h as well as the instruction “return with the value 20h in W.”
To create the maximum frequency, use: 3fh
Centre frequency = 20h
Minimum frequency = 00h
During the running of the program (when the chip is in the project), this value is put into the OSCCAL location, to adjust the frequency of the internal oscillator.
To get the micro to do this, the following instructions are added to your program:
;**************************************************************** ;* Calibrating the internal oscillator * ;**************************************************************** bsf status,rp0 ;bank 1 call 3ffh ;get the calibration value movwf OSCCAL ;calibrate bcf status,rp0 ;bank 0
The location of the oscillator calibration register is 90h. This is in Bank 1 and is identified in your program by writing: “OSCCAL” It is a 6-bit register, with values from 00h to 3fh.
If none of the above work, or if the calibration value is missing from location 3FF (for a PIC12F629), you can insert it by hand by carrying out the following:
You will find some of the instructions and code in other people’s programs very difficult to understand. You will need to know “high-level languages” to interpret the meaning of some of them. We do not intend to teach any of these “complex sentences” or Pseudo Instructions. We will be showing you how to produce a program using just the 32 - 35 instructions needed to perform all the functions the microcontrollers are capable of.
Of course you can go one step higher and one step better by including extra complexity in your code but our intention is to start everyone at “level-zero” to “level-one” where you can produce a program to perform a reasonably simple task using the mnemonics of the instruction-set.
Never use any instructions you do not fully understand.
However here is some explanations of instructions you will find in other people’s programs:
OPERATOR | Example | |
---|---|---|
$ | Current address | goto $+3 ;goes to 3 locations down the program goto $ ;halts the micro goto $-4 ;goes to 4 locations up the program |
( | Left parenthesis | 1 + ( d * 4) |
) | Right parenthesis | (length + 1) * 256 |
! | NOT (logical complement) | if ! (a == b) |
– | Negation (2’s complement) | – 1 * length |
~ | Complement | flags = ~ flags |
* | Multiply | a = b * c |
/ | Divide | a = b / c |
% | Modulus | entry_len = tot_len % 16 |
+ | Add | tot_len = entry_len * 8 + 1 |
– | Subtract | entry_len = (tot – 1) / 8 |
<< | Left Shift | flags = flags << 1 |
>> | Right Shift | flags = flags >> 1 |
>= | Greater or equal | if entry_idx >= num_entries |
> | Greater than | if entry_idx > num_entries |
< | Less than | if entry_idx < num_entries |
<= | Less or equal | if entry_idx <= num_entries |
\== | Equal to | if entry_idx == num_entries |
! = | Not equal to | if entry_idx ! = num_entries |
& | Bitwise AND | flags = flags & ERROR_BIT |
^ | Bitwise EXclusive OR | flags = flags ^ ERROR_BIT |
| | Bitwise Inclusive OR | flags = flags | ERROR_BIT |
&& | Logical AND | if (len == 512) && (b == c) |
| | | Logical OR | if (len == 512) | | (b == c) |
\= | Set equal to | entry index = 0 |
+= | Add to, set equal | entry index += 1 |
– \= | Subtract, set equal | entry index – \= 1 |
*= | Multiply, set equal | entry index *= entry_length |
/= | Divide, set equal | entry total /= entry_length |
%= | Modulus, set equal | entry index %= 8 |
<<= | Left shift, set equal | flags <<= 3 |
>>= | Right shift, set equal | flags >>= 3 |
&= | AND, set equal | flags &= ERROR_FLAG |
| = | Inclusive OR, set equal | flags | = ERROR_FLAG |
^ = | EXclusive OR, set equal | flags ^= ERROR_FLAG |
++ | Increment | i ++ |
– – | Decrement | i – – |
Pseudo Instructions - these are additional Instructions understood by MPASM:
Mnemonic | Description | Equivalent Operation(s) | Status | ||
---|---|---|---|---|---|
addcf | f,d | Add Carry to File | btfsc incf | 3,0 f,d | Z |
adddcf | f,d | Add Digit Carry to File | btfsc incf | 3,1 f,d | Z |
b | k | Branch | goto | k | - |
bc | k | Branch on Carry | btfsc goto | 3,0 k | - |
bdc | k | Branch on Digit Carry | btfsc goto | 3,1 k | - |
bnc | k | Branch on No Carry | btfsc goto | 3,0 k | - |
bndc | k | Branch on No Digit Carry | btfsc goto | 3,1 k | - |
bnz | k | Branch on No Zero | btfsc goto | 3,2 k | - |
bz | k | Branch on Zero | btfsc goto | 3,2 k | - |
clrc | Clear Carry | bcf | 3,0 | - | |
clrdc | Clear Digit Carry | bcf | 3,1 | - | |
clrz | Clear Zero | bcf | 3,2 | - | |
lcall | k | Long Call | bcf/bsf bcf/bsf call | 0x0A,3 0x0A,4 k | |
lgoto | k | Long GOTO | bcf/bsf bcf/bsf goto | 0x0A,3 0x0A,4 k | |
movfw | f | Move File to W | movf | f,0 | Z |
negf | f,d | Negate File | comf incf | f,1 f,d | Z |
setc | Set Carry | bsf | 3,0 | - | |
setdc | Set Digit Carry | bsf | 3,1 | - | |
setz | Set Zero | bsf | 3,2 | - | |
skpc | Skip on Carry | btfss | 3,0 | - | |
skpdc | Skip on Digit Carry | btfss | 3,1 | - | |
skpnc | Skip on No Carry | btfsc | 3,0 | - | |
skpndc | Skip on No Digit Carry | btfsc | 3,1 | - | |
skpnz | Skip on Non Zero | btfsc | 3,2 | - | |
skpz | Skip on Zero | btfss | 3,2 | - | |
subcf | f,d | Subtract Carry from File | btfsc decf | 3,0 f,d | Z |
subdcf | f,d | Subtract Digit Carry from File | btfsc decf | 3,1 f,d | Z |
tstf | f | Test File | movf | f,1 | Z |
This is the name given to the latest PICkit programmer. When PICkit 3 is used in conjunction with MPLAB IDE (Integrated Development Environment) the MPLAB IDE software will show you what is going on and this will help you in debugging your program.
When any of the bits of file 05 are configured as “input,” (this is done via the TRISIO instruction) the HIGH or LOW on the pin of the chip (this HIGH or LOW will be created by something in the outside world making the line HIGH or LOW) will be read by the micro as a HIGH or LOW, (when the file is read via an instruction such as btfss GPIO,1 or btfsc GPIO,1 - test bit1 in file 05h, skip if set or test bit1 file 05h, skip if clear).
This “reading process” can also be done when the contents of file 05 (GPIO) is moved to W. The instruction to do this is movf 05h,0 (movf GPIO,0). This instruction tells the micro to move the in/out port to the working register. The working register is called “W” and has the destination “0” - a file has the destination “1.” The contents can also be shifted, incremented, plus other instructions.
Here are some instructions to read the input bit:
In most cases, the first bit (or line) to use in a program is pin 4 as this line is INPUT ONLY. It corresponds to GPIO,3.
Using the instructions from above, we have GPIO,3 as an INPUT and all other lines are OUTPUT.
We are looking for a HIGH on the input line.
To read the bit, use the following instructions:
btfsc GPIO,3 ;This will test the input bit and if it is LOW, the micro goes to movlw xx GOTO PhaseA ;This instruction takes the micro to a new sub-routine movlw xx
If you don’t know the state of some of the bits (or don’t want to alter them - by mistake), you can use the XOR instruction.
For example, to turn ON bits 0, 1 and 2, the instructions can be:
bsf GPIO,0 b’00000001’
bsf GPIO,1 b’00000010’
bsf GPIO,2 b’00000100’
But this will result in only the third instruction being carried out. We mentioned above, not to use multiple bit-setting as it will fail to work.
The answer is to use the XOR instruction
Combine the 3 instructions to get: b’00000111’
movlw 07h
xorwf GPIO,1
Only the three lowest outputs will go HIGH.
To turn OFF the three lowest outputs, repeat the same instructions:
movlw 07h
xorwf GPIO,1
Only the three lowest outputs will go LOW.
Actually, the bits will TOGGLE.
If you have trouble re-programming a chip, here are some possible solutions:
Some chips are just difficult to program and you should buy a number of chips and only use those that are easy to program, when experimenting.
The PIC12F629 has an 8-CALL stack. (8-level stack).
Suppose you have a value from a table (it will be in w) and want to subtract (say) 10. The PIC12F629 micro does not have an instruction for this.
You cannot use: sublw .10
because the instruction subtracts w from .10 (decimal ten)
The instruction to use is: addlw -.10
The TRIS register determines if each line is to be input or output.
It can be accessed by the following two lines of code:
movlw b'xx111111' ;or b'xx000000' or any combination tris gpio ;
you do not need: bsf status, rp0 / bcf status, rp0 to get to bank 1 then back to bank 0.
When any of the pins of a PIC12F629 or PIC16F628 are configured as inputs, you can turn on the weak pull-up feature by clearing bit 7 in the option_reg.
Note: GP3 does NOT have this feature. When-ever a pin is configured as an input it will have a weak pull-up of about 47k. This means you can have a switch connected between an input line and 0v rail and when the switch is pressed, the input goes LOW.
Quick Links
Legal Stuff
Social Media