單片機方案開發商深圳英銳恩分享PIC16F877單片機硬件IIC編程實例。
;****************************************************
;* 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 !!
BANKSEL I2C_Addr
movlw 0x18
movwf I2C_Addr ;
call I2C_BYTE_READ
nop ;
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 !!!!!