Full Version : Bipolar Stepper Motor Dirver (AVR ASM)
avr >>MOTORS SERVOS & PWM >>Bipolar Stepper Motor Dirver (AVR ASM)


AVR_Admin- 04-16-2006
stepper motor driverThis is my second asm program, made for controlling three stepper-motors which I intend on using to make a cnc machine, together with the program turbocnc.

Chip controls motors with 6 input-pins, 2 for each motor. One for step, and one for direction of step, and 4 outputs per motor.

Edit: I've updated the source alot, very small easy program but does it's job very fast. Made a board in eagle which works as it should.

CODE
;**********************************************************************
; 3 axis stepper motor driver, by Njål Brekke aka Elenhinan
; 01/09-2005 -> 19/09-2005
;
; This program is meant for controlling three stepper-motors used
; in conjunction with TurboCNC
;
;**********************************************************************
; notes
;**********************************************************************
;
; program is made 72 cycles long, and uses all 18 io-ports.
; reset must be disabled
;
;
;**********************************************************************

; port a:

; pa0 = motor 1, step
; pa1 = motor 1, dir
; pa2 = motor 2, step

; port b:

; pb0 = motor 1, coil 11
; pb1 = motor 1, coil 12
; pb2 = motor 1, coil 21
; pb3 = motor 1, coil 22
; pb4 = motor 2, coil 11
; pb5 = motor 2, coil 12
; pb6 = motor 2, coil 21
; pb7 = motor 2, coil 22
;
; port d:

; pd0 = motor 2 dir
; pd1 = motor 3 step
; pd2 = motor 3 dir
; pd3 = motor 3, coil 11
; pd4 = motor 3, coil 11
; pd5 = motor 3, coil 11
; pd6 = motor 3, coil 11
; pd7 = n/a

;**********************************************************************

.include "tn2313def.inc"

;**********************************************************************
; register usage
;**********************************************************************

; low registers, 0-15
.def last_input = r0

.def motorA_step = r1
.def motorB_step = r2
.def motorC_step = r3

; high registers, 16-31

.def tmp = r16
.def tmp2= r17
.def input = r18

.def motorA_out = r19
.def motorB_out = r20
.def motorC_out = r21

;**********************************************************************
; ports
;**********************************************************************

; bit in register "input"
.equ axisA_step = 2
.equ axisA_dir = 3
.equ axisB_step = 4
.equ axisB_dir = 1
.equ axisC_step = 0
.equ axisC_dir = 5

.equ porta_out = 0b11111000; input: pin 123
.equ portb_out = 0b11111111; ouput: 0123 4567
.equ portd_out = 0b11111000; input: pin 012, output: 3456

.equ porta_pup = 0b00000111
.equ portd_pup = 0b00000111

;**********************************************************************
; bipolar step patterns
;**********************************************************************

.equ stepA0 = 0b01010000
.equ stepA1 = 0b01100000
.equ stepA2 = 0b10100000
.equ stepA3 = 0b10010000

.equ stepB0 = 0b00000101
.equ stepB1 = 0b00000110
.equ stepB2 = 0b00001010
.equ stepB3 = 0b00001001

.equ stepC0 = 0b00101000
.equ stepC1 = 0b00110000
.equ stepC2 = 0b01010000
.equ stepC3 = 0b01001000

;**********************************************************************
; program segment
;**********************************************************************

.cseg
.org  0x0000
rjmp start ; start/reset
reti  ; int0
reti  ; int1
reti  ; timer1 capture
reti  ; timer1 compare a
reti  ; timer1 overflow
reti  ; timer0 overflow
reti  ; usart
reti  ; usart
reti  ; usart
reti  ; analog comparator
reti  ; pin change interrupt
reti  ; timer1 compare b
reti  ; timer0 compare a
reti  ; timer0 compare b
reti  ; usi
reti  ; usi
reti  ; eeprom ready
reti  ; watchdog overflow

;**********************************************************************
; init
;**********************************************************************
start:
; setup stack
ldi tmp,low(RAMEND); Set initial stack pointer location at ram end
out SPL, tmp

; setup ports

ldi tmp, porta_out
out ddra, tmp
ldi tmp, porta_pup
out porta, tmp

ldi tmp, portd_out
out ddrd, tmp
ldi tmp, portd_pup
out portd, tmp

ldi tmp, portb_out
out ddrb, tmp

clr tmp
out portb, tmp

ldi motorA_out,stepA0; set inital step for motors
ldi motorB_out,stepB0
ldi motorC_out,stepC0

clr tmp
clr tmp2
start_end:
inc tmp
brvc start_end2
inc tmp2
brvc main
start_end2:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
rjmp start_end

;**********************************************************************
; main
;**********************************************************************
main:
; get input from pinA(0,1,2) & pinD(4,5,6)
in input,pina; read input from port A
in tmp, pind; read input from port D
cbr tmp, 0b11111000; isolate pin 4 5 6
swap tmp   ; shift to bit 3 4 5
lsr tmp
add input, tmp ; add results from portA and portD to input

;**********************************************************************

stepA:
sbrc input,axisA_step
rjmp stepA_2
sbrs last_input,axisA_step
rjmp stepA_3

stepA_1:
sbrc input,axisA_dir; check direction
dec motorA_step
sbrs input,axisA_dir
inc motorA_step
mov tmp, motorA_step; copy step# to param tmp
cbr tmp, 0b11111100 ; use only 0-3
lsl tmp    ; multiply with 2
ldi ZL,low(stepA_jump)
ldi ZH,high(stepA_jump)
add ZL,tmp   ; jump to adr (step_jump + step# * 2)
ijmp
stepA_jump:
ldi motorA_out,stepA0
rjmp stepB
ldi motorA_out,stepA1
rjmp stepB
ldi motorA_out,stepA2
rjmp stepB
ldi motorA_out,stepA3
rjmp stepB
stepA_2:
nop; compensate for jump if step isn't high, 2 cycles
nop
stepA_3:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop

;**********************************************************************

stepB:
sbrc input,axisB_step
rjmp stepB_2
sbrs last_input,axisB_step
rjmp stepB_3

stepB_1:
sbrc input,axisB_dir; check direction
dec motorB_step
sbrs input,axisB_dir
inc motorB_step
mov tmp, motorB_step; copy step# to param tmp
cbr tmp, 0b11111100 ; use only 0-3
lsl tmp    ; multiply with 2
ldi ZL,low(stepB_jump)
ldi ZH,high(stepB_jump)
add ZL,tmp   ; jump to adr (step_jump + step# * 2)
ijmp
stepB_jump:
ldi motorB_out,stepB0
rjmp stepC
ldi motorB_out,stepB1
rjmp stepC
ldi motorB_out,stepB2
rjmp stepC
ldi motorB_out,stepB3
rjmp stepC
stepB_2:
nop; compensate for jump if step isn't high, 2 cycles
nop
stepB_3:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop

;**********************************************************************

stepC:
sbrc input,axisC_step
rjmp stepC_2
sbrs last_input,axisC_step
rjmp stepC_3

stepC_1:
sbrc input,axisC_dir; check direction
dec motorC_step
sbrs input,axisC_dir
inc motorC_step
mov tmp, motorC_step; copy step# to param tmp
cbr tmp, 0b11111100 ; use only 0-3
lsl tmp    ; multiply with 2
ldi ZL,low(stepC_jump)
ldi ZH,high(stepC_jump)
add ZL,tmp   ; jump to adr (step_jump + step# * 2)
ijmp
stepC_jump:
ldi motorC_out,stepC0
rjmp main_end
ldi motorC_out,stepC1
rjmp main_end
ldi motorC_out,stepC2
rjmp main_end
ldi motorC_out,stepC3
rjmp main_end
stepC_2:
nop; compensate for jump if step isn't high, 2 cycles
nop
stepC_3:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop

;**********************************************************************

main_end:
mov tmp,motorA_out
add tmp,motorB_out
out portb,tmp; update output to motor 1 & 2

mov tmp,motorC_out
sbr tmp,portd_pup
out portd,tmp; update output to motor 3

mov last_input,input; move last input for checking next run
rjmp main

;**********************************************************************



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.