;.......................................................................................................................
;.......................................................................................................................
;Define Global Deifnitions:
I2C_PORT equ PORTC
I2C_TRIS equ TRISC
#define SDA 2
#define SCL 3
;.......................................................................................................................
;.......................................................................................................................
START_PROGRAM
;Initialize Inputs/Outputs, and Registers on the PIC16F684.
;Initialize TRISA and TRISB registers.
bsf STATUS, RP0 ;Bank 1
movlw b'00001100'
movwf TRISC ;Assigns SDA and SCL Inputs.
movlw b'00000000'
movwf TRISA ;Assigns all TRISA as outputs.
movlw 0x03
movwf OSCCON ;Loads internal 31.25kHz clock
bcf STATUS, RP0 ;Bank 0
clrf CCP1CON
;......................................................................................................................
;.......................................................................................................................
Start_Loop
clrf TEST1
clrf TEST2
clrf TEST3
;Write to Bank 0, Word 0 (Control Byte: 10100000)
movlw 0x0A
movwf Write_Delay
Write_Delay_Loop
call Clock_Pulse_Delay
decfsz Write_Delay
goto Write_Delay_Loop
call Clock_Pulse_Delay
call Start_Command
movlw 0xA0
call Send_i2c_Byte
call ACK
movlw 0x58
call Transmit_RS_232
movlw 0x01
call Send_i2c_Byte
call ACK
movlw 0x56
call Send_i2c_Byte
call ACK
call Stop_Command
;;TEST TO WRITE TO JUST ONE REGISTER
goto Read_EEPROM
call Clock_Pulse_Delay
call Clock_Pulse_Delay
call Start_Command
movlw 0xA4
call Send_i2c_Byte
call ACK
movlw 0x55
call Send_i2c_Byte
call ACK
movlw 0x57
call Send_i2c_Byte
call ACK
call Stop_Command
call Clock_Pulse_Delay
call Clock_Pulse_Delay
call Start_Command
movlw b'10101110'
call Send_i2c_Byte
call ACK
movlw 0xff
call Send_i2c_Byte
call ACK
movlw 0x58
call Send_i2c_Byte
call ACK
call Stop_Command
;Read from Bank 0, Word 0 (Control Byte: 10100001)
Read_EEPROM
movlw 0x0A
movwf Read_Delay
Read_Delay_Loop1
call Clock_Pulse_Delay
decfsz Read_Delay
goto Read_Delay_Loop1
call Start_Command
movlw b'10100000'
call Send_i2c_Byte
call ACK
movlw b'00000001'
call Send_i2c_Byte
call ACK
call Clock_Pulse_Delay
call Start_Command
movlw b'10100001'
call Send_i2c_Byte
call ACK
call Receive_i2c_Byte
movf Received_I2C_Byte, w
movwf TEST1
call NACK
call Stop_Command
goto Send_Output
call Clock_Pulse_Delay
call Clock_Pulse_Delay
call Start_Command
movlw b'10100100'
call Send_i2c_Byte
call ACK
movlw b'01010101'
call Send_i2c_Byte
call ACK
call Clock_Pulse_Delay
call Start_Command
movlw b'10100101'
call Send_i2c_Byte
call ACK
call Receive_i2c_Byte
movf Received_I2C_Byte, w
movwf TEST2
call NACK
call Stop_Command
call Clock_Pulse_Delay
call Clock_Pulse_Delay
call Start_Command ;Start
movlw b'10101110'
call Send_i2c_Byte ;
call ACK
movlw b'11111111'
call Send_i2c_Byte
call ACK
call Clock_Pulse_Delay
call Start_Command
movlw b'10101111'
call Send_i2c_Byte
call ACK
call Receive_i2c_Byte
movf Received_I2C_Byte, w
movwf TEST1
call NACK
call Stop_Command
Send_Output
movf TEST1, w
call Transmit_RS_232
;; movf TEST2, w
; call Transmit_RS_232
; movf TEST3, w
; call Transmit_RS_232
done
goto Start_Loop
;---------------------------------------------------------------------------------------
;Sub Routines for PIC
;---------------------------------------------------------------------------------------
;i2c Routines
;----------------------------------
Start_Command
call Set_SCL_High ;Release SCL
call Set_SDA_High ;Release SDA
call Clock_Pulse_Delay ;Delay
call Set_SDA_Low ;Set SDA Low
call Clock_Pulse_Delay ;Delay
return
;----------------------------------
SAD_W
movlw 0x1E
call Send_i2c_Byte ;(SAD+W)Slave Address plus write.
return
;----------------------------------
SAD_R
movlw 0x1F
call Send_i2c_Byte ;(SAD+R)Slave Address plus read.
return
;----------------------------------
ACK
call Set_SCL_High ;Release SCL
call Set_SDA_High ;Release SDA
call Clock_Pulse_Delay ;Delay
Clock_Stretch
btfss I2C_PORT, SCL
goto Clock_Stretch ;Wait for slave to release clock line (if "stretching")
call Clock_Pulse_Delay ;Delay
bcf STATUS, C ;Initally clears the carry bit
btfsc I2C_PORT, SDA ;Checks if slave is pulling SDA low (giving its ACK)
; goto _Error ;Clear carry for NACK
bsf STATUS, C ;Set carry for ACK
btfss STATUS, C ;Check carry bit to ensure ACK
goto START_PROGRAM ;Start over if NACK
call Set_SCL_Low
return ;If ACK received, continue
;----------------------------------
SEND_ACK
call Clock_Pulse_Delay
call Set_SCL_Low
Get_ACK_SDA
btfss I2C_PORT, SDA ;Wait to see if the SDA line is released.
goto Get_ACK_SDA ;Loop
call Set_SDA_Low
; call Set_SDA_High ;Ensure SDA is released.
call Set_SCL_High ;Trigger SCL
call Clock_Pulse_Delay ;Delay
call Set_SCL_Low
; call Set_SCL_High ;Trigger Clock
call Set_SDA_High ;Release SDA
call Clock_Pulse_Delay ;Delay
; call Clock_Pulse_Delay ;Delay
; call Set_SDA_High ;Release SDA
; call Set_SCL_Low
return
NACK
call Set_SDA_High ;Release SCL
call Clock_Pulse_Delay ;Delay
call Set_SCL_High ;Set SCL Low
; call Set_SDA_High ;Release SDA
call Clock_Pulse_Delay ;Delay
call Set_SCL_Low
return
;----------------------------------
Stop_Command
call Set_SCL_High ;Release SCL
call Clock_Pulse_Delay ;Delay
call Set_SDA_High ;Release SDA
call Clock_Pulse_Delay ;Delay
call Clock_Pulse_Delay ;Delay
return
;----------------------------------
Send_i2c_Byte
movwf i2c_transmit_byte ;Moves whatever value is in the working register into i2c_transmit_byte
movlw 0x08
movwf i2c_bit_counter ;Sets 8 bits to be sent out
Send_i2c_Bit
call Set_SCL_Low ;Ensure SCL is low initially
call Clock_Pulse_Delay ;Delay
rlf i2c_transmit_byte, f ;MSB is now in carry (MSB is sent first)
btfsc STATUS, C
call Set_SDA_High
btfss STATUS, C
call Set_SDA_Low ;Sets either 0 or 1 to be sent out. (Checks carry bit)
call Clock_Pulse_Delay ;Delay
call Set_SCL_High ;Trigger Clock; set SCL high
call Clock_Pulse_Delay ;Delay
decfsz i2c_bit_counter, f ;Checks if 8 bits have been sent out
goto Send_i2c_Bit ;No
call Set_SCL_Low ;Yes; Set SCL Low
call Clock_Pulse_Delay ;Delay
return
;-------------------------------------
Receive_i2c_Byte
clrf Received_I2C_Byte ;Clears previous received byte
bsf Received_I2C_Byte, 0
; call Set_SDA_High
call Clock_Pulse_Delay
Get_i2c_Bit
call Set_SCL_Low
call Set_SDA_High ;Set SCL Low
call Clock_Pulse_Delay ;Delay
bcf STATUS, C ;Defaults to incoming bit = 0 (sets carry = 0)
call Set_SCL_High ;Release SCL
call Clock_Pulse_Delay
btfsc I2C_PORT, SDA ;Read port, skip if clear
bsf STATUS, C ;If incoming bit = 1, set carry flag to 1
rlf Received_I2C_Byte, f ;move carry into data (MSB first)
call Clock_Pulse_Delay
btfss STATUS, C
goto Get_i2c_Bit ;No
;Test to ensure hypertermianl works correctly.
; movlw 0x55
; movwf Received_I2C_Byte
; call Set_SCL_Low
call Clock_Pulse_Delay
call Clock_Pulse_Delay
call Clock_Pulse_Delay
return ;Yes, return
;Routines to Set SDA and SCL High/Low
Set_SCL_High
bsf STATUS, RP0 ;Bank 1
bsf I2C_TRIS, SCL ;Sets SCL as an input
clrf ANSEL
bcf STATUS, RP0 ;Bank 0
movlw 0x07
movwf CMCON0
return
Set_SCL_Low
bcf I2C_PORT, SCL ;Sets SCL port pin low
bsf STATUS, RP0 ;Bank 1
bcf I2C_TRIS, SCL ;Sets SCL as an output
clrf ANSEL
bcf STATUS, RP0 ;Bank 0
movlw 0x07
movwf CMCON0
return
Set_SDA_High
bsf STATUS, RP0 ;Bank 1
bsf I2C_TRIS, SDA ;Sets SDA as an input (high impedance)
clrf ANSEL
bcf STATUS, RP0 ;Bank 0
movlw 0x07
movwf CMCON0
return
Set_SDA_Low
bcf I2C_PORT, SDA ;Sets SDA port pin low
bsf STATUS, RP0 ;Bank 1
bcf I2C_TRIS, SDA ;Sets SDA as an output
clrf ANSEL
bcf STATUS, RP0 ;Bank 0
movlw 0x07
movwf CMCON0
return
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;Delays
Clock_Pulse_Delay
movlw 0x03
movwf pw_counter
Clock_Pulse_Delay_Wait
nop
movlw 0x01
movwf pw_counter1
Clock_Pulse_Delay_Wait1
decfsz pw_counter1, f
goto Clock_Pulse_Delay_Wait1
decfsz pw_counter, f
goto Clock_Pulse_Delay_Wait
return