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

📄 drivera.asm

📁 步进微步控制(采用了10细分的方式)很好实现了步进的细分控制
💻 ASM
📖 第 1 页 / 共 4 页
字号:
		movlw	8		; First state = t1accel
		lgoto	raslewall	;
;
; dslowslew starts a slow slew on dec drive
;    speedh, speedl, stepcmd, inccmd all set up previously
;
dslowslew
		bsf	dstatus, ST_STOP ; Signal that we need to stop
dslowslew2
		btfss	dstatus, ST_STOPPED ; Check for stopped
		goto	dslowslew2	; Wait for a stop
dslowslew1
		movfw	speedh		; Set up compare regs for int level
		movwf	dspdhigh	;
		movfw	speedl		;
		movwf	dspdlow		;
		movlw	0		; Start in state 0
dslewall ; start up the engine...  Enter here with initial state in w
		movwf	t2state		;
		clrf	dstatus		;
		movfw	inccmd		; Set up interrupt level vbls
		movwf	dinc		;
		movfw	stepcmd		;
		movwf	t2stepcmd	;	
		splh			; Disable ints while we get timer 1
		movfw	TMR1H		; Mark1 - Pick up high
		addwf	dspdhigh, w	; calc capture reg
		movwf	CCPR2H		;
		movlw	5		; Mark2-Mark1+1 timing
		subwf	TMR1L, w	; Mark2 - Pick up low
		spl0			; Reenable
		addwf	dspdlow, w	; Calc other reg
		movwf	CCPR2L		;
		skpnc			;
		incf	CCPR2H, f	;
		movlw	B'00001010'	; CCP1X:CCP1Y=0 CCP1M3:CCP1M0=1010
		movwf	CCP2CON		; Set up for compare mode, int on match
		bcf	PIR2, 0		; Be sure CCP2IF is clear
		banksel	PIE2		;
		bsf	PIE2, 0		; Enable the capture interrupt
		banksel	0		;
; dstep expanded here by hand to allow the lcall of gettraj
		movfw	t2stepcmd	; Step 1 of 8
		addwf	dtrajp, f	; see where to go next
		movlw	0x1f		; Wrap pointer
		andwf	dtrajp, w	; w gets ptr for gettraj
		movwf	dtrajp		; Save new ptr
		lcall	gettraj		; Get the table value
		dec_out			; Send to motor
		mlretlw	0		; Successful completion
;
; dfastslew starts a fast slew
;	speedh, speedl, stepcmd, inccmd all set up previously
;
dfastslew
		bsf	dstatus, ST_STOP ; Signal that we need to stop
dfastslew2
		btfss	dstatus, ST_STOPPED ; Check for stopped
		goto	dfastslew	; Wait for a stop
dfastslew1
		movlw	0		; Start at 0
		movwf	dcuridx		; Set starting point
		lcall	dgetaccel	; Set up rac_cnt, rspdhigh, rspdlow
		movfw	speedh		; Pick up high index
		movwf	dhiacidx	; Set stopping point
		movlw	8		; First state = t2accel
		lgoto	dslewall	;		

;
; Full step command
;
dofstep
		mreturn
;
; Micro step command
;
domicrostep
		mreturn
;
; Quit commands
;	w = 0 means just quit, leave motors running
;	w = 1 means quit, shut motors off (idle)
;
doquit
		movwf	temp		; Save parameter
		incf	FSR, f		; Advance to next in cmd
		movfw	INDF		; Get the cmd
		sublw	0x0D		; CR?
		skpz			;
		goto	doquit1		;
; No parameter means both
		movfw	temp		;
		mcall	stopboth	;
		goto	doquitok	;
doquit1
		movfw	INDF		; Maybe it's an R?
		sublw	'R'		;
		skpz			;
		goto	doquit3		;
		bsf	rstatus, ST_STOP ; Signal RA to stop
doquit2		btfss	rstatus, ST_STOPPED ; Wait for RA to stop
		goto	doquit2		;
		movfw	temp		; Idle too?
		skpnz			;
		goto	doquitok	; Done, RA stopped
		movlw	0		;
		ra_out			; Kill power to the motor
		goto	doquitok	;
doquit3
		movfw	INDF		; OK, got to be a D...
		sublw	'D'		;
		skpnz			; Return if not
		goto	doquit5		;
		mretlw	1		; Error return
doquit5		bsf	dstatus, ST_STOP ; Signal DEC to stop
doquit4		btfss	dstatus, ST_STOPPED ;
		goto	doquit4		;
		movfw	temp		; Idle too?
		skpnz			;
		goto	doquitok	; Done, DEC stopped
		movlw	0		;
		dec_out			; Kill power to the motor
doquitok	mretlw	0		;
;
; Subroutine used to stop both motors.
;	w = 1 means kill the power too
;
stopboth
		movwf	temp
		bsf	rstatus, ST_STOP ; Stop RA motion
		bsf	dstatus, ST_STOP ; Stop Dec motion
stopboth1	btfss	rstatus, ST_STOPPED ; Wait for both axes to stop
		goto	stopboth1	;
		btfss	dstatus, ST_STOPPED ;
		goto	stopboth1	;
		movfw	temp		; Idle?
		skpnz			;
		goto	stopbothok	; Done - both are stopped
		movlw	0		;
		ra_out			; Turn off both motors
		movlw	0		;
		dec_out			;
stopbothok	mreturn			;
;	
; Get commands
;
doget
		incf	FSR, f		; Advance to C, hopefully
		movfw	INDF		;
		sublw	'C'		; Get count?
		skpz			;
		goto	doget1		; Jump if not a C
		mcall	dogetsub	;
		splh
		movd	rapos, d0	; Convert rapos first
		spl0
		mcall	dtoa		;
		movlw	' '		;
		movwf	INDF		; Put in a space
		incf	FSR, f		;
		splh
		movd	dpos, d0	; Now convert dec pos
		spl0
		mcall	dtoa		;
		mcall	dogetwrap	; Wrap it up
		mretlw	0		; Successful completion
doget1
		movfw	INDF		;
		sublw	'B'		; Get battery value?
		skpnz			;
		goto	doget2		;
		mretlw 	1		; Error return if not "C" or "B"
doget2
		mcall	dogetsub	; Set up for return
		mcall	getbatt		; Get the battery voltage
		movpwd	d0		; Put in d0
		mcall	dtoa		; Convert to ascii
		movlw	' '		;
		movwf	INDF		;
		incf	FSR, f		;
		movfw	avgbatt		; Get the average too
		movpwd	d0		;
		mcall	dtoa		; 
		mcall	dogetwrap	;
		mretlw	0		; And done
		
;
; Helper subroutine for doget - sets up cmdbuff for a return value
;
dogetsub
		movlw	cmdbuff		; Point to start of buffer
		movwf	FSR		;
		movlw	0x0D		; CR
		movwf	INDF		;
		incf	FSR, f		;
		movlw	0x0A		; LF
		movwf	INDF		;
		incf	FSR, f		;
		mreturn
;
; Wrapup doget routines
;
dogetwrap
		movlw	0x0D		; CR; LF supplied by docmd()
		movwf	INDF		;
		incf	FSR, F		;
		movlw	0		; Mark the end with a null
		movwf	INDF		;
		movlw	cmdbuff		; Set up to send buff
		movwf	FSR		;
		mcall	buffout		; Send the buffer
		mreturn
;
; Set commands
;	Call with FSR pointing into the buffer at the "S"
;	Returns 0 for success, 1 for error
;	SS<speed>		Sets speed for next Slew command (both axes)
;	SC<m> <count>		Sets the saved count for an axis
;	<speed> is "T" for Tracking speed
;		   "G" for Guide
;		   "L" for Lunar
;		   "S" for Solar
;		   "M" for Medium
;		   "F" for Fast
;
doset
		incf	FSR, f		; Advance to "S" or "C"
		movfw	INDF		;
		sublw	'S'		; Speed?
		skpz			;
		goto	doset1		; Skip if not
; Set speed
		incf	FSR, f		; Advance to speed parameter
		clrf	temp		; Index starts at 0
dosetlp
		call	getspeed	; Get the speed name (F, M, etc)
		andlw	0xff		; Is it zero?
		skpnz			;
		goto	dosetbad	; Error return if end of speedtbl
		subwf	INDF, w		; Same as table entry?
		skpnz			;
		goto	doset2		;
		movlw	4		; Advance index
		addwf	temp, f		;
		goto	dosetlp		; Check next
doset2
		incf	temp, f		; Advance index
		call	getspeed	; Get flag
		movwf	slew		; Set slew
		incf	temp, f		;
		call	getspeed	;
		movwf	speedh		; set speedh
		incf	temp, f
		call	getspeed	;
		movfw	speedl		;
		goto	dosetok		; Successful return
doset1
		movfw	INDF		;
		sublw	'C'		; Count?
		skpz			;
		goto	dosetbad	; Nothing else to set
; Set Count
		incf	FSR, f		; Point to R/D
		movfw	INDF		;
		sublw	'R'		; RA?
		skpz			;
		goto	dosetc1		;
		incf	FSR, f		; Advance past R
		mcall	atod		; Convert RA count to binary
		splh			;
		movd	d0, rapos	; Set count
		spl0			;
		goto	dosetok		;
dosetc1		movfw	INDF		;
		sublw	'D'		; Dec?
		skpz			;
		goto	dosetbad	; Error if neither R nor D
		incf	FSR, f		; Advance past D
		mcall	atod		; Convert DEC count to binary
		splh			;
		movd	d0, dpos	; fall through to dosetok
		spl0		
dosetok		mretlw	0		; Good return
dosetbad	mretlw	1		; Bad return
;
;
; Check the limit switches
;	No parameters passed
;	Nothing returned
;	Side effects are somewhat dramatic..
;
chklim

		mreturn
;
; Check the battery voltage
;	No parameters passed
;	Nothing returned
;	Implments a length 16 rolling average.  Anything below 10V
;	shuts things down.
;
chkbatt
		movfw	t0ticks		; Find out if we need to check
		subwf	timbatt, w	; 
		skpnz			;
		goto	chkbattdone	; Done if the same
		incf	timbatt, f	; Follow the timer
		movfw	avgbatt		; Pick up rolling average
		movpwd	d0		; Save in d0
		movlw	15		; Multiply by 15
		mulpwd	d0, d1, temp, temp1, temp2
		mcall	getbatt		; Pick up the current battery value
		addpwd	d0		; Add to it
		clrf	temp		; Assume no rounding
		movfw	d0+b3		; Check for rounding error
		andlw	0x0f		;
		sublw	7		;
		andlw	0x80		;
		skpnz			;
		goto	chkbatt1	;
		movlw	1		; add in 1 to rount it up
		movwf	temp		;
chkbatt1	rrd	d0		; Divide by 16
		rrd	d0		;
		rrd	d0		;
		rrd	d0		;
		movfw	temp		;
		addpwd	d0		; Round if needed
		movfw	d0+b3		; Pick up the new average
		movwf	avgbatt		; And save
		sublw	MINBATT		; Is it still OK?
		andlw	0x80		;
	ifndef SIM
		skpz			;
	endif
		goto	chkbattdone	;
; Shut it down...
		movlw	1		; Want to kill the power
		mcall	stopboth	;
; xxx need to do LED signals...
chkbattdone	mreturn
;
; getbatt gets the value from the battery a-to-d converter
;
getbatt
		movlw	B'11000001'	; FRC, Channel 0, ADON (Turn on converter)
		movwf	ADCON0		;
		movlw	5		; 16 clocks coming up
		movwf	temp		;
getbatt1	decfsz	temp, f		; Spin it down
		goto	getbatt1	;
		bsf	ADCON0, 2	; Set GO/DONE
		nop			; May not need this..
getbatt2	btfsc	ADCON0, 2	; Spin until conversion is done
		goto	getbatt2	;
		movfw	ADRES		; Pick up result
		bcf	ADCON0, 0	; Shut off unit
		mreturn
;
; atod converts ascii to 32bit
; 	Call with fsr pointing at the number
; 	returns the result in d0
;
atod
		movfw	INDF		; Skip past zeros
		sublw	' '		;
		skpz			;
		goto	atod1		; 
		incf	FSR, f		;
		goto	atod		;
atod1		clrf	temp		; temp = 0 means the number is positive
		movfw	INDF		;		
		sublw	'-'		; Is it negative?
		skpz			;
		goto	atod2		;
		incf	temp, f		; temp = 1 means the result is negative
		incf	FSR, f		;
atod2 ; Pointing at the the number, should be all digits from here on
		clrd	d0		; start with zeros
atod3		movlw	'0'		; 
		subwf	INDF, f		; Pick up the number and convert to binary
		movfw	INDF		; Check for less than '0'
		andlw	0x80		;
		skpz			;
		goto	atodend		; Negative means was less than ascii 0
		movfw	INDF		;
		sublw	9		; w = 9 - w
		andlw	0x80		;
		skpz			;
		goto	atodend		; Must have been greater than ascii 9
		movlw	10		; Multiply previous results by 10	
		mulpwd	d0, d1, temp1, temp2, temp3
		movfw	INDF		; Pick up the new digit
		addwd	d0		; Add it in
		incf	FSR, f		; Advance to next char
		goto	atod3		; Check next char
atodend
		movf	temp, f		; Pos?
		skpnz			;
		goto	atodend1	;
		negd	d0, d1, temp1	; Negate if temp is set
atodend1
		mreturn			; Done
;
; dtoa converts 32 bit binary numbers to ascii
; 	Pass start of buffer in FSR.
;	Returns with FSR pointing at the next space past the number
; 	The number should be in d0
;	uses pottbl to decompose the number
;
dtoa
		movfw	d0+b0		; Is it negative?
		andlw	0x80		;
		skpnz			;
		goto	dtoa1		;
		movlw	'-'		; Put in a minus sign
		movwf	INDF		;
		incf	FSR, f		;
		negd	d0, d1, temp1	; Negate d0
dtoa1
		clrf	temp		; Used as an argument to getpot
		movlw	'0'		;
		movwf	INDF		; Start with a zero
dtoa2 ; This loop looks for the first non-zero digit
      ; Surpresses leading zeros
		mcall	nxtpot		;
		subd	d0, d1, temp1	; d0 = d0 - d1
		movfw	d0+b0		;
		andlw	0x80		; Negative?
		skpnz			;
		goto	dtoa3		;
		addd	d0, d1, temp1	; Put it back
		movlw	40		; At the end of pottbl?
		subwf	temp, w		;
		skpz			;
		goto	dtoa2		; Loop to next try
		incf	FSR, f		; Point to next digit
		goto	dtoadone	; It's zero if whole table finished
dtoa3 ; Got a positive result
		movlw	'1'		;
		movwf	INDF		;
dtoa4 ; Main conversion loop
		subd	d0, d1, temp1	;
		movfw	d0+b0		;
		andlw	0x80		;
		skpz			; Continue if still pos
		goto	dtoa5		;
		incf	INDF, f		; Increment the digit
		goto	dtoa4		;
dtoa5 ; d0 went from d0 >= 0 to d0 < 0
		incf	FSR, f		; Advance to next output digit
		movlw	40		; End of table?
		subwf	temp, w		;
		skpnz			;
		goto	dtoadone	; Done if end of table
		movlw	'9'		;
		movwf	INDF		; Start next digit
		mcall	nxtpot		; Get next power of 10
dtoa6 ; on negative side waiting to go positive
		addd	d0, d1, temp1	; Add in power of 10
		movfw	d0+b0		;
		andlw	0x80		;
		skpnz			;
		goto	dtoa7		;
		decf	INDF, f		;
		goto	dtoa6		;
dtoa7 ; d0 went from d0 < 0 to d0 >= 0
		incf	FSR, f		;
		movlw	40		; Are we done yet?
		subwf	temp, w		;
		skpnz			;
		goto	dtoadone	;
		movlw	'0'		;
		movwf	INDF		;
		mcall	nxtpot		;
		goto	dtoa4		;
dtoadone	mreturn			;
;
; nxtpot calls getpot repeatedly and stuffs the 32 bit number
; 	in d1.  Increments temp (in getpot) as a side effect
nxtpot
		call	getpot		; Pick up current power of 10
		movwf	d1+b0		;
		call	getpot		;
		movwf	d1+b1		;
		call	getpot		;
		movwf	d1+b2		;
		call	getpot		;
		movwf	d1+b3		;
		mreturn			;
		END			; directive 'end of program'

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -