📄 iicmstr.asm
字号:
LIST P=16C74A
TITLE "I2C interface PICmicro to serial EEPROM"
;
;
;*****************************************************************************
;** Two wire/I2C Bus READ/WRITE Sample Routines of Microchip's
;** 24Cxx / 85Cxx serial CMOS EEPROM interfacing to a
;** PIC16C74 8-bit CMOS single chip microcomputer
;** Revised Version (3/1/94).
;**
;** Note: 1) All timing is based on a reference crystal frequency of 4MHz
;** which is equivalent to an instruction cycle time of 1 usec.
;** 2) Address and literal values are read in hexidecimal unless
;** otherwise specified.
;*****************************************************************************
;
;-----------------------------------------------------------------------------
; Register File Assignment
;-----------------------------------------------------------------------------
;
#include <P16C74a.INC>
;
FLAG equ 20 ; Common flag bits register
EEPROM equ 21 ; Bit buffer
ERCODE equ 22 ; Error code (to indicate bus status)
ADDR equ 23 ; Address register
DATAI equ 24 ; Stored data input register
DATAO equ 25 ; Stored data output register
SLAVE equ 26 ; Device address (1010xxx0)
TXBUF equ 27 ; TX buffer
RXBUF equ 28 ; RX buffer
COUNT equ 29 ; Bit counter
TEMP equ 2A ; Temporary storage
TEMP1 equ 2B ; More Temporary storage
;
;-----------------------------------------------------------------------------
; Bit Assignments
;-----------------------------------------------------------------------------
;
; FLAG Bits
;
ERRORFLG EQU 0 ; Error flag
;
; EEPROM Bits
;
DI EQU 7 ; EEPROM input
DO EQU 6 ; EEPROM output
;
; I2C Device Bits
;
SDA EQU 4 ; RB7, data in/out
SCL EQU 3 ; RB6, serial clock
;------------------------------------------------------------------------------
; Vector Assignment
;------------------------------------------------------------------------------
ORG 00h ; Reset Vector
goto Start
;
ORG 04h ; Interrupt Vector
goto Service_int ; Not actually used by this program
;
ORG 10h ; Begining of Program space
;------------------------------------------------------------------------------
; Main Program
;------------------------------------------------------------------------------
Start
clrf FLAG
clrf ERCODE
bsf STATUS,RP0 ; Select Page 1
clrf TRISB ; Set PORT_B as all outputs
movlw 0FFh ; Set PORT_B as all inputs
movwf TRISC
bcf STATUS,RP0 ; Select Page 0
movlw 01h
movwf PORTB ; Light first LED
movlw B'00111011' ; I2C master mode enabled
movwf SSPCON
movlw B'00000000' ; Disable interrupts
movwf INTCON
movlw B'00000000' ; Disable all interrupts
movwf PIE1
clrf PORTC ; Set SCL, SDA to low when not in tri-state
Bigloop
movf PORTB,W
movwf DATAO ; Output Data
; movlw 00h ; EEPROM data address
; movwf ADDR
; movlw B'10100000' ; EEPROM I2C address
movlw B'00001110'
movwf SLAVE
Wrtloop
call WRBYTE ; Output byte to EEPROM
btfsc FLAG,ERRORFLG ; Check for error
goto Errorloop
call Delay ; 10mS Delay for 24LC01 EEPROM write delay
; incf ADDR, F ; Point to next address
; btfss ADDR,7 ; Check if at end of EEPROM
; goto Wrtloop
bcf STATUS,RP0 ; Address page 1
; movlw 00h ; EEPROM data address
; movwf ADDR
; movlw B'10100000' ; EEPROM I2C address
movlw B'00001111'
movwf SLAVE
Rdloop
call RDBYTE ; Input byte from EEPROM
btfsc FLAG,ERRORFLG ; Check for error
goto Errorloop
movf DATAI,W ; Get received byte
xorlw B'11111111' ; Add by Steven Lin 032099
subwf PORTB,W ; Make sure correct data read
btfss STATUS,Z
goto Errorloop
; incf ADDR, F ; Point to next address
; btfss ADDR,7 ; Check if at end of EEPROM;
; goto Rdloop
incf PORTB, F ; Increment value displayed on LEDs
goto Bigloop
Errorloop
clrf PORTB ; Turn off all LEDs
Errloop1
call Delay ; Delay so that flashing of LEDs
call Delay ; is apparent
call Delay
call Delay
call Delay
call Delay
comf PORTB, F ; Change state of all LEDs
goto Errloop1
Service_int ; Interrupts are not used
return
;-----------------------------------------------------------------------------
; BYTE-WRITE, write one byte to EEPROM device
;-----------------------------------------------------------------------------
; Input : DATAO = data to be written
; ADDR = EEPROM data address
; SLAVE = device address (1010xxx0)
; Output : Data written to EEPROM device
;-----------------------------------------------------------------------------
WRBYTE
bcf STATUS,RP0
movf SLAVE,W ; Put SLAVE address
movwf TXBUF ; in xmit buffer
call BSTART ; Generate START bit
call TX ; Output SLAVE address
; bcf STATUS,RP0
; movf ADDR,W ; Put WORD address
; movwf TXBUF ; in xmit buffer
; call TX ; Output WORD address
bcf STATUS,RP0
movf DATAO,W ; Move DATA
movwf TXBUF ; into buffer
call TX ; Output DATA and detect acknowledgement
call BSTOP ; Generate STOP bit
return
;-----------------------------------------------------------------------------
; TRANSMIT 8 data bits subroutine
;-----------------------------------------------------------------------------
; Input : TXBUF
; Output : Data transmitted to EEPROM device
;-----------------------------------------------------------------------------
TX
bcf STATUS,RP0
movlw .8 ; Set counter for eight bits
movwf COUNT
TXLP
bcf EEPROM,DO ; Default 0 bit out
btfsc TXBUF,7 ; If shifted bit = 0, data bit = 0
bsf EEPROM,DO ; otherwise data bit = 1
call BITOUT ; Send bit
bcf STATUS,RP0
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
bcf STATUS,RP0
movlw 3
btfsc EEPROM,DI ; Check for acknowledgement
call ERR ; No acknowledge from device
bcf STATUS,RP0
retlw 0
;-----------------------------------------------------------------------------
; Single bit data transmit from PIC to serial EEPROM
;-----------------------------------------------------------------------------
; Input : EEPROM register, bit DO
; Output : Bit transmitted over I2C
; Error bits set as necessary
;-----------------------------------------------------------------------------
BITOUT
btfss EEPROM,DO
goto BIT0
bsf STATUS,RP0
bsf TRISC,SDA ; Output bit 0
nop
movlw 2
bcf STATUS,RP0
btfsc PORTC,SDA ; Check for error code 2
goto CLK1
call ERR
goto CLK1 ; SDA locked low by device
BIT0
bsf STATUS,RP0
bcf TRISC,SDA ; Output bit 0
nop ; Delay
CLK1
bsf STATUS,RP0
bsf TRISC,SCL ; Attempt to set SCL high
NOP ;STEVEN LIN
NOP
NOP
NOP
NOP
NOP
movlw 1 ; Error code 1
bcf STATUS,RP0
btfsc PORTC,SCL ; SCL locked low?
goto BIT2 ; No.
call ERR ; Yes, set error
BIT2
nop ; Timing delay
nop
bsf STATUS,RP0
bcf TRISC,SCL ; Return SCL to low
nop
bcf STATUS,RP0
retlw 0
;-----------------------------------------------------------------------------
; BYTE-READ, read one byte from serial EEPROM device
;-----------------------------------------------------------------------------
; Input : ADDR = source address
; SLAVE = device address (1010xxx0)
; Output : DATAI = data read from serial EEPROM
;-----------------------------------------------------------------------------
;
RDBYTE
bcf STATUS,RP0
movf SLAVE,W ; Move SLAVE address
movwf TXBUF ; into xmit buffer (R/W = 0)
call BSTART ; Generate START bit
call TX ; Output SLAVE address. Check ACK.
; bcf STATUS,RP0
; movf ADDR,W ; Move WORD address
; movwf TXBUF ; into xmit buffer
; call TX ; Output WORD address. Check ACK.
; call BSTART ; START READ (if only one device is
; bcf STATUS,RP0 ; connected to the I2C bus)
; movf SLAVE,W
; 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
bcf STATUS,RP0
movf RXBUF,W ; Save data from buffer
movwf DATAI ; to DATAI file register.
return
;
;-----------------------------------------------------------------------------
; RECEIVE eight data bits subroutine
;-----------------------------------------------------------------------------
; Input : None
; Output : RXBUF = 8-bit data received
;-----------------------------------------------------------------------------
;
RX
bcf STATUS,RP0
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
bcf STATUS,RP0
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
;
;-----------------------------------------------------------------------------
; Single bit receive from serial EEPROM to PIC
;-----------------------------------------------------------------------------
; Input : None
; Output : Data bit received
;-----------------------------------------------------------------------------
;
BITIN
bsf STATUS,RP0
bsf TRISC,SDA ; Set SDA for input
nop
bcf STATUS,RP0
bcf EEPROM,DI
bsf STATUS,RP0
bsf TRISC,SCL ; Clock high
nop
movlw 1
bcf STATUS,RP0
btfsc PORTC,SCL ; Skip if SCL is high
goto BIT1
call ERR
BIT1
bcf STATUS,RP0
nop ;by steven Lin
nop
nop
nop
nop
nop
nop
nop
nop
btfss PORTC,SDA ; Read SDA pin, for ACK low
goto ACKOK
bsf EEPROM,DI ; DI = 1
ACKOK
bsf STATUS,RP0
nop ; Delay
bcf TRISC,SCL ; Return SCL to low
nop
bcf STATUS,RP0
retlw 0
;-----------------------------------------------------------------------------
; DELAY, Provide a 10.78mS delay
;-----------------------------------------------------------------------------
; Input : None
; Output : None
;-----------------------------------------------------------------------------
Delay
bcf STATUS,RP0
movlw 7
movwf TEMP1
clrf TEMP ;clear last location
dly1
nop
nop
nop
decfsz TEMP, F ;reduce count
goto dly1 ;Inner loop time = 1.54mS
decfsz TEMP1, F
goto dly1 ;Total time = 10.78mS
retlw 0
;-----------------------------------------------------------------------------
; START bit generation 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
bsf STATUS,RP0
bsf TRISC,SDA ; Make sure SDA is high
nop
bsf TRISC,SCL ; Set clock high
nop
movlw 1 ; Ready error status code 1
bcf STATUS,RP0
btfss PORTC,SCL ; Locked?
call ERR ; SCL locked low by device, flag error
bsf STATUS,RP0
bcf TRISC,SDA ; SDA goes low during SCL high
nop ; Timing adjustment, 1uS @4MHz
bcf TRISC,SCL ; Start clock train
nop
bcf STATUS,RP0
RETLW 0
;-----------------------------------------------------------------------------
; STOP bit generation 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
bsf STATUS,RP0
bcf TRISC,SDA ; Return SDA to low
nop
bsf TRISC,SCL ; Set SCL high
nop
movlw 1 ; Ready error code 1
bcf STATUS,RP0
btfss PORTC,SCL ; High?
call ERR ; No, SCL locked low by device
bsf STATUS,RP0
bsf TRISC,SDA ; SDA goes from low to high during SCL high
nop
movlw 4 ; Ready error code 4
btfss TRISC,SDA ; High?
call ERR ; No, SDA bus not release for STOP
bcf STATUS,RP0
retlw 0
;
;-----------------------------------------------------------------------------
; Two wire/I2C - CPU communication error status table and subroutine
;-----------------------------------------------------------------------------
; input : W-reg = error code
; output : ERCODE = error code
; FLAG(ERROR) = 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
bcf STATUS,RP0
btfss FLAG,ERRORFLG ; If not first error, do not change code
movwf ERCODE ; Save error code
bsf FLAG,ERRORFLG ; Set error flag
retlw 0
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -