📄 sw_i2c_slave.s43
字号:
jc SDA_High ; Jmp if carry bit is set
SDA_Low bic.b #SDA_PIN,&SDA_OUT ; Set SDA low
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
reti ; Return from interrupt
;
SDA_High bis.b #SDA_PIN,&SDA_OUT ; Set SDA high
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
reti ; Return from interrupt
;
Tx_8HL ; 1->0 edge for SCL clk 8
bic.b #SDA_PIN,&SDA_DIR ; Release SDA (set SDA as input)
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
reti ; Return from interrupt
;
Addr_8HL ; 1->0 edge for SCL clk 8
bis.b #SCL_PIN,&SCL_DIR ; Hold SCL low (set SCL as output)
bit.b #SDA_PIN,&SDA_IES ; SDA value saved in SDA_IES
rlc.b I2C_DATA ; Left shift carry bit into I2C val
bic.b #001h,I2C_DATA ; Clear R/W bit for address test
cmp.b #I2C_ADDR,I2C_DATA ; Is my I2C address?
jnz NotMyAddr ; Not my address
bic.b #SDA_PIN,&SDA_OUT ; Set SDA output low
bis.b #SDA_PIN,&SDA_DIR ; Hold SDA low (set SDA as output)
bit.b #SDA_PIN,&SDA_IES ; SDA value saved in SDA_IES
adc.b I2C_DATA ; Reset R/W bit to original value
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bis.b #I2C_MATCH,&I2CEvent ; Set I2C address match event flag
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
NotMyAddr ; Not my I2C address
mov.w #SCL_NMATbl+32,SCL_TBL ; Point to Not My Address Table+16
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
Addr_9HL ; 1->0 edge for SCL clk 9
bis.b #SCL_PIN,&SCL_DIR ; Hold SCL low (set SCL as output)
clr.w &I2CIdx ; Clear I2C buffer index
bit.b #001h,I2C_DATA ; Is R/W bit set?
jc I2C_Read ; Yes, go to I2C_Read
I2C_Write ; No, process I2C write
bic.b #SDA_PIN,&SDA_DIR ; Release SDA (set SDA as input)
mov.w #SCL_RxTbl,SCL_TBL ; Point to I2C receive table
clr.b I2C_DATA ; Clear I2C data
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
I2C_Read ; Process I2C read
mov.w #SCL_TxTbl,SCL_TBL ; Point to I2C transmit table
push.w I2C_IDX ; Save register on stack
mov.w &I2CIdx,I2C_IDX ; Load I2C buffer index
mov.b I2CTxBuff(I2C_IDX),I2C_DATA
; Load I2C data
inc.w I2C_IDX ; Increment I2C buffer index
mov.w I2C_IDX,&I2CIdx ; Save I2C buffer index
pop.w I2C_IDX ; Restore register from stack
rla.b I2C_DATA ; Shift I2C data left
jnc RlsSCL ; Jmp if carry bit is not set
bis.b #SDA_PIN,&SDA_OUT ; Set SDA high
RlsSCL bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
Rx_9HL ; 1->0 edge for SCL clk 9
bis.b #SCL_PIN,&SCL_DIR ; Hold SCL low (set SCL as output)
bic.b #SDA_PIN,&SDA_DIR ; Release SDA (set SDA as input)
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
mov.w #SCL_RxTbl,SCL_TBL ; Point to I2C receive table
mov.w #0,&TACCTL2 ; Stop TA2
cmp.w #0,&I2CCBFunc ; Is a callback func registered?
jeq SkipCB ; No, skip callback function
push.w R12 ; Yes, save R12 on stack
mov.w I2C_DATA,R12 ; Copy I2C data to R12
call &I2CCBFunc ; Call callback function
pop.w R12 ; Restore R12
jmp Rx_9HL_End ; Go to label
SkipCB push.w I2C_IDX ; Save register on stack
mov.w &I2CIdx,I2C_IDX ; Load I2C buffer index
mov.b I2C_DATA,I2CRxBuff(I2C_IDX)
; Move I2C data reg to I2C buffer
inc.w I2C_IDX ; Increment I2C buffer index
and.w #I2CRXINDEXMASK,I2C_IDX ; Prevent buffer overflow
mov.w I2C_IDX,&I2CIdx ; Save I2C buffer index
pop.w I2C_IDX ; Restore register from stack
Rx_9HL_End clr.b I2C_DATA ; Clear I2C data
mov.w &TAR,&TACCR2 ; Load TAR into TACCR2
add.w #I2C_TIMEOUT,&TACCR2 ; Add I2C timeout to TACCR2
mov.w #CCIE,&TACCTL2 ; Enable TACCTL2 interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
Tx_9HL ; 1->0 edge for SCL clk 9
bis.b #SCL_PIN,&SCL_DIR ; Hold SCL low (set SCL as output)
bit.b #SDA_PIN,&SDA_IES ; SDA value saved in SDA_IES
jc NoAck ; Yes, no Ack from Master
mov.w #SCL_TxTbl,SCL_TBL ; Point to I2C transmit table
push.w I2C_IDX ; Save register on stack
mov.w &I2CIdx,I2C_IDX ; Load I2C buffer index
mov.b I2CTxBuff(I2C_IDX),I2C_DATA
; Load I2C data
inc.w I2C_IDX ; Increment I2C buffer index
and.w #I2CTXINDEXMASK,I2C_IDX ; Prevent buffer overflow
mov.w I2C_IDX,&I2CIdx ; Save I2C buffer index
pop.w I2C_IDX ; Restore register from stack
rla.b I2C_DATA ; Shift I2C data left
jc SDA_High1 ; Jmp if carry bit is set
bic.b #SDA_PIN,&SDA_OUT ; Set SDA low
jmp SDA_Out ; Go to SDA out
SDA_High1 bis.b #SDA_PIN,&SDA_OUT ; Set SDA high
SDA_Out bis.b #SDA_PIN,&SDA_DIR ; Set SDA (set SDA as output)
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
mov.w &TAR,&TACCR2 ; Load TAR into TACCR2
add.w #I2C_TIMEOUT,&TACCR2 ; Add I2C timeout to TACCR2
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
NoAck ; No ACK from Master
mov.w #SCL_NMATbl,SCL_TBL ; Point to I2C not my address table
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
NMA_9HL ; 1->0 edge for SCL clk 9
bis.b #SCL_PIN,&SCL_DIR ; Hold SCL low (set SCL as output)
bic.b #SDA_PIN,&SDA_DIR ; Release SDA (set SDA as output)
mov.w #SCL_NMATbl,SCL_TBL ; Point to Not My Address Table
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
mov.w &TAR,&TACCR2 ; Load TAR into TACCR2
add.w #I2C_TIMEOUT,&TACCR2 ; Add I2C timeout to TACCR2
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
bic.b #SCL_PIN,&SCL_DIR ; Release SCL (set SCL as input)
reti ; Return from interrupt
;
;------------------------------------------------------------------------------
port2_ISR ; Port 2 Interrupt Service Routine
; I2C SDA input triggers this ISR
;------------------------------------------------------------------------------
bit.b #SCL_PIN,&SCL_IN ; MW Sample I2C SCL in carry bit
jc Std_Entry ; MW If SCL is low, ignore SDA transition
bic.b #SDA_PIN,&SDA_IFG ; Clear SDA interrupt flag
reti ; Return from interrupt
Std_Entry
; xor.b #8h,&P1OUT ; Toggle debug pin DEBUG MW-+
bit.b #SDA_PIN,&SDA_IES ; Is SDA set for 1->0 interrupt?
jnc Stop_Cond ; No, go to stop condition
;
Start_Cond ; Start condition
mov.w #SCL_AddrTbl,SCL_TBL ; Point to I2C Address Table
mov.w &TAR,&TACCR2 ; Load TAR into TACCR2
add.w #I2C_TIMEOUT,&TACCR2 ; Add I2C timeout to TACCR2
mov.w #CCIE,&TACCTL2 ; Enable TACCTL2 interrupt
// MW FLAG clr.b &IE1 ; Disable all IE1 interrupts
// MW FLAG clr.b &IE2 ; Disable all IE2 interrupt
mov.w #0,&TACCTL0 ; Disable TA0
mov.w #0,&TACCTL1 ; Disable TA1
bic.b #SDA_PIN,&SDA_IE ; Disable SDA interrupt
// MW bis.w #CPUOFF,0(SP) ; Enter LPM0 on return
; xor.b #001h,&P3OUT ; DEBUG MW
clr.b &i2cIndex ; Clear I2C state MW
reti ; Return from interrupt
;
Stop_Cond ; Stop condition
bis.b #SDA_PIN,&SDA_IES ; Set SDA for 1->0 edge interrupt
bic.b #SDA_PIN,&SDA_IFG ; Clear SDA interrupt flag
bic.b #SCL_PIN,&SCL_IES ; Set SCL for 0->1 interrupt edge
bic.b #SCL_PIN,&SCL_IFG ; Clear SCL interrupt flag
bis.b #I2C_STOP,&I2CEvent ; Set I2C stop event flag
; xor.b #008h,&P3OUT ; DEBUG MW
reti ; Return from interrupt
;
;------------------------------------------------------------------------------
COMMON INTVEC ; Interrupt Vectors
;------------------------------------------------------------------------------
ORG PORT1_VECTOR ; Port 1 Vector
DW port1_ISR ;
;
ORG PORT2_VECTOR ; Port 2 Vector
DW port2_ISR ;
;
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -