Blame | Last modification | View Log | RSS feed
list p=16F84A
include "p16F84a.inc"
;***** CONFIGURATION
__CONFIG _PWRTE_ON & _HS_OSC & _WDT_OFF
; pin assignments
#define SDA 0 ; Pin 0
#define SCL 1 ; Pin 1
#define TRIS_SDA TRISB,SDA
#define TRIS_SCL TRISB,SCL
#define I2C_SDA PORTB,SDA
#define I2C_SCL PORTB,SCL
#define LED PORTB,2
#define I2C_SLAVE1 0x27
CBLOCK 0CH
counter
_I
byte_send
i2c_addr
i2c_ret ; I2C Return Value
dly_loop1 ; Loops for delays
dly_loop2
ENDC
ORG 0
goto start ; jump over to main routine
;***** Initialisation
start
; configure ports
clrw ; configure PORTB and PORTC as all outputs
tris PORTB
clrf PORTB
movlw b'00000000' ; Init our counter
movwf counter
;***** Main loop
main_loop
bsf LED
call SendCount
bcf LED
goto main_loop
SendCount
movlw I2C_SLAVE1 ; 7-bit address of dev
bcf STATUS,C ; Use Write mode ('0')
call I2C_Start ; Start a transmission
call ReadAck ; Wait for Ack from slave
movf i2c_ret ; Check return value
btfss STATUS,Z ; Goto SendEnd on NACK
goto SendErr
movfw counter ; Copy byte to write (counter) to w
call I2C_Write ; Write the byte to the line
call ReadAck ; Should read byte from bus here
; checking that its a Nack
call I2C_End ; End the packet
bcf LED
incf counter,f
call Delay_Short
return
SendErr
call I2C_End
;call Delay_Long ; Wait a while before resend
return
I2C_Start
movwf i2c_addr ; Save the address in W
rlf i2c_addr,f ; Attach '0' to 8th bit
call Start ; Start the Trans
movfw i2c_addr
call I2C_Write ; Write byte to port
return
I2C_End
call Stop
return
I2C_Write
movwf byte_send
movlw .8 ; 8 bits to send
movwf _I
_WriteBit
rlf byte_send,f ; Move highest bit to C
btfss STATUS,C ; If 'C' is clear
call SDA_Low ; -> Set data low
btfsc STATUS,C ; If 'C' is set
call SDA_High ; -> Set data high
call SCL_Pulse
decfsz _I,f ; Decrement counter, if not clear
goto _WriteBit ; -> Send next bit
call SDA_Low ; Set low to allow slave to write
return
Nack ; Clock a high SDA
call SDA_High
call SCL_Pulse
return
Ack ; Clock a high SDA
call SDA_Low
call SCL_Pulse
return
ReadAck
call SCL_High
clrf i2c_ret
btfsc I2C_SDA
bsf i2c_ret,0
call SCL_Low
return
Start
call SDA_High
call SCL_High
call SDA_Low
call SCL_Low
return
Stop ; Bring SDA high while Clock high
call SCL_Low
call SDA_Low
call SCL_High
call SDA_High
return
SCL_Pulse
call SCL_High
call SCL_Low
return
SDA_High
bsf STATUS,RP0 ; Bank 1
bsf TRIS_SDA ; Make SDA pin input
bcf STATUS,RP0 ; Back to bank 0
call Delay_Short
return
SDA_Low
bcf I2C_SDA
bsf STATUS,RP0
bcf TRIS_SDA ; Make SDA pin output
bcf STATUS,RP0
call Delay_Short
return
SCL_High
bsf STATUS,RP0 ; Bank 1
bsf TRIS_SCL ; Make SDA pin input
bcf STATUS,RP0 ; Back to bank 0
call Delay_Short
return
SCL_Low
bcf I2C_SCL
bsf STATUS,RP0
bcf TRIS_SCL ; Make SDA pin output
bcf STATUS,RP0
call Delay_Short
return
Delay_Short ; 25us delay
movlw .5
movwf dly_loop2
Delay_Short_1
nop
decfsz dly_loop2,f
goto Delay_Short_1
return
Delay_Long
movlw .250 ; 250ms delay
movwf dly_loop1
Outer
movlw .110 ; Close to 1ms when set to .110
movwf dly_loop2
Inner
nop
nop
nop
nop
nop
nop
decfsz dly_loop2,f
goto Inner
decfsz dly_loop1,f
goto Outer
return
END