⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.asm

📁 运用单片机实现时序输出,daddadasdad
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	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 + -