Hc11 program for automatic motor control
Submitted By:
WEBMASTER
Rating:
Not rated (
Rate It)
* Program for the HC11
** MMOTOR - manual motor operation
* With the use of a terminal this program allows a user
* to control the duty cycle percentage of a pwm signal
* thus controlling the speed of a motor. The direction of the
* motor can also be changed with this program. The program
* displays menus that guide the user. The user will be
* prompted for a direction then a duty cycle percentage. To
* return to the direction prompt depress the delete key. The
* function keys are used to dictate the direction. Out of reset
* the program will display an introductory message then will
* wait for any key to be depressed before continuing. This
* program takes advantage of the many routines available
* in BUFFALO for I/O and initialization of the SCI port and
* the interrupt vectors. The frequency of the pwm signal
* is a constant and is approximately 14khz.
*
* This program is to be used with any HC11 with BUFFALO
* (monitor and debug program) availabe in ROM. The program length
* is approximately 512 bytes and can therefore also be used with
* EEPROM versions of the HC11.
*
** The HC11 is used in conjunction with kits KITDEVB103 and KITDEVB118
* and application notes AN1300 and AN1301 for dc brushed motor drive.
* Kits and ap notes are availale through Motorola Literature Distribution.
*
*
*TIMER REGISTER ADDRESSES
REGBAS EQU $1000 * Register base
OC1M EQU $0C * OC1 action mask register
OC1D EQU $0D * OC1 action data register
TOC1 EQU $16 * Output compare 1 register
TOC2 EQU $18 * Output compare 2 register
TCTL1 EQU $20 * Timer control register 1
TMSK1 EQU $22 * Timer interrupt mask register 1
TFLG1 EQU $23 * Timer interrupt flag register 1
TCNT EQU $0E * Timer counter register
*BUFFALO I/O AND INITIALIZATION ROUTINE ADDRESSES
INCHAR EQU $FFCD * Get character from terminal
OUTCRLF EQU $FFC4 * Output a CR and LF to screen
OUTSTRG EQU $FFC7 * Output a string
OTSTRGO EQU $FFCA * Out string w/o preceedin crlf
OUTA EQU $FFB8 * Output contents of acca
OUTLHLF EQU $FFB2 * Cnvrt lft nibble to ascii & out
OUTRHLF EQU $FFB5 * Cnvrt rt nibble to ascii & out
INIT EQU $FFA9 * Initialize I/O device in IODEV
VECINIT EQU $FFD0 * Initialize vectors
*ADDITIONAL VARIABLE ADDRESSES AND CONSTANT EQUATES
AUTOLF EQU $A6 * Auto lf flag byte
BAUD EQU $102B * Baud select register
BPROT EQU $1035 * Block protect register
OPTION EQU $1039 * Option register
EXTDEV EQU $A8 * Buffalo variable 0=none, 1=acia
IODEV EQU $A7 * Buffalo var 0=sci, 1=acia, 2=duart
HOSTDEV EQU $A9 * Buffalo var 0=sci, 1=acia
SP EQU $006F * Default user stack pointer
UCCR EQU $006E * Defaul user CCR
PERIOD EQU $0000 * Program location of constant period
PERCENT EQU $0002 * Program variable % duty cycle input
PWIDTH EQU $0004 * Program variable pulse width
TRIBYTS EQU $0006 * Program 24 bit # location
FLAGS EQU $0009 * Program flag byte
PORTB EQU $1004 * Port B address
EOT EQU $04 * End of transmission
*PSEUDO VECTOR EQUATES FOR OUTPUT COMPARE INTERRUPTS
PVOC1 EQU $00DF
PVOC2 EQU $00DC
*
** START OF MAIN PROGRAM
*
ORG $B600 * Start of EEPROM
LDS #$0033 * User's stack area on EVB
JSR SETUP
*INTRODUCTION STATEMENT OUT OF RESET
LDX #INTRO * Introduction message
JSR OUTSTRG * Output messasge
JSR INCHAR * Keep on screen till key depressed
* * then continue executing
URUN JSR INIT_OC * Initialize the output compare registers
CLR PERCENT * Clear percent hi byte
CLR PERCENT+1 * Clear percent lo byte
CLI * Enable interrupts
JSR GET_DIR * Display direction prompt &
* * get direction
ANOTHER JSR OUTCRLF * Output a cr and lf
JSR DSPLASP * Display duty cycle percentage
LDX #SPDPRMT * Prompt user for duty cycle %
JSR OUTSTRG * Output prompt
JSR IN_SPD * Get new Duty Cycle% from keybd
BRSET FLAGS $02 EXIT * Exit if mode flag is set
JSR BCDHEX * Convert from ascii bcd to hex
JSR MUL2BY1 * period*percent=tribyts
JSR DIV3BYT * tribyts/100=pwidth(accd)
STD PWIDTH * Store result in PWIDTH
BSET FLAGS $80 * Set the newspeed flag for OC2
BRA ANOTHER * Repeat
EXIT SEI * Disable interrupts
BCLR FLAGS $02 * Clear mode escape flag
BRA URUN * Exit to mode prompt routine
*
* SETUP- This subroutine configures the communication port
* initializes interrupt vectors, sets the default user stack
* and ccr, clears program flags, stores the period of the pwm
* signal, and sets up the pseudo vectors for the output compares.
*
SETUP LDAA #$93 *
STAA OPTION * adpu, dly, irqe, cop
CLRA * 0 into acca
STAA BPROT * Clear 'E9 eeprom block protect
STAA IODEV * I/O through sci
STAA EXTDEV * No external device
JSR VECINIT * Initialize interrupt vectors
LDX #$0047 * $0047 into X
STX SP * Default user stack
LDAA #$D0 * $D0 into acca
STAA UCCR * Default user ccr
CLR HOSTDEV * Host = sci
CLR $4000 * Clear D flip-flop location
JSR INIT * Initialize I/O device
LDAA #$32 * Change to 2400 baud for terminal
STAA BAUD
LDAA #$01
STAA AUTOLF * Auto lf when cr occurs on
LDAA #
CLR FLAGS * Clear all program flags
LDD #$008D * Time between oc1 interrupts
STD PERIOD * Save in period
*SETUP OF PSEUDO VECTORS***
LDAA #$7E * Op code for jump
STAA PVOC1 * OC1 pseudo vector
STAA PVOC2 * "
LDD #OC1ISR * Address of OC1 interrupt service routine
STD PVOC1+1 * Finish JMP inst to OC1 routine
LDD #OC2ISR * Address of OC2 interrupt servic
STD PVOC2+1 * Finish JMP inst to OC1 routine
RTS
*
*INIT_OC- This set of instructions initializes oc1 and
* oc2 and sets toc1 and toc2 registers.
INIT_OC LDX #REGBAS * Set for indexed addressing
LDAA #%11000000 * Set OM2 & OML
STAA TCTL1,X * OC2 sets its pin hi
LDAA #%01000000 * OC1 affects OC2 pin
STAA OC1M,X * Sets OC1 action mask
CLRA * OC1 sets all OCs low
STAA OC1D,X * OC1 action data reg.
LDD PERIOD * Period into accd
LSLD * Period times 2
ADDD TCNT,X * Add 2 periods of TCNT
STD TOC1,X * Store in OC1 time
ADDD PERIOD * Add period to OC1 time
STD TOC2,X * Store OC2 time
BCLR TFLG1,X %00111111 * Clear OC1, OC2, &OC3 flags
BSET TMSK1,X %11000000 * Enable OCI & OC2 interrupts
RTS
*
*GET_DIR- This subroutine prompts the user for a direction
* F1=fwd, F2=rev, then writes the appropriate byte to port b.
* It also check for a flag to return to intro message
GET_DIR LDX #DIR_MSG * X points to message
JSR OUTSTRG * Output message
JSR INCHAR * Get character from terminal
CMPA #$46 * Not an "F" then invalid repeat
* * terminal is sending ascii
* * F1='$4631' and F2='$4632'
BNE GET_DIR * If "F" then get 2nd character
JSR INCHAR * Get second character from terminal
CMPA #$31 * =1 ?
BNE CMPARE2 * =1 then continue, else 2nd compare
LDAA #$01 * Portb0=1, portb1=0
STAA PORTB * Store fwd bits in port b
BRA BACK * Return from subroutine
CMPARE2 CMPA #$32 * =2 ?
BNE GET_DIR * If invalid char repeat prompt
LDAA #$02 * =2 then portb0=1, portb1=0
STAA PORTB * Store reverse bits in port b
BACK RTS
*DSPLYSPD- This subroutine displays current % duty cycle message then
* the current %. Ascii characters are at PERCENT
*
DSPLASP LDX #SPDMSG * X points to message
JSR OTSTRGO * Out message w/o preceeding crlf
LDAA PERCENT * Get first characer
JSR OUTA * Output character
LDAA PERCENT+1 * Get 2nd character
JSR OUTA * Output character
RTS
*
*IN_SPD- This subroutine takes characters for the new speed as a
* a percentage. When a cr is received the input is com-
* plete or when more than 2 characters without a cr the
* input is assumed to be 100%. The inputs are stored at
* location PERCENT (2 BYTES).
*
IN_SPD JSR INCHAR * Get 1st input from terminal
CMPA #$0D * cr ?
BEQ IN_SPD * If cr then try again
CMPA #$7F * Del ?
BEQ SETFLG * If del then setflag,else continu
STAA PERCENT * Save first charcater
JSR INCHAR * Get 2nd input from terminal
CMPA #$0D * CR ?
BEQ SHIFT * If cr then only on digit, shift
CMPA #$7F * DEl ?
BEQ SETFLG * If del then setflag, else contin
STAA PERCENT+1 * Save 2nd character
JSR INCHAR * Need a cr to indicate # entered
CMPA #$0D * cr ?
BEQ RETURN * If cr then return, else continue
CMPA #$7F * Del ?
BEQ SETFLG * If del the setflag,else continue
* * Redisplay prompt, invalid # entered
JSR OUTCRLF * Output crlf
LDX #SPDPRMT * X points to message
JSR OTSTRGO * Output message w/o preceeding cr
BRA IN_SPD * Start again
SETFLG BSET FLAGS $02 * Set mode escape flag
BRA RETURN * Branch to return from subroutine
SHIFT LDAB PERCENT * Only one digit, char into accb
LDAA #$20 * Ascii space into acca
STD PERCENT * Store double at percent
RETURN RTS
*
*BCD_HEX- This subroutine takes the two bytes at PERCENT
* as an ascii two digit bcd number and converts to a hex equiv-
* alent and returns the result in ACCA.
BCDHEX LDAA PERCENT * Get hi byte of ascii bcd number
CMPA #$20 * If a space then only one digit
BNE TUDGITS * not space then 2 digits
LDAA PERCENT+1 * Only one digit
ANDA #$0F * Mask out the 4 msbs
BRA DONE * result in acca so done
TUDGITS ANDA #$0F * Mask out the 4 msbs of hi byte
LDAB #$0A * Ten into accb
MUL * Acca*accb=accb(result of mul)
LDAA PERCENT+1 * Lo byte of ascii num into acca
ANDA #$0F * Mask out the 4 msbs of lo byte
ABA * acca+accb=hex number in acca
DONE RTS
*MUL2BY1- This subroutine multiplies a 2 byte number @ PERIOD
* as a 1byte number located in acca with the result stored
* number located in ACCB with the result stored in location
* TRIBYTS
MUL2BY1 PSHA * Save hex number on the stack
LDAB PERIOD+1 * Get low byte of period
MUL * multiply
STAB TRIBYTS+2 * Lowest byte of total result
PULB * Get copy of hex rep of %
PSHA * To be added to next mul result
LDAA PERIOD * Get high byte of period
MUL * Multiply
STD TRIBYTS * Store this result in TRIBYTS
PULB * Part to be added to last mul
CLRA * Hi byte of accd = 0
ADDD TRIBYTS * Add accd to last mul result
STD TRIBYTS * 24 bit result @ TRIBYTS
RTS
*
*DIV3BYT- This subroutine divides a 24 bit number @ TRIBYTS
* by a number in X with the result to be in ACCD
*
DIV3BYT LDD TRIBYTS * Get upper 16 bits of dividend
LDX #$0064 * Load X with divisor
IDIV * Divide
PSHB * Save remainder
XGDX * Put quotient in accb
PULA * Remainder as hi byte in accd
PSHB * Save hi byte of result
LDAB TRIBYTS+2 * Get last byte of dividend
LDX #$0064 * Load X with divisor
IDIV * Divide
XGDX * Quotient of 2nd div in accb
PULA * Get hi byte of total result
* * Total result now in accd
RTS
* OC1 INTERRUPT SERVICE ROUTINE
OC1ISR LDX #REGBAS * Set for indexed addressing
LDD TOC1,X * Get old OC1 time
ADDD PERIOD * Add one period
STD TOC1,X * Store next OC1 time
BCLR TFLG1,X %01111111 * Clear OC1 flag bit
RTI
* OC2 INTERRUPT SERVICE ROUTINE
OC2ISR LDX #REGBAS * Set for indexed addressing
BRSET FLAGS $80 NEWPW * bra if newspeed flag set
LDD TOC2,X * Get old OC2 tim
ADDD PERIOD * Add a period
STD TOC2,X * Store next OC2 time
BCLR TFLG1,X %10111111 * Clear OC2 flag
RTI
NEWPW LDD TOC1,X * Use time for oc1 as reference
ADDD PERIOD * Add a period
ADDD PERIOD * Add a second period
SUBD PWIDTH * Subtract pw % to get oc2
STD TOC2,X * Store next oc2 time
BCLR FLAGS %10000000 * Clear newspeed flag
BCLR TFLG1,X %10111111 * Clear OC2 flag
RTI
*
*MESSAGES
*
INTRO FCC ' MC68HC11/ICePAK MOTOR CONTROL'
FCB $0D
FCB EOT
DIR_MSG FCB $0D
FCC 'ENTER DIRECTION (F1=fwd, F2=rev): '
FCB EOT
SPDMSG FCC 'PWM DUTY CYCLE %: '
FCB EOT
SPDPRMT FCC 'ENTER PWM DUTY CYCLE %(1-99): '
FCB EOT