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
i2c.asm
global-defines.inc
i2c-slave.inc
memory-map.inc
Makefile
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
; ---------------------------------------------------------------------------------------------------------------------------------------
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
; ---------------------------------------------------------------------------------------------------------------------------------------
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
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
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
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