LIST p=16F876 ;tell assembler what chip we are using
include "P16F876.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x393A ;sets the configuration settings (oscillator type etc.)
cblock 0x20 ;start of general purpose registers
OUT1 ;first byte to send out on spi
OUT2 ;second byte to send out on spi
TMP1 ;temp storage for spi
CNT ;Count for byte for spi
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
p_temp ;save register
s_temp ;save register
w_temp ;save register
;registers for display
row_pos ;position on row
zero1 ;zero storage
one1 ;one storage
two1 ;two storage
three1 ;three storage
four1 ;four storage
five1 ;five storage
six1 ;six storage
seven1 ;seven storage
zero2 ;zero storage
one2 ;one storage
two2 ;two storage
three2 ;three storage
four2 ;four storage
five2 ;five storage
six2 ;six storage
seven2 ;seven storage
zerol ;zero storage
onel ;one storage
twol ;two storage
threel ;three storage
fourl ;four storage
fivel ;five storage
sixl ;six storage
sevenl ;seven storage
TEN ;CONVERT CLOCK RESULT TENS TO SINGLE UNIT
UNITS ;CONVERT CLOCK RESULT UNITS TO SINGLE UNIT
TEMPCLOCK ;HOLDS TEMP CLOCK RESULT FOR TENSANDUNITS
SCRATCH ; 1 by general-purpose scratchpad
TMP ; temp register
TMP2 ; temp register
COUNT
YRS
MON
DOW
DAYS
HRS
MINS
SEC
endc
#define SCL PORTA,1 ; bus clock line
#define SDA PORTA,4 ; bus data line
CS EQU 0 ;enable stobe
MOSI EQU 3 ;output for spi from master
SPICLK EQU 2 ;clock for spi
ROW_PORT Equ PORTB ;row port
org 0x0000
goto START
;**************************************************************************
; Interrupt routine
;**************************************************************************
; Interrupt routine handles TMR2 which generates a 1ms tick
; Interrupt vector
ORG 0x0004
INT
movwf w_temp ; Save W register
swapf STATUS,W ; Swap status to be saved into W
movwf s_temp ; Save STATUS register
movfw PCLATH
movwf p_temp ; Save PCLATH
btfss PIR1,TMR2IF ; Flag set if TMR2 interrupt
goto INTX ; Jump if not timed out
; Timer (TMR2) timeout
btfss row_pos, 0 ;check which ROW was last
goto Do_One
btfss row_pos, 1 ;check which ROW was last
goto Do_Two
btfss row_pos, 2 ;check which ROW was last
goto Do_Three
btfss row_pos, 3 ;check which ROW was last
goto Do_Four
btfss row_pos, 4 ;check which ROW was last
goto Do_Five
btfss row_pos, 5 ;check which ROW was last
goto Do_Six
btfss row_pos, 6 ;check which ROW was last
goto Do_Seven
Do_Zero movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf zero1, w
MOVWF OUT1
MOVF zero2, w
movwf OUT2
CALL xfer16
bcf row_pos, 0
call DisplayOn
bcf ROW_PORT, 0 ;turn ON row zero
goto INTX
Do_One movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf one1, w
MOVWF OUT1
MOVF one2, w
movwf OUT2
CALL xfer16
bcf row_pos, 1
call DisplayOn
bcf ROW_PORT, 1 ;turn ON row one
goto INTX
Do_Two movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf two1, w
MOVWF OUT1
MOVF two2, w
movwf OUT2
CALL xfer16
bcf row_pos, 2
call DisplayOn
bcf ROW_PORT, 2 ;turn ON row one
goto INTX
Do_Three movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf three1, w
MOVWF OUT1
MOVF three2, w
movwf OUT2
CALL xfer16
bcf row_pos, 3
call DisplayOn
bcf ROW_PORT, 3 ;turn ON row one
goto INTX
Do_Four movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf four1, w
MOVWF OUT1
MOVF four2, w
movwf OUT2
CALL xfer16
bcf row_pos, 4
call DisplayOn
bcf ROW_PORT, 4 ;turn ON row one
goto INTX
Do_Five movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf five1, w
MOVWF OUT1
MOVF five2, w
movwf OUT2
CALL xfer16
bcf row_pos, 5
call DisplayOn
bcf ROW_PORT, 5 ;turn ON row one
goto INTX
Do_Six movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf six1, w
MOVWF OUT1
MOVF six2, w
movwf OUT2
CALL xfer16
bcf row_pos, 6
call DisplayOn
bcf ROW_PORT, 6 ;turn ON row one
goto INTX
Do_Seven movlw 0xFF
movwf ROW_PORT ;turn off all rows
movwf row_pos
movf seven1, w
MOVWF OUT1
MOVF seven2, w
movwf OUT2
CALL xfer16
bcf row_pos, 7
call DisplayOn
bcf ROW_PORT, 7 ;turn ON row one
INTX
movfw p_temp
movwf PCLATH ; Restore PCLATH
swapf s_temp,W
movwf STATUS ; Restore STATUS register - restores bank
swapf w_temp,F
swapf w_temp,W ; Restore W register
bcf PIR1,TMR2IF ; Clear the calling flag
retfie
;program initialisation
START
BANKSEL ADCON1 ;disable analogue inputs
movlw 0x06
movwf ADCON1
BANKSEL PORTA
bsf STATUS, RP0 ;select bank 1
movlw b'00000000' ;Set port data directions, data output
movwf TRISA
movwf TRISB
MOVLW B'00000111'
MOVWF OPTION_REG
bcf STATUS, RP0 ;select bank 0
movlw 0x01
movwf row_pos
call Clear ;clear display registers
; Set up Timer 2.
;movlw b'01111110' ; Post scale /16, pre scale /16, TMR2 ON
;uncomment previous line, and comment next line, to slow multiplexing speed
;so you can see the multiplexing happening
movlw b'00000110' ; Post scale /4, pre scale /16, TMR2 ON
movwf T2CON
bsf STATUS, RP0 ;select bank 1
movlw .249 ; Set up comparator
movwf PR2
*************;I2C Initialization**************************
BANKSEL TRISC
movlw B'00011000' ; Initial PortC,bit 3 & 4 as Input
movwf TRISC ; RC3 = SCL , RC4 = SDA
BANKSEL PORTC
movlw 0xff
movwf PORTC
movlw .49 ; This gives 100KHz I2C clock @ 20MHZ
banksel SSPADD
movwf SSPADD
movlw b'10000000' ; Disable slew rate control.
banksel SSPSTAT
movwf SSPSTAT
movlw b'00000000' ;
movwf SSPCON2 ; Setup MSSP for continuous reception.
movlw b'00101000' ; Enable MSSP and setup for I2C master
banksel SSPCON ; mode.
movwf SSPCON
Main
bcf INTCON,PEIE ; Enable all peripheral interrupts
bcf INTCON,GIE ; Global interrupt enable
bsf STATUS, RP0 ;select bank 1
bcf PIE1,TMR2IE ; disable TMR2 interrupt
bcf STATUS, RP0 ;select bank 0
call RTC_brst_rd
bsf STATUS, RP0 ;select bank 1
bsf PIE1,TMR2IE ; Enable TMR2 interrupt
bcf STATUS, RP0 ;select bank
bsf INTCON,PEIE ; Enable all peripheral interrupts
bsf INTCON,GIE ; Global interrupt enable
MOVF HRS,W
CALL TENSANDUNITS
MOVF TEN,W
CALL NUMBERTABLE
CALL ScrollL8
MOVF UNITS,W
CALL NUMBERTABLE
CALL ScrollL8
CALL DOUBLEDOT
CALL ScrollL8
MOVF MINS,W
CALL TENSANDUNITS
MOVF TEN,W
CALL NUMBERTABLE
CALL ScrollL8
MOVF UNITS,W
CALL NUMBERTABLE
CALL ScrollL8
CALL DOT
CALL ScrollL8
MOVF SEC,W
CALL TENSANDUNITS
MOVF TEN,W
CALL NUMBERTABLE
CALL ScrollL8
MOVF UNITS,W
CALL NUMBERTABLE
CALL ScrollL8
CALL Delay1Sec
CALL Clear
goto Main ;endless loop
;***********************************************************
;*****************start of subroutines**********************
;***********************************************************
TENSANDUNITS
movwf TEMPCLOCK
andlw b'00001111'
movwf UNITS
swapf TEMPCLOCK,w
andlw b'00001111'
movwf TEN
RETURN
NUMBERTABLE
ADDWF PCL
goto Load_Zero
goto Load_One
goto Load_Two
goto Load_Three
goto Load_Four
goto Load_Five
goto Load_Six
goto Load_Seven
goto Load_Eight
goto Load_Nine
Clear clrf zero1
CLRF zero2 ;clear display storage
clrf one1
clrf one2
clrf two1
clrf three2
clrf three1
clrf four1
clrf four2
clrf five1
clrf five2
clrf six1
clrf six2
clrf seven1
clrf seven2
return
DOUBLEDOT
movlw 0x00
movwf zerol
movlw 0X18
movwf onel
movlw 0x18
movwf twol
movlw 0x00
movwf threel
movlw 0x00
movwf fourl
movlw 0x18
movwf fivel
movlw 0x18
movwf sixl
movlw 0x00
movwf sevenl
return
DOT
movlw 0x00
movwf zerol
movlw 0X18
movwf onel
movlw 0x18
movwf twol
movlw 0x00
movwf threel
movlw 0x00
movwf fourl
movlw 0x00
movwf fivel
movlw 0x00
movwf sixl
movlw 0x00
movwf sevenl
return
Load_Zero movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x4C
movwf threel
movlw 0x54
movwf fourl
movlw 0x64
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
Load_One movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x10
movwf twol
movlw 0x10
movwf threel
movlw 0x10
movwf fourl
movlw 0x10
movwf fivel
movlw 0x30
movwf sixl
movlw 0x10
movwf sevenl
return
Load_Two movlw 0x00
movwf zerol
movlw 0x7C
movwf onel
movlw 0x20
movwf twol
movlw 0x10
movwf threel
movlw 0x08
movwf fourl
movlw 0x04
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
Load_Three movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x04
movwf threel
movlw 0x08
movwf fourl
movlw 0x10
movwf fivel
movlw 0x08
movwf sixl
movlw 0x7C
movwf sevenl
return
Load_Four movlw 0x00
movwf zerol
movlw 0x08
movwf onel
movlw 0x08
movwf twol
movlw 0x7C
movwf threel
movlw 0x48
movwf fourl
movlw 0x28
movwf fivel
movlw 0x18
movwf sixl
movlw 0x08
movwf sevenl
return
Load_Five movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x04
movwf threel
movlw 0x04
movwf fourl
movlw 0x78
movwf fivel
movlw 0x40
movwf sixl
movlw 0x7C
movwf sevenl
return
Load_Six movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x44
movwf threel
movlw 0x78
movwf fourl
movlw 0x40
movwf fivel
movlw 0x20
movwf sixl
movlw 0x18
movwf sevenl
return
Load_Seven movlw 0x00
movwf zerol
movlw 0x20
movwf onel
movlw 0x20
movwf twol
movlw 0x20
movwf threel
movlw 0x10
movwf fourl
movlw 0x08
movwf fivel
movlw 0x04
movwf sixl
movlw 0x7C
movwf sevenl
return
Load_Eight movlw 0x00
movwf zerol
movlw 0x38
movwf onel
movlw 0x44
movwf twol
movlw 0x44
movwf threel
movlw 0x38
movwf fourl
movlw 0x44
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
Load_Nine movlw 0x00
movwf zerol
movlw 0x30
movwf onel
movlw 0x08
movwf twol
movlw 0x04
movwf threel
movlw 0x3C
movwf fourl
movlw 0x44
movwf fivel
movlw 0x44
movwf sixl
movlw 0x38
movwf sevenl
return
ScrollL8 call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
call ScrollL
call Delay50
return
ScrollL bcf STATUS, C
rlf zerol, f
rlf zero1, f
rlf zero2, f
bcf STATUS, C
rlf onel, f
rlf one1, f
rlf one2, f
bcf STATUS, C
rlf twol, f
rlf two1, f
rlf two2, f
bcf STATUS, C
rlf threel, f
rlf three1, f
rlf three2, f
bcf STATUS, C
rlf fourl, f
rlf four1, f
rlf four2, f
bcf STATUS, C
rlf fivel, f
rlf five1, f
rlf five2, f
bcf STATUS, C
rlf sixl, f
rlf six1, f
rlf six2, f
bcf STATUS, C
rlf sevenl, f
rlf seven1, f
rlf seven2, f
return
;***********************************************************
;***************DELAY ROUTINE*******************************
;***********************************************************
Delay1Sec call Delay250
call Delay250
call Delay250
call Delay250
Return
Delay255 movlw 0xff ;delay 255mS
goto d0
Delay250 movlw d'250' ;delay 250mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay10 movlw d'10' ;delay 10mS
goto d0
Delay1 movlw d'1' ;delay 1mS
goto d0
Delay5 movlw 0x05 ;delay 5ms
d0 movwf count1
d1 movlw 0xE7
movwf counta
movlw 0x04
movwf countb
Delay_0 decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
;-----------------------------------------
;-- RTC routines --
;-----------------------------------------
RTC_brst_rd:
call I2CSTART
movlw 0D0h ; slave address + write
call I2CSEND
movlw 0X00 ; set word address to seconds register
call I2CSEND
call I2CRESTART
movlw 0D1h ; slave address + read
call I2CSEND
call I2CREAD ; read the seconds data
movwf SEC ; save it
call I2CACK
call I2CREAD ; and so on
movwf MINS
call I2CACK
call I2CREAD
movwf HRS
call I2CACK
call I2CREAD
movwf DOW
call I2CACK
call I2CREAD
movwf DAYS
call I2CACK
call I2CREAD
movwf MON
call I2CACK
call I2CREAD
movwf YRS
CALL I2CNACK
return
;-----------------------------------------
;-- I2C routines --
;-----------------------------------------
I2CWAIT
banksel PIR1
FLoop btfss PIR1,SSPIF
goto FLoop
bcf PIR1,SSPIF
return
I2CRESTART
BANKSEL 1
BSF SSPCON2,RSEN
CALL I2CWAIT
BANKSEL 0
RETURN
I2CSTART
BANKSEL 1
BSF SSPCON2,0
CALL I2CWAIT
BANKSEL 0
RETURN
I2CSEND
BANKSEL 0
MOVWF SSPBUF
CALL I2CWAIT
RETURN
I2CREAD
BANKSEL 1
BSF SSPCON2, 3
CALL I2CWAIT
MOVF SSPBUF, W
BANKSEL 0
RETURN
I2CACK
BANKSEL 1
BCF SSPCON2, ACKDT
BSF SSPCON2, ACKEN
BANKSEL 0
RETURN
I2CNACK
BANKSEL 1
BSF SSPCON2, ACKDT
BSF SSPCON2, ACKEN
BANKSEL 0
RETURN
;I2CACKSTAT
; BTFSC SSPCON2, 6
; GOTO ACKSTATERROR
; RETLW 0
;*****************************************************
;*********** S.P.I ROUTINE **********************
;*****************************************************
xfer08:
movf OUT1, 0
call xfer8 ; send first byte
; wait
return
xfer16:
movf OUT1, 0
call xfer8 ; send first byte
movf OUT2, 0
call xfer8 ; send second byte
; wait
return
xfer8: movwf TMP1
movlw 0x8
movwf CNT
xfer1:
rlf TMP1, 1 ;rotate MSB of TMP1 into C
bcf PORTA, MOSI ;clear output bit
btfsc STATUS, C ;if rotated-out bit was high,
bsf PORTA, MOSI ;output high bit
nop ;keep time constant
bsf PORTA, SPICLK ;bring clock high
nop
nop
nop
nop
nop
nop
nop
nop ;8x nop to make clock symmetric
bcf PORTA, SPICLK
; this would implement MISO, except that we don't need it.
; bcf STATUS, C ;clear C
; btfsc PORTB, MISO ;test MISO bit
; bsf STATUS, C ;set C if MISO bit set
; nop ;keep time constant
; rlf TMP2, 1 ;rotate carry into TMP2
decfsz CNT, 1
goto xfer1
return
DisplayOn
BCf PORTA,CS
BSf PORTA,CS
RETLW 0
END
BANKSEL TRISC
movlw B'00011000' ; Initial PortC,bit 3 & 4 as Input
movwf TRISC ; RC3 = SCL , RC4 = SDA
i noticed iv made the scl and sda lines as inputs, is this right or should they be outputs
jason
I2cInit bsf STATUS,RP0 ;1
bsf TRISC,3
bsf TRISC,4
bcf STATUS,RP0
ClockLoop btfsc PORTC,4
goto BusFixed
bcf PORTC,3
bsf STATUS,RP0
bcf TRISC,3
goto $+1
bsf TRISC,3
bcf STATUS,RP0
goto ClockLoop
BusFixed
bsf STATUS,RP0
movlw .20000/4/.400
movwf SSPADD
clrf SSPSTAT
bsf SSPSTAT,SMP
bcf STATUS,RP0 ;0
movlw 0x28
movwf SSPCON
bcf PIR1,SSPIF
bcf PIR2,BCLIF
return
One of the devices has to be set to send clock, the other to receive clock. My question is which device will provide clock if both are inputs?
are is right.
The code you wrote, is that just executed on the pic start up or each time b4 you use the i2c interface, Does it not just keep doing a loop back to clockloop???
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?