
| |
Tips on PIC
Programming
by
Michele
Schieppati
Version 2 dated 04 November 2003
The following
notes are a short example of ASSEMBLER code for a PIC that can be used as a
reference for code writing in a ‘clean’ and ‘tidy’ manner.
Coloured
numbers, which are hyperlinks, have been placed to identify the different notes in the code. The
notes are brief and are not a total ‘explanation’ .
|
1 |
It is a
good practice to start the program listing of the code with some information
about the version, date, remarks, etc.; You should always describe the
device pin-out as well.
|
|
2 |
Sometimes
it is easier to develop the code on a bigger microprocessor and move the
code to a smaller device when it works well. Using a bigger CPU, you have
more pins available that can be dedicated to the debug function, such as
stopping the microprocessor after some blocks of operations and reading a
coded output to verify the CPU state, or simply sending information to a PC
using the serial line.
Using a
flash microcontroller allows you to quickly re-program the code without
removing the microcontroller from the circuit and burning the OTP (chip that
has to be 'burned') only at
the end when everything is right.
The
ifdef __microcontroller name
allows you to select part of the code that must be assembled as function
of the microcontroller selected in the MPLAB environment. In the example
below, the final micro is a 12C508A, but the code can be also debugged on a
16F84A.
Editor's Note: The 12C508A is an older chip (OTP) that is "burned" and can only
be erased using ultraviolet light. The 16F84A is a "flash" chip that
is an EEPROM - it is programmed electrically and can be erased and
reprogrammed thousands of times electrically.
|
|
3 |
RAM_START
defines the first RAM location for variables storage. In the example, it is
automatically adopted according with the microcontroller selection.
The
include “p12C508A.inc” is used to
have the standard original names for microcontroller registers, port,
special bit,… without having to re-declare the address, the name of the port
and other registers.
#DEFINE
will insert in the code during assembling the value (second operand) in
place of the first name. In the example, when the 508A is selected the name
IOPORT is replaced by GPIO, while when the 84A is selected it is replaced by
PORTB. In the common part of the code referring to IOPORT, it will address
operations to the correct port register depending on the selected
microcontroller.
|
|
4 |
Defining
I/O with a mnemonic name associated to the address (name of the IO Port) and
bit number allows the use of the bit instruction using the symbolic name.
For example, btfsc Inp will
test bit 3 of the IO port (GPIO or PORTB).
In the future, if you have to
move to a different bit, the code remains the same and you have to change
only the declaration line defining Inp
to a different bit.
When you write your code you can concentrate
on the function (testing the Inp),
rather than on the port name and bit number.
|
|
5 |
CBLOCK
defines a variable block definition. The starting address is defined in
the cblock directives and all
other variables are automatically allocated.
Using this directive allows you to handle variables with the symbolic name
in the watch windows during program debug.
|
|
6 |
Constant
defines all
the constant values that can be entered and evaluated as an expression. |
|
7 |
The same
concept used in IO port declaration can be used to assign a symbolic name to
bits used as a flag.
|
|
8 |
At the
start of the code, in the init section, the conditional statement is used
again to select two different initialization sections. |
1
;*******************************************************************
; Flasher V1.0 03.02.2002
; code developed by Michele Schieppati - all rights reserved
; CPU Deb. 12C508A/16F84A Clock 1 uS 4 Mhz
;
; 12C508A/16F84A Pin Out
;
; Pin 1/14: VDD +5V
; Pin 8/5: VSS GND
; Pin 15-16 Osc F84A only
;
; Pin 7/6: GP0/RB0 Output Navigation light
; Pin 6/7: GP1/RB1 Output Flash 1
; Pin 5/8: GP2/RB2 Output Flash 2
; Pin 4/9: GP3/RB3 Input Command
; Pin 3/10: GP4/RB4 Output Flash 3
; Pin 2/11: GP5/RB5 Output Flash 4
;
;*******************************************************************
2
ifdef __12C508A
3
RAM_START equ 0x07
LIST P=12C508A, C=132, N=74, ST=OFF
include "p12C508A.inc"
__CONFIG _IntRC_OSC & _WDT_ON & _CP_ON & _MCLRE_OFF
#DEFINE IOPORT GPIO
else
RAM_START equ 0x20
LIST P=16F84A, C=132, N=74, ST=OFF
include "p16F84A.inc"
__CONFIG _XT_OSC & _WDT_OFF & _CP_OFF
#DEFINE IOPORT PORTB
#DEFINE Page_1 STATUS,RP0 ; Page 1 bank switch
endif
;*******************************************************************
; Definition I/O
;*******************************************************************
;
4
#DEFINE Inp IOPORT,3
;*******************************************************************
; Variables
;*******************************************************************
;
5
CBLOCK RAM_START
Count_P ; Pulse counter H
Count ; Generic counter
Cnt_On ; Command on pulse counter
Cnt_Off ; Command off pulse counter
TabPtr ; Table pointer
TabCnt ; Table counter
SlotCnt ; Bit counter
FlDat1 ; Data flash sequence 1
FlDat2 ; Data flash sequence 2
FlDat3 ; Data flash sequence 3
FlDat4 ; Data flash sequence 4
FMode ; Flash mode [0-7]
PortImg ; Image of output port
Temp ; Temporary register
Flag ; Flag register
ENDC
;*******************************************************************
; Constants
;*******************************************************************
;
6
;Editor's
Note: The radio control receiver interprets a centre stick value as 1.5
msecs, left stick 1.0 msecs ;and right stick 2.0 msecs. In the lines
below, any value less than 1.3 mSecs will turn OFF something and ;anything above
1.7 msecs will turn ON something.
CONSTANT Trg_Off=1300/10 ; < 1300
CONSTANT Trg_On=1700/10 ; > 1700
CONSTANT NChan = 4 ; Number of channel
CONSTANT NPulse = 6 ; Number of valid pulses to trigger
; Editor: Demanding multiple pulses rejects spurious
glitches
;*******************************************************************
; Description flag bit
;*******************************************************************
;
7
#DEFINE TOver TMR0,7 ; Half Timer overflow flag
#DEFINE OldCmd Flag,0 ; Last command 0:Off 1:On
#DEFINE Direct Flag,1 ; Direct / table data
8
;*******************************************************************
; Start of Code
;*******************************************************************
;
ORG 0
goto SysInit
SysInit
ifdef __12C508A ; Assemble for 12C508/9
movlw 0x08 ; xxOO IOOO Data direction
TRIS GPIO ; I/O Port
movlw 0x80 ; No WU, P-up
OPTION ; Presc to WD
movlw 0x00 ; xx00 0000
movwf GPIO ; Clear output
else ; Assemble for 16F84A
bsf Page_1 ; Set page 1
movlw 0x01 ; xxOO OOOI Data direction
movwf TRISA ; I/O Port
movlw 0x08 ; OOOO IOOO Data direction
movwf TRISB ; I/O Port
movlw 0x87 ; No WU, No P-up
movwf OPTION_REG ; Presc to WDT
bcf Page_1 ; Clr page 1
movlw 0x00 ; xx00 0100
movwf PORTB ; Clear output
endif
clrf Flag
clrf TMR0
clrf FMode ; Flash mode
DataInit
…
|