Hi All;
I'm stuck with receiving an ACK during i2c communication. I am using a PIC16F688 as the master and a Kionix KFTJ9 accelerometer as the slave. This PIC does not have i2c hardware built in, so I am doing it in software. The SCL and SDA lines are pulled high with a 2.1kohm resistor and I am using the PICs internal 31.25kHz clock.
Below is the code, Thank you all in advance.
S
;Define Constant Working Register Variables
cblock 0x20
i2c_transmit_byte
i2c_bit_counter
pw_counter
wait_startup_counter
ACK_counter
i2c_flags
Received_I2C_Byte
transmit_byte_rs232
bit_counter_rs232
delay_counter
endc
;.......................................................................................................................
;.......................................................................................................................
;Define Global Deifnitions:
I2C_PORT equ PORTC
I2C_TRIS equ TRISC
#define SDA 0
#define SCL 1
;.......................................................................................................................
;.......................................................................................................................
START_PROGRAM
;Initialize Inputs/Outputs, and Registers on the PIC16F684.
;Initialize TRISA and TRISB registers.
bsf STATUS, RP0 ;Sets bit RP0 in address STATUS to 1 (switches from bank 0 to 1).
movlw b'00000000'
movwf TRISC ;Assigns all TRISC as outputs.
movlw b'00000000'
movwf TRISA ;Assigns all TRISA as outputs. Note - RA2 must be bi-directional. Default is output.
movlw 0x03
movwf OSCCON ;Loads internal 31.25kHz clock
clrf ANSEL ;Clears default analog inputs and allows for digital I/O on analog pins
bcf STATUS, RP0 ;Moves back to bank 0 for execution
movlw b'00000111'
movwf CMCON0 ;Turns analog comparators off and allows for digital I/O on all pins
;......................................................................................................................
;.......................................................................................................................
;READ Register from accelerometer -- WHO_AM_I
call Wait_Startup ;Startup delay
call Start_Command
call SAD_W
call ACK
bsf PORTC, 4
done
goto done
end
;---------------------------------------------------------------------------------------
;i2c routines
Start_Command
call Clock_Pulse_Delay
call Set_SCL_Low
call Set_SDA_High
call Set_SCL_High
call Set_SDA_Low
call Clock_Pulse_Delay ;(S) - Sets SDA low while SCL is high
return
;----------------------------------
SAD_W
movlw 0x1C
; movlw 0x38
call Send_i2c_Byte ; Slave Address plus write.
call Clock_Pulse_Delay
return
;----------------------------------
SAD_R
movlw 0x1D
call Send_i2c_Byte
call Clock_Pulse_Delay
return
;----------------------------------
ACK
call Set_SDA_High
call Set_SCL_High
Get_ACK
bsf PORTC, 4
btfsc I2C_PORT, SDA
goto Get_ACK
bcf PORTC, 4
call Set_SCL_Low
return
;-----------------------------------
Set_SCL_High
bsf STATUS, RP0 ;Bank 1
bsf I2C_TRIS, SCL ;Sets SCL as an input
bcf STATUS, RP0 ;Bank 0
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
bcf STATUS, RP0 ;Bank 0
return
Set_SDA_High
bsf STATUS, RP0 ;Bank 1
bsf I2C_TRIS, SDA ;Sets SDA as an input (high impedance)
bcf STATUS, RP0 ;Bank 0
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
bcf STATUS, RP0 ;Bank 0
return
Send_i2c_Byte
movwf i2c_transmit_byte
movlw 0x08
movwf i2c_bit_counter
Send_i2c_Bit
call Clock_Pulse_Delay
call Set_SCL_Low
rrf i2c_transmit_byte, f
btfsc STATUS, C
call Set_SDA_High
btfss STATUS, C
call Clock_Pulse_Delay
call Set_SDA_Low
call Clock_Pulse_Delay
call Set_SCL_High
decfsz i2c_bit_counter, f
goto Send_i2c_Bit
return
end
I'm stuck with receiving an ACK during i2c communication. I am using a PIC16F688 as the master and a Kionix KFTJ9 accelerometer as the slave. This PIC does not have i2c hardware built in, so I am doing it in software. The SCL and SDA lines are pulled high with a 2.1kohm resistor and I am using the PICs internal 31.25kHz clock.
Below is the code, Thank you all in advance.
S
;Define Constant Working Register Variables
cblock 0x20
i2c_transmit_byte
i2c_bit_counter
pw_counter
wait_startup_counter
ACK_counter
i2c_flags
Received_I2C_Byte
transmit_byte_rs232
bit_counter_rs232
delay_counter
endc
;.......................................................................................................................
;.......................................................................................................................
;Define Global Deifnitions:
I2C_PORT equ PORTC
I2C_TRIS equ TRISC
#define SDA 0
#define SCL 1
;.......................................................................................................................
;.......................................................................................................................
START_PROGRAM
;Initialize Inputs/Outputs, and Registers on the PIC16F684.
;Initialize TRISA and TRISB registers.
bsf STATUS, RP0 ;Sets bit RP0 in address STATUS to 1 (switches from bank 0 to 1).
movlw b'00000000'
movwf TRISC ;Assigns all TRISC as outputs.
movlw b'00000000'
movwf TRISA ;Assigns all TRISA as outputs. Note - RA2 must be bi-directional. Default is output.
movlw 0x03
movwf OSCCON ;Loads internal 31.25kHz clock
clrf ANSEL ;Clears default analog inputs and allows for digital I/O on analog pins
bcf STATUS, RP0 ;Moves back to bank 0 for execution
movlw b'00000111'
movwf CMCON0 ;Turns analog comparators off and allows for digital I/O on all pins
;......................................................................................................................
;.......................................................................................................................
;READ Register from accelerometer -- WHO_AM_I
call Wait_Startup ;Startup delay
call Start_Command
call SAD_W
call ACK
bsf PORTC, 4
done
goto done
end
;---------------------------------------------------------------------------------------
;i2c routines
Start_Command
call Clock_Pulse_Delay
call Set_SCL_Low
call Set_SDA_High
call Set_SCL_High
call Set_SDA_Low
call Clock_Pulse_Delay ;(S) - Sets SDA low while SCL is high
return
;----------------------------------
SAD_W
movlw 0x1C
; movlw 0x38
call Send_i2c_Byte ; Slave Address plus write.
call Clock_Pulse_Delay
return
;----------------------------------
SAD_R
movlw 0x1D
call Send_i2c_Byte
call Clock_Pulse_Delay
return
;----------------------------------
ACK
call Set_SDA_High
call Set_SCL_High
Get_ACK
bsf PORTC, 4
btfsc I2C_PORT, SDA
goto Get_ACK
bcf PORTC, 4
call Set_SCL_Low
return
;-----------------------------------
Set_SCL_High
bsf STATUS, RP0 ;Bank 1
bsf I2C_TRIS, SCL ;Sets SCL as an input
bcf STATUS, RP0 ;Bank 0
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
bcf STATUS, RP0 ;Bank 0
return
Set_SDA_High
bsf STATUS, RP0 ;Bank 1
bsf I2C_TRIS, SDA ;Sets SDA as an input (high impedance)
bcf STATUS, RP0 ;Bank 0
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
bcf STATUS, RP0 ;Bank 0
return
Send_i2c_Byte
movwf i2c_transmit_byte
movlw 0x08
movwf i2c_bit_counter
Send_i2c_Bit
call Clock_Pulse_Delay
call Set_SCL_Low
rrf i2c_transmit_byte, f
btfsc STATUS, C
call Set_SDA_High
btfss STATUS, C
call Clock_Pulse_Delay
call Set_SDA_Low
call Clock_Pulse_Delay
call Set_SCL_High
decfsz i2c_bit_counter, f
goto Send_i2c_Bit
return
end