技术热线: 4007-888-234

PIC单片机的I2C读写源程序

更新时间: 2019-03-21
阅读量:412

TITLE " TWO WIRE/I2C BUS INTERFACE WITH PIC16C5x "

;

LIST P=16C54

;*****************************************************************************

;**  Two wire/I2C Bus READ/WRITE Sample Routines of Microchip's

;**  24Cxx / 85Cxx serial CMOS EEPROM interfacing to a 

;**  PIC16C54 8-bit CMOS single chip microcomputer

;**  Revsied Version 2.0 (4/2/92).

;**

;**     Part use = PIC16C54-XT/JW                                           

;**  Note:  1) All timings are based on a reference crystal frequency of 2MHz

;**            which is equivalent to an instruction cycle time of 2 usec.

;**         2) Address and literal values are read in octal unless otherwise

;**            specified.

;

;

;       Program:          I2CBUS.ASM 

;       Revision Date:   

;                         12-12-95      Compatibility with MPASMWIN 1.30

;

;********************************************************************** 

;

;*****************************************************************************

;

;-----------------------------------------------------------------------------

;       Files Assignment

;-----------------------------------------------------------------------------

;

PC      EQU     2               ; Program counter

STAT    EQU     3               ; PIC status byte

FSR     EQU     4               ; File Select Register

RA      EQU     5               ; Port A use to select device address

RB      EQU     6               ; RB7 = SDA, RB6 = SCL

;

STATUS  EQU     08              ; Status register

FLAG    EQU     09              ; Common flag bits register

EEPROM  EQU     0A              ; Bit buffer

ERCODE  EQU     0B              ; Error code (to indicate bus status)

ADDR    EQU     10              ; Address register

DATAI   EQU     11              ; Stored data input register

DATAO   EQU     12              ; Stored data output register

SLAVE   EQU     13              ; Device address (1010xxx0)

TXBUF   EQU     14              ; TX buffer

RXBUF   EQU     15              ; RX buffer

COUNT   EQU     16              ; Bit counter

;

TIMER0  EQU     18              ; Delay timer0

TIMER1  EQU     19              ; Delay timer1

;

;

;-----------------------------------------------------------------------------

;                     Bit Assignments

;-----------------------------------------------------------------------------

;

; Status bits

;

Z       EQU     2

C       EQU     0

;

; FLAG Bits

;

ERR1    EQU     0               ; Error flag

;

; Instruction Destination Bits

;

F       EQU     1

W       EQU     0

;

; EEPROM Bits

;

DI      EQU     7               ; EEPROM input

DO      EQU     6               ; EEPROM output

;

; I2C Device Bits

;

SDA     EQU     7               ; RB7, data in/out

SCL     EQU     6               ; RB6, serial clock

;

;END FILES/BITS EQUATE

 PAGE

;

;-----------------------------------------------------------------------------

;       Two wire/I2C - CPU communication error status table and subroutine

;-----------------------------------------------------------------------------

;  input  :     W-reg   = error code

;  output :     ERCODE  = error code

;           FLAG(ERR1) = 1

;

;         code          error status mode

;       -------         ------------------------------------------------------

;           1   :       SCL locked low by device (bus is still busy)

;           2   :       SDA locked low by device (bus is still busy)

;           3   :       No acknowledge from device (no handshake)

;           4   :       SDA bus not released for master to generate STOP bit

;-----------------------------------------------------------------------------

;

;Subroutine to identify the status of the serial clock (SCL) and serial data

;(SDA) condition according to the error status table. Codes generated are

;useful for bus/device diagnosis.

;

ERR

BTFSS   FLAG,ERR1       ; Remain as first error encountered

MOVWF   ERCODE          ; Save error code

BSF     FLAG,ERR1       ; Set error flag

RETLW   0

;

;-----------------------------------------------------------------------------

;       START bus communication routine

;-----------------------------------------------------------------------------

;       input   : none

;       output  : initialize bus communication

;-----------------------------------------------------------------------------

;

;Generate START bit (SCL is high while SDA goes from high to low transition)

;and check status of the serial clock.

BSTART

MOVLW   B'00111111'     ; Put SCL, SDA line in output state

TRIS    RB

;***************************************************************************

bsf     RB,SDA          ;make sure sda is high

;***************************************************************************

BSF     RB,SCL          ; Set clock high

MOVLW   1               ; Ready error status code 1

BTFSS   RB,SCL          ; Locked?

CALL    ERR             ; SCL locked low by device

BCF     RB,SDA          ; SDA goes low during SCL high

NOP                     ; Timing adjustment

NOP

NOP

BCF     RB,SCL          ; Start clock train

RETLW   0

;

;END SUB

 PAGE

;

;-----------------------------------------------------------------------------

;       STOP bus communication routine

;-----------------------------------------------------------------------------

;       Input   :       None

;       Output  :       Bus communication, STOP condition

;-----------------------------------------------------------------------------

;

;Generate STOP bit (SDA goes from low to high during SCL high state)

;and check bus conditions.

;

BSTOP

;****************************************************************************

MOVLW   B'00111111'     ; Put SCL, SDA line in output state

TRIS    RB

;****************************************************************************

BCF     RB,SDA          ; Return SDA to low

BSF     RB,SCL          ; Set SCL high

nop

nop

nop

MOVLW   1               ; Ready error code 1

BTFSS   RB,SCL          ; High?

CALL    ERR             ; No, SCL locked low by device

BSF     RB,SDA          ; SDA goes from low to high during SCL high

MOVLW   4               ; Ready error code 4

BTFSS   RB,SDA          ; High?

CALL    ERR             ; No, SDA bus not release for STOP

RETLW   0

;

;END SUB

;

;-----------------------------------------------------------------------------

;       Serial data send from PIC to serial EEPROM, bit-by-bit subroutine

;-----------------------------------------------------------------------------

;       Input   :       None

;       Output  :       To (DI) of serial EEPROM device

;-----------------------------------------------------------------------------

;

BITIN

MOVLW   B'10111111'     ; Force SDA line as input

TRIS    RB

BSF     RB,SDA          ; Set SDA for input

BCF     EEPROM,DI

BSF     RB,SCL          ; Clock high

MOVLW   1

BTFSC   RB,SCL          ; Skip if SCL  is high

GOTO    BIT1

BTFSS   FLAG,ERR1       ; Remain as first error encountered

MOVWF   ERCODE          ; Save error code

BSF     FLAG,ERR1       ; Set error flag

BIT1

BTFSC   RB,SDA          ; Read SDA pin

BSF     EEPROM,DI       ; DI = 1

NOP                     ; Delay

BCF     RB,SCL          ; Return SCL to low     

RETLW   0

;

;END SUB

 PAGE

;

;-----------------------------------------------------------------------------

;       Serial data receive from serial EEPROM to PIC, bit-by-bit subroutine

;-----------------------------------------------------------------------------

;       Input   :       EEPROM file

;       Output  :       From (DO) of serial EEPROM device to PIC

;-----------------------------------------------------------------------------

;

BITOUT

MOVLW   B'00111111'     ; Set SDA, SCL as outputs

TRIS    RB

BTFSS   EEPROM,DO

GOTO    BIT0

BSF     RB,SDA          ; Output bit 0

MOVLW   2

BTFSC   RB,SDA          ; Check for error code 2

GOTO    CLK1

BTFSS   FLAG,ERR1       ; Remain as first error encountered

MOVWF   ERCODE          ; Save error code

BSF     FLAG,ERR1       ; Set error flag

GOTO    CLK1            ; SDA locked low by device

;

BIT0

BCF     RB,SDA          ; Output bit 0

NOP                     ; Delay

NOP

NOP

CLK1

BSF     RB,SCL

MOVLW   1               ; Error code 1

BTFSC   RB,SCL          ; SCL locked low?

GOTO    BIT2            ; No.

BTFSS   FLAG,ERR1       ; Yes.

MOVWF   ERCODE          ; Save error code

BSF     FLAG,ERR1       ; Set error flag

BIT2

NOP

NOP

BCF     RB,SCL          ; Return SCL to low

RETLW   0

;

;END SUB

 PAGE

;

;

;-----------------------------------------------------------------------------

;       RECEIVE         DATA    subroutine

;-----------------------------------------------------------------------------

;       Input   :       None

;       Output  :       RXBUF = Receive 8-bit data

;-----------------------------------------------------------------------------

;

RX

MOVLW   .8              ; 8 bits of data

MOVWF   COUNT

CLRF    RXBUF

;

RXLP

RLF     RXBUF, F        ; Shift data to buffer

SKPC

BCF     RXBUF,0         ; carry ---> f(0)

SKPNC

BSF     RXBUF,0

CALL    BITIN

BTFSC   EEPROM,DI

BSF     RXBUF,0         ; Input bit =1

DECFSZ  COUNT, F        ; 8 bits?

GOTO    RXLP

BSF     EEPROM,DO       ; Set acknowledge bit = 1

CALL    BITOUT          ; to STOP further input

RETLW   0

;

;END SUB

;

;-----------------------------------------------------------------------------

;       TRANSMIT        DATA    subroutine

;-----------------------------------------------------------------------------

;       Input   :       TXBUF

;       Output  :       Data X'mitted to EEPROM device

;-----------------------------------------------------------------------------

;

TX

MOVLW   .8

MOVWF   COUNT

;

TXLP

BCF     EEPROM,DO       ; Shift data bit out.

BTFSC   TXBUF,7         ; If shifted bit = 0, data bit = 0

BSF     EEPROM,DO       ; Otherwise data bit = 1

CALL    BITOUT          ; Serial data out

RLF     TXBUF, F        ; Rotate TXBUF left

SKPC                    ; f(6) ---> f(7)

BCF     TXBUF,0         ; f(7) ---> carry

SKPNC                   ; carry ---> f(0)

BSF     TXBUF,0

DECFSZ  COUNT, F        ; 8 bits done?

GOTO    TXLP            ; No.

CALL    BITIN           ; Read acknowledge bit

MOVLW   3

BTFSC   EEPROM,DI       ; Check for acknowledgement

CALL    ERR             ; No acknowledge from device

RETLW   0

;

;END SUB

 PAGE

;

;-----------------------------------------------------------------------------

;       BYTE-WRITE, write one byte to EEPROM device

;-----------------------------------------------------------------------------

;       Input   :       DATAO= data to be written

;                       ADDR    = destination address

;                       SLAVE   = device address (1010xxx0)

;       Output  :       Data written to EEPROM device

;-----------------------------------------------------------------------------

;

ORG     080             ; The location for BYTE-WRITE routine can be

;                               ; assigned anywhere between (377-777) octal.

WRBYTE

MOVF    SLAVE,W         ; Get SLAVE address

MOVWF   TXBUF           ; to TX buffer

CALL    BSTART          ; Generate START bit

CALL    TX              ; Output SLAVE address

MOVF    ADDR,W          ; Get WORD address

MOVWF   TXBUF           ; into buffer

CALL    TX              ; Output WORD address

MOVF    DATAO,W         ; Move DATA 

MOVWF   TXBUF           ; into buffer

CALL    TX              ; Output DATA and detect acknowledgement

CALL    BSTOP           ; Generate STOP bit

goto    wrt_end

;

;

;

;-----------------------------------------------------------------------------

;       BYTE-READ, read one byte from serial EEPROM device

;-----------------------------------------------------------------------------

;       Input   :       ADDR    = source address

;                       SLAVE   = device address (1010xxx0)

;       Output  :       DATAI   = data read from serial EEPROM

;-----------------------------------------------------------------------------

;

ORG     0C0             ; The location for BYTE-READ routine can be

;                               ; assigned anywhere between (377-777) octal.

RDBYTE

MOVF    SLAVE,W         ; Move SLAVE address 

MOVWF   TXBUF           ; into buffer (R/W = 0)

CALL    BSTART          ; Generate START bit

CALL    TX              ; Output SLAVE address. Check ACK.

MOVF    ADDR,W          ; Get WORD address

MOVWF   TXBUF

CALL    TX              ; Output WORD address. Check ACK.

CALL    BSTART          ; START READ (if only one device is

MOVF    SLAVE,W         ; connected to the I2C bus)

MOVWF   TXBUF

BSF     TXBUF,0         ; Specify READ mode (R/W = 1)

CALL    TX              ; Output SLAVE address

CALL    RX              ; READ in data and acknowledge

CALL    BSTOP           ; Generate STOP bit

MOVF    RXBUF,W         ; Save data from buffer

MOVWF   DATAI           ; to DATAI file.

goto    rd_end

;

;Test program to read and write ramdom

start

movlw   0AE             ;set A2=A1=A0=1

movwf   SLAVE           ;       /

movlw   2               ;set r/w loc. = 2

movwf   ADDR            ;       /

movlw   55              ;write 55 to SEEPROM

movwf   DATAO           ;       /

goto    WRBYTE          ;write a byte

wrt_end

call    delay           ;wait for write

;operation (internal)

goto    RDBYTE          ;read back data

rd_end

movlw   55              ;test if read

xorwf   DATAI,W         ;correct?

btfss   STAT,Z          ;yes then skip

wrong   

goto    wrong

correct

goto    correct

;

;At 2.0Mhz, delay = approx. 3mS.

delay

clrf    1F              ;clear last location

dly1

nop

nop

nop

decfsz  1F, F           ;reduce count

goto    dly1            ;loop

retlw   0

;

org     0x1FF

goto    start

;

END