list p=16C74, st=off
;PIC单片机
; PORTC PIN DESCRIPTION
; SCK bit 3, SDI bit 4, SDO bit 5, CS bit 7
; Fosc = 10.0 MHz, thus each instr. cycle = 400ns
;***************Ram Register Definitions*******************************
rxdata equ 25h
addr equ 26h
loops equ 27h
;***************Bit Definitions****************************************
;#define CS PORTC,7 ; SPI chip select bit definition
;**********************************************************************
;***************25Cxxx command definitions
;#define WREN 6 ;write enable latch
;#define WRDI 4 ;reset the write enable latch
;#define RDSR 5 ;read status register
;#define WRSR 1 ;write status register
;#define READ 3 ;read data from memory
;#define WRITE 2 ;write data to memory
; Bit defines within status register
;#define WIP 0 ;write in progress
;#define WEL 1 ;write enable latch
;#define BP0 2 ;block protection bit
;#define BP1 3 ;block protection bit
;**********************************************************************
; include "p16c74.inc" ; 16C74 include file
; __CONFIG _WDT_OFF & _CP_OFF & _HS_OSC & _PWRTE_ON
;**********************************************************************
page
org 0000 ; Reset Vector
clrf PCLATH ; ensure PCLATH bit 3 is cleared
clrf INTCON ; ensure all interrupts are disabled
goto start ; jump to the beginning of the program
org 004 ; interrupt vector, do nothing
isr: goto isr ; do nothing, location just
; identified in code
;***************BEGIN MAIN PROGRAM*************************************
;
start: bcf STATUS,5 ; need to set bank 0
clrf PORTC ; initialize port c
bsf CS ; make sure cs is set
bsf STATUS,5 ; need to set bank 1
movlw 0x10 ; all bits are outputs except SDI
movwf TRISC ; for SPI setup
bcf STATUS,RP0 ; need to set bank 0
movlw 0x31 ; SPI master, clk/16, ckp=1
movwf SSPCON ; SSPEN enabled
movlw 0x10 ; *** put beginning address in addr**
movwf addr ; for later use
loop
;The first thing we will do is the WREN
call wren ; call the write enable routine
;Next write status reg. to clear the block protect bits
call wrsr ; call the write status routine
;Next do a busy test
call busy_test ; test WIP bit in status register
;Then do the WREN before writing to the array
call wren ; call the write enable command
;Next write 0xA5 (or any other value) to 0x10
bcf CS ; set chip select line low
movlw WRITE ; WRITE control byte
call output ; call the output subroutine
movlw b'00000000' ; high addr byte is all 0's
call output ; call the output subroutine
movf addr,w ; low addr byte
call output ; call the output subroutine
movlw b'10100101' ; load 0xA5 as data to be sent out
call output ; call the output subroutine
bcf SSPCON,CKP ; set clock idle low, mode 0,1
bsf CS ; set chip select, begin write cycle
bsf SSPCON,CKP ; set clock idle high, mode 1,1
call busy_test
call rdsr ; call the read status subroutine
;Now, read location 0x10h and store in rxdata. With Picmaster a
;user can break, read that memory location to see if the read worked
bcf CS ; set chip select line low
movlw READ ; READ control byte
call output ; call the output subroutine
movlw b'00000000' ; high addr byte is all 0's
call output ; call the output subroutine
movf addr,w ; get ready to send next byte
call output ; call the output subroutine
movlw b'01011010' ; move don't care byte of 0x5A into
call output ; call the output subroutine
bsf CS ; bring chip select high end
; terminate read command
;While program is continuously looping, the user may halt (if using an
;emulator), and look at the data in rxdata. If it is 0xA5, the
;read/write worked.
call wait ; little delay between SPI sequence
goto loop ; do it all over again
; loop can be used to evaluate SPI
; signals on oscilloscope
;********************* BEGIN SUBROUTINES*******************************
;*** DELAY ROUTINE - 400uS ***
;
wait movlw .200 ; timing adjustment variable
movwf loops ; move variable into loops
top nop ; sit and wait
nop ; no operation
decfsz loops,f ; loop complete?
goto top ; no, go again
return ; yes, return from sub
;****** This is the OUTPUT transmit/receive subroutine. ***************
output movwf SSPBUF ; place data in buffer to send
loop1 bsf STATUS,RP0 ; specify bank 1
btfss SSPSTAT,BF ; has data been received (xmit done)?
goto loop1 ; not done yet, keep trying
bcf STATUS,RP0 ; specify bank 0
movf SSPBUF,W ; empty receive buffer
movwf rxdata ; put received byte into rxdata
return ; return from subroutine
;*******Write Enable Subroutine****************************************
wren bcf CS ; set chip select line low
movlw WREN ; WREN control byte
call output ; Call the output subroutine
bcf SSPCON,CKP ; set clock idle low, mode 0,1
bsf CS ; set chip select, begin write
bsf SSPCON,CKP ; set clock idle high, mode 1,1
return ; return from subroutine
;*******Read Status Register Subroutine********************************
rdsr movlw RDSR ; RDSR control byte
call output ; Call the output subroutine
movlw b'00000101' ; this byte is a don't care byte
call output ; status reg data will be in rxdata
bsf CS ; set chip select
return ; return from subroutine
;*******Write Status Register Subroutine*******************************
wrsr bcf CS ; set chip select line low
movlw WRSR ; WRSR control byte
call output ; Call the output subroutine
movlw b'00001000' ; set BP1 bit in status register
call output ; this will clear block protect bits
bcf SSPCON,CKP ; set clock idle low, mode 0,1
bsf CS ; set chip select
bsf SSPCON,CKP ; set clock idle high, mode 1,1
return ; return from subroutine
;*******Busy Test - WIP bit in Status Register*************************
busy_test
bcf CS ; set chip select line low
movlw RDSR ; RDSR control byte
call output ; Call the output subroutine
movlw b'00000000' ; send dummy byte
call output ; to initiate clock sequence for read
bsf CS ; else, set chip select high
btfsc rxdata,WIP ; test WIP bit read from status register
goto busy_test ; repeat busy test
return ; return from subroutine
end