?? can.asm
字號:
call SPI_WRITE
; banksel TXREG
; movlw 0x33
; movwf TXREG
; call txwait
;+========================+
;| Main Sequence |
;+========================+
banksel PORTB
bsf PORTB, 7 ;Hit the power indicator
clrf PIR1
clrf PIR2
banksel TXREG
movlw INIT_MSG
movwf TXREG
call txwait
banksel INTCON
bsf INTCON, 6 ;Enable peripheral interrupts
bsf INTCON, 7 ;Enable global interrupts
mainloop
; Okay, now let's take all those buffers we filled up and direct their data to where it
; needs to go
btfsc CAN_RX0_READY
call READ_RXB0
;Is there anything in the transmit buffer?
;(I should really be using a flag for this instead!)
banksel CAN_buff_ctr
movf CAN_buff_ctr, F
bz checkPCbuffer
banksel CAN_buff_out
movfw CAN_buff_out
movwf FSR
banksel TXREG
movfw INDF ;Data
movwf TXREG
banksel CAN_buff_out
movfw CAN_buff_out ;Have we read beyond our alloted space?
addlw 0x1F ; This will overflow if we've overflowed
bnc CANdecnormally ;branch-no-carry
movlw CAN_buff
movwf CAN_buff_out
decf CAN_buff_ctr
goto endservice
CANdecnormally
incf CAN_buff_out
decf CAN_buff_ctr ; I'm not checking for underflow, since we already checked
checkPCbuffer
;Is there anything in the transmit buffer?
banksel PC_buff_ctr
movf PC_buff_ctr, F
bz endservice
banksel PC_buff_out
movfw PC_buff_out
movwf FSR
banksel TXREG
movfw INDF ;Data
movwf TXREG
movfw PC_buff_out ;Have we read beyond our alloted space?
addlw 0xB0 ; This will overflow if we've overflowed
bnc PCnormaldec ;branch-no-carry
movlw PC_buff
movwf PC_buff_out
decf PC_buff_ctr
goto endservice
PCnormaldec
incf PC_buff_out
decf PC_buff_ctr ; I'm not checking for underflow, since we already checked
endservice
;Include any necessary clean-up here
goto mainloop
;+=========================+
;| Function Calls |
;+=========================+
wait
banksel delay
movlw B'11100000'
movwf delay
del decf delay
skpz
goto del
return
txwait
banksel PIR1
txloop btfss PIR1, TXIF
goto txloop
bcf PIR1, TXIF
return
SPI_WRITE ;Do NOT call until SPI has been configured!!!
banksel PORTB
bcf CAN_CS ;MCP2510's chip select line
#ifdef debug
movlw 0x57
movwf TXREG ;Debugging message
#endif
movlw B'00000010' ;MCP2510 Write command
banksel SSPBUF
movwf SSPBUF
movf SSPBUF, W
movfw SPI1
banksel SSPBUF
movwf SSPBUF
movf SSPBUF, W
movfw SPI2
banksel SSPBUF
movwf SSPBUF
movf SSPBUF, W
;We've moved our three bytes, now let's go home
banksel PORTB
bsf CAN_CS
return
BIT_MODIFY ;Do NOT call until SPI has been configured!!!
banksel PORTB
bcf CAN_CS ;MCP2510's chip select line
#ifdef debug
movlw 0x42
movwf TXREG ;Debugging message
#endif
movlw B'00000101' ;MCP2510 Bitwise Modify
banksel SSPBUF
movwf SSPBUF
movfw SPI1
banksel SSPBUF
movwf SSPBUF
movfw SPI2
banksel SSPBUF
movwf SSPBUF
movfw SPI3
banksel SSPBUF
movfw SSPBUF
;We've edited the register, let's go back
banksel PORTB
bsf CAN_CS
return
SPI_READ
banksel PORTB
bcf CAN_CS
#ifdef debug
movlw 0x52
movwf TXREG ;Debugging message
#endif
movlw B'00000011' ;MCP2510 Read command
banksel SSPBUF
movwf SSPBUF
movwf SPI1
banksel SSPBUF
movwf SSPBUF
;The next thing that comes in is the contents of that register.
; At this stage, nothing that comes from the 2510 is used by the PIC --
; it's just a straight pass-through
banksel SSPSTAT
rgo2 btfss SSPSTAT, BF
goto rgo2
banksel SSPBUF
movfw SSPBUF
banksel SPIOUT
movwf SPIOUT
banksel PORTB
bsf CAN_CS
return
READ_RXB0
;This function "calls up" the 2510, reads out the Data Length register, and loops that many
; times, feeding into the CAN_buff ring buffer.
;Right now, interrupts are turned OFF during the entire operation. This is ridiculous.
; I bet that turning interrupts back on during any wait periods, or just briefly in between
; cycles would help a lot.
; The CLEVER way to do this would be to externally load an offset, since adding 0x10 to each of
; these address bytes would select RXB1, instead.
; However, there is some doubt as to whether we will actually ever need RXB1.
banksel INTCON
bcf INTCON, 7 ;OK, it's dumb, but it's temporary.
banksel PORTB
bcf CAN_CS ;Poke the 2510
movlw B'00000011' ;MCP2510 Read command
banksel SSPBUF
movwf SSPBUF
movwf RXB0DLC ;Address of RX Buffer 0's Data Length Code
movwf SSPBUF
;The next thing that comes in is the contents of that register.
banksel SSPSTAT
rxb01 btfss SSPSTAT, BF
goto rxb01
banksel SSPBUF
movfw SSPBUF
andlw B'00001111' ;Mask out all but the bottom four bits
; creating a nice loop timer
banksel loopctr0
movwf loopctr0
bz rxb0done ; It may be empty, in which case, don't waste time
banksel SSPBUF
movlw B'00000011'
movwf SSPBUF
movlw RXBUF0 ;Address of start bit
movwf SSPBUF
rxb0loop
banksel PC_buff_in
movfw PC_buff_in
movwf FSR
banksel SSPSTAT
rxb0loopinner
btfss SSPSTAT, BF
goto rxb0loopinner
banksel SSPBUF
movfw SSPBUF
banksel CAN_buff
movwf INDF
incf CAN_buff_in
movlw CAN_buff_end
xorwf CAN_buff_in, W ;Is the new address out of bounds?
skpz ;If it is, loop around
goto rb0_rest
movlw CAN_buff
movwf CAN_buff_in ;Loop around
rb0_rest
incf CAN_buff_ctr
movlw 0x40 ;64 bytes -- HUGE counter
xorwf CAN_buff_ctr, W
skpnz ;If the counter overflows, set the error bit
bsf CAN_BUFF_OVERFLOW
banksel loopctr0 ;Decrement our counter, and see if we're done.
decf loopctr0
bnz rxb0loop
bsf CAN_BUFF_NOTEMPTY
rxb0done
banksel PORTB
bsf CAN_CS ;Do this before re-enabling interrupts, to prevent overflows
banksel INTCON
bsf INTCON, 7
return
CF_READY
BTFSS CF_RDY
goto CF_READY
return
CF_READ
call CF_READY
;Input from data lines
banksel TRISD
movlw 0xFF
movwf TRISD
banksel PORTD
clrf PORTD
bsf CF_OE
; ********************************
; Handle incoming communications from the PC
PC_SERVICE
banksel PC_buff_in
movfw PC_buff_in
movwf FSR
banksel RCREG
movfw RCREG
; The following code grabs that byte from RCREG and puts it into the PC_buff buffer
; When that buffer's counter is an integer multiple of eight, it gets flushed out
; onto the CAN bus.
movwf INDF
incf PC_buff_in
movlw PC_buff_end
xorwf PC_buff_in, W ;Is the new address out of bounds?
skpz ;If it is, loop around
goto pc_rest
movlw PC_buff
movwf PC_buff_in ;Loop around
pc_rest
incf PC_buff_ctr
movlw 0x10 ;16 bytes
xorwf PC_buff_ctr, W
skpnz ;If the counter overflows, set the error bit
bsf PC_BUFF_OVERFLOW
; At this point, we've loaded the new byte into the buffer, incremented the position
; and checked for overflow. We now indicate that the PC buffer contains data
; and head back to IntService
bsf PC_BUFF_NOTEMPTY
goto CheckCAN
CAN_SERVICE
;Since the MCP2510 generates an external interrupt for various things,
; This routine needs to read off portb (To clear the interrupt)
; Then poll the 2510 for the error. If it IS a message, then a flag
; should be set for the MAIN LOOP to read the buffer. Don't do it here
banksel PORTB
movf PORTB, F ;Clear that interrupt
bcf CAN_CS
movlw B'00000011' ;MCP2510 Read command
banksel SSPBUF
movwf SSPBUF
movwf CANSTAT ;the 2510's status register
banksel SSPBUF
movwf SSPBUF
;The next thing that comes in is the contents of that register.
; We don't care about errors. They aren't processed in listen mode, anyhow.
banksel SSPSTAT
CS2 btfss SSPSTAT, BF
goto CS2
banksel SSPBUF
movfw SSPBUF
andlw B'00001110'
banksel PORTB
bsf CAN_CS
xorlw B'00001100' ;RXB0 Interrupt
bnz NextISR ;If anything else, then forget it.
bsf CAN_RX0_READY
goto NextISR
;+==========================+
;| Interrupt Routines |
;+==========================+
IntService
movwf W_TEMP ;save W, STATUS, PCLATH, and FSR
swapf STATUS, W
movwf STATUS_TEMP
movfw FSR
movwf FSR_TEMP
movfw PCLATH
movwf PCLATH_TEMP
banksel PIR1
;Perform interrupt routines
CheckPC
btfsc PIR1, RCIF
goto PC_SERVICE
CheckCAN
btfsc PIR1, INTE
goto CAN_SERVICE
NextISR
;Clear Receive errors
bcf RCREG, CREN
bsf RCREG, CREN
bcf PIR1, RCIF
;All done! Now let's put everything back where it was
movfw PCLATH_TEMP
movwf PCLATH
movfw FSR_TEMP
movwf FSR
swapf STATUS_TEMP, W
movwf STATUS
swapf W_TEMP, F
swapf W_TEMP, W
retfie
end
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -