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?????????????????????????? ; tristate SCL
?? bcf??? Txmt_Progress????????????????? ; reset progress bit in Bus Status
?? bcf??? Txmt_Success?????????????????? ; Transmission NOT successful
?? bsf??? ACK_Error????????????????????? ; No ACK From Slave
?? return
;************************************************************
GetData
?? bsf??? Rcv_Progress?????????????????? ; set Bus status for txmt progress
?? bcf??? Rcv_Success??????????????????? ; reset status bit
?? movlw? 0x08
?? movwf? I2CBitCount
RcvNextBit
?? bsf??? STATUS, RP0??????????????????? ; page 1 for TRIS manipulation
?? bcf??? _SCL?????????????????????????? ; lower clock
?? bcf??? _SDA?????????????????????????? ; lower data line
?? call?? Delay47uSec??????????????????? ; guarantee min LOW TIME tLOW & setup time
?? bsf??? _SCL?????????????????????????? ; clock high, data sent by slave
?? call?? Delay40uSec??????????????????? ; guarantee min HIGH TIME tHIGH
?? bcf??? STATUS, RP0??????????????????? ; select page 0 to read Ports
?? bcf??? STATUS, C????????????????????? ; 0 out Status
?? btfsc? SdaPin???????????????????????? ; Check state of pin
?? bsf??? STATUS, C????????????????????? ; Pin was high, set status
?? rlf??? I2CData, F???????????????????? ; left Shift data (MSB first)
?? decfsz I2CBitCount, F???????????????? ; Are we done yet
?? goto?? RcvNextBit???????????????????? ; Nope, go get the next one
;
; Generate ACK bit if not last byte to be read,
; if last byte Gennerate NACK ; do not send ACK on last byte, main routine will send a STOP bit
;
?? bsf??? STATUS, RP0??????????????????? ; Page 1 for TRIS manipulation
?? bcf??? _SCL?????????????????????????? ; pull SCL low
?? bcf??? _SDA?????????????????????????? ; ACK by pulling SDA low
?? btfsc? Last_Byte_Rcv????????????????? ; Is it the last byte to receive
?? bsf??? _SDA?????????????????????????? ; If so, send NACK by setting SDA high
?? call?? Delay47uSec??????????????????? ; guarantee min LOW TIME tLOW & Setup time
?? bsf??? _SCL?????????????????????????? ; Raise Clock back up
?? call?? Delay40uSec??????????????????? ; guarantee min HIGH TIME tHIGH
RcvEnd:
?? bcf??? _SCL?????????????????????????? ; reset clock
?? bcf??? Rcv_Progress?????????????????? ; reset bit in Bus Status
?? bsf??? Rcv_Success??????????????????? ; transmission successful
?? bcf??? ACK_Error????????????????????? ; ACK OK
?? return
Delay47uSec:
?? movlw ((_47uS_Delay-5)/3 + 1)???????? ; move delay into W
DlyK
?? movwf DelayCount????????????????????? ; move what is in W to DelayCount
?? decfsz?? DelayCount, F??????????????? ; Decrement DelayCount
?? goto? $-1???????????????????????????? ; Loop until 0
?? return??????????????????????????????? ; return
Delay40uSec:
?? movlw ((_40uS_Delay-8)/3 + 1)???????? ; move delay into W
?? goto? DlyK??????????????????????????? ; goto DlyK loop
?
評論
查看更多