📄 drivera.asm
字号:
dt 0, 1, 134, 160 ; 100000
dt 0, 0, 39, 16 ; 10000
dt 0, 0, 3, 232 ; 1000
dt 0, 0, 0, 100 ; 100
dt 0, 0, 0, 10 ; 10
dt 0, 0, 0, 1 ; 1
;
; User level subroutine call
; call with:
; PCLATH set to return addr top
; w set to return addr bottom
; b0mwsave set to calling w
;
savertn
banksel stackptr ;
movwf mlsave ; Save bottom of return addr
movfw FSR ; Save FSR
movwf mfsave ;
movfw stackptr ; Pick up stack pointer
movwf FSR ;
movfw mlsave ; Pick up bottom
movwf INDF ; Push on stack
decf FSR, f ;
movfw PCLATH ; Pick up top
movwf INDF ; Push on stack
decf FSR, f ;
movfw FSR ; Stash stack pointer
movwf stackptr ;
movfw mfsave ; Restore FSR
movwf FSR ;
banksel 0 ; Back to bank 0
movfw b0mwsave ;
return ; All done
;
; User level subroutine return
; Just jump here
;
restrtn
movwf b0mwsave ; Save w
banksel stackptr ;
movfw FSR ; Save FSR
movwf mfsave ;
movfw stackptr ; Load FSR from stack pointer
movwf FSR ;
incf FSR, f ; Back to saved hi addr
movfw INDF ;
movwf PCLATH ; Save in PCLATH
incf FSR, f ; Back to saved low addr
movfw INDF ;
movwf mlsave ; Stash for a minute
movfw FSR ;
movwf stackptr ; Save new stack pointer
movfw mfsave ;
movwf FSR ; Restore FSR
movfw mlsave ; Pick low addr back up
movwf PCL ; And return
;
; Start of code
;
main
; Initalize main registers - shut everything off for now
movlw B'10000111' ; RBPU=1 INTEDG=0 TOCS=0 TOSE=0 PSA=0 PS0:PS2=7
banksel OPTION_REG ;
movwf OPTION_REG ;
movlw B'00000000' ; Turn off all interrupts, clear bits
banksel INTCON ;
movwf INTCON ;
movlw B'00000000' ; Turn off all interrupt enables in PIE1
banksel PIE1 ;
movwf PIE1 ;
movlw B'00000000' ; Clear all interrupt flag bits in PIR1
banksel PIR1 ;
movwf PIR1 ;
movlw B'00000000' ; Clear CCP2IE in PIE2
banksel PIE2 ;
movwf PIE2 ;
movlw B'00000000' ; Clear all flags in PIR2
banksel PIR2 ;
movwf PIR2 ;
banksel 0
; Set up user level stack
banksel stackptr ;
movlw stack ;
movwf stackptr ;
banksel 0
; Initialize port registers
banksel PORTA ; Initalize PORTs
clrf PORTA ;
clrf PORTB ;
clrf PORTC ;
banksel TRISA ;
movlw B'00111111' ; Set all as inputs
movwf TRISA ;
clrf TRISB ; Set all as outputs
movlw B'11000000' ; Transmit, receive = in, others = out
movwf TRISC ;
banksel 0
; First thing, shut down the motors.
movlw 0 ;
ra_out ; 0 to RA motor latch
movlw 0 ;
dec_out ;
; Set up globals that need it
clrd rapos ;
clrd dpos ;
clrf rtrajp ;
clrf dtrajp ;
clrf cmdidx ; point at first char
clrf rstatus ;
clrf dstatus ;
bsf rstatus, ST_STOPPED ;
bsf dstatus, ST_STOPPED ;
movlw TRACKH ; default for slew command
movwf speedh ;
movlw TRACKL ;
movwf speedl ;
movlw SL_SLOW_MASK ;
movwf slew ;
movlw USTEPF ;
movwf stepcmd ;
movlw 1 ;
movwf inccmd ;
movlw STARTBATT ; Set up start for rolling average
movwf avgbatt ;
clrf t0ticks ; No ticks received yet
clrf timbatt ; Last time the battery was checked = 0
ifdef SIM
clrf fakeidx
endif
; Set up timers
movlw B'00000000' ; TICKPS1:TICKPS0=0 T1OSCEN=0 T1SYNC=0 TMR1CS=0
movwf T1CON ; Set up for internal clock, leave off for now
clrf TMR1L ; Zero out timer 1
clrf TMR1H ;
bsf T1CON, 0 ; Start Timer 1 ticking
clrf TMR0 ; Clear timer 0
bcf INTCON, 2 ; Clear T0IF
bsf INTCON, 5 ; Set T0IE - want an interrupt on each rollover
; Set up a/d
banksel ADCON1 ;
movlw 0 ; RA0:RA5 all analog inputs
movwf ADCON1 ;
banksel ADCON0 ;
movlw B'11000000' ; ADCS1:ADCS0=Internal Osc, ADON=converter off
movwf ADCON0 ;
; Set up RS232
movlw baud(9600) ; Should be 25 for 9615 baud
banksel SPBRG ;
movwf SPBRG ;
banksel 0 ;
movlw B'00100100' ; CSRC=0 TX9=0 TXEN=1 SYNC=0 BRGH=1
banksel TXSTA ;
movwf TXSTA ;
banksel 0 ;
movlw B'10010000' ; SPEN=1 RX9=0 SREN=0 CREN=1
movwf RCSTA ;
bsf PORTC, SHDN ; Enable the MAX222 chip
bsf PORTC, LED ; Set the LED, ready to roll
; Send out a "Hello" message
mcall sayhi ;
; Finally, enable interrupts - everything is ready to go
bsf INTCON, 7 ; Set GIE
bsf INTCON, 6 ; Set PEIE
; Default mode is track so we don't need a paddle to start
mcall dotrack ; Start it tracking
;
; Main loop
;
loop
mcall rs232in ; Try to get a character
andlw 0xff ; Check to see if we got one
skpnz ;
goto main1 ;
mcall bufchar ; Buffer char if yes
sublw 0x0D ; Is it a CR?
skpz
goto main1 ;
mcall docmd ; Do the command if yes
main1
mcall chklim ; Check the limit switches
mcall chkbatt ; Check the battery voltage
goto loop
;
; Hello, we're here msg
;
sayhi
movlw high sayhisub ;
movwf PCLATH ;
movlw 0 ; Set up index
movwf temp ;
sayhi1 movfw temp ; Pick up the index
call sayhisub ; Get the char
andlw 0xff ; Zero?
skpnz ;
goto sayhidone ; End if done
mcall rs232out ; Send the char
incf temp, f ; Advance the index
goto sayhi1 ; Loop
sayhidone mreturn ;
sayhisub addwf PCL, f ; Get a char
dt "\r\ndrivera V1.0 7/5/00\r\n>"
dt 0
;
; Send a character out the RS232 port
; Character passed in w
; (Same) character returned in w
rs232out
IFNDEF SIM
btfss PIR1, TXIF ; Check for buffer full
goto rs232out ;
ENDIF
movwf TXREG ; Send the character
toggle_led ; Let them know we sent one
mreturn ;
;
; Check for a character in the RS232 input register
; Returns character in w or 0 if no char
; Echoes character to output line if we got one
;
rs232in
movlw 0 ; assume no char
IFDEF SIM
mcall fakeinput ;
ELSE
btfss PIR1, RCIF ; Check receive buffer full
goto rs232indone ; Return if no char
movfw RCREG ; Get the char
ENDIF
mcall rs232out ; Echo it
rs232indone mreturn ; Return the character
;
; Buffer up an ascii character
; Character passed in w
; Returns the character in w
;
bufchar
movwf temp ; Stash the char
movfw cmdidx ; Pick up the index to the next char
sublw CMDLEN ; Check length
skpz ;
goto bufchar1 ;
movfw temp ; don't store if buff is full
goto bufchardone ;
bufchar1
movfw cmdidx ; Grab it again
addlw cmdbuff ; index into buffer
movwf FSR ;
movfw temp ; Get the character
movwf INDF ; indirect store
incf cmdidx, f ; Increment the index
bufchardone mreturn ; And done
;
; Send buffer at FSR to the output rs232
; Buffer is null terminated
;
buffout
movfw INDF ; Get a char
skpnz ;
goto buffoutend ; Done if null
mcall rs232out ; Send the char
incf FSR, f ; Advance to the next one
goto buffout ; And loop
buffoutend mreturn
;
; Do the command in the buffer
; No parameters passed
; No return value
docmd
movlw cmdbuff ; Point at the buffer
movwf FSR ;
movfw INDF ; Pick off the 1st char
sublw 'F' ; Full step?
skpz ;
goto docmd1 ;
mcall dofstep ; Do full step cmd
goto docmdend ;
docmd1 movfw INDF ;
sublw 'G' ; Get?
skpz ;
goto docmd2 ;
mcall doget ; Do the get commands
goto docmdend ;
docmd2 movfw INDF ;
sublw 'U' ; Microstep?
skpz ;
goto docmd3 ;
mcall domicrostep ; Do microstep commands
goto docmdend ;
docmd3 movfw INDF ;
sublw 'Q' ; Quit?
skpz ;
goto docmd4 ;
movlw 0 ; Quit, don't idle
mcall doquit ; Do quit cmd
goto docmdend ;
docmd4 movfw INDF ;
sublw 'R' ; Reset?
skpz ;
goto docmd5 ;
lgoto 0x00 ; xxx may not be adequate
docmd5 movfw INDF ;
sublw 'S' ; Set?
skpz ;
goto docmd6 ;
mcall doset ; Do Set commands
goto docmdend ;
docmd6 movfw INDF ;
sublw 'T' ; Track?
skpz ;
goto docmd7 ;
mcall dotrack ; Do Track cmd
goto docmdend ;
docmd7 movfw INDF ;
sublw 'M' ; Slew?
skpz ;
goto docmd8 ;
mcall doslew ; Do Slew cmd
goto docmdend ;
docmd8 movfw INDF ;
sublw 'I' ; Idle?
skpz ;
goto docmd9 ;
movlw 1 ; Quit and idle
mcall doquit ; Do Idle command
goto docmdend ;
docmd9 ; Didn't recognize the cmd...
movlw 1 ; - error invalid command
; Wrap it up, prompt for next cmd
docmdend
movwf temp
movlw 0x0A ; LF
mcall rs232out ;
movfw temp ; Get command return status
skpnz ;
goto dcmde1 ;
movlw '?' ; Error indicator
mcall rs232out ;
dcmde1 movlw '>' ; Prompt
mcall rs232out ;
clrf cmdidx ; Set the index back to start
mreturn ;
;
; Start tracking
; Hard code the speeds and slew...
;
dotrack
movlw TRACKH ; Set up parameters for raslowslew
movwf speedh ;
movlw TRACKL ;
movwf speedl ;
movlw USTEPB ;
movwf stepcmd ;
movlw -1 ;
movwf inccmd
goto raslowslew ;
;
; Start slewing
; Call with FSR pointing to M
; M<m><dir>
;
doslew
incf FSR, f ; Advance to "R" or "D"
movfw INDF ;
sublw 'R' ; RA?
skpz ;
goto doslewnr ;
movlw 0 ; 0 clear = ra
goto doslewfb ;
doslewnr movfw INDF ;
sublw 'D' ; Dec?
skpz ;
goto doslewbad ;
movlw 1 ; 0 set = dec
doslewfb movwf temp ; bit 0 of temp = ra/dec
incf FSR, f ; Advance to '+' or '-'
movfw INDF ; Get direction
sublw '+' ; Forward?
skpz ;
goto doslewcm ;
bsf temp, 1 ; 1 set = +
goto doslew1
doslewcm movfw INDF ;
sublw '-' ;
skpz ;
goto doslewbad ; 1 clear = -
doslew1
btfss slew, SL_GUIDE ; Guide?
goto doslew2 ;
btfss temp, 1 ; Forward, back
goto doslew3
movlw GUIDEFH ; Set speed to guide forward
movwf speedh ;
movlw GUIDEFL ;
movwf speedl ; 2 clear = slow
goto doslew4 ;
doslew3 movlw GUIDEBH ;
movwf speedh ;
movlw GUIDEBL ;
movwf speedl ;
bsf temp, 1 ; Really forward
doslew2 btfsc slew, SL_FAST ;
bsf temp, 2 ; 2 set = fast, 2 clear = slow
btfsc slew, SL_MED ;
bsf temp, 2 ;
doslew4 ; Temp all set up
btfss temp, 1 ; Forward?
goto doslew6 ;
movlw USTEPF ; Yes, forward, Set up for motor start
movwf stepcmd ;
movlw 1 ;
movwf inccmd ;
goto doslew7 ;
doslew6 movlw USTEPB ; Nope, backwards
movwf stepcmd ;
movlw -1 ;
movwf inccmd ;
doslew7 btfsc temp, 0 ; RA set?
goto doslew5 ;
btfss temp, 2 ; Fast?
goto raslowslew ;
goto rafastslew ;
doslew5 btfss temp, 2 ;
goto dslowslew ;
goto dfastslew ;
doslewbad mretlw 1 ; Error
;
; raslowslew starts a slow slew
; speedh, speedl, stepcmd, inccmd all set up previously
;
raslowslew
bsf rstatus, ST_STOP ; Signal that we need to stop
raslowslew2
btfss rstatus, ST_STOPPED ; Check for stopped
goto raslowslew2 ; Wait for a stop
raslowslew1
movfw speedh ; Set up compare regs for int level
movwf rspdhigh ;
movfw speedl ;
movwf rspdlow ;
movlw 0 ; Start in state 0
raslewall ; start up the engine... Enter here with initial state in w
movwf t1state ;
clrf rstatus ;
movfw inccmd ; Set up interrupt level vbls
movwf rinc ;
movfw stepcmd ;
movwf t1stepcmd ;
splh ; Disable ints while we get timer 1
movfw TMR1H ; Mark1 - Pick up high
addwf rspdhigh, w ; calc capture reg
movwf CCPR1H ;
movlw 5 ; Mark2-Mark1+1 timing
subwf TMR1L, w ; Mark2 - Pick up low
spl0 ; Reenable
addwf rspdlow, w ; Calc other reg
movwf CCPR1L ;
skpnc ;
incf CCPR1H, f ;
movlw B'00001010' ; CCP1X:CCP1Y=0 CCP1M3:CCP1M0=1010
movwf CCP1CON ; Set up for compare mode, int on match
bcf PIR1, 2 ; Be sure CCP1IF is clear
banksel PIE1 ;
bsf PIE1, 2 ; Enable the capture interrupt
banksel 0 ;
; rstep expanded here by hand to allow for lcall of gettraj
movfw t1stepcmd ; Step 1 of 8
addwf rtrajp, f ; see where to go next
movlw 0x1f ; Wrap pointer
andwf rtrajp, w ; w gets ptr for gettraj
movwf rtrajp ; Save new ptr
lcall gettraj ; Get the table value
ra_out ; Send to motor
mlretlw 0 ; Successful completion
;
; rafastslew starts a fast slew
; speedh, speedl, stepcmd, inccmd all set up previously
;
rafastslew
bsf rstatus, ST_STOP ; Signal that we need to stop
rafastslew2
btfss rstatus, ST_STOPPED ; Check for stopped
goto rafastslew ; Wait for a stop
rafastslew1
movlw 0 ; Start at 0
movwf rcuridx ; Set starting point
lcall rgetaccel ; Set up rac_cnt, rspdhigh, rspdlow
movfw speedh ; Pick up high index
movwf rhiacidx ; Set stopping point
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -