📄 i2c.asm
字号:
; i2c.asm
_I2c_ASM EQU 1
include "ht49c80.inc"
include "i2c.inc"
include "var.inc"
;--------------------------------------------------------
; _i2c_eeprom : code error status mode
; ------ ------------------------------------------------
; bit0 = 1 : error bit
; bit6 : DO
; bit7 : DI
;--------------------------------------------------------
DI EQU 7 ; EEPROM input
DO EQU 6 ; EEPROM output
code .section 'code'
;i2c initial, set to master mode
_i2cInit:
clr pcc.SDA
clr pcc.SCL
jmp $+1
clr pc.SDA ; Set SDA, SCL low when not tri-stated
clr pc.SCL
ret
;------------------------------------------------------------------------
;_i2cWaitTest
_i2cWaitTest:
call _i2cInit
clr _i2c_eeprom
call i2cBSTART
mov a,_i2c_daddr
mov var4,a
call i2cTX
mov a,0fh
and a,_i2c_eeprom
snz z
jmp _i2cWaitTest
call i2cBSTOP
ret a,00 ;free
;------------------------------------------------------------------------
; _i2cWrite I2C (Master Mode)
;------------------------------------------------------------------------
; Input : _i2c_wbuf = data to be written
; _i2c_raddr = destination register address
; _i2c_daddr = device address
; _i2c_num = data number should write to I2C, not change
; Output : return error code in _i2c_eeprom
;------------------------------------------------------------------------
_i2cWrite:
call _i2cInit
clr _i2c_eeprom
call i2cBSTART
mov a,02
mov var2,a
mov a,offset _i2c_daddr
mov mp0,a
mov a,_i2c_num ;do not change _i2c_num
and a,0fh
addm a,var2
i2cWrite_LOOP:
mov a,r0
mov var4,a
call i2cTX
inc mp0
sdz var2
jmp i2cWrite_LOOP
i2cWrite_STOP:
call i2cBSTOP
ret
;------------------------------------------------------------------------
; _i2cRead I2C read (Master Mode)
;------------------------------------------------------------------------
; Input : _i2c_rbuf = buf to receive data
; _i2c_raddr = destination register address,2bytes,if first byte is 0xff then send 1byte araddr
; _i2c_daddr = device address
; _i2c_num = data number should read from I2C,, not change
; Output : return error code in _i2c_eeprom
;------------------------------------------------------------------------
_i2cRead:
call _i2cInit
clr _i2c_eeprom
;first change I2C data pointer
call i2cBSTART
mov a,_i2c_daddr
mov var4,a
call i2cTX
mov a,_i2c_raddr
mov var4,a
call i2cTX
; call i2cBSTOP
;then read data
call i2cBSTART
mov a,_i2c_daddr
mov var4,a
set var4.0 ;clear R/W bit
call i2cTX
mov a,offset _i2c_rbuf
mov mp0,a
mov a,_i2c_num
and a,0fh
mov var2,a
i2cRead_LOOP:
call i2cRX
mov a,var4
mov r0,a
inc mp0
sdz var2
jmp i2cRead_LOOP
i2cRead_STOP:
call i2cBSTOP
ret
;------------------------------------------------------------------------
; RECEIVE eight data bits subroutine
;------------------------------------------------------------------------
;input: var2
; Output : var4 = 8-bit data received
;------------------------------------------------------------------------
i2cRX:
mov a,08 ; 8 bits of data
mov _i2c_count,a
clr var4
i2cRX_LOOP:
rlc var4 ; Shift data to buffer
call i2cBITIN
clr var4.0
sz _i2c_eeprom.DI
set var4.0 ; Input bit =1
sdz _i2c_count ; 8 bits?
jmp i2cRX_LOOP
clr _i2c_eeprom.DO
mov a,var2
xor a,01
sz z ;test if the last read byte
set _i2c_eeprom.DO ; Set acknowledge bit = 1, means no ACK
i2cRX_ARK:
call i2cBITOUT ; to STOP further input
ret a,0
;------------------------------------------------------------------------
; TRANSMIT 8 data bits subroutine
;------------------------------------------------------------------------
; Input : var4
; Output : Data X'mitted to EEPROM device
;------------------------------------------------------------------------
i2cTX:
mov a,08
mov _i2c_count,a
i2cTX_LOOP:
clr _i2c_eeprom.DO ; Shift data bit out.
sz var4.7 ; If shifted bit = 0, data bit = 0
set _i2c_eeprom.DO ; Otherwise data bit = 1
call i2cBITOUT ; Serial data out
rlc var4 ; Rotate TXBUF left
sdz _i2c_count ; 8 bits done?
jmp i2cTX_LOOP ; No.
call i2cBITIN ; Read acknowledge bit
sz _i2c_eeprom.DI ; Check for acknowledgement
set _i2c_eeprom.0 ; No acknowledge from device
i2cTX_RET:
ret a,0
;------------------------------------------------------------------------
; Single bit receive from I2C to PIC
;------------------------------------------------------------------------
; Input : None
; Output : Data bit received
;------------------------------------------------------------------------
i2cBITIN:
set pcc.SDA ; Set SDA for input
clr _i2c_eeprom.DI
set pcc.SCL
call i2cWait5us
sz pc.SCL ; Skip if SCL is high
jmp i2cBITIN_BIT1
set _i2c_eeprom.0 ; SCL locked low by device
i2cBITIN_BIT1:
jmp $+1
jmp $+1
jmp $+1
jmp $+1
snz pc.SDA ; Read SDA pin, for ACK low
jmp i2cBITIN_ACKOK
set _i2c_eeprom.DI
i2cBITIN_ACKOK:
call i2cWait5us
clr pcc.SCL ; Return SCL to low
jmp $+1
ret a,0
;------------------------------------------------------------------------
; Single bit data transmit from PIC to I2C
;------------------------------------------------------------------------
; Input : EEPROM register, bit DO
; Output : Bit transmitted over I2C
; Error bits set as necessary
;------------------------------------------------------------------------
i2cBITOUT:
snz _i2c_eeprom.DO
jmp i2cBITOUT_BIT0
set pcc.SDA ; Output bit 1
jmp $+1
jmp $+1
jmp $+1
jmp $+1
sz pc.SDA ; Check for error code 2
jmp i2cBITOUT_CLK1
set _i2c_eeprom.0 ; SDA locked low by device
jmp i2cBITOUT_CLK1
i2cBITOUT_BIT0:
clr pcc.SDA ; Output bit 0
i2cBITOUT_CLK1:
call i2cWait5us
set pcc.SCL
jmp $+1
jmp $+1
jmp $+1
jmp $+1
sz pc.SCL ; SCL locked low?
jmp i2cBITOUT_BIT2 ; No.
set _i2c_eeprom.0 ; SCL locked low by device
i2cBITOUT_BIT2:
call i2cWait5us
clr pcc.SCL ; Return SCL to low
ret a,0
;------------------------------------------------------------------------
; i2cBSTART startbit 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.
i2cBSTART:
set pcc.SDA ; Make sure SDA is high
set pcc.SCL ; Set clock high
jmp $+1
jmp $+1
jmp $+1
jmp $+1
sz pc.SCL ; Locked?
jmp i2cBSTART_OK
set _i2c_eeprom.0 ; SCL locked low by device
i2cBSTART_OK:
call i2cWait5us
clr pcc.SDA ; SDA goes low during SCL high
call i2cWait5us
clr pcc.SCL ; Return SCL to low
ret a,0
;------------------------------------------------------------------------
; i2cBSTOP 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.
i2cBSTOP:
clr pcc.SDA ; Return SDA to low
set pcc.SCL ; Set SCL high
call i2cWait5us
sz pc.SCL ; Locked?
jmp i2cBSTOP_OK1
set _i2c_eeprom.0 ; SCL locked low by device
i2cBSTOP_OK1:
set pcc.SDA ; SDA goes low to high during SCL high
jmp $+1
jmp $+1
jmp $+1
jmp $+1
sz pc.SDA ; High?
jmp i2cBSTOP_OK2
set _i2c_eeprom.0 ; SDA locked low by device
i2cBSTOP_OK2:
call i2cWait5us
ret a,0
;call + nop +return is 5us at 4MHz
i2cWait5us:
jmp $+1
jmp $+1
ret
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -