新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > PIC單片機的I2C應用程序1

        PIC單片機的I2C應用程序1

        作者: 時間:2011-02-24 來源:網絡 收藏
        ; File: an734.asm
        ; data: feb.23.2001

        ; Functionality:
        ;
        ; This code implements the basic functions for an I2C slave device
        ; using the SSP module. All I2C functions are handled in an ISR.
        ; Bytes written to the slave are stored in a buffer. After a number
        ; of bytes have been written, the master device can then read the
        ; bytes back from the buffer.
        ;
        ; Variables and Constants used in the program:
        ;
        ; The start address for the receive buffer is stored in the variable
        ; 'RXBuffer'. The length of the buffer is denoted by the constant
        ; value 'RX_BUF_LEN'. The current buffer index is stored in the
        ; variable 'Index'.
        ;
        ;--------------------------------------------------------------------
        ;
        ; The following files should be included in the MPLAB project:
        ;
        ; an734.asm-- Main source code file
        ;
        ; 16f872.lkr-- Linker script file
        ; (change this file for the device
        ; you are using)
        ;---------------------------------------------------------------------
        #include p16f872.inc> ; Change to device that you are using.
        ;---------------------------------------------------------------------
        ;Constant Definitions
        ;---------------------------------------------------------------------
        #define NODE_ADDR 0x02 ; I2C address of this node
        ; Change this value to address that
        ; you wish to use.
        ;---------------------------------------------------------------------
        ; Buffer Length Definition
        ;---------------------------------------------------------------------

        #define RX_BUF_LEN 32 ; Length of receive buffer

        ;---------------------------------------------------------------------
        ; Variable declarations
        ;---------------------------------------------------------------------
        udata

        WREGsave res 1
        STATUSsave res 1
        FSRsave res 1
        PCLATHsave res 1

        Index res 1 ; Index to receive buffer
        Temp res 1 ;
        RXBuffer res RX_BUF_LEN ; Holds rec'd bytes from master
        ; device.

        ;---------------------------------------------------------------------
        ; Vectors
        ;---------------------------------------------------------------------

        STARTUP code
        nop
        goto Startup ;
        nop ; 0x0002
        nop ; 0x0003
        goto ISR ; 0x0004

        PROG code

        ;---------------------------------------------------------------------
        ; Macros
        ;---------------------------------------------------------------------

        memset macro Buf_addr,Value,Length

        movlw Length ; This macro loads a range of data memory
        movwf Temp ; with a specified value. The starting
        movlw Buf_addr ; address and number of bytes are also
        movwf FSR ; specified.
        SetNext movlw Value
        movwf INDF
        incf FSR,F
        decfsz Temp,F
        goto SetNext
        endm


        LFSR macro Address,Offset ; This macro loads the correct value
        movlw Address ; into the FSR given an initial data
        movwf FSR ; memory address and offset value.
        movf Offset,W
        addwf FSR,F
        endm

        ;---------------------------------------------------------------------
        ; Main Code
        ;---------------------------------------------------------------------

        Startup
        bcf STATUS,RP1
        bsf STATUS,RP0
        call Setup

        Main clrwdt ; Clear the WDT
        goto Main ; Loop forever.


        ;---------------------------------------------------------------------
        ; Interrupt Code
        ;---------------------------------------------------------------------

        ISR
        movwf WREGsave ; Save WREG
        movf STATUS,W ; Get STATUS register
        banksel STATUSsave ; Switch banks, if needed.
        movwf STATUSsave ; Save the STATUS register
        movf PCLATH,W ;
        movwf PCLATHsave ; Save PCLATH
        movf FSR,W ;
        movwf FSRsave ; Save FSR

        banksel PIR1
        btfss PIR1,SSPIF ; Is this a SSP interrupt?
        goto $ ; No, just trap here.
        bcf PIR1,SSPIF
        call SSP_Handler ; Yes, service SSP interrupt.

        banksel FSRsave
        movf FSRsave,W ;
        movwf FSR ; Restore FSR
        movf PCLATHsave,W ;
        movwf PCLATH ; Restore PCLATH
        movf STATUSsave,W ;
        movwf STATUS ; Restore STATUS
        swapf WREGsave,F ;
        swapf WREGsave,W ; Restore WREG

        retfie ; Return from interrupt.

        ;---------------------------------------------------------------------
        Setup
        ;
        ; Initializes program variables and peripheral registers.
        ;---------------------------------------------------------------------

        banksel PCON
        bsf PCON,NOT_POR
        bsf PCON,NOT_BOR

        banksel Index ; Clear various program variables
        clrf Index

        clrf PORTB
        clrf PIR1
        banksel TRISB
        clrf TRISB

        movlw 0x36 ; Setup SSP module for 7-bit
        banksel SSPCON
        movwf SSPCON ; address, slave mode
        movlw NODE_ADDR
        banksel SSPADD
        movwf SSPADD
        clrf SSPSTAT


        banksel PIE1 ; Enable interrupts
        bsf PIE1,SSPIE
        bsf INTCON,PEIE ; Enable all peripheral interrupts
        bsf INTCON,GIE ; Enable global interrupts

        bcf STATUS,RP0
        return

        ;---------------------------------------------------------------------
        SSP_Handler
        ;---------------------------------------------------------------------
        ; The I2C code below checks for 5 states:
        ;---------------------------------------------------------------------
        ; State 1: I2C write operation, last byte was an address byte.
        ;
        ; SSPSTAT bits: S = 1, D_A = 0, R_W = 0, BF = 1
        ;
        ; State 2: I2C write operation, last byte was a data byte.
        ;
        ; SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 1
        ;
        ; State 3: I2C read operation, last byte was an address byte.
        ;
        ; SSPSTAT bits: S = 1, D_A = 0, R_W = 1, BF = 0
        ;
        ; State 4: I2C read operation, last byte was a data byte.
        ;
        ; SSPSTAT bits: S = 1, D_A = 1, R_W = 1, BF = 0
        ;
        ; State 5: Slave I2C logic reset by NACK from master.
        ;
        ; SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 0
        ;
        ; For convenience, WriteI2C and ReadI2C functions have been used.
        ;----------------------------------------------------------------------

        banksel SSPSTAT
        movf SSPSTAT,W ; Get the value of SSPSTAT
        andlw b'00101101' ; Mask out unimportant bits in SSPSTAT.
        banksel Temp ; Put masked value in Temp
        movwf Temp ; for comparision checking.

        State1: ; Write operation, last byte was an
        movlw b'00001001' ; address, buffer is full.
        xorwf Temp,W ;
        btfss STATUS,Z ; Are we in State1?
        goto State2 ; No, check for next state.....

        memset RXBuffer,0,RX_BUF_LEN ; Clear the receive buffer.
        clrf Index ; Clear the buffer index.
        call ReadI2C ; Do a dummy read of the SSPBUF.
        return

        State2: ; Write operation, last byte was data,
        movlw b'00101001' ; buffer is full.
        xorwf Temp,W
        btfss STATUS,Z ; Are we in State2?
        goto State3 ; No, check for next state.....

        LFSR RXBuffer,Index ; Point to the buffer.
        call ReadI2C ; Get the byte from the SSP.
        movwf INDF ; Put it in the buffer.
        incf Index,F ; Increment the buffer pointer.
        movf Index,W ; Get the current buffer index.
        sublw RX_BUF_LEN ; Subtract the buffer length.
        btfsc STATUS,Z ; Has the index exceeded the buffer length?
        clrf Index ; Yes, clear the buffer index.
        return

        State3: ; Read operation, last byte was an
        movlw b'00001100' ; address, buffer is empty.
        xorwf Temp,W
        btfss STATUS,Z ; Are we in State3?
        goto State4 ; No, check for next state.....

        clrf Index ; Clear the buffer index.
        LFSR RXBuffer,Index ; Point to the buffer
        movf INDF,W ; Get the byte from buffer.
        call WriteI2C ; Write the byte to SSPBUF
        incf Index,F ; Increment the buffer index.
        return

        State4: ; Read operation, last byte was data,
        movlw b'00101100' ; buffer is empty.
        xorwf Temp,W
        btfss STATUS,Z ; Are we in State4?
        goto State5 ; No, check for next state....

        movf Index,W ; Get the current buffer index.
        sublw RX_BUF_LEN ; Subtract the buffer length.
        btfsc STATUS,Z ; Has the index exceeded the buffer length?
        clrf Index ; Yes, clear the buffer index.
        LFSR RXBuffer,Index ; Point to the buffer
        movf INDF,W ; Get the byte
        call WriteI2C ; Write to SSPBUF
        incf Index,F ; Increment the buffer index.
        return

        State5:
        movlw b'00101000' ; A NACK was received when transmitting
        xorwf Temp,W ; data back from the master. Slave logic
        btfss STATUS,Z ; is reset in this case. R_W = 0, D_A = 1
        goto I2CErr ; and BF = 0
        return ; If we aren抰 in State5, then something is
        ; wrong.

        I2CErr nop
        banksel PORTB ; Something went wrong! Set LED
        bsf PORTB,7 ; and loop forever. WDT will reset
        goto $ ; device, if enabled.
        return

        ;---------------------------------------------------------------------
        ; WriteI2C
        ;---------------------------------------------------------------------

        WriteI2C
        banksel SSPSTAT
        btfsc SSPSTAT,BF ; Is the buffer full?
        goto WriteI2C ; Yes, keep waiting.
        banksel SSPCON ; No, continue.
        DoI2CWrite
        bcf SSPCON,WCOL ; Clear the WCOL flag.
        movwf SSPBUF ; Write the byte in WREG
        btfsc SSPCON,WCOL ; Was there a write collision?
        goto DoI2CWrite
        bsf SSPCON,CKP ; Release the clock.
        return

        ;---------------------------------------------------------------------
        ReadI2C
        ;---------------------------------------------------------------------

        banksel SSPBUF
        movf SSPBUF,W ; Get the byte and put in WREG
        return

        end ; End of file



        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 康平县| 璧山县| 岳西县| 黑水县| 和政县| 茂名市| 九龙城区| 鄄城县| 崇左市| 灵武市| 兴和县| 栾川县| 昭通市| 修文县| 囊谦县| 嘉黎县| 鄂温| 东港市| 蛟河市| 南京市| 浦北县| 云南省| 那曲县| 驻马店市| 宁津县| 舒兰市| 米脂县| 临邑县| 西乌珠穆沁旗| 凤凰县| 兴安盟| 湘阴县| 武乡县| 孟津县| 华阴市| 阿勒泰市| 宁武县| 钟祥市| 建水县| 贺兰县| 扎兰屯市|