; ******
<META http-equiv="Bulletin-Text" content="">
************************************************************************
;
; LiniStepper v2
; PIC 16F84 / 16F628 / 16F628A code (updated 628A June 2007)
; Copyright Aug 2002 - Nov 2009 - Roman Black http://www.romanblack.com
;
; PIC assembler code for the LiniStepper stepper motor driver board.
; 200/400/1200/3600 steps
;
; v2.0 New version 2.0; 2nd Nov 2009.
; * modified v1 source to work with new Lini v2 PCB.
; * STEP and DIR are the same, but POWER is now "ENABLE" (active LOW)
; (so the POWER pin function is inverted in Lini v2)
; v2.1 Updated 16th Nov 2010.
; Now incorporates update suggested by Brian D Freeman; improves
; performance by skipping the current calculation on the hi-lo
; transition of the step input.
;
; (set mplab TABS to 5 for best viewing this .asm file)
;******************************************************************************
;==============================================================================
; mplab settings
ERRORLEVEL -224 ; suppress annoying message because of option/tris
ERRORLEVEL -302 ; suppress message because of bank select in setup ports
LIST b=5, n=97, t=ON, st=OFF ;
; absolute listing tabs=5, lines=97, trim long lines=ON, symbol table=OFF
;==============================================================================
; processor defined
;include <p16f84A.inc>
;include <p16f628.inc>
include <p16f628A.inc>
; processor config
IFDEF __16F84A
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
ENDIF
IFDEF __16F628
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _MCLRE_ON & _BODEN_OFF & _LVP_OFF
ENDIF
IFDEF __16F628A
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _MCLRE_ON & _BODEN_OFF & _LVP_OFF
ENDIF
;==============================================================================
; Variables here
;-------------------------------------------------
IFDEF __16F84A
#define RAM_START 0x0C
#define RAM_END RAM_START+d'68' ; 16F84 has only 68 ram
ENDIF
IFDEF __16F628
#define RAM_START 0x20
#define RAM_END RAM_START+d'96' ; F628 has 96 ram
ENDIF
IFDEF __16F628A
#define RAM_START 0x20
#define RAM_END RAM_START+d'96' ; F628A has 96 ram
ENDIF
;-------------------------------------------------
CBLOCK RAM_START
status_temp ; used for int servicing
w_temp ; used for int servicing
step ; (0-71) ustep position!
steptemp ; for calcs
phase ; stores the 4 motor phase pins 0000xxxx
current1 ; for current tween pwm
current2 ; for current tween pwm
inputs ; stores new input pins
inputs_last ; stores last states of input pins
ENDC
;-------------------------------------------------
; PIC input pins for porta
#define STEP 0 ; / = move 1 step, \=do nothing
#define DIR 1 ; lo= cw, hi=ccw
#define POWER 2 ; lo=full power, hi=half power
; (Note! POWER pin was inverted for v2 !!!)
;-------------------------------------------------
; Custom instructions!
#define skpwne skpnz ; after subxx, uses zero
#define skpweq skpz ; after subxx, uses zero
#define skpwle skpc ; after subxx, uses carry
#define skpwgt skpnc ; after subxx, uses carry
;==============================================================================
; CODE GOES HERE
org 0x0000 ; Set program memory base at reset vector 0x00
reset
goto main ;
;==============================================================================
; INTERRUPT vector here
org 0x0004 ; interrupt routine must start here
int_routine
;-------------------------------------------------
; first we preserve w and status register
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
;-------------------------------------------------
; we get here every 256 timer0 ticks 3900Hz
; int body code here if you want
;-------------------------------------------------
; finally we restore w and status registers and
; clear TMRO int flag now we are finished.
int_exit
bcf INTCON,T0IF ; reset the tmr0 interrupt flag
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
;-------------------------------------------------
;==============================================================================
;******************************************************************************
; MOVE MOTOR sets 8 portb output pins to control motor
;******************************************************************************
; NOTE!! var step is used for sequencing the 0-71 steps
; uses tables! so keep it first in the code and set PCLATH to page 0
;------------------
move_motor ; goto label
;------------------
;-------------------------------------------------
; this code controls the phase sequencing and current
; settings for the motor.
; there are always 72 steps (0-71)
; we can split the main table into 2 halves, each have identical
; current sequencing. That is only 12 entries for hardware current.
; Then can x3 the table to get 36 table entries which cover all 72 steps.
; the 36 entries jump to 36 code pieces, which set the current values
; for the 2 possible tween steps... We need 2 current values, one
; for the x2 value and one for the x1 value.
;-------------------------------------------------
; PHASE SEQUENCING (switch the 4 coils)
; there are 4 possible combinations for the phase switching:
; each have 18 steps, total 72 steps:
; A+ B+ range 0 step 0-17
; A- B+ range 1 18-35
; A- B- range 2 36-53
; A+ B- range 3 54-71
;-------------------------------------------------
; find which of the 4 ranges we are in
movf step,w ; get step
movwf steptemp ; store as working temp
movf steptemp,w ;
sublw d'35' ; sub to test
skpwle ;
goto half_hi ; wgt, steptemp is 36-71 (upper half)
;-------------------------
half_low ; wle, steptemp is 0-35
movf steptemp,w ;
sublw d'17' ; sub to test
skpwle ;
goto range1 ; wgt
range0 ; wle
movlw b'00000101' ; 0101 = A+ B+
goto phase_done ;
range1
movlw b'00001001' ; 1001 = A- B+
goto phase_done ;
;-------------------------
half_hi ; steptemp is 36-71
; NOTE! must subtract 36 from steptemp, so it
; will become 0-35 and ok with table later!
movlw d'36' ; subtract 36 from steptemp,
subwf steptemp,f ; (now steptemp is 0-35)
; now find the range
movf steptemp,w ;
sublw d'17' ; sub to test
skpwle ;
goto range3 ; wgt
range2 ; wle
movlw b'00001010' ; 1010 = A- B-
goto phase_done ;
range3
movlw b'00000110' ; 0110 = A+ B-
phase_done ; note! steptemp is always 0-35 by here
movwf phase ; store phase values
;-------------------------------------------------
; at this point we have the phasing done and stored as the last
; 4 bits in var phase; 0000xxxx
; now we have 36 possible current combinations, which we can do
; by separate code fragments, from a jump table.
; as we have 2 power modes; full and low power, we
; need 2 tables.
;-------------------------------------------------
btfsc inputs,POWER ; select table to use
goto table_lowpower ;
;-------------------------------------------------
; HIGH POWER TABLE
;-------------------------------------------------
table_highpower ;
movf steptemp,w ; add steptemp to the PCL
addwf PCL,f ;
; here are the 36 possible values;
;-------------------------
goto st00 ; * (hardware 6th steps)
goto st01 ; (pwm tween steps)
goto st02 ; (pwm tween steps)
goto st03 ; *
goto st04 ;
goto st05 ;
goto st06 ; *
goto st07 ;
goto st08 ;
goto st09 ; *
goto st10 ;
goto st11 ;
goto st12 ; *
goto st13 ;
goto st14 ;
goto st15 ; *
goto st16 ;
goto st17 ;
goto st18 ; *
goto st19 ;
goto st20 ;
goto st21 ; *
goto st22 ;
goto st23 ;
goto st24 ; *
goto st25 ;
goto st26 ;
goto st27 ; *
goto st28 ;
goto st29 ;
goto st30 ; *
goto st31 ;
goto st32 ;
goto st33 ; *
goto st34 ;
goto st35 ;
;-------------------------------------------------
; LOW POWER TABLE
;-------------------------------------------------
; as low power mode is for wait periods we don't need to
; maintain the full step precision and can wait on the
; half-step (400 steps/rev). This means much easier code tables.
; The nature of the board electronics is not really suited
; for LOW power microstepping, but it could be programmed here
; if needed.
; NOTE!! uses my hi-torque half stepping, not normal half step.
; doing half stepping with the 55,25 current values gives;
; 55+25 = 80
; max current 100+100 = 200
; typical (high) current 100+50 = 150
; so low power is about 1/2 the current of high power mode,
; giving about 1/4 the motor heating and half the driver heating.
; for now it uses only half-steps or 8 separate current modes.
; we only have to use 4 actual current modes as
; the table is doubled like the table_highpower is.
; NOTE!! I have left the table full sized so it can be modified
; to 1200 or 3600 steps if needed.
;-------------------------------------------------
table_lowpower ;
movf steptemp,w ; add steptemp to the PCL
addwf PCL,f ;
; here are the 36 possible values;
;-------------------------
; A+ B+ (A- B-)
goto lp00 ;
goto lp00 ;
goto lp00 ;
goto lp00 ;
goto lp00 ; 55,25 (100,45) current low (high)
goto lp00 ;
goto lp00 ;
goto lp00 ;
goto lp00 ;
goto lp09 ;
goto lp09 ;
goto lp09 ;
goto lp09 ;
goto lp09 ; 25,55 (45,100)
goto lp09 ;
goto lp09 ;
goto lp09 ;
goto lp09 ;
;-------------------------
; A- B+ (A+ B-)
goto lp18 ;
goto lp18 ;
goto lp18 ;
goto lp18 ;
goto lp18 ; 25,55 (45,100)
goto lp18 ;
goto lp18 ;
goto lp18 ;
goto lp18 ;
goto lp27 ;
goto lp27 ;
goto lp27 ;
goto lp27 ;
goto lp27 ; 55,25 (100,45)
goto lp27 ;
goto lp27 ;
goto lp27 ;
goto lp27 ;
;-------------------------------------------------
; all tables done, no more tables after this point!
;-------------------------------------------------
; next are the 36 code fragments for the high power table.
; CURRENT INFO.
; hardware requires that we send the entire 8 bits to the motor
; at one time, to keep pwm fast.
; ----xxxx, where xxxx is the coils on/off phasing (done)
; xxxx----, where xxxx is the current settings for the A and B phases;
; xx------, where xx is current for A phase
; --xx----, where xx is current for B phase
; hardware currents for 6th stepping have 4 possible values;
; 00 = 0% current
; 01 = 25% current
; 10 = 55% current
; 11 = 100% current
;-------------------------------------------------
; PWM INFO.
; hardware gives us 6th steps, or 1200 steps/rev.
; to get 3600 steps/rev we need TWO more
; "tween" steps between every proper hardware 6th step.
; to do this we set 2 currents, current1 and current2.
; then we do FAST pwm, with 2 time units at current2,
; and 1 time unit at current1.
; this gives a current which is between the two currents,
; proportionally closer to current2. (2/3 obviously)
; this gives the ability to get 2 evenly spaced "tween" currents
; between our hardware 6th step currents, and go from 1200 to 3600.
; the next 36 code fragments set the 2 currents desired, then
; we goto a fast-pwm loop (same loop used for all currents)
; which modulates between the 2 currents and gives final
; output current.
;-------------------------------------------------
st00 ; (6th step)
movf phase,w ; get coil phasing (is 0000xxxx)
iorlw b'11000000' ; set currents; 100,0
movwf current2 ;
movwf current1 ;
goto pwm ;
st01 ; (tween step)
movf phase,w ; get coil phasing
iorlw b'11000000' ; set 100,0
movwf current2 ;
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current1 ;
goto pwm ;
st02 ; (tween step)
movf phase,w ; get coil phasing
iorlw b'11010000' ; set 100,25
movwf current2 ;
movf phase,w ;
iorlw b'11000000' ; set 100,0
movwf current1 ;
goto pwm ;
;-------------------------
st03 ; (6th step)
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current2 ;
movwf current1 ;
goto pwm ;
st04 ;
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current2 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current1 ;
goto pwm ;
st05 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current2 ;
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current1 ;
goto pwm ;
;-------------------------
st06 ; (6th step)
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current2 ;
movwf current1 ;
goto pwm ;
st07 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current2 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current1 ;
goto pwm ;
st08 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current2 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current1 ;
goto pwm ;
;-------------------------
st09 ; (6th step)
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current2 ;
movwf current1 ;
goto pwm ;
st10 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current2 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current1 ;
goto pwm ;
st11 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current2 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current1 ;
goto pwm ;
;-------------------------
st12 ; (6th step)
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current2 ;
movwf current1 ;
goto pwm ;
st13 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current2 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current1 ;
goto pwm ;
st14 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current2 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current1 ;
goto pwm ;
;-------------------------
st15 ; (6th step)
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current2 ;
movwf current1 ;
goto pwm ;
st16 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current2 ;
movf phase,w ;
iorlw b'00110000' ; set 0,100
movwf current1 ;
goto pwm ;
st17 ;
movf phase,w ;
iorlw b'00110000' ; set 0,100
movwf current2 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current1 ;
goto pwm ;
;-------------------------
;-------------------------
st18 ; (6th step)
movf phase,w ;
iorlw b'00110000' ; set 0,100
movwf current2 ;
movwf current1 ;
goto pwm ;
st19 ;
movf phase,w ;
iorlw b'00110000' ; set 0,100
movwf current2 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current1 ;
goto pwm ;
st20 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current2 ;
movf phase,w ;
iorlw b'00110000' ; set 0,100
movwf current1 ;
goto pwm ;
;-------------------------
st21 ; (6th step)
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current2 ;
movwf current1 ;
goto pwm ;
st22 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current2 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current1 ;
goto pwm ;
st23 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current2 ;
movf phase,w ;
iorlw b'01110000' ; set 25,100
movwf current1 ;
goto pwm ;
;-------------------------
st24 ; (6th step)
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current2 ;
movwf current1 ;
goto pwm ;
st25 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current2 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current1 ;
goto pwm ;
st26 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current2 ;
movf phase,w ;
iorlw b'10110000' ; set 55,100
movwf current1 ;
goto pwm ;
;-------------------------
st27 ; (6th step)
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current2 ;
movwf current1 ;
goto pwm ;
st28 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current2 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current1 ;
goto pwm ;
st29 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current2 ;
movf phase,w ;
iorlw b'11110000' ; set 100,100
movwf current1 ;
goto pwm ;
;-------------------------
st30 ; (6th step)
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current2 ;
movwf current1 ;
goto pwm ;
st31 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current2 ;
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current1 ;
goto pwm ;
st32 ;
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current2 ;
movf phase,w ;
iorlw b'11100000' ; set 100,55
movwf current1 ;
goto pwm ;
;-------------------------
st33 ; (6th step)
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current2 ;
movwf current1 ;
goto pwm ;
st34 ;
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current2 ;
movf phase,w ;
iorlw b'11000000' ; set 100,0
movwf current1 ;
goto pwm ;
st35 ;
movf phase,w ;
iorlw b'11000000' ; set 100,0
movwf current2 ;
movf phase,w ;
iorlw b'11010000' ; set 100,25
movwf current1 ;
goto pwm ;
; high power table done!
;-------------------------------------------------
; next are the 4 code fragments for the low power table.
; (no PWM is used)
;-------------------------------------------------
lp00 ;
movf phase,w ;
iorlw b'10010000' ; set 55,25
movwf current2 ;
movwf current1 ;
goto pwm ;
lp09 ;
movf phase,w ;
iorlw b'01100000' ; set 25,55
movwf current2 ;
movwf current1 ;
goto pwm ;
lp18 ;
movf phase,w ;
iorlw b'01100000' ; set 25,55
movwf current2 ;
movwf current1 ;
goto pwm ;
lp27 ;
movf phase,w ;
iorlw b'10010000' ; set 55,25
movwf current2 ;
movwf current1 ;
goto pwm ;
;-------------------------------------------------
;------------------------------------------------------------------------------
;******************************************************************************
; Main
;******************************************************************************
;
;------------------
main ; goto label
;------------------
;---------------------------------------------
; do initial setup for ports and ints and stuff
call setup ; this is our only proper call...
; it is called only once, and does not really need
; to be a function.
;---------------------------------------------
; main operating loop is here.
;---------------------------------------------
goto move_motor ; will set the motor to step 0,
; and loop permanently from there
;---------------------------------------------
goto main ; safe loop, should never get here anyway.
;==============================================================================
;******************************************************************************
; NEW INPUTS input change was detected
;******************************************************************************
;
;------------------
new_inputs ; goto tag
;------------------
;-------------------------------------------------
; when we enter here:
; * one or more PORTA inputs have just changed
; * inputs_last contains last PORTA inputs values
; * inputs contains new PORTA inputs values
;-------------------------------------------------
; must first detect which input pins changed.
; ---x---- RA4 * mode bit1 ( 00=200 step 01=400 step
; ----x--- RA3 * mode bit0 10=1200 step 11=3600 step )
; -----x-- RA2 * power (Lini v2; now 0 = full power!)
; ------x- RA1 * direction
; -------x RA0 * step
; if step went hi, we move the step (step++ or step--)
; if step went low, ignore
; ignore change in direction pin
; ignore change in power pin
; ignore change in mode pins
; (all pins besides step are handled automatically in move_motor)
;-------------------------------------------------
movf inputs,w ; xor to compare new inputs with last values
xorwf inputs_last,f ; now inputs_last has the diff.
btfss inputs_last,STEP ; test if step input changed
goto ni_end ;
; step input changed!
btfsc inputs,STEP ; test if change was lo-hi or hi-lo
goto trans_hi ; lo-hi, so process a step!
; hi-lo, so ignore this transition
bcf inputs_last,STEP ; record new state of step pin
goto pwm ; fast exit back to pwm()
;-------------------------------------------------
; step input changed lo-hi!
; now must make a step forward or back, based
; on the state of the dir pin.
; here it gets complex as we have 4 operating modes,
; determined by the state of the 2 input pins RA4 and RA3;
; ---00--- 200 steps
; ---01--- 400 steps
; ---10--- 1200 steps
; ---11--- 3600 steps
; there are 4 separate code systems to handle stepping
; in the 4 modes;
;-------------------------------------------------
trans_hi
; find which of the 4 modes we are in
btfss inputs,4 ; test hi bit
goto mode_lo ;
mode_hi ; must be 1200 or 3600
btfss inputs,3 ; test lo bit
goto mode_1200 ;
;-------------------------------------------------
mode_3600 ; 3600 mode (72/1)
; each step is 1
btfss inputs,DIR ; test direction input
goto m36_up ;
m36_down
decf step,f ; step--
btfss step,7 ; test for roll under <0
goto ni_end ; ok
; rolled under!
movlw d'71' ; force to top step (72-1)
movwf step ;
goto ni_end ;
m36_up
incf step,f ; step++
movf step,w ; test for roll over >71
sublw d'71' ; sub to test
skpwle ;
clrf step ; wgt, rolled over so force to step 0
goto ni_end ;
;-------------------------------------------------
mode_1200 ; 1200 mode (72/3)
; each step is mod 3 (0,3,6,9,12 - 66, 69 etc)
btfss inputs,DIR ; test direction input
goto m12_up ;
m12_down
movlw d'3' ; amount to subtract
subwf step,f ; step-=3
btfss step,7 ; test for roll under <0
goto ni_end ; ok
; rolled under!
movlw d'69' ; force to top step (72-3)
movwf step ;
goto ni_end ;
m12_up
movlw d'3' ; amount to add
addwf step,f ; step+=3
;
movf step,w ; test for roll over >69
sublw d'69' ; sub to test
skpwle ;
clrf step ; wgt, rolled over so force to step 0
goto ni_end ;
;-------------------------------------------------
mode_lo ; must be 200 or 400
btfss inputs,3 ; test lo bit
goto mode_200 ;
;-------------------------------------------------
mode_400 ; 400 mode (72/9)
; note! we do special half stepping here.
; there are ONLY 8 valid steps:
; 4, 13, 22, 31, 40, 49, 58, 67
; these steps give 100,45 and 35,100 combos, good
; enough for now. (should average 100,41)
btfss inputs,DIR ; test direction input
goto m4_up ;
m4_down
movlw d'9' ; amount to subtract
subwf step,f ; step-=9
btfss step,7 ; test for roll under <0
goto ni_end ; ok
; rolled under!
movlw d'67' ; force to top (full) step
movwf step ;
goto ni_end ;
m4_up
movlw d'9' ; amount to add
addwf step,f ; step+=9
;
movf step,w ; test for roll over
sublw d'67' ; sub to test
skpwgt ;
goto ni_end ; wle, is ok
movlw d'4' ; wgt, rolled over so force to bottom step 5
movwf step ;
goto ni_end ;
;-------------------------------------------------
mode_200 ; 200 mode (72/18)
; NOTE!! this has special needs as we can't use
; step 0, we need to stay on the "2 steps on" steps.
; there are ONLY 4 valid steps; 9, 27, 45, 63
btfss inputs,DIR ; test direction input
goto m2_up ;
m2_down
movlw d'18' ; amount to subtract
subwf step,f ; step-=18
btfss step,7 ; test for roll under <0
goto ni_end ; ok
; rolled under!
movlw d'63' ; force to top (full) step (72-(18/2))
movwf step ;
goto ni_end ;
m2_up
movlw d'18' ; amount to add
addwf step,f ; step+=18
;
movf step,w ; test for roll over
sublw d'63' ; sub to test
skpwgt ;
goto ni_end ; wle, is ok
movlw d'9' ; wgt, rolled over so force to bottom step 9
movwf step ;
goto ni_end ;
;-------------------------------------------------
ni_end
movf inputs,w ; save a copy of the inputs
movwf inputs_last ;
goto move_motor ; go and make it all happen
;------------------------------------------------------------------------------
;******************************************************************************
; PWM is the fast pwm loop
;******************************************************************************
; NOTE!! we enter the code in the middle of the loop!
;-------------------------------------------------
; the 2 target currents were set in the move_motor code.
; what this function does is spend 2 time units at current2,
; and 1 time unit at current1.
; actual is 8 clocks at current2
; and 4 clocks at current 1
; total 12 cycles, so 333 kHz with 16MHz resonator.
; this gives an average pwm current of 2/3 the way between
; current2 and current1.
; the routine is kept short to keep pwm frequency high, so it
; is easy to smooth in hardware by the ramping caps.
; IMPORTANT! is timed by clock cycles, don't change this code!
; it also checks for any change in input pins here
; the 8/4 code seen here was supplied by Eric Bohlman (thanks!)
;-------------------------------------------------
pwm_loop
; first output current1 to motor
movf current1,w ; get currents and phase switching
movwf PORTB ; send to motor!
nop ; timing delay
nop ;
; (4 cycles)
;-------------------------
pwm ; main entry!
; better to enter at current2 for motor power.
; now output current2
movf current2,w ;
movwf PORTB ; send to motor!
nop ; safe wait 250nS
; now test input pins
movf PORTA,w ; get pin values from port
xorwf inputs_last,w ; xor to compare new inputs with last values
skpnz
goto pwm_loop ; z, inputs not changed, so keep looping
; (8 cycles)
;-------------------------------------------------
; nz, one or more input pins have changed!
xorwf inputs_last,w ; restore xored value back to the orig inputs value
movwf inputs ;
goto new_inputs ;
;-------------------------------------------------
;------------------------------------------------------------------------------
;******************************************************************************
; SETUP sets port directions and interrupt stuff etc,
;******************************************************************************
; NOTE!! is the only proper funtion, is done before other activity
;------------------
setup ; routine tag
;------------------
;-------------------------------------------------
; Note! there are added bits for the 16F628!
; here we set up peripherals and port directions.
; this will need to be changed for different PICs.
;-------------------------------------------------
; OPTION setup
movlw b'10000010' ;
; x------- ; 7, 0=enable, 1=disable, portb pullups
; -x------ ; 6, 1=/, int edge select bit
; --x----- ; 5, timer0 source, 0=internal clock, 1=ext pin.
; ---x---- ; 4, timer0 ext edge, 1=\
; ----x--- ; 3, prescaler assign, 1=wdt, 0=timer0
; -----x-- ; 2,1,0, timer0 prescaler rate select
; ------x- ; 000=2, 001=4, 010=8, 011=16, etc.
; -------x ;
;
banksel OPTION_REG ; go proper reg bank
movwf OPTION_REG ; load data into OPTION_REG
banksel 0 ;
;-------------------------------------------------
; note! check for 16F628 (and A) and do extra setup for it.
IFDEF __16F628
banksel VRCON ; do bank 1 stuff
clrf VRCON ; disable Vref
clrf PIE1 ; disable pi etc
banksel 0 ;
clrf T1CON ; disable timer1
clrf T2CON ; disable timer2
clrf CCP1CON ; disable CCP module
movlw b'00000111' ; disable comparators
movwf CMCON ;
ENDIF
IFDEF __16F628A
banksel VRCON ; do bank 1 stuff
clrf VRCON ; disable Vref
clrf PIE1 ; disable pi etc
banksel 0 ;
clrf T1CON ; disable timer1
clrf T2CON ; disable timer2
clrf CCP1CON ; disable CCP module
movlw b'00000111' ; disable comparators
movwf CMCON ;
ENDIF
;-------------------------------------------------
; PORTB pins direction setup
; 1=input, 0=output
clrf PORTB ;
;
movlw b'00000000' ; all 8 portb are outputs
;
banksel TRISB ; go proper reg bank
movwf TRISB ; send mask to portb
banksel 0 ;
;-------------------------------------------------
; PORTA pins direction setup
; 1=input, 0=output
clrf PORTA ;
; NOTE!! all 5 PORTA pins are inputs
movlw b'00011111' ;
; ---x---- ; RA4
; ----x--- ; RA3
; -----x-- ; RA2
; ------x- ; RA1
; -------x ; RA0
banksel TRISA ; go proper reg bank
movwf TRISA ; send mask to porta
banksel 0 ;
;-------------------------------------------------
movlw 0x00 ; set up PCLATH for all jump tables on page 0
movwf PCLATH ; (all tables are in move_motor)
;-------------------------------------------------
; CLEAR RAM! for lower bank
movlw RAM_START ; first byte of ram
movwf FSR ; load pointer
ram_clear_loop
clrf INDF ; clear the ram we pointed to
incf FSR,f ; inc pointer to next ram byte
movf FSR,w ; get copy of pointer to w
sublw RAM_END ; test if PAST the last byte now
skpweq ;
goto ram_clear_loop ;
;-------------------------------------------------
; here we can set the user variables and output pins
movlw 0x00 ; for step 0 of 0-71
movwf step ; loaded ready for jump table
movf PORTA,w ; get initial value for inputs
movwf inputs ;
movwf inputs_last ;
;-------------------------------------------------
; set up INTCON register last
movlw b'00000000' ; set the bit value
; x------- ; bit7 GIE global int enable, 1=enabled
; -x------ ; bit6 EE write complete enable, 1=en
; --x----- ; bit5 TMR0 overflow int enable, 1=en
; ---x---- ; bit4 RB0/INT enable, 1=en
; ----x--- ; bit3 RB port change int enable, 1=en
; -----x-- ; bit2 TMR0 int flag bit, 1=did overflow and get int
; ------x- ; bit1 RB0/INT flag bit, 1=did get int
; -------x ; bit0 RB port int flag bit, 1=did get int
movwf INTCON ; put in INTCON register
;-------------------------------------------------
return ;
;------------------------------------------------------------------------------
;==============================================================================
; this code is only to display 1k of the memory usage chart
; in the absolute listing!
; page 0 256 byte block--------------------
;org 0x40-2
;nop
;org 0x80-1
;nop
;org 0xC0-1
;nop
;org 0x100-1
;nop
; page 1 256 byte block--------------------
;org 0x140-2
;nop
;org 0x180-1
;nop
;org 0x1C0-1
;nop
;org 0x200-1
;nop
; page 2 256 byte block--------------------
org 0x240-2
nop
org 0x280-1
nop
org 0x2C0-1
nop
org 0x300-1
nop
; page 3 256 byte block--------------------
org 0x340-2
nop
org 0x380-1
nop
org 0x3C0-1
nop
org 0x400-1
nop
IFDEF __16F628A
; page 4 256 byte block--------------------
org 0x440-2
nop
org 0x480-1
nop
org 0x4C0-1
nop
org 0x500-1
nop
; page 5 256 byte block--------------------
org 0x540-2
nop
org 0x580-1
nop
org 0x5C0-1
nop
org 0x600-1
nop
; page 6 256 byte block--------------------
org 0x640-2
nop
org 0x680-1
nop
org 0x6C0-1
nop
org 0x700-1
nop
; page 7 256 byte block--------------------
org 0x740-2
nop
org 0x780-1
nop
org 0x7C0-1
nop
org 0x800-1
nop
ENDIF
;-------------------------------------------------------------------------
end
;-------------------------------------------------------------------------
;==============================================================================
;==============================================================================
;==============================================================================
;-------------------------------------------------
; NOTE!! example! below is the original (non-pwm) table for the
; 24x hardware 6th steps.
; this will be useful to code a minimum-rom microstepper
; if you don't need 3600 and can make do with 1200 steps.
; same system as the main code;
; ----xxxx are the phase sequencing
; xxxx---- are the current values
; (this code table has been used and tested!)
;-------------------------------------------------
; COMMENTED OUT!
;movlw b'11000101' ; 0, 100,0 A+ B+ 00=0 01=25
;movlw b'11010101' ; 1, 100,25 A+ B+ 10=55 11=100
;movlw b'11100101' ; 2, 100,55 A+ B+
;movlw b'11110101' ; 3, 100,100 A+ B+
;movlw b'10110101' ; 4, 55,100 A+ B+
;movlw b'01110101' ; 5, 25,100 A+ B+
;-------------------------
;movlw b'00111001' ; 6, 0,100 A- B+
;movlw b'01111001' ; 7, 25,100 A- B+
;movlw b'10111001' ; 8, 55,100 A- B+
;movlw b'11111001' ; 9, 100,100 A- B+
;movlw b'11101001' ; 10, 100,55 A- B+
;movlw b'11011001' ; 11, 100,25 A- B+
;-------------------------
;movlw b'11001010' ; 12, 100,0 A- B-
;movlw b'11011010' ; 13, 100,25 A- B-
;movlw b'11101010' ; 14, 100,55 A- B-
;movlw b'11111010' ; 15, 100,100 A- B-
;movlw b'10111010' ; 16, 55,100 A- B-
;movlw b'01111010' ; 17, 25,100 A- B-
;-------------------------
;movlw b'00110110' ; 18, 0,100 A+ B-
;movlw b'01110110' ; 19, 25,100 A+ B-
;movlw b'10110110' ; 20, 55,100 A+ B-
;movlw b'11110110' ; 21, 100,100 A+ B-
;movlw b'11100110' ; 22, 100,55 A+ B-
;movlw b'11010110' ; 23, 100,25 A+ B-
EXAMPLE! full table example here, 0-71 steps showing every step...
;-------------------------
0 100,0 A+ B+
1 100,8 (pwm tween)
2 100,17 (pwm tween)
3 100,25 A+ B+
4 100,35 (pwm tween)
5 100,45 (pwm tween)
6 100,55 A+ B+
7 100,70 (pwm tween)
8 100,85 (pwm tween)
9 100,100 A+ B+ (rest of table is same, tweens not shown)
10
11
12 55,100 A+ B+
13
14
15 25,100 A+ B+
16
17
;-------------------------
18 0,100 A- B+
19
20
21 25,100 A- B+
22
23
24 55,100 A- B+
25
26
27 100,100 A- B+
28
29
30 100,55 A- B+
31
32
33 100,25 A- B+
34
35
;-------------------------
36 100,0 A- B-
37
38
39 100,25 A- B-
40
41
42 100,55 A- B-
43
44
45 100,100 A- B-
46
47
48 55,100 A- B-
49
50
51 25,100 A- B-
52
53
;-------------------------
54 0,100 A+ B-
55
56
57 25,100 A+ B-
58
59
60 55,100 A+ B-
61
62
63 100,100 A+ B-
64
65
66 100,55 A+ B-
67
68
69 100,25 A+ B-
70
71
;-------------------------------------------------
file: /Techref/io/stepper/linistep/Lini_asm_v21.asm, 36KB, , updated: 2019/6/10 20:10, local time: 2024/11/15 20:32,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/io/stepper/linistep/Lini_asm_v21.asm"> io stepper linistep Lini_asm_v21</A> |
Did you find what you needed?
|