📄 i2cbus.a30
字号:
inc.b md_cnt ; Increment master data receive counter.
cmp.b mr_lng,md_cnt ; Compare data receive count to expected data receive count.
rolc.b R1H ; ack/nack Rotate right bit 9.
mov.b #0ffh,R1L ;
bclr 2,U2SMR2 ; First bit hold on, "every byte."
ms_r_ln: ;
btst 1,P7 ; ---- Wait for SCL to go high.
jz ms_r_ln ; --/
btst 0,P7 ; Bit test SDA for ACK.
jnz rcv_end ; If NO ACK then jump to rcv_end.
mov.w R1,U2TB ; Else ACK received, copy R1 data to UART2 transmit buffer.
bset 2,U2SMR2 ; Set SWC enable, SCL clock on hold enabled.
jsr wait_2usec ; New counter delay by Bruce Embry, July 1999.
bset 5,U2SMR2 ; Hold SCL low.
jsr wait_15usec ; New counter delay by Bruce Embry, July 1999.
bclr 5,U2SMR2 ; Release SCL and start Master data receive.
jmp u2rcv_int_end ;
;;; -----------------------------------------------------------------------------
.align ; End of master receive.
;;;------------------------------------------------------------------------------
rcv_nack_err: ;
mov.b #01h,R1L ; Master receive NO ACK.
jmp ms_r_end ;
;;; -----------------------------------------------------------------------------
.align ;
rcv_end: ;
mov.b #00h,R1L ;
ms_r_end: ;
jsr make_stop ;
mov.b #00h,m_iic ; Set I2C bus mode condition to wait mode stop to start condition.
;;; for C
push.b md_cnt ; ---\
mov.b #00h,R1L ; \
jsr $iic_mr_end ; \____For C Code return.
pop.b md_cnt ; /
mov.b #00h,md_cnt ; ___/
jmp u2rcv_int_end ;
;;; ===========================================================================
;; Slave "Receive" ID byte "First Byte"
;; ACK of "First ID byte" and send first data byte.
;;; ===========================================================================
.align ;
sl_rcv_1: ;
.if DEBUG == 1 ; ---DEBUG---
bset 4,dp ; ---DEBUG---
.endif ; ---DEBUG---
bclr 2,U2SMR2 ; Disable hold at 9th bit.
bclr 1,PD7 ;
sl_r_l1: ;
btst 1,P7 ; -- Wait for SCL to go high.
jz sl_r_l1 ; -/
mov.b #0ah,U2MR ; Set standard clock input mode.
mov.w #0ffh,U2TB ; Init UART2 to dummy data and ACK
bset 2,U2SMR2 ; 9th bit low set "ACK".
bclr 0,PD7 ; Set SDA pin to input.
;
btst 1,m_iic ; Test I2C bus mode condition for arbitration.
jz sl_rcv10 ; IF 0 jump to s1_rcv10.
jsr abt_lost ; Else, jump to abt_lost.
sl_rcv10: ;
bset 7,sd_p ; Bit set 7th bit of Slave Data Counter.
mov.b #05h,m_iic ; Set I2C bus mode condition to slave receive mode.
jmp u2rcv_int_end ;
;;; ===========================================================================
;; ACK Slave ID and start first transmit first data byte.
;;; ===========================================================================
.align ;
sl_snd_1: ;
.if DEBUG == 1 ; ---DEBUG---
bset 3,dp ; ---DEBUG---
.endif ; ---DEBUG---
mov.b sd_p,R1L ; Copy slave data counter to R1L.
mov.b #00h,R1H ; Init R1H.
mov.w slave_ram,A0 ; Copy slave ram start address to A0.
add.w R1,A0 ; Add slave data counter to slave ram start address.
mov.b [A0],R1L ; Copy data pointed to by A0 to R1L.
mov.b #01h,R1H ; Set 9th bit NACK.
inc.b sd_p ; Increment slave data counter.
and.b #07fh,sd_p ; Set 8th bit of slave data counter to zero.
bclr 2,U2SMR2 ; Disable SCL clock.
bclr 1,PD7 ; Set SCL pin direction to input.
sl_s_l1: ;
btst 1,P7 ; ----- Wait for SCL to go high.
jz sl_s_l1 ; --/
mov.b #0ah,U2MR ; Set use external clock.
mov.w R1,U2TB ; Copy data in R1 to UART2 transmit buffer.
bset 2,U2SMR2 ; Set 9th bit low, hold function enable, keep low at 9th bit.
bclr 0,PD7 ; Set SDA pin direction to input.
;
btst 1,m_iic ; Test for arbitration lost.
jz sl_snd10 ; if arbitration has not been lost, jump to s1_and10.
jsr abt_lost ; Else arbitration has been lost, jump to abt_lost.
sl_snd10: ;
mov.b #04h,m_iic ; Set I2C mode condition to set slave transmit mode.
jmp u2rcv_int_end ;
;;; ===========================================================================
;; Receive ACK to 1st data byte and start second data byte.
;;; ===========================================================================
.align ;
sl_rcv_n: ;
.if DEBUG == 1 ; --- DEBUG ---
bset 4,dp ; --- DEBUG ---
.endif ; --- DEBUG ---
btst 2,U2SMR2 ; Bit test 9bit low.
jz u2rcv_int_end ; if 0 jump.
;
mov.b sd_p,R1L ; Load slave receive data counter to R1L.
mov.b #00h,R1H ; Set R1H to zero.
mov.w slave_ram,A0 ; Set A0 to slave ram address.
add.w R1,A0 ; Add slave receive data counter to slave ram address.
;
mov.w U2RB,R1 ; Copy data receive in UART2 receive buffer to R1.
btst 8,R1 ; Test 8th bit
rolc.b R1L ; If 8th bit high restore data to R1L.
;;;
;;;
;;;
btst 7,sd_p ; Test bit 7 of slave receive data counter.
jz sl_rcv_n03 ; If bit 7 is 0 them jump to s1_rcv_n03.
mov.b R1L,sd_p ; Copy R1L to slave data counter.
jmp sl_rcv_n05 ;
sl_rcv_n03: ;
mov.b R1L,[A0] ; copy RIL to slave data ram location pointer to by A0.
inc.b sd_p ; Increment slave data counter.
sl_rcv_n05: ;
and.b #07fh,sd_p ; Set 8th bit of slave data pointer to 0.
;;;
;;;
;;;
bclr 2,U2SMR2 ; After 9th bit disable keep low function.
sl_r_ln: ;
btst 1,P7 ; ----- Wait for SCL to go high.
jz sl_r_ln ; ---/
mov.b #0ah,U2MR ; Set, use external clock.
mov.w #00ffh,U2TB ; Place dummy data into UART2 transmit buffer.
bset 2,U2SMR2 ; Enable keep low function.
jmp u2rcv_int_end ;
;;; ===========================================================================
;; Slave transmit data
;; Test for ACK and send next data byte.
;;; ===========================================================================
.align ;
sl_snd_n: ;
.if DEBUG == 1 ; --- DEBUG ---
bset 3,dp ; --- DEBUG ---
.endif ; --- DEBUG ---
mov.b sd_p,R1L ; Copy slave data counter to R1L.
mov.b #00h,R1H ; Init R1H to zero.
mov.w slave_ram,A0 ; Copy slave ram address to A0.
add.w R1,A0 ; Add slave data counter to slave ram address.
mov.b [A0],R1L ; Copy data pointed to by A0 to R1L
mov.b #01h,R1H ; Init bit 9 of R1 to nack.
bclr 2,U2SMR2 ; After 9th bit disable keep low function.
sl_s_ln: ;
btst 1,P7 ; ---- Wait for SCL to go high.
jz sl_s_ln ; --/
btst 0,P7 ; Test logic value of SDA.
jnz sl_s_end ; If no ACK, jump to al_s_end.
;; ACK received.
mov.b #0ah,U2MR ; Set SCL to external clock.
mov.w R1,U2TB ; Copy data from R1 to UART2 transmit buffer.
bset 2,U2SMR2 ; Enable keep low function.
inc.b sd_p ; Increment slave data counter.
and.b #07fh,sd_p ; Set bit 8th of slave data counter to zero.
jmp u2rcv_int_end ;
;;; ----------------------------
.align ;
sl_s_end: ;
mov.b #0ah,U2MR ;
mov.b #0d1h,U2SMR2 ;
mov.b #00h,m_iic ; Set I2C bus condition register to wait mode stop to start condition.
jmp u2rcv_int_end ;
;;; ----------------------------
.align ;
slave_taiki: ; Slave wait mode stop.
and.b #08h,S2RIC ;
bset 6,U2SMR2 ; Set SDA pin to input.
bclr 2,U2SMR2 ; Disable 9th bit keep low function.
sl_t_l1: ;
btst 1,P7 ; ----- Wait for SCL input to go high.
jz sl_t_l1 ; --/
bset 0,P7 ; Set SDA to high "high impedance".
mov.b #0d1h,U2SMR2 ; ---- Set up UART for next I2C bus communication.
mov.b #0ah,U2MR ; --/
mov.b #00h,m_iic ; Set I2C bus condition register to wait mode stop to start condition.
u2rcv_int_end: ;
popm A0,R1 ; Pop registers from stack.
.if DEBUG == 1 ; --- DEBUG ---
mov.b #00h,dp ; --- DEBUG ---
.endif ; --- DEBUG ---
reit ;
;;; --------------------------------------------------------------------------
;; Test for Arbitration lost function.
;;; --------------------------------------------------------------------------
;;
abt_lost: ;
.if DEBUG == 1 ; --- DEBUG ---
bset 7,dp ; --- DEBUG ---
.endif ; --- DEBUG ---
mov.b #03h,R1L ; Return error #3
push.b md_cnt ; Push master data count onto stack.
btst 0,m_iic ; Test I2C bus condition register for Read or Write.
jc abt_lost10 ; If Read jump.
;; ; Else Write.
jsr $iic_mw_end ; Jump to sub-routine.
jmp abt_lost_end ; Jump to abt_lost_end.
.align ;
abt_lost10: ;
jsr $iic_mr_end ; Jump to sub-routine.
abt_lost_end: ;
pop.b md_cnt ; Pop master data count from stack.
mov.b #00h,md_cnt ; Init master data count to 0.
rts ;
;;; --------------------------------------------------------------------------
;; Make stop condition.
;;; --------------------------------------------------------------------------
;;
;;
make_stop:
and.b #0fch,P7 ; Set SDA and SCL to low output.
or.b #03h,PD7 ;
jsr wait_0us ; Wait 0us
mov.b #00h,U2MR ; Disable I2C mode
bclr 1,P7 ; SCL = L
bclr 0,P7 ; SDA = L
jsr wait_5usec ; New counter delay routine by Bruce Embry, July 1999.
bclr 1,PD7 ; Set SCLD to high impedance.
make_stop_wait: ;
btst 1,P7 ; ---- Wait for SCL pin to go high.
jz make_stop_wait ; --/
jsr wait_2usec ; New counter delay routine by Bruce Embry, July 1999.
bclr 0,PD7 ; Set SDA pin to high impedance.
bset 0,P7 ;
mov.b #0ah,U2MR ; Enable I2C bus to external clock (slave mode).
mov.b #0d1h,U2SMR2 ; Enable I2C bus external SYNC function.
bclr 3,U2RB+1 ; Clear arbitration flag.
rts ;
;;; --------------------------------------------------------------------------
;; Generate delay function. By Bruce A. Embry July 1999.
;; Delay values are set in I2C.H
;;; --------------------------------------------------------------------------
.align
wait_2usec:
mov.w _del_2usec,A1 ;; 2 clock cycles. Value assigned in i2c.h and defined in i2c.c.
jmp delay
wait_4usec:
mov.w _del_4usec,A1 ; Value assigned in i2c.h and defined in i2c.c.
jmp delay
wait_5usec:
mov.w _del_5usec,A1 ; Value assigned in i2c.h and defined in i2c.c.
jmp delay
wait_15usec:
mov.w _del_15usec,A1 ; Value assigned in i2c.h and defined in i2c.c.
jmp delay
wait_20usec:
mov.w _del_20usec,A1 ; Value assigned in i2c.h and defined in i2c.c.
delay:
dec.w A1 ; Decrement delay counter.
jnz delay ; If result of decrement operation is not zero then jump to delay.
wait_0us:
rts ;
;;; ---------------------------------------------------------------------------
.end ;
;;;
;;; ./i2cbus.a30 end
;;;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -