| 
 | 
 
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 |   
 
 
 
 |