Hi All, I am working with a PIC16F684 which does not have i2c hardware, so I am doing it all in the software. I am stuck with receiving an ACK pulse from the slave (Kionix KXTJ9). Its slave address is 0x1C. My code below shows a start command (S), and slave address plus write (SAD + W). I then set RC3 high if the PIC receives an ACK from the KXTJ9 (just as a test, and in infinite loop to terminate the program for this troubleshoot.
I should be able to see the data line get pulled low by the slave. However I do not. Here are my i2c lines (as in code):
SCL = RC4
SDA = RA2
Thanks all!
;.......................................................................................................................
;.......................................................................................................................
;Call proper header, include and source files to initialize PIC
LIST p=16F684 ; Tells Assembler what PIC is used
#INCLUDE <p16f684.inc> ; Includes factory defaults for the PIC
;.......................................................................................................................
;Configure PIC optional properties
__CONFIG _INTRC_OSC_CLKOUT & _WDT_OFF & _MCLRE_OFF ; Enables CLKOUT, WDT, and Digital I/O on MCLR/RA3
;.......................................................................................................................
;errorlevel -302, -207, -305
;.......................................................................................................................
;.......................................................................................................................
;Define Constant Working Register Variables
cblock 0x20
i2c_transmit_byte
i2c_bit_counter
pw_counter
wait_startup_counter
endc
;.......................................................................................................................
;.......................................................................................................................
;Define Global Deifnitions:
;#define _p825Volt 0x4e
;.......................................................................................................................
;.......................................................................................................................
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
bsf PORTA, 2 ;Set DATA high
bsf PORTC, 4 ;Set CLK high
call Wait_Startup ;Startup delay
call Start_Command
call SAD_W
call ACK
bsf PORTC, 3 ;TEST -- If program recieves ACK, set RC3 and loop forever
done
goto done
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;Sub Routines for PIC
Send_i2c_Byte
movwf i2c_transmit_byte
call Set_RA2_Output
movlw 0x08
movwf i2c_bit_counter
Send_i2c_Bit
bcf PORTC, 4 ;Sets Clock high to say a data bit is not present yet.
rrf i2c_transmit_byte, f
btfsc STATUS, C
bsf PORTA, 2
btfss STATUS, C
bcf PORTA, 2
call Clock_Pulse_Delay
bcf PORTC, 4
call Clock_Pulse_Delay
bsf PORTC, 4 ;Sets CLock High to allow for another low transition to say a new data bit is present.
call Clock_Pulse_Delay
decfsz i2c_bit_counter, f
goto Send_i2c_Bit
return
Set_RA2_Input
bsf STATUS, RP0
movlw b'00000100'
movwf TRISA
bcf STATUS, RP0 ;Sets RA2 as input to check for the line being low.
return
Set_RA2_Output
bsf STATUS, RP0
movlw b'00000000'
movwf TRISA
bcf STATUS, RP0 ;Sets RA2 as output for sending data.
return
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;Delays
Clock_Pulse_Delay
movlw 0x0F
movwf pw_counter
Clock_Pulse_Delay_Wait
nop
decfsz pw_counter, f
goto Clock_Pulse_Delay_Wait
return
Wait_Startup
movlw 0xFF
movwf wait_startup_counter
Wait_Startup_Count
nop
decfsz wait_startup_counter, f
goto Wait_Startup_Count
return
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;i2c routines
Start_Command
call Clock_Pulse_Delay
call Set_RA2_Output
bsf PORTA, 2 ;Sets DATA high.
bsf PORTC, 4 ;Turns on CLK
call Clock_Pulse_Delay
bcf PORTA, 2 ;Toggles DATA from high to low indicating a start command (S).
call Clock_Pulse_Delay
return
;----------------------------------
SAD_W
call Set_RA2_Output
; movlw 0x1C
movlw 0x38
call Send_i2c_Byte ; Slave Address plus write.
call Clock_Pulse_Delay
return
;----------------------------------
ACK
bcf PORTC, 4 ;Set CLK low
call Clock_Pulse_Delay
bsf PORTA, 2 ;Sets DATA high
call Clock_Pulse_Delay ;Delay
bsf PORTC, 4 ;Release Clock
call Set_RA2_Input ;Sets DATA as input
Get_ACK
btfsc PORTA, 2
goto Get_ACK
bsf PORTC, 4 ;Set CLK high
call Set_RA2_Output
return
;-----------------------------------
end
I should be able to see the data line get pulled low by the slave. However I do not. Here are my i2c lines (as in code):
SCL = RC4
SDA = RA2
Thanks all!
;.......................................................................................................................
;.......................................................................................................................
;Call proper header, include and source files to initialize PIC
LIST p=16F684 ; Tells Assembler what PIC is used
#INCLUDE <p16f684.inc> ; Includes factory defaults for the PIC
;.......................................................................................................................
;Configure PIC optional properties
__CONFIG _INTRC_OSC_CLKOUT & _WDT_OFF & _MCLRE_OFF ; Enables CLKOUT, WDT, and Digital I/O on MCLR/RA3
;.......................................................................................................................
;errorlevel -302, -207, -305
;.......................................................................................................................
;.......................................................................................................................
;Define Constant Working Register Variables
cblock 0x20
i2c_transmit_byte
i2c_bit_counter
pw_counter
wait_startup_counter
endc
;.......................................................................................................................
;.......................................................................................................................
;Define Global Deifnitions:
;#define _p825Volt 0x4e
;.......................................................................................................................
;.......................................................................................................................
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
bsf PORTA, 2 ;Set DATA high
bsf PORTC, 4 ;Set CLK high
call Wait_Startup ;Startup delay
call Start_Command
call SAD_W
call ACK
bsf PORTC, 3 ;TEST -- If program recieves ACK, set RC3 and loop forever
done
goto done
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;Sub Routines for PIC
Send_i2c_Byte
movwf i2c_transmit_byte
call Set_RA2_Output
movlw 0x08
movwf i2c_bit_counter
Send_i2c_Bit
bcf PORTC, 4 ;Sets Clock high to say a data bit is not present yet.
rrf i2c_transmit_byte, f
btfsc STATUS, C
bsf PORTA, 2
btfss STATUS, C
bcf PORTA, 2
call Clock_Pulse_Delay
bcf PORTC, 4
call Clock_Pulse_Delay
bsf PORTC, 4 ;Sets CLock High to allow for another low transition to say a new data bit is present.
call Clock_Pulse_Delay
decfsz i2c_bit_counter, f
goto Send_i2c_Bit
return
Set_RA2_Input
bsf STATUS, RP0
movlw b'00000100'
movwf TRISA
bcf STATUS, RP0 ;Sets RA2 as input to check for the line being low.
return
Set_RA2_Output
bsf STATUS, RP0
movlw b'00000000'
movwf TRISA
bcf STATUS, RP0 ;Sets RA2 as output for sending data.
return
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;Delays
Clock_Pulse_Delay
movlw 0x0F
movwf pw_counter
Clock_Pulse_Delay_Wait
nop
decfsz pw_counter, f
goto Clock_Pulse_Delay_Wait
return
Wait_Startup
movlw 0xFF
movwf wait_startup_counter
Wait_Startup_Count
nop
decfsz wait_startup_counter, f
goto Wait_Startup_Count
return
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;i2c routines
Start_Command
call Clock_Pulse_Delay
call Set_RA2_Output
bsf PORTA, 2 ;Sets DATA high.
bsf PORTC, 4 ;Turns on CLK
call Clock_Pulse_Delay
bcf PORTA, 2 ;Toggles DATA from high to low indicating a start command (S).
call Clock_Pulse_Delay
return
;----------------------------------
SAD_W
call Set_RA2_Output
; movlw 0x1C
movlw 0x38
call Send_i2c_Byte ; Slave Address plus write.
call Clock_Pulse_Delay
return
;----------------------------------
ACK
bcf PORTC, 4 ;Set CLK low
call Clock_Pulse_Delay
bsf PORTA, 2 ;Sets DATA high
call Clock_Pulse_Delay ;Delay
bsf PORTC, 4 ;Release Clock
call Set_RA2_Input ;Sets DATA as input
Get_ACK
btfsc PORTA, 2
goto Get_ACK
bsf PORTC, 4 ;Set CLK high
call Set_RA2_Output
return
;-----------------------------------
end