📄 iic.asm
字号:
;**********************************************************************************************************
; I2C_WRITE_SUB
;
; Writes a message just like I2C_WRITE, except that the data is preceeded by a sub-address
; to a slave device.
; Eg. : A serial EEPROM would need an address of memory location for Random Writes
;
; Parameters :
; BYTES #of bytes starting from RAM pointer _SourcePointer_
; SourcePointer Data Start Buffer pointer in RAM (file Registers)
; SubAddress The sub-address of the 24Cxx
;
; Sequence :
; S-SlvAW-A-SubA-A-D[0]-A.....A-D[N-1]-A-P
;
; If an error occurs then the routine simply returns and user should check for
; flags in Bus_Status Reg (for eg. Txmt_Success flag
;
; Returns : WREG = 1 on success, else WREG = 0
;
; NOTE : The address of the slave must be loaded into SlaveAddress Registers, and 10 or 8 bit
; mode addressing must be set
;
; COMMENTS :
; I2C_WR may prove to be more efficient than this macro in most situations
; Advantages will be found for Random Address Block Writes for Slaves with
; Auto Increment Sub-Addresses (like Microchip's 24CXX series Serial EEPROMS)
;
;**********************************************************************************************************
W24C02:
;_i2c_block_write:
bsf STATUS,RP0 ; bank 1
bcf SCL_TRIS ; SCL set to output
bcf STATUS,RP0 ; bank 0
movf BYTES,W
movwf tempCount
movf SourcePointer,W
movwf FSR
call SendStart ; send START bit
movlw AT24C02
movwf EETEMP
call SendData ; 发器件地址
btfss Txmt_Success ; skip if successful
goto SendFail
movf SubAddress,W
movwf EETEMP ; start from the first byte starting at _DataPointer_
call SendData ; 发字节地址
btfss Txmt_Success ; skip if successful
goto SendFail
;
_block_wr1_loop:
movf INDF,W
movwf EETEMP ; start from the first byte starting at _DataPointer_
incf FSR, F
call SendData ; send next byte, bus is our's !
decfsz tempCount, F
goto _block_wr1_loop ; loop until desired bytes of data transmitted to slave
call SendStop ; Issue a stop bit for slave to end transmission
call DELAY10ms
retlw TRUE
SendFail:
call SendStop
clrwdt
retlw FALSE ; Addr Txmt Unsuccessful, so return 0
;**********************************************************************************************************
;
; I2C_READ_SUB
; This MACRO/Subroutine reads a message from a slave device preceeded by a write of the sub-address
; Between the sub-addrers write & the following reads, a STOP condition is not issued and
; a "REPEATED START" condition is used so that an other master will not take over the bus,
; and also that no other master will overwrite the sub-address of the same salve.
;
; This function is very commonly used in accessing Random/Sequential reads from a
; memory device (e.g : 24Cxx serial of Serial EEPROMs from Microchip).
;
; Parameters :
; BYTES # of bytes to read
; DestPointer The destination pointer of data to be received.
; SubAddress The sub-address of the 24Cxx
;
; Sequence :
; S-SlvAW-A-SubAddress-A-S-SlvAR-A-D[0]-A-.....-A-D[N-1]-N-P
;
;
;**********************************************************************************************************
R24C02:
;_i2c_block_read:
bsf STATUS,RP0 ; bank 1
bcf SCL_TRIS ; SCL set to output
bcf STATUS,RP0 ; bank 0
movf DestPointer,W
movwf FSR ; FIFO destination address pointer
call SendStart ; send START bit
movlw AT24C02
movwf EETEMP
call SendData ; send next byte
movf SubAddress,W
movwf EETEMP ; start from the first byte starting at _DataPointer_
call SendData
btfss Txmt_Success
goto SendFail
call SendStart ; send START bit
movlw AT24C02
iorlw B'00000001'
movwf EETEMP
call SendData
btfss Txmt_Success
goto SendFail
movf BYTES,W
movwf tempCount
_block_rd1_loop:
call GetData
movf EETEMP,W
movwf INDF ; start receiving data, starting at Destination Pointer
incf FSR, F
movlw .1
subwf tempCount,W
btfsc STATUS,Z
goto X31A
call ACK
decfsz tempCount, F
goto _block_rd1_loop ; loop until desired bytes of data transmitted to slave
goto X33
X31A:
call NAK
X33:
call SendStop ; Issue a stop bit for slave to end transmission
retlw TRUE
;----------------------------------------------------------
; 24C02 Read NO_ACK
;----------------------------------------------------------
NAK: ;
bsf SDA
goto $+1
bsf SCL
goto $+1
goto $+1
goto $+1
bcf SCL
nop
return
ACK:
bcf SDA
goto $+1
bsf SCL
goto $+1
goto $+1
goto $+1
bcf SCL
NOP ; Delay
return
;***************************************************************************
; Sends Start Bit - SDA falls while SCL is high
;***************************************************************************
; Inputs: none
; Outputs: none
SendStart:
; start bit - data goes low while clock is high
bsf SDA ; PORTA, bit1
goto $+1
bsf SCL ; PORTA, bit0
goto $+1
goto $+1
goto $+1
bcf SDA ; data set low
goto $+1
goto $+1
goto $+1
bcf SCL ; clock goes low
nop
return
;***************************************************************************
; Sends Stop Bit - SDA rises while SCL is high
;***************************************************************************
; Inputs: none
; Outputs: none
SendStop: ; stop bit - data goes high while clock is high
bcf SDA ; data goes low
goto $+1
bsf SCL ; clock goes high
goto $+1
goto $+1
goto $+1
bsf SDA ; data goes high
nop
return
;***************************************************************************
; Inputs: EETEMP (data to transmit)
; Outputs: none
; used: J (bit counter)
SendData: ; generates clock, reads SDA
bcf Txmt_Success ; reset status bit
movlw .8 ; send eight bits
movwf J
SendDataLoop
clrwdt ; clear WDT, set for 18 mSec
btfsc EETEMP,7 ; EETEMP MSB
goto SDAHigh
SDALow bcf SDA ; SDA goes low
goto SCLPulse
SDAHigh bsf SDA ; SDA goes high
SCLPulse:
bsf SCL ; clock pulse goes high
goto $+1
goto $+1
goto $+1
bcf SCL ; clock pulses goes low
DecCntA rlf EETEMP,F ; rotate data to transmit
decfsz J,F ; count bit as sent
goto SendDataLoop ; not done yet, repeat loop
;
; Check For Acknowledge
;
bcf SCL ; reset clock
bsf SDA ; Release SDA line for Slave to pull down
goto $+1
bsf SCL ; clock for slave to ACK
goto $+1
goto $+1
goto $+1
bsf STATUS,RP0 ; bank 1
bsf SDA_TRIS ; SDA set to output
bcf STATUS,RP0 ; bank 0
btfsc SDA ; SDA should be pulled low by slave if OK
goto TxmtErrorAck
bcf SCL ; reset clock
bsf Txmt_Success ; transmission successful
bsf STATUS,RP0 ; bank 1
bcf SDA_TRIS ; SDA set to output
bcf STATUS,RP0 ; bank 0
return
TxmtErrorAck:
bcf Txmt_Success ; transmission NOT successful
bsf STATUS,RP0 ; bank 1
bcf SDA_TRIS ; SDA set to output
bcf STATUS,RP0 ; bank 0
return ; done with loop, return
;***************************************************************************
; Inputs: none
; Outputs: EETEMP (received data)
; used: J (bit counter)
GetData:
clrf EETEMP
movlw .8
movwf J ; init bit counter
bsf STATUS,RP0 ; bank 1
bsf SDA_TRIS ; SDA set to output
bcf STATUS,RP0 ; bank 0
ReadData bsf SCL ; clock high
goto $+1
goto $+1
goto $+1
btfsc SDA ; read data
goto RDHigh
bcf EETEMP,0
goto DRCount
RDHigh bsf EETEMP,0
DRCount bcf SCL ; clock low
decfsz J,F
goto NextBit
bsf STATUS,RP0 ; bank 1
bcf SDA_TRIS ; SDA set to output
bcf STATUS,RP0 ; bank 0
return
NextBit rlf EETEMP,F
goto $+1
goto ReadData
;***************************************************************************
; Generates a 9th clock pulsse so slave can send ACK bit. This bit is not
; recorded.
;***************************************************************************
; Inputs: none
; Outputs: none
GetACK
bsf STATUS,RP0 ; bank 1
bsf SDA_TRIS ; set SDA to input
bcf STATUS,RP0 ; bank 0
bsf SCL ; clock pulse for ACK
goto $+1
nop
bcf SCL
nop
return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -