Jon Wilder
Active Member
For those who are new to the 16F887, this is an example ASM code template complete with initialization routine, interrupt handler placement, as well as a fixed 100mS and a variable delay routine. Use it and make changes as you see fit. As shown the config bits are set up for an 8MHz internal oscillator. For the sake of the example, I've placed the minimum needed instructions to set up ports A, B and E as digital output with ports C and D as digital input.
I have also included data EEPROM write, read and verify subroutines as well.
This init code has been fully tested and debugged. This particular code as shown, while non-functional until you add in your code, has also been test assembled and it assembled with no errors, messages or warnings.
I have also included data EEPROM write, read and verify subroutines as well.
This init code has been fully tested and debugged. This particular code as shown, while non-functional until you add in your code, has also been test assembled and it assembled with no errors, messages or warnings.
Code:
;*********************************************************************************************************
;** **
;** Basic Digital I/O Setup Template for 16F887 **
;** By: Jon Wilder **
;** Date: 8/9/2011 **
;** **
;*********************************************************************************************************
;*********************************************************************************************************
;** **
;** Header Information **
;** **
;*********************************************************************************************************
list p=16F887, r=dec, w=-302
include <P16F887.INC>
__config _CONFIG1,b'1110000011100100'
__config _CONFIG2,b'1111100011111111'
;config word 1_____ ___ __ _____
;| - | - |DEBUG|FCMEN|IESO | LVP |BOREN1|BOREN0| CPD | CP |MCLRE|PWRTE|WDTE |FOSC2|FOSC1|FOSC0|
;| 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
;config word 2
;| - | - | - | - | - |WRT0 | WRT1 |BOR4V | - | - | - | - | - | - | - | - |
;| 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
;Processor is PIC16F887 (p=16F887)
;Default Radix is Decimal (r=dec)
;Suppress all bank select assembler messages (w=-302)
;In Circuit Debug Mode Off (DEBUG)
;Fail Safe Clock Monitor Bit Off (FCMEN)
;Internal External Switchover Bit Off (IESO)
;Low Voltage Programming Off (LVP)
;Brown Out Reset Off (BOREN1-BOREN0)
;Data Code Protection Off (CPD)
;Program Code Protection Off (CP)
;RE3 is External Master Clear (MCLRE)
;Power Up Timer On (PWRTE)
;Watchdog Timer Off (WDTE)
;Internal Oscillator RA6-RA7 digital I/O
;*********************************************************************************************************
;** **
;** Variable Declarations **
;** **
;*********************************************************************************************************
;declare variables here
cblock 0x20
COUNT1 ;delay counter 1
COUNT2 ;delay counter 2
COUNT3 ;delay counter 3
<Delete this line, then and add more variable names if you need more>
endc
;software stack
cblock 0x70
W_TEMP ;software stack for interrupt handler
STATUS_TEMP ;software stack for interrupt handler
PCLATH_TEMP ;software stack for interrupt handler
DATA_EE_ADDR ;data EEPROM address buffer
DATA_EE_DATA ;data EEPROM data buffer
endc
;*********************************************************************************************************
;** **
;** Place Non-Relocatable Code **
;** **
;*********************************************************************************************************
org 0x000 ;reset vector address
goto START
org 0x004 ;interrupt vector address
;*********************************************************************************************************
;** **
;** Interrupt Handler **
;** **
;*********************************************************************************************************
ISR ;software stack
movwf W_TEMP ;back up W
swapf STATUS,W ;back up STATUS
movwf STATUS_TEMP
banksel 0x00 ;bank 0
movfw PCLATH ;back up PCLATH
movwf PCLATH_TEMP
; <Delete this line and place rest of Interrupt Handler code here>
ISRExit ;software stack
movfw PCLATH_TEMP ;restore PCLATH
movwf PCLATH
swapf STATUS,W ;restore STATUS
movwf STATUS
swapf W_TEMP,F ;restore W
swapf W_TEMP,W
retfie ;done with interrupt
;*********************************************************************************************************
;** **
;** Initialization Routine **
;** **
;*********************************************************************************************************
START clrf INTCON ;disable interrupts
banksel OSCCON ;bank 1
movlw b'01110000' ;8MHz Internal Oscillator
movwf OSCCON
btfss OSCCON,HTS ;is oscillator stable?
goto $-1 ;no, check again
banksel ANSEL ;yes, bank 3
movlw b'00000000' ;all ports digital I/O
movwf ANSEL
movwf ANSELH
banksel PORTA ;bank 0
clrf PORTA ;initialize all ports
clrf PORTB
clrf PORTC
clrf PORTD
clrf PORTE
banksel TRISA ;bank 1
movlw b'00000000' ;ports A, B and E outputs
movwf TRISA
movwf TRISB
movwf TRISE
movlw b'11111111' ;ports C and D inputs
movwf TRISC
movwf TRISD
banksel PORTA ;bank 0
;*********************************************************************************************************
;** **
;** Main Program **
;** **
;*********************************************************************************************************
MAIN <Delete this line and place the first line of your main program code here>
goto MAIN ;last line of code (can change where it jumps to)
;*********************************************************************************************************
;** **
;** Delay Routines **
;** **
;*********************************************************************************************************
;fixed 100mS delay
Delay_100mS movlw 0xFF ;init delay counter 1 and 2
movwf COUNT1
movwf COUNT2
decfsz COUNT1,F ;decrement counter 1 to 0
goto $-1 ;continue decrementing counter 1 if counter 1 > 0
decfsz COUNT2,F ;decrement counter 2
goto $-3 ;continue decrementing counter 1 if counter 2 > 0
return ;done
;variable delay - load a value into W prior to calling this delay for a variable delay in 100mS increments
;value of 0x05 yields a 500mS delay
Delay movwf COUNT3 ;init delay counter 2
call Delay_100mS ;run 100mS delay
decfsz COUNT3,F ;decrement counter 2
goto $-2 ;jump back to run 100mS delay if counter 2 > 0
return ;done
;*********************************************************************************************************
;** **
;** Other Subroutines **
;** **
;*********************************************************************************************************
;write address and data to write should already be loaded into EEADR and EEDATA buffers
;prior to calling write
EEWrite bcf INTCON,GIE ;disable interrupts
banksel EEADR ;bank 3
movfw DATA_EE_ADDR ;move contents of EEADR buffer to W
movwf EEADR ;load address into EEADR
movfw DATA_EE_DATA ;move contents of EEDATA buffer to W
movwf EEDAT ;load data into EEDATA
banksel EECON1 ;bank 4
bcf EECON1,EEPGD ;select data EEPROM for write
bsf EECON1,WREN ;write mode enable
movlw 0x55 ;unlock codes
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1,WR ;initiate write
btfsc EECON1,WR ;is write complete?
goto $-1 ;no, check again
bcf EECON1,WREN ;yes, disable write mode
banksel PIR2 ;bank 0
bcf PIR2,EEIF ;clear EEPROM write interrupt flag
bsf INTCON,GIE ;enable unmasked interrupts
return ;done
;read address should already be loaded into EEADR buffer prior to calling read
EERead bcf INTCON,GIE ;disable interrupts
banksel EEADR ;bank 3
movfw DATA_EE_ADDR ;move read address to W
movwf EEADR ;move read address to EEADR
banksel EECON1 ;bank 4
bcf EECON1,EEPGD ;select data EEPROM
bsf EECON1,RD ;initiate read
banksel EEDAT ;bank 3
movfw EEDAT ;move EEPROM data into W
movwf DATA_EE_DATA ;move data to EEPROM data buffer
banksel 0x00 ;bank 0
bsf INTCON,GIE ;enable all unmasked interrupts
return ;done
;verify address should already be loaded into EEADR prior to calling verify
EEVerify bcf INTCON,GIE ;disable interrupts
banksel EEADR ;bank 3
movfw DATA_EE_ADDR ;move verify address to W
movwf EEADR ;move verify address to EEADR
banksel EECON1 ;bank 4
bcf EECON1,EEPGD ;select data EEPROM
bsf EECON1,RD ;initiate read
banksel EEDATA ;bank 3
movfw EEDATA ;move EEPROM data into W
xorwf EEDATA,W ;compare to data in EEDATA
btfss STATUS,Z ;is data in W equal to data in EEDATA?
goto EEErr ;no, set EEPROM error
banksel 0x00 ;bank 0
bsf INTCON,GIE ;enable unmasked interrupts
return ;done
EEErr <Delete this line and place EEPROM Verify error code here (write it yourself)>
<Delete this line and place all subroutine codes here>
end ;end of file
Last edited: