www.pudn.com > PIC16F877A_I2C.rar > 877i2ca.asm


;**************************************************** 
;* 877I2CA.asm                                      * 
;* Very simple I2C sample program without Display   * 
;**************************************************** 
;*                                                  * 
;* Written by:  Calvin Ho                           * 
;*              Senior Applications Engr.           * 
;*              Microchip Technology Inc.           * 
;* Date:        12 April 2000                       * 
;* Revision:	1.00                                * 
;**************************************************** 
 
 
;********************************************************************************************* 
; This source code provides a demonstration of the MSSP peripheral 
; on the PIC16F877 MCU.   
; The additional external subroutine are used for LCD Module 
; PIC16F877 執行頻率 : 4 Mhz 
; 
;	The subroutines for I2C 
;	:I2C_BYTE_READ		; Read a Byte from Address I2C_Addr and put into I2C_Data 
;	:I2C_BYTE_WRITE		; Write to I2C_Addr with data @ I2C_Data 
;	:I2C_ACK_CHECK		; Wait until I2C device can accept further command 
;	:InitI2C		; Initial I2C Module 
;	:StartI2C		; Set START Condition !! 
;	:StopI2C		; Set STOP Condition 
;	:RstartI2C		; Set Restart Condition 
;	:RecI2C			; Enable I2C Receive 
;	:ACKI2C			; Initial ACK response 
;	:NACKI2C 		; Initial NACK response 
;	:WaitI2C		; Wait until SSPIF Set  
;*********************************************************************************************  
 
	list p=16f877 
	#include  
 
 		CBLOCK	0x20 
 
		I2C_Data	  
		I2C_Addr	  
		 
		ENDC 
 
w_temp		EQU	0x72 
status_temp	EQU	0x73 
pclath_temp	EQU	0x74  
 
   
;******************************************** 
; Locates startup code @ the reset vector 
;******************************************** 
Reset_Addr 
	org	0x00 
	nop 
	goto	Prog_Main 
	nop 
	nop 
  
	;*************************************************************************** 
	;****	The Start Address of ISR is 0x004 
	;****	"PUSH" & "POP" 的使用範例 : 適用於像 PIC16F877 有SHARE BANK 的 PIC 
	;*************************************************************************** 
 
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 
	  
 
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	 
	 	 
  
;---------------------------------------------------------------------- 
 
Prog_Main    
 
	BANKSEL	TRISB			; Select Bank 1 
	movlw	b'11000000'		; setup PORTB 
	movwf	TRISB	 
  
	BSF     OPTION_REG,NOT_RBPU  	; Disable PORTB pull-ups 
	BCF     STATUS, RP0     	; Select Bank 0 
 
        call    InitI2C 
  	 
Main: 
	 
	BANKSEL	I2C_Addr 
	movlw	0x18 
	movwf	I2C_Addr	; 設定要寫入的資料的位址 
 
	BANKSEL	I2C_Data	; Bank Switching, in case its bank is differ than I2C_Addr !! 
	movlw	0x99 
	movwf	I2C_Data	; 設定欲寫入的資料 
	call	I2C_BYTE_WRITE	; Write to I2C Device when Address & Data are set OK 
 
	call	I2C_ACK_CHECK	; Check the ACK response, Wait until the Device Acknowledge  
				; Issue !! The subroutine will not return until the device send ACK !! 
				; 中文 : 檢查 WRITE 的動作是否已完成 !! 
				;	 若 EEPROM 完成寫入會開始回應 ACK  
	BANKSEL	I2C_Addr 
	movlw	0x18 
	movwf	I2C_Addr	; 設定欲讀取的位址 
	call	I2C_BYTE_READ 
 
	nop			; 將中斷點設定於此 , 應該看到 W 暫存器的值 
	nop			; 等於剛才寫入的資料 
	goto	$ 
 
 
;**************************************************************************** 
I2C_BYTE_READ:			; Read a Byte @ I2C_Addr to Buffer I2C_Data 
;**************************************************************************** 
 
 	call	StartI2C	; Set SSPCON2.SEN 
	call	WaitI2C		; Wait PIR1,SSPIF 
	 
	BANKSEL	SSPBUF 
	movlw	B'10100000'	; Write Command 
	movwf	SSPBUF 
	call	WaitI2C 
 
	BANKSEL	I2C_Addr	; The "BANKSEL" may not necessary if I2C_Addr is @ the same bank with SSPBUF 
	movf	I2C_Addr,W	; The Address you wish to "READ" from 
 
	BANKSEL	SSPBUF 
 	movwf	SSPBUF 
	call	WaitI2C 
	 
 	call	RstartI2C	; Restart Condition !! 
	call	WaitI2C		; Wait Until Restart OK !! 
 
	BANKSEL	SSPBUF 
	movlw	B'10100001'	; Write Read Command 
	movwf	SSPBUF 
	call	WaitI2C 
 
	call	RecI2C		; Enable I2C Receive  
	call	WaitI2C		; Wait Until Buffer Received 
	BANKSEL	SSPBUF 
	movf	SSPBUF,W	; Save to I2C_Data First !!	 
	BANKSEL	I2C_Data 
	movwf	I2C_Data 
 
	call	NACKI2C		; Initial NACK Response !! 
	call	WaitI2C		; Wait until NACK sent out 
	call	StopI2C		; Initial STOP Condition  
	call	WaitI2C		; Wait Until STOP Condition Terminated  
	return 
 
;**************************************************************************** 
I2C_ACK_CHECK:			; Read a Byte @ I2C_Addr to Buffer I2C_Data 
;**************************************************************************** 
 
 	call	StartI2C	; Set SSPCON2.SEN 
	call	WaitI2C		; Wait PIR1,SSPIF 
	 
	BANKSEL	SSPBUF 
	movlw	B'10100001'	; Read Command 
	movwf	SSPBUF 
	call	WaitI2C 
	 
	BANKSEL	SSPCON2 
	btfss	SSPCON2,ACKSTAT	; Check ACKSTAT bit , 0 = ACK , 1 = NACK 
	goto	ACK_Return 
	call	StopI2C 
	call	WaitI2C 
	goto	I2C_ACK_CHECK 
	 
ACK_Return: 
	call	StopI2C		; Initial STOP Condition  
	call	WaitI2C		; Wait Until STOP Condition Terminated  
	return 
 
;**************************************************************************** 
I2C_BYTE_WRITE:			; Write a Byte to I2C_Addr with I2C_Data 
;**************************************************************************** 
 
 	call	StartI2C	; Set SSPCON2.SEN 
	call	WaitI2C		; Wait PIR1,SSPIF 
	 
	BANKSEL	SSPBUF 
	movlw	B'10100000'	; Write Command 
	movwf	SSPBUF 
	call	WaitI2C 
 
	BANKSEL	I2C_Addr	; The "BANKSEL" may not necessary if I2C_Addr is @ the same bank with SSPBUF 
	movf	I2C_Addr,W	; The Address you wish to "READ" from 
	BANKSEL	SSPBUF 
 	movwf	SSPBUF 
	call	WaitI2C 
 
	BANKSEL	I2C_Data 
	movf	I2C_Data,W	 
	BANKSEL	SSPBUF 
	movwf	SSPBUF 
	call	WaitI2C 
 
 	call	StopI2C		; Initial STOP Condition  
	call	WaitI2C		; Wait Until STOP Condition Terminated  
	return 
 
  
;********************************************************************** 
; The following subroutines perform commonly used I2C functions. 
;********************************************************************** 
 
InitI2C:			; The subroutine of I2C Initialization  
	BANKSEL	TRISC 
 	movlw	B'00011000'	; Initial PortC,bit 3 & 4 as Input 
	movwf	TRISC		; RC3 = SCL  ,  RC4 = SDA 
 
	BANKSEL	PORTC 
	movlw	0xff 
	movwf	PORTC 
 
        movlw   0x09            ; This gives 100KHz I2C clock @ 4MHz 
        banksel SSPADD 
        movwf   SSPADD 
        movlw   b'10000000'     ; Disable slew rate control. 
        banksel SSPSTAT 
        movwf   SSPSTAT 
        movlw   b'00000000'     ; 
        movwf   SSPCON2         ; Setup MSSP for continuous reception. 
        movlw   b'00101000'     ; Enable MSSP and setup for I2C master 
        banksel SSPCON          ; mode. 
        movwf   SSPCON 
	return 
 
 
StartI2C			; Initiate the I2C START condition. 
        banksel SSPCON2 
        bsf     SSPCON2,SEN 
        return 
         
StopI2C				; Initiate the I2C STOP condition. 
        banksel SSPCON2 
        bsf     SSPCON2,PEN 
        return 
         
RstartI2C			; Initiate the I2C restart condition. 
        banksel SSPCON2 
        bsf     SSPCON2,RSEN 
        return 
         
NACKI2C 
        banksel SSPCON2 
        bsf     SSPCON2,ACKDT    ; Set the ACK bit 
        bsf     SSPCON2,ACKEN    ; Initiate the NACK sequence. 
        return 
         
ACKI2C 
        banksel SSPCON2 
        bcf     SSPCON2,ACKDT    ; Clear the ACK bit 
        bsf     SSPCON2,ACKEN    ; Initiate the NACK sequence. 
        return 
 
RecI2C 
        banksel SSPCON2         ; 
        bsf     SSPCON2,RCEN    ; Set the receive enable bit. 
        return 
 
 
WaitI2C				; Poll for SSPIF 
        banksel PIR1 
FLoop   btfss   PIR1,SSPIF 
        goto    FLoop 
        bcf     PIR1,SSPIF 
        return 
 
  
;---------------------------------------------------------------------- 
  
	end		; *********** End Of Program !!!!!