PIC 16f15323 I2C not acknowledging address

Thread Starter

geekoftheweek

Joined Oct 6, 2013
1,215
I have a small template program below I use to more or less use to get to know the various PICs I've worked with. It has worked every time so far after the proper bank modifications and a couple SFR names now and again. This time the led flashes as it should, but after several days of staring at it over and over either I'm missing something or it just won't work in slave mode.

One problem I had is I usually use gputils to compile the programs, but it does not support the 16f15323 so I took my first round with mpasm. I know there shouldn't be any difference more or less, but maybe I missed something there.

At any rate... any ideas?

main.asm
Code:
#include "inc/global-defines.inc"
#include "inc/memory-map.inc"
#include "inc/i2c-slave.inc"

; ---------------------------------------------------------------------------------------------------------------------------------------	

    __config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON 
    __config _CONFIG2, _MCLRE_OFF & _PWRTE_ON & _LPBOREN_OFF & _BOREN_OFF & _ZCD_OFF
    __config _CONFIG3, _WDTE_OFF
    __config _CONFIG4, _LVP_OFF
    
; ---------------------------------------------------------------------------------------------------------------------------------------	

    code
    
; ---------------------------------------------------------------------------------------------------------------------------------------
	org 0
	
	
__start
; set all ADC pins to digital
    movlb d'62'
    clrf ANSELA
    clrf ANSELC    
    
; set up timer 0 for status led
    movlb d'11'
    clrf TMR0H
    clrf TMR0L
    movlf b'01000001', T0CON1
    movlf b'00011111', T0CON0
    bsf T0CON0, T0EN
    movlb d'14'
    bcf PIR0, TMR0IF
    
; set all latches to 0
    movlb 0
    clrf LATA
    clrf LATC
    bcf STATUS_LED_TRIS
    
; set up status led
    movlb 2
    movlf 1, STATUS_LED_COUNT
    movlf 1, STATUS_LED_CODE
 
    call __i2c_slave_init
    
    
; ---------------------------------------------------------------------------------------------------------------------------------------

__main__loop
    movlb d'14'
	btfsc PIR0, TMR0IF
	call _timer0
	
	call __i2c_slave_poll
	
	goto __main__loop
	
	
	
; ---------------------------------------------------------------------------------------------------------------------------------------	

_timer0
    bcf PIR0, TMR0IF
    
    movlb 0
    btfsc STATUS_LED_TRIS
    bra _timer0_led_off
    
    bsf STATUS_LED_TRIS
    
    movlb 2
    decfsz STATUS_LED_COUNT, f
    bra _timer0_done

    movlf 0x88, STATUS_LED_COUNT
    bra _timer0_done
    
_timer0_done    
    movlb 0
    return
    
_timer0_led_off
    movlb 2
    btfss STATUS_LED_COUNT, 7
    bra _timer0_led_off_not_holding
    
    bcf STATUS_LED_COUNT, 7
    decfsz STATUS_LED_COUNT, f
    bra _timer0_led_off_still_counting
    
    movfwf STATUS_LED_CODE, STATUS_LED_COUNT
    movlb 0
    bcf STATUS_LED_TRIS
    return
    
_timer0_led_off_not_holding    
    movlb 0
    bcf STATUS_LED_TRIS
    return

_timer0_led_off_still_counting
    bsf STATUS_LED_COUNT, 7
    movlb 0
    return
    
; ---------------------------------------------------------------------------------------------------------------------------------------	

    end

; ---------------------------------------------------------------------------------------------------------------------------------------
i2c.asm
Code:
#include "inc/global-defines.inc"

#include "inc/memory-map.inc"

#define __I2C_SLAVE_ASM__
#include "inc/i2c-slave.inc"

; ---------------------------------------------------------------------------------------------------------------------------------------	


; ---------------------------------------------------------------------------------------------------------------------------------------	

    code
    
; ---------------------------------------------------------------------------------------------------------------------------------------
	
__i2c_slave_init
    movlb 3
    movlf I2C_SLAVE_ADDRESS, SSP1ADD
    movlf b'00000110', SSP1CON1
    bsf SSP1STAT, SMP
    bsf SSP1CON2, SEN
    bsf SSP1CON1, SSPEN
    
    clrf i2c_flags  
    
    movlb d'14'
    bcf PIR3, SSP1IF
    movlb 0
    return
	
; ---------------------------------------------------------------------------------------------------------------------------------------	

__i2c_slave_poll
    movlb d'14'
    btfss PIR3, SSP1IF
    return
    
    bcf PIR3, SSP1IF
    
    movlb 3
    
; find out if address or data
    btfsc SSP1STAT, 5
    bra _i2c__data
   
; address sent
    movf SSP1BUF, w
    movwf i2c_address
    
    bcf i2c_flags, I2C_PTR_H_SET
    bcf i2c_flags, I2C_PTR_L_SET
    
; find out if reading and if is reading send first byte back
    btfsc SSP1STAT, 2
    bra _i2c__master_reading
    
    bsf SSP1CON1, CKP
    movlb 0
    return
    
_i2c__data    
    btfsc SSP1STAT, 2
    bra _i2c__master_reading

    movf SSP1BUF, w
    movwf temp_var
    
    bsf SSP1CON1, CKP

    
; find out if ptr already set
    btfsc i2c_flags, I2C_PTR_H_SET
    bra _i2c__master_write_ptr_h_set
    
; ptr h is not set... set it now
    movwf i2c_ptr_h
    bsf i2c_flags, I2C_PTR_H_SET
    movlb 0
    return
    
_i2c__master_write_ptr_h_set
    btfsc i2c_flags, I2C_PTR_L_SET
    bra _i2c__master_write_ptr_l_set
    
; ptr l is not set... set it now
    movwf i2c_ptr_l
    bsf i2c_flags, I2C_PTR_L_SET
    movlb 0
    return


_i2c__master_write_ptr_l_set
    
; check for invalid addresses here....

    movf i2c_ptr_h, w
    movwf FSR0H
    movf i2c_ptr_l, w
    movwf FSR0L
    
    movf temp_var, w
    movwf INDF0
    
    incf i2c_ptr_l, f
    btfsc STATUS, C
    incf i2c_ptr_h, f
    movlb 0
    return
   
    
; ---------------------------------------------------------------------------------------------------------------------------------------	    
    
_i2c__master_reading
    btfsc SSP1CON2, ACKSTAT
    bra _i2c__master_reading_done
    
    movf i2c_ptr_h, w
    movwf FSR0H
    movf i2c_ptr_l, w
    movwf FSR0L
    
    movf INDF0, w
    movwf SSP1BUF
    
    
    incf i2c_ptr_l, f
    btfsc STATUS, C
    incf i2c_ptr_h, f
    
_i2c__master_reading_done    
    bsf SSP1CON1, CKP
    movlb 0
    return
    
; ---------------------------------------------------------------------------------------------------------------------------------------	

    end

; ---------------------------------------------------------------------------------------------------------------------------------------
global-defines.inc
Code:
    list p=16f15323
	radix dec

    include <p16f15323.inc>

#define STATUS_LED_LATCH LATA, 5
#define STATUS_LED_TRIS TRISA, 5

movlf macro l, f
    movlw l
    movwf f
    endm
    
movfwf macro f1, f2
    movf f1, w
    movwf f2
    endm
    
#define AF_I2C_BUFFER_SET 7
i2c-slave.inc
Code:
    ifndef __I2C_SLAVE_INC__
    
#define __I2C_SLAVE_INC__

#define I2C_SLAVE_ADDRESS 0x40

#define I2C_PTR_H_SET 7
#define I2C_PTR_L_SET 6


        ifndef __I2C_SLAVE_ASM__
            extern __i2c_slave_init
            extern __i2c_slave_poll

        else 
            global __i2c_slave_init
            global __i2c_slave_poll

        endif
    endif
memory-map.inc
Code:
; common
#define temp_var                0x70

#define i2c_address             0x7c
#define i2c_ptr_h               0x7d
#define i2c_ptr_l               0x7e
#define i2c_flags               0x7f


; bank 1
#define i2c_buffer              0xa0 ; 64 bytes


; bank 2

#define STATUS_LED_COUNT        0x120
#define STATUS_LED_CODE         0x121
Makefile
Code:
OBJ=obj/main.o obj/i2c-slave.o
BIN=bin.hex

MPASM=/opt/microchip/xc8/v2.10/mpasmx/mpasmx
MPLINK=/opt/microchip/xc8/v2.10/mpasmx/mplink

.PHONY:make-all clean

make-all: $(BIN)

$(BIN): $(OBJ) 
	$(MPLINK) -p16f15323 -o $(BIN) $(OBJ) 
	
$(OBJ): obj/%.o: asm/%.asm
	$(MPASM) -o$@ $< 
	

clean: 
	rm -fv obj/* $(BIN) *.cod *.lst
 

Thread Starter

geekoftheweek

Joined Oct 6, 2013
1,215
I decided to give this project another try and it works. Even though the datasheet shows default settings for the I2C pins, the pins actually have to be set up. After adding...
Code:
movlb d'62'
movlf 0x15, RC0PPS ; scl
movlf 0x16, RC1PPS ; sda
   
movlb d'61'
movlf 0x11, SSP1DATPPS
movlf 0x10, SSP1CLKPPS
it now works!!
Thinking maybe a found an answer to other problems with a couple other newer PICs I've tried tinkering with...
 
Top