⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.asm

📁 ht芯片通过IO口读写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 + -