| 【侃单片机】主题文章: 回复文章: PIC16C74单片机SPI方式读写串行EEPROM程序 |
; list p=16C74, st=off ;PIC单片机 www.pic16.com ; 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 ※ 来源: 21IC社区 PIC单片机 www.pic16.com |