pic單片機的模擬I2C通信
發布時間:2008/8/16 0:00:00 訪問次數:945
; copyright (c) 1997 by innovatus
; this code may be distributed and used freely provided that this
; copyright notice stays intact and that any modifications are noted.
; for more information about innovatus:
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; file name: i2c_low.asm
; author: alan g. smith
; purpose: this code is borrowed from microchip with all of the fancy
; stuff taken out.
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
initi2cbusmaster
;************************************************************
txmtstartbit
bsf bus_busy ; on a start condition bus is busy
bsf status, rp0 ; select page 1
bsf _sda ; set sda high
bsf _scl ; clock is high
call delay40usec ; this is necessary for setup time
bcf _sda ; this gives a falling edge on sda while clock is high
call delay47usec ; necessary for start hold time
return
;************************************************************
txmtstopbit
bsf status, rp0 ; select page 1
bcf _scl ; clock is low
bcf _sda ; set sda low
bsf _scl ; clock is pulled up
call delay40usec ; setup time for stop condition
bsf _sda ; rising edge on sda while clock is high
call delay47usec ; makes sure a start isn‘t sent immediately after a stop
bcf bus_busy ; the bus isn‘t busy anymore
return
;************************************************************
aborti2c
call txmtstopbit ; send a stop bit
bsf abort ; set the abort bit
return
;************************************************************
txmtslaveaddr
movf slaveaddr, w ; move slave address to w
bcf ack_error ; reset acknowledge error bit
movwf i2cdata ; move w to i2c data
bcf i2cdata, lsb ; set for write
btfsc slave_rw ; if skip then write operation
bsf i2cdata, lsb ; clear for read
call senddata ; send the address
btfss txmt_success ; skip if successful
goto addrsendfail ; oops, we failed
retlw true ; return true
addrsendfail
btfss ack_error ; was there an error acknowledging
retlw false ; no, so return 0
call txmtstopbit ; address not acknowleged, so send stop bit
retlw false ; unsuccessful, so return 0
;************************************************************
senddata
; we might should make a copy of the data here, the example does but i don‘t see why!!!
bsf txmt_progress ; we are in the middle of transmitting
bcf txmt_success ; reset success bit
movlw 0x08
movwf i2cbitcount ; set i2c bit count to 8
bsf status, rp0 ; select page 1
txmtnextbit:
bcf _scl ; set clock low
rlf i2cdata, f ; msb first, note that i2cdata is destroyed
bcf _sda ; set clock based on what the msb is
btfsc status,c ; was the msb a 1
bsf _sda ; nope set it high
call delay47usec ; guarantee min low time tlow & setup time
bsf _scl ; set clock high
call delay40usec ; guarantee min high time thigh
decfsz i2cbitcount, f ; are we done yet
goto txmtnextbit ; nope, send the next bit
;
; check for acknowledge
;
bcf _scl ; reset clock
bsf _sda ; release sda line for slave to pull down
call delay47usec ; guarantee min low time tlow & setup time
bsf _scl ; clock for slave to ack
call delay40usec ; guarantee min high time thigh
bcf status, rp0 ; select page 0 to test sda pin
btfsc sdapin ; sda should be pulled low by slave if ok
goto txmterrorack ; uh oh, slave isn‘t behaving (or isn‘t there)
bsf status, rp0 ; select page 1
bcf _scl ; reset clock
bcf txmt_progress ; reset progress bit in bus status
bsf txmt_success ; transmission successful
bcf ack_error ; ack ok
return
txmterrorack
bsf status,rp0 ; select page 1
bsf _sda ; tristate sda
bsf _scl ; t
; copyright (c) 1997 by innovatus
; this code may be distributed and used freely provided that this
; copyright notice stays intact and that any modifications are noted.
; for more information about innovatus:
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; file name: i2c_low.asm
; author: alan g. smith
; purpose: this code is borrowed from microchip with all of the fancy
; stuff taken out.
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
initi2cbusmaster
;************************************************************
txmtstartbit
bsf bus_busy ; on a start condition bus is busy
bsf status, rp0 ; select page 1
bsf _sda ; set sda high
bsf _scl ; clock is high
call delay40usec ; this is necessary for setup time
bcf _sda ; this gives a falling edge on sda while clock is high
call delay47usec ; necessary for start hold time
return
;************************************************************
txmtstopbit
bsf status, rp0 ; select page 1
bcf _scl ; clock is low
bcf _sda ; set sda low
bsf _scl ; clock is pulled up
call delay40usec ; setup time for stop condition
bsf _sda ; rising edge on sda while clock is high
call delay47usec ; makes sure a start isn‘t sent immediately after a stop
bcf bus_busy ; the bus isn‘t busy anymore
return
;************************************************************
aborti2c
call txmtstopbit ; send a stop bit
bsf abort ; set the abort bit
return
;************************************************************
txmtslaveaddr
movf slaveaddr, w ; move slave address to w
bcf ack_error ; reset acknowledge error bit
movwf i2cdata ; move w to i2c data
bcf i2cdata, lsb ; set for write
btfsc slave_rw ; if skip then write operation
bsf i2cdata, lsb ; clear for read
call senddata ; send the address
btfss txmt_success ; skip if successful
goto addrsendfail ; oops, we failed
retlw true ; return true
addrsendfail
btfss ack_error ; was there an error acknowledging
retlw false ; no, so return 0
call txmtstopbit ; address not acknowleged, so send stop bit
retlw false ; unsuccessful, so return 0
;************************************************************
senddata
; we might should make a copy of the data here, the example does but i don‘t see why!!!
bsf txmt_progress ; we are in the middle of transmitting
bcf txmt_success ; reset success bit
movlw 0x08
movwf i2cbitcount ; set i2c bit count to 8
bsf status, rp0 ; select page 1
txmtnextbit:
bcf _scl ; set clock low
rlf i2cdata, f ; msb first, note that i2cdata is destroyed
bcf _sda ; set clock based on what the msb is
btfsc status,c ; was the msb a 1
bsf _sda ; nope set it high
call delay47usec ; guarantee min low time tlow & setup time
bsf _scl ; set clock high
call delay40usec ; guarantee min high time thigh
decfsz i2cbitcount, f ; are we done yet
goto txmtnextbit ; nope, send the next bit
;
; check for acknowledge
;
bcf _scl ; reset clock
bsf _sda ; release sda line for slave to pull down
call delay47usec ; guarantee min low time tlow & setup time
bsf _scl ; clock for slave to ack
call delay40usec ; guarantee min high time thigh
bcf status, rp0 ; select page 0 to test sda pin
btfsc sdapin ; sda should be pulled low by slave if ok
goto txmterrorack ; uh oh, slave isn‘t behaving (or isn‘t there)
bsf status, rp0 ; select page 1
bcf _scl ; reset clock
bcf txmt_progress ; reset progress bit in bus status
bsf txmt_success ; transmission successful
bcf ack_error ; ack ok
return
txmterrorack
bsf status,rp0 ; select page 1
bsf _sda ; tristate sda
bsf _scl ; t