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.
BINARY, DECIMAL AND HEX
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
cblock
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.
CALL AND GOTO
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.
DEFINING
THINGS
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
goto $+1
goto $-1 goto $
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
DsPIC
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).
IN/OUT PORT
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:
1. Make sure GPIO,0 is an OUTPUT bit by making the corresponding bit in
the TRISIO register "0." This is done via the following
instructions: Remember: "0" = output, "1" = input
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
2. Make the lowest bit of the output port = 1 (HIGH). This is done via
the following instruction:
bsf GPIO,0
SETTING MORE THAN
ONE BIT AT A TIME
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
MACRO'S
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
MCLR PIN
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
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.
MPLAB IDE
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.
MULTIPLYING AND DIVIDING
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
OSCILLATOR CALIBRATION VALUE
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:
1. This operation will erase the program in the chip and only install
the osccal value, so make sure the program can be re-installed after
this operation.
2. Connect the chip to a programmer and open the software on your
desktop: PICkit 2 Programmer.
3. Under Tools OSCCAL, select "Set Manually" from the drop-down
window that appears on the right-hand side.
4. Scroll down to location 3FF in the Program Memory window and change
location 3FF from 0000 or 3FFF to 3420.
5. Now you can re-install the program to the chip and the oscillator
will operate a mid-position of its frequency-adjustment.
The PICkit 2 Programmer software will not burn any value placed in
location 3FF, during a normal burn operation. You must select: Tools OSCCAL,
"Set Manually" to burn the osccal value.
OTHER PROGRAMMER'S CODE
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:
ARITHMETIC
OPERATORS AND PRECEDENCE:
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
|
|
3,0
k
|
-
|
bndc
|
k
|
Branch on No Digit Carry
|
|
3,1
k
|
-
|
bnz
|
k
|
Branch on No Zero
|
btfsc
goto
|
3,2
k
|
-
|
bz
|
k
|
Branch on Zero
|
|
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
|
PICkit 3 Debug Express
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.
READING
AN INPUT LINE
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.
RE-PROGRAMMING:
If you have trouble
re-programming a chip, here are some possible solutions:
1.
Put a 47k across the power rails to discharge ALL THE CELLS so
the programmer can re-program the chip and prevent "failure to
re-program" messages appearing on the screen, or:
2. If a chip is difficult to re-program, remove and replace it. The cells are discharged in this process.
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.
STACK
The PIC12F629 has an 8-CALL stack. (8-level
stack).
SUBTRACT - BE CAREFUL!
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
TRIS
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.
WEAK PULL-UP FEATURE
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.
P1(list
of projects)
P3 The XOR Trick
|