LIST P=16F84A
INCLUDE <p16f84a.inc>
__CONFIG _PWRTE_ON & _CP_OFF & _WDT_OFF & _RC_OSC
ERRORLEVEL 1
RADIX DEC
cblock 0x0c
cstep ;current step index
istep ;invert current step index
nopcnt ;something to do
save_w ;W register
save_status ;status bits
endc
#define f_ledon flag,0 ; it is 1 if LED is ON
;start program at memory location zero
org 0
;fill memory spots 0-3 w/ house keeping and goto real start
clrf TMR0
clrf PORTB
clrf PORTB
goto begin
;0004h - Interupt memory location - this is a 'goto int routine'
goto inter
;MAIN PROGRAM
begin
;porta not used
movlw 0xff
banksel TRISA
movwf TRISA
;portb pin 0,1 input, rest output
movlw 0x03 ;0000 0011
banksel TRISB
movwf TRISB
movlw B'10000000'
banksel PORTB
clrf PORTB
iorwf PORTB
;OPTION register bits
;B7 - !RBPU - internal pull-up resitors on port B are disabled
;B6 - INTEDG - external interrupt in on rising edge (0 to 1 transition)
;B5 - RTS - instruction clock is from internal oscillator
;B4 - RTE - RA4 rise/fall select (if RTS = 1)
;B3 - PSA - prescaler is assigned to timer 0
;B2,B1,B0 - PS2,1,0 - set to zero for faster resets.
; for clarity the value is specified in binary notation
movlw B'11001001'
banksel OPTION_REG
movwf OPTION_REG
banksel 0
; now we go back to bank 0 of RAM, where we have our variables
bcf STATUS,RP0
; we clear some variables, as needed
clrf cstep ;current step index
clrf nopcnt ;no op counter. just give the CPU something to do
; now we enable the interrupts, setting three bits in the INTCON register
; they are the external interrupt enable (INTE), the timer 0 interrupt
; enable (T0IE) and the general interrupt enable (GIE)
; to be shorter we do it loading a single value in INTCON
movlw B'10110000'
movwf INTCON
;initialization complete - begin main loop
loop ;incf TMR0
goto loop
; here is the interrupt service routine! all things will happen here
; first of all we MUST save the current STATUS and W registers
; the istruction MOVF must be avoided, because in alters the status!
inter movwf save_w
swapf STATUS,W
movwf save_status
; since there are two possibile interupt source in this program,
; first of all we must know who generated this interrupt;
; if it was the step pulse, we jump to its routine
btfss INTCON,T0IF
goto stepin
; we're here because of the timer
; we clear the timer interrupt flag, to enable it for the next time
bcf INTCON,T0IF
; if hearbeat = 0 (rolled around the byte cycle) toggle LED (RB3)
incfsz nopcnt
goto endint
movlw B'00001000' ; mask for bit 3
banksel PORTB
xorwf PORTB ; toggle PORTA,bit3 (toggle the led)
banksel 0
goto endint
;step in time! - disable further stepin interrupts?
stepin bcf INTCON,INTE
bcf INTCON,INTF ;clear RB0 int flag
;test dir flag - RB1, if 1 go forward, 0 go backward
btfss PORTB, 1 ;skip goto if set
goto bckup
incf cstep ; add 1
goto mod8
bckup decf cstep ; subtract 1
mod8 movlw B'00000111' ; setup bitmap for AND
andwf cstep ; bitwise AND with 7 to mod8
;convert cstep into output bits (stpdec)
;output bits on PORTB
movfw cstep
call stpdec
banksel PORTB
movwf PORTB
banksel 0
;restore step toggle interrupt
bsf INTCON,INTE
; this is the common end for the two interrupt routines
; we restore the STATUS and W registers, then we end the interrupt
endint swapf save_status,w
movwf STATUS
swapf save_w,f
swapf save_w,w
retfie
;===========================
;Next step
; 8 steps of the motor (0-7)
stpdec addwf PCL, f
retlw B'10000000'
retlw B'11000000'
retlw B'01000000'
retlw B'01100000'
retlw B'00100000'
retlw B'00110000'
retlw B'00010000'
retlw B'10010000'
end