金沙js5线路(中国)有限公司

技术热线: 4007-888-234

PIC16F877单片机硬件IIC编程实例

更新时间: 2019-03-22
阅读量:2981

单片机方案开发商深圳金沙js5线路分享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 !!!!!

XML 地图