讀寫24LCxx系列的EEPROM的實(shí)例程序
	;******************************************************** 
	;*                     *
	;*    ? PIC16F877A($4.6800) ?I2C Master 家&Alpha($5.2300);???﹃?&Alpha($5.2300); EEPROM ?絛ㄒ祘&Alpha($5.2300);  *
	;*                                                   *
	;* Written by:  Richard Yang                                *
	;*              Sr. Corporate Application Engineer($26.0000)            *
	;*              Microchip Technology Inc.                *
	;* Date:        Oct. 2nd '2002                            *
	;* Revision: 1.00                                     *
	;********************************************************
	;*************************************************
	; This source code provides a demonstration of the MSSP peripheral
	; on the PIC16F87x MCU. 
	;
	;
	;***********      The subroutines for EEPROM      *****************
	;
	; EE_Random_Read  ; EEPROM Random address Read from EEPROM
	; EE_SEQU_Read  ; EEPROM Sequential Read form EEPROM
	; EE_Ack_Check  ; Polling current status of EEPROM
	; EE_Page_Write  ; Page Write function for EEPROM
	; EE_Byte_Write  ; Write a byte to EEPROM with address setting
	;
	;***********      The subroutines for I2C      *****************
	;
	; Init_I2C_Master  ; Initial I2C Module for Master Mode , 7-bit address
	; START($0.5760)I2C  ; Send a START($0.5760) Condition !!
	; StopI2C   ; Send s STOP Condition
	; RSTART($0.5760)I2C  ; Send a Repeat START($0.5760) conditional to I2C
	; Non_Ack   ; Send a Non-acknowledge signal to I2C
	; An_Ack   ; Send a acknowledge signal to I2C
	; Sebd_Byte  ; Send a byte to I2C bus
	; RecI2C    ; Enable Read a byte form slave device
	; I2C_Done  : Wait the I2C completed the currect process
	;
	;***************************************************
	  list p=16f877a
	  #i nclude <p16f877a.inc>
	;
	;***************************************
	;       ﹚竡跑計(jì)?RAM???
	;
	   CBLOCK 0x20
	  I2C_Ctrl 
	  I2C_Addr
	  I2C_Data
	  I2C_Page_Length
	  D_Count
	  ENDC
	  cblock 0x40
	  I2C_Page_Buffer:8
	  I2C_SEQU_Buffer:8
	  endc
	;
	;***************************************
	;       ﹚竡い耞?既?竟??
	w_temp  EQU 0x72
	status_temp EQU 0x73
	pclath_temp EQU 0x74
	;
	;***************************************
	;       ﹚竡 I2C ???の竲?
	;
	EEPROM_CMD equ 0xA0  ; Device adress of Slave Point
	EE_Read  equ .1
	EE_Write equ .0
	;
	#define  SCL PORTC,3  ; I2C SCL pin
	#define  SDA PORTC,4  ; I2C SDA pin
;
	;********************************************
	; Locates START($0.5760)up code @ the reset vector
	;********************************************
	Reset_Addr
	   org  0x00
	   nop
	   goto Main_Init
	;
	   org  0x04
	   goto ISR
	;
	;*************************************************************
	;**** The START($0.5760) Address of ISR is 0x004
	;**** "PUSH" & "POP" ?ㄏノ絛ㄒ : 続ノ?鉤 PIC16F877($4.6800) ΤSHARE BANK ?PIC
	;**************************************************************
	ISR 
	Push  movwf   w_temp             ; save off current W register contents
	   movf STATUS,w           ; move status register into W register
	   movwf status_temp        ; save off contents of STATUS register
	   movf PCLATH,W
	   movwf pclath_temp
	; 
	;        Put your interrupt code here
	;
	Pop   movf pclath_temp,W
	   movwf PCLATH
	   movf    status_temp,w    ; retrieve copy of STATUS register
	   movwf STATUS            ; restore pre-isr STATUS register contents
	   swapf   w_temp,f
	   swapf   w_temp,w          ; restore pre-isr W register contents
	;
	   retfie                    ; return from interrupt
	  
	 
	;----------------------------------------------------------------------
	Main_Init  
	   pagesel Init_I2C_Master  ; Set PAGE to PCLATH Register
	      call    Init_I2C_Master  ; Init the MSSP for I2C Master
	;
	      banksel I2C_Ctrl
	   movlw EEPROM_CMD   ; Load EEPROM command address @ 0xA0
	   movwf I2C_Ctrl
	;
	;
	Main
	;
	;----------------------------------------------------------------------
	;
	;* ???代剛祘&Alpha($5.2300);穦?盢?艙計(jì)?(0x40-0x47)糶??RMA0x40-0x47??竚     
	;* ?ノPage Write?よ&Alpha($5.2300);盢8??じ艙?戈?糶? EEPROM ?                 
	;* 秈︽?篈?盎代EEPROM琌??ЧΘ糶??笆??程?盢?糶                  
	;* ??戈??Sequential Read?よ&Alpha($5.2300);眖EEPROM弄?ㄓ??I2C_SEQU_Bufferい    
	;
	Test_Page_RW
	   movlw 0x08
	   movwf I2C_Page_Length
	   movlw I2C_Page_Buffer
	_Fill_RAM movwf FSR
	   movwf INDF
	   incf FSR,W
	   decfsz I2C_Page_Length,F
	   goto _Fill_RAM
	;   
	Test_Page_Write
	;   banksel I2C_Ctrl
	   movlw EEPROM_CMD   ; Load EEPROM command address @ 0xA0
	   movwf I2C_Ctrl
	   movlw 0x10     ; Select EEPROM location at 0x00
	   movwf I2C_Addr
	   movlw .8
	   movwf I2C_Page_Length
	   call EE_Page_Write
	;
	   call EE_Ack_Check
	;
	   banksel I2C_Ctrl
	   movlw EEPROM_CMD   ; Load EEPROM command address @ 0xA0
	   movwf I2C_Ctrl
	   movlw 0x10
	   movwf I2C_Addr
	   movlw .8
	   movwf I2C_Page_Length
	   call EE_SEQU_Read
	;
	   goto $
	;
	;---------------------------------------------------------
	;
	;* ???代剛祘&Alpha($5.2300);穦?糶????じ艙?戈?糶? EEPROM い               
	;* ?秈︽?篈?盎代琌??ЧΘ糶??笆??程?盢?糶                           
	;* ??戈??眖EEPROM弄?ㄓ??I2C_Data既?竟い                      
	;       
	Test_1byte_RW
	   banksel I2C_Ctrl
	   movlw EEPROM_CMD   ; Load EEPROM command address @ 0xA0
	   movwf I2C_Ctrl
	   movlw 0x00    ; Select EEPROM location at 0x00
	   movwf I2C_Addr
	   movlw 0xAA    ; Write data 0x5A to location 0x00 of EEPROM
	   movwf I2C_Data
	   call EE_Byte_Write
	;
	Test2($0.3696)  call EE_Ack_Check  ; Polling Acknowledge for next access($49.9920)
	;
	   banksel I2C_Data
	   movlw 0x00    ; Clear I2C data buffer
	   movwf I2C_Data
	;
	Test3
	   banksel I2C_Ctrl
	   movlw EEPROM_CMD   ; Load EEPROM command address @ 0xA0
	   movwf I2C_Ctrl
	   movlw 0x00
	   movwf I2C_Addr
	   call EE_Random_Read
	   ;
	   goto  $
	;
	;
	;******************************************************
	;*           Random Read a Byte from EEPROM         
	;*
	;* Input:
	;*     - I2C_Ctrl : Control Byte of EEPROM   
	;*      - I2C_Addr : Location of EEPROM  
	;* Output:
	;*      - I2C_Data : Read Data from EEPROM   
	;******************************************************
	;
	; Send Command for RANDOM READ :
	; " START($0.5760)+ 0xA0 + EE_Address + ReSTART($0.5760) + 0xA1 + Read_Data + NAck + Stop "
	;
	EE_Random_Read
	    call START($0.5760)I2C  ; Set SSPCON2.SEN
	;
	   bcf  I2C_Ctrl,0  ; set for write Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	;
	   movf I2C_Addr,W  ; Send out the Rendom address of EEPROM 
	   call Send_Byte
	;
	   call RSTART($0.5760)I2C  ; Send a Repeat START($0.5760) to I2C
	;
	   bsf  I2C_Ctrl,0  ; set for Read Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	;
	   call RecI2C  ; Enable I2C Receive
	;
	   BANKSEL SSPBUF
	   movf SSPBUF,W ; Save to I2C_Data First !!
	   movwf I2C_Data
call Non_Ack ; Initial NACK Response !!
	   call StopI2C  ; Initial STOP Condition
	   return
	;
	;***************************************************************
	;*                Sequential Read from EEPROM         
	;*
	;* Input:
	;*     - I2C_Ctrl : Control Byte of EEPROM   
	;*      - I2C_Addr : START($0.5760) Location of EEPROM
	;*     - I2C_Page_Length : How many byte need to read  
	;* Output:
	;*      - I2C_SEQU_Buffer : Sequential Read Data buffer
	;*  
	;***************************************************************
	;
	; Send Command for RANDOM READ :
	; " START($0.5760)+ 0xA0 + EE_Address + ReSTART($0.5760) + 0xA1 + Read_Data + NAck + Stop "
	;
	EE_SEQU_Read
	    call START($0.5760)I2C  ; Set SSPCON2.SEN
	;
	   bcf  I2C_Ctrl,0  ; set for write Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	;
	   movf I2C_Addr,W  ; Send out the Rendom address of EEPROM 
	   call Send_Byte
	;
	   call RSTART($0.5760)I2C  ; Send a Repeat START($0.5760) to I2C
	;
	   bsf  I2C_Ctrl,0  ; set for Read Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	;
	   movlw I2C_SEQU_Buffer
	   movwf FSR
	;
	_Sequ_Loop call RecI2C   ; Enable I2C Receive
	   BANKSEL SSPBUF
	   movf SSPBUF,W  ; Save to I2C_Data First !!
	   movwf INDF
	   incf FSR,F
	   decfsz I2C_Page_Length,F
	   goto _Cont_Read
	   goto _End_Read
	_Cont_Read call An_Ack
	   goto _Sequ_Loop
	;
	_End_Read call Non_Ack   ; Initial NACK Response !!
	   call StopI2C   ; Initial STOP Condition
	   return
	;
	;******************************************************
	;*              EEPROM Acknowledge Polling
	;*           
	;*     --  The routine will polling the ACK  
	;*           response from EEPROM       
	;*    --  ACK=0 return        
	;*   --  ACK=1 send ReSTART($0.5760) & loop check
	;* 
	;******************************************************
	;
	EE_Ack_Check
	    call START($0.5760)I2C  ; Set SSPCON2.SEN
	   
	   bcf  I2C_Ctrl,0  ; Clear for Write Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	_Ack_Polling
	   BANKSEL SSPCON2
	   btfss SSPCON2,ACKSTAT ; Check ACKSTAT bit , 0 = ACK , 1 = NACK
	   goto ACK_Return  ; Ack = 0 ; EEPROM is Ready
	_Ack_Hi        ; Ack = 1 ; EEPROM is Busy for Write
	   call Delay_mS  ; Delay 500uS for next Ack polling
	   call RSTART($0.5760)I2C  ; Send a Repeat START($0.5760) to I2C
	   bcf  I2C_Ctrl,0  ; Clear for Write Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	   goto _Ack_Polling
	 
	ACK_Return
	   call StopI2C   ; Initial STOP Condition
	   return
	;
	;**********************************************************
	;*           Page Write 1 to 8 Bytes to EEPROM        
	;*
	;*  Input:
	;*     - I2C_Ctrl : Control Byte of EEPROM  
	;*     - I2C_Addr : Location of EEPROM  
	;*   - I2C_Page_Buffer: RAM location of Data
	;*     - I2C_Page_Length : Data length count
	;*  
	;**********************************************************
	;
	; Send Command for PAGE WRITE :
	; " START($0.5760)+ 0xA0 + EE_Address + W_Data 0+ .. + W_Data N + Stop "
	;
	EE_Page_Write
	   movf I2C_Page_Length,W
	   btfsc STATUS,Z
	   return
	;  
	    call START($0.5760)I2C  ; Set SSPCON2.SEN
	;
	   bcf  I2C_Ctrl,0  ; Clear for Write Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	;
	   movf I2C_Addr,W  ; Send out the Command 
	   call Send_Byte
	;
	   movlw I2C_Page_Buffer
	   movwf FSR
	_W1   movf INDF,W
	   call Send_Byte
	   incf FSR,F
	   decfsz I2C_Page_Length,F
	   goto _W1
	;
	    call StopI2C   ; Initial STOP Condition
	   return
	;
	;
	;*******************************************************
	;*               Write a Byte to EEPROM               
	;*
	;* Input:
	;*     - I2C_Ctrl : Control Byte of EEPROM   
	;*      - I2C_Addr : Location of EEPROM  
	;*      - I2C_Data : Data to EEPROM
	;*  
	;*******************************************************
	;
	; Send Command for BYTE WRITE :
	; " START($0.5760)+ 0xA0 + EE_Address + Write_Data + Stop "
	;
	EE_Byte_Write
	    call START($0.5760)I2C  ; Set SSPCON2.SEN
	;
	   bcf  I2C_Ctrl,0  ; Clear for Write Command
	   movf I2C_Ctrl,W  ; Send Slave Address to I2C Bus
	   call Send_Byte
	;
	   movf I2C_Addr,W  ; Send out the Command 
	   call Send_Byte
	;
	   movf I2C_Data,W  ; Send out the Data
	   call Send_Byte
	;
	    call StopI2C   ; Initial STOP Condition
	   return
	;
	;**********************************************************************
	;
	;   As following subroutines perform commonly used I2C functions.
	;      You can use these subroutines for your I2C access($49.9920)
	;
	;**********************************************************************
	;
	;*** Initial I2Cmodule fot 7-bit I2C Master Mode with 100Kcps @4MHz
	;
	Init_I2C_Master    
	   BANKSEL TRISC   ; Initial PortC,bit 3 & 4 as Input
	    bsf  SCL    ; RC3 = SCL  ,  RC4 = SDA
	   bsf  SDA  
	;
	    BANKSEL PORTC
	    bsf  SCL    ; SCL = Hi
	    bsf  SDA    ; SDA = Hi
	;
	   movlw b'00101000'  ; I2C Master Mode, Clock Rate: FOSC/(4*SSPADD+1)
	   movwf SSPCON   ;
	;
	         banksel SSPADD
	         movlw   .9              ; This gives 100KHz I2C clock @ 4MHz
	   movwf   SSPADD   ; (4MHz/4) / (9+1)= 100KHz
	;
	       movlw   b'10000000'     ; Disable slew rate control,
	         movwf   SSPSTAT   ; and clear status bits
	;
	          movlw   b'00000000'     ; Set SCL,SDA into Ready status
	         movwf   SSPCON2         
	;    
	   return
	;
	;******   Send START($0.5760) condition to bus   *******
	;
	START($0.5760)I2C    ; Initiate the I2C START($0.5760) condition.
	         banksel SSPCON2
	          bsf     SSPCON2,SEN
	         goto I2C_Done
	;
	;******   Send STOP condition to bus   *******
	;
	StopI2C    
	        banksel SSPCON2
	         bsf     SSPCON2,PEN
	         goto I2C_Done
	;
	;******   Send RESTART($0.5760) condition to bus   *******
	;     
	RSTART($0.5760)I2C   
	         banksel SSPCON2
	         bsf     SSPCON2,RSEN
	         goto I2C_Done
	;
	;******   Send a Non-Acknowledge status to bus (ACK=1)    *******
	;       
	Non_Ack
	         banksel SSPCON2
	         bsf     SSPCON2,ACKDT    ; Set the ACK bit
	         bsf     SSPCON2,ACKEN    ; Initiate the NACK sequence.
	         goto I2C_Done
	;
	;******   Send an Acknowledge status to bus (ACK=0)     *******
	;        
	An_Ack
	          banksel SSPCON2
	         bcf     SSPCON2,ACKDT    ; Clear the ACK bit
	         bsf     SSPCON2,ACKEN    ; Initiate the NACK sequence.
	         goto I2C_Done
	;
	;******   Send data to I2C bus from Wreg.     *******
	;
	Send_Byte
	   banksel SSPBUF
	   movwf SSPBUF
	   goto I2C_Done
	;
	;******   Enable I2C Receive for Master Mode     *******
	;
	RecI2C
	        banksel SSPCON2         
	         bsf     SSPCON2,RCEN    ; Set the receive enable bit.
	   goto I2C_Done
	;
	;******  Check the I2C stage is completed   ********
	;
	I2C_Done
	         banksel PIR1
	    btfss   PIR1,SSPIF ; Poll for SSPIF
	         goto    $-1
	         bcf     PIR1,SSPIF
	         return
	;
	Delay_mS
	   banksel D_Count
	   movlw .124   ; Load .5mS Dealy Value
	    movwf D_Count   
	_D_mS  nop
	   decfsz D_Count,F  
	   goto _D_mS 
	   return         
	;
	; *********** End Of Program !!!!!
	;
	   end
