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

📄 stepi2c.asm

📁 pic得电机控制程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
pto_lsb:							;premature lsb timeout
	movwf scratch					;save timeout time
	movf timeouthb,f		
	btfsc STATUS,Z					;look for msb to decrement		
	goto too_fast					;if there is no msb to decrement then interval is too short for code!
	movf scratch,w					;restore timeout time
	movwf TMR0
	decf timeouthb,f
	bcf INTCON,T0IF
	bsf iflag_stat,T0IF
	retfie                 			;end with success
too_fast:
	sleep							;in lieu of something useful
	retfie

step:
;-----------------------------------------------------------
;Stepping proc occurs every time timer interrupt flag is set
;Mode of operation:
;A step of the motor is broken doWn into a number of phases. The number
;of phases is a measure of the motor current control resolution. Each phase is
;repeated for a length of time governed by the train repetition count. 
;A train is a fixed-length series of pulses off and on output to the motor.
;The relative number of pulses off and on in a train govern
;the average output current for that phase to the motor.
;After the train has repeated a number of times, governed by the speed
;required - fast has a loW repeat count, sloW  high repeat count- the
;motor current changes to the next phase. After all the phases in a step
;have been completed the next step pattern is loaded and all counts are
;reset. 
;The number of train repeat counts is governed by the i2c input to
;alloW control of the motor speed. This input is checked at the end of
;every step and the required number for that step is stored for use.

step_on_timer:
set_phase:
ifdef uniphase
;if(  pulse_cnt lt   _phase_count) 
;		current step is high
	movf   pulse_cnt,W
	bsf    STATUS,C					;C is not affected by a-b=0 so set prior to test 
	subWf  phase_cnt,W				;W->  phase_cnt-  pulse_cnt
	btfsc  STATUS,C					;if pulse <= phase carry is set - use current step mask 
    goto   mask_no_change 			;step bit is independent of direction if mask bit is on
    btfss  step_status,  dirn
    goto   reverse
forwards:
	bsf    STATUS,C					;preset C for test of >=
	movf   step_cnt,W    			;get number of current step output format
    sublW  stepmode-1        		;check for Wraparound of phase number
    btfsc  STATUS,C
    goto   forWard_load    			;no carry so no Wrap-around yet
    movlW  D'1'                		;Wrapped around to first phase
    goto   get_mask
forward_load:
	incf   step_cnt,W
	goto   get_mask
reverse:
	decf   step_cnt,W
	btfss  STATUS,Z                 ;at zero phase?
    goto   get_mask        			;yes
    movlW  stepmode	        		;set neW
	goto   get_mask
mask_no_change:
    movf   step_cnt,W    			;get current phase mask from step table
get_mask:
    call   step_table         		;value returned in W
dirn_end:
	movWf PORTA                     ;output on PORTA
endif

;max number of pulses in a pulse train is also equal to   phases_per_step 
;if (  pulse_cnt EQ 0) then
;	  pulse_cnt=  phases_per_step
;         trn_rp_cnt--
	decfsz pulse_cnt,F
	goto   no_rollover				;if no rollover at all can go to the end
	movlw  phases_per_step			;have end of train rep loop
	movwf  pulse_cnt

;  train_reps_per_phase is the step rate determinant - controlling how many times
;the same pwm pulse train is repeated before the next phase starts
;if (  trn_rp_cnt EQ 0) then
;         trn_rp_cnt=train_reps_req
;	  phase_cnt--
	decfsz trn_rp_cnt,F
	goto   no_rollover
	movf   trn_reps_rq,W			;have end of phase loop so reset value
	movwf  trn_rp_cnt

;phase_count measures Which phase in a step We are up to 
;if(  phase_cnt EQ 0) 
;	  phase_cnt=  phases_per_step
	decfsz  phase_cnt,F
	goto    no_rollover
	movlw   phases_per_step			;have step transition
   	movwf   phase_cnt          		;reset phase couner

;Check direction.
    btfsc  Actual_dirn,dirn   		;If direction = forward
    goto   step_forwards

;decrement step_counter and watch for rollover at 1-> stepmode        
step_reverse:
    decf  step_cnt,F       			;decrement step count for reverse motion
    btfss STATUS,Z             		;check for zero, min phase is 1
    goto  rate_adjust          		;not zero yet
    movlw stepmode             		;zero found so reset count to stepmode
	movwf step_cnt
    goto  rate_adjust

;increment step counter and Watch for rollover at stepmode->1
step_forwards:
    movlw stepmode
    subwf step_cnt,W       			;W->  step_cnt-stepmode
    btfsc STATUS,C             		;carry is set if no rollover
    goto forward_roll       		;rollover found 
    incf step_cnt,F        			;no rollover so increment count
    goto rate_adjust

forward_roll
    movlw D'1'
    movwf step_cnt

;If there is a change required handle it. Could insert change detection
into idle loop and use a flag to indicate 
check_rate:
ifndef dbg _excludekeybd
	;compare required direction and rate with actual
	;if no difference then finish
	;else call adjust_rate
endif
no_rollover:
    bcf iflag_stat,T0IF				;re-enable timer interrupt
    return

;------------------------------------------------------
;stepper phase jump table
;phase number supplied in W on entry- minimum value is 1, max 'stepmode'
;phase format returned in W on exit
if stepmode==uniphase
step_table:
	andwf H'07' 					;safety mask 
    addwf PCL,f  					;PCL-> PCL + W
	nop
    retlW b'00000101'			
    retlW b'00001001'			
    retlW b'00001010'			
	retlW b'00000110'
    retlW b'00000101'			
    retlW b'00001001'			
    retlW b'00001010'			
endif

if stepmode == biphase
;etc
endif


rate_adjust:
;=---------------------------------------------------
;Procedure for smooth adjustment of rate between steps
;To avoid cogging and jerking, the rate of motion, including direction changes,
;is ramped. Because of this we need to look for changes in rate and direction and on/off.
;The direction may only be changed when the stepper is moving at the slowest rate and
;so this must be achieved by ramping down the rate prior to reversing the direction
;and then ramping up the rate to that required in that direction.
;Similarly when the stepper is turned off, the stepping motion must not come to an
;abrupt stop but achieve the slowest rate (track) prior to being turned off
;-----------------------------------------------------
;Insert 'off' test here
dirn_test:
    swapf   step_status,W    		;swap nibbles of step_status byte into W
    xorwf   step_status,W    		;xor to see if reqd and actual directions agree
    andlw b'11000000'   			;mask off other bits
    btfsc W,  dirn      			;clear means reqd and set dirns are different
    goto   Same	    				;c->1 -> same
    goto   Diff	    				;c->0 -> different

;DIFFERING DIRECTIONS:   Diff
;1, If rate is higher than track then reduce to track
;2, if rate is lower than track then set to track
;3, If rate = track then change direction
Diff:
    movf trn_reps_rq,W				;test for current == track 
    sublw track_train_reps      	;W->current-track
    btfsc STATUS,Z              
    goto D_track					;rates are equal
    btfsc STATUS,C
    goto D_scan          			;current is faster than track 
D_track_high:
    movlw track_train_reps	
    movwf trn_reps_rq    			;set value to track
    goto Xdirn							
D_track:
    movlw track_train_reps			;set initial track value
    movWf trn_reps_rq
Xdirn:
	clrw
	bsf W,dirn
	xorwf step_status,F				;toggle dirn flag
	goto Dend_adjust

D_scan:
	bsf STATUS,C
	movf trn_reps_rq,W				;test for current < scan 
    sublw track_train_reps      	;W->current-scan
    btfss STATUS,C              
    goto D_slew						;current < scan
    movlw scan_train_reps_increment
    addwf trn_reps_rq,F
    goto Dend_adjust				;end

D_slew:
    movlw slew_train_reps_increment
    addwf trn_reps_rq,F
    
Dend_adjust:
	swapf step_status,W
	xorlw .3
	btfss STAUS,Z
	retlw .0
;Dirn_changed
	;Anything more required doing? - dirn only changes at step completion
    retlw D'1'
        
;SAME DIRECTIONS:   Same
;When going the same dirn, need to do different things for different keyboard presses
Same:
    swapf step_status,W            	;jump table based on rate input
    andlW b'00000011'
    addWf PCL,F
ifdefined RA
	goto   S_track 					;track set
else
	goto   S_stop               	;set off -error condition
endif
	goto   S_track 					;track set
    goto   S_scan               	;scan set
    goto   S_sleW					;sleW set

S_track:
    movlw track_train_reps			;test for current == track
	subwf trn_reps_rq,W 			;W-> current - track
	btfsc STATUS,Z
	goto S_track_end_adjust      	;no changes required - end

S_track_high:
	btfss STATUS,C    				;test for current > track
	goto S_track_slew
   	movlw track_train_reps 		  	;set current to track
	movWf trn_reps_rq
	goto S_track_end_adjust      	;end    

S_track_slew:
	movlw scan_train_reps	    	;test for count < scan
	subwf trn_reps_rq,W				;W->current - scan
	btfsc STATUS,C					;C=1, current > scan 
	goto S_track_scan
    movlw slew_train_reps_increment
    addwf trn_reps_rq,f
    goto S_track_end_adjust      	;end

S_track_scan:
    movlw scan_train_reps_increment	
    addwf trn_reps_rq,F
    goto S_track_end_adjust      	;end

S_track_end_adjust:
	retlw D'1'
		
S_scan:								;section
    movlw scan_train_reps	    	;test if count > scan
    subwf trn_reps_rq,W   			;W->count - scan 
	btfss STATUS,Z					;if z->1 count=scan
	goto S_scan_end_adjust
    btfss STATUS,C              	;c=1 if count>scan
    goto S_scan_low

S_scan_high:
    movlw scan_train_reps_increment
    addwf trn_reps_rq,f
    goto S_scan_end_adjust

S_scan_low:
    movlw slew_train_reps_increment
    addWf trn_reps_rq,F
    goto S_scan_end_adjust

S_scan_end_adjust:
    retlw .1
        

S_slew
	movlw slew_train_reps			;test if count=sleW
	subwf trn_reps_rq,W			;W->count-sleW
	btfsc STATUS,Z					;if z->1 count=sleW
	goto S_sleW_end_adjust       	;end
	btfsc STATUS,C
	goto S_slew_scan    	      	;count > sleW
    movlw slew_train_reps_increment
    addwf trn_reps_rq,F
    goto S_slew_end_adjust

S_slew_scan:
    movlw scan_train_reps			;test if count=scan
	subwf trn_reps_rq,W				;W->count-scan
	btfsc STATUS,C				
	goto S_slew_high          		;count > scan

S_sleW_low:
	movlw scan_train_reps_increment	;c->0: decrease count by scan increment
	subwf trn_reps_rq,F
	goto S_slew_end_adjust

S_slew_high:
	movlw slew_train_reps_increment	;count < scan :decrease by sleW increment
	addwf trn_reps_rq,F
	goto S_slew_end_adjust

S_slew_end_adjust:
    retlw D'1'

cmd_wr_interpret:
;------------------------------------------------
;command interpreter and dispatch functions for data update
;uses W to pass error numbers - 0 is ok
;Uses FSR, CNTR, W & Z
	movf BUFFER,W
	xorlw .00
	btfsc STATUS,Z
	goto cmd_wr_track
;	xorlw .01^.00
;	btfsc STATUS,Z
;	goto cmd_set_move
	retlw .1

cmd_rd_interpret:
;------------------------------------------------
;command interpreter and dispatch functions for data request
;uses W to pass error numbers - 0 is ok
;Uses FSR, CNTR, W & Z to setup output data buffer
	movf BUFFER,W
	xorlw .00
	btfsc STATUS,Z
	goto cmd_rd_track
;	xorlw .01^.00
;	btfsc STATUS,Z
;	goto cmd_set_move
	movlw BUFFER
	movwf FSR
	movlw .0
	movwf CNTR
	retlw .1

cmd_rd_move:
	movf train_rep_req,W
	movwf BUFFER
	movlw .1
	movwf CNTR
	retlw .0

cmd_wr_track
	movf BUFFER,W
	movwf track_rate
	clrf CNTR
	retlw 0

;command to control type of movement required of stepper
cmd_wr_move:
	movf BUFFER,W
cmd0:
	xorlw .00
	btfss STATUS,Z
	goto cmd1
	movf track_rate,W
	movwf train_rep_req
	bcf step_status,rateH
	bsf step_status,rateL
	bsf step_status,reqd_dirn
	retlw .0
cmd1:
	xorlw .01^.00
	btfss STATUS,Z
	goto cmd2
	bsf step_status,rateH
	bcf step_status,rateL
	bcf step_status,reqd_dirn
	retlw .0
cmd2:
	xorlw .02^.01
	btfss STATUS,Z
	goto cmd3
	bsf step_status,rateH
	bcf step_status,rateL
	bsf step_status,reqd_dirn
	retlw .0
cmd3:
	xorlw .03^.02
	btfss STATUS,Z
	goto cmd4
	bsf step_status,rateH
	bsf step_status,rateL
	bcf step_status,reqd_dirn
	retlw .0
cmd4:
	xorlw .04^.03
	btfss STATUS,Z
	retlw .1
	bsf step_status,rateH
	bsf step_status,rateL
	bsf step_status,reqd_dirn
	retlw .0
END

⌨️ 快捷键说明

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