Written some cool source code? Upload it to Programmer's Heaven.
*/
*/

View \AMOTOR.ASM

Hc11 program for automatic motor control

Submitted By: WEBMASTER
Rating: Not rated (Rate It)


** AMOTOR - HC11 PROGRAM FOR AUTOMATIC MOTOR CONTROL
*       This program generates a pwm signal of constant frequency
*       and variable duty cycle. The duty cycle changes from 0%
*       to 99% then back to 1% then the cycle is repeated until
*       the HC11 is reset. Port B bits 0 and 1 are complememts of
*       eachother and represent the direction of a turning motor.
*       The direction changes after each cycle.
*       The motor with this program will start in the forward direction
*       and accelerate to full speed then will deccelarate to stop.
*       The motor will now change direction and accelerate in the
*       reverse direction until full speed then will deccelerate to
*       stop then the whole cycle is repeated. Short delays occurr
*       between each change in duty cycle to decrease the acceleration
*       and deceleration of the motor. Longer delays are present at
*       full speed and at stop to have a trapoziodal profile.
*
*       The program also outputs to a terminal the current speed and
*       direction through the SCI port to a dummy terminal.
*
*       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
TOC3    EQU     $1A             * Output compare 3 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 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 routine
VECINIT EQU     $FFD0           * Initialize interrupt vectors routine

* ADDITIONAL ADDRESS AND CONSTANT EQUATES
ACIA    EQU     $9800           * ACIA address
AUTOLF EQU     $00A6           * Auto lf flag location
BPROT  EQU     $1035           * Block protect
COPRST EQU     $103A           * Coprest register
DELAY  EQU     $FF00           * Delay time for oc3
PIOC    EQU     $1002           * Parallel i/o control reg
OPTION EQU     $1039           * Option register
IODEV  EQU     $A7             * I/O device 0=sci 1=acia 2=duarta
EXTDEV EQU     $A8             * External device 0=none 1=acia
HOSTDEV EQU     $A9             * Host device 0=sci 1=acia
SP      EQU     $006F           * User sp location
UCCR    EQU     $006E           * User ccr location
PERIOD EQU     $0000           * Program variable location
PERCENT EQU     $0002           *       "
PWIDTH  EQU     $0004           *       "

TRIBYTS EQU     $0006           *       "
FLAGS   EQU     $0009           *       "

PORTB  EQU     $1004           * Port B
EOT    EQU     $04             * End of transmission

* PSEUDO VECTOR EQUATES FOR OUTPUT COMPARE INTERRUPTS
PVOC1  EQU     $00DF
PVOC2  EQU     $00DC
PVOC3  EQU     $00D9
 
 
* START OF MAIN PROGRAM
        ORG     $B600
        LDS     #$0033          * User's stack area on EVB
        JSR     SETUP
***INTRO MESSAGE AND WAIT TILL KEY PRESS TO CONTINUE
        LDX     #INTRO          * X points to intro message
        JSR     OUTSTRG                 * Output message
        JSR     INCHAR          * Wait for a key to continue program
        JSR     INIT_OC         * Initialize timer stuff

*
*RUN CODE FOR AUTOMATIC MODE
RUN     BCLR    FLAGS $01               * Clear cntdir flag (count up 1st)
        LDAA    #$01            * Fwd pin hi rev pin low
        STAA    PORTB           * Initialize the direction
        CLI                     * Enable interrputs
DIRECT  COM     PORTB           * Change directions
        LDAA    PORTB           * Check bit 0
        LSLA                    * Shift Bit 0 into carry
        BCC     BACKWD          * Carry=0, then backward else forward
        LDX     #FWD            * X points to forward sign
        JSR     OUTSTRG         * Output message
        BRA     HOP             * Hop over reverse message
BACKWD  LDX     #REV            * X points to reverse sign
        JSR     OUTSTRG         * Output message
HOP     LDX     #SPDMSG         * X points to % duty cycle message
        JSR     OUTSTRG         * Output message
                LDAA #$01               * Start from 1
CHANGE  PSHA                    * save count on stack
        JSR     UPDATE          * display and change pwidth approp
        PULA                    * Get count from stack
        BSET    FLAGS $80               * Set chgspd flag
        LDY     #$0006          * Count to wait until next change
        JSR     WAIT            * Wait between increments routine
        LDAB    FLAGS           * Get flags byte
        BITB    #$01            * Count direction = 1 ?
        BNE     DOWN            * Count down if =1 else count up
        ADDA    #$01            * Add one to count in acca
        DAA                     * Adding in BCD
        BNE     CHANGE          * Sum not = 0 branch to change
        BSET    FLAGS $01               * Set count direction flag
        LDY     #$0013          * Long delay count before changing
*                               * count direction.
        JSR     WAIT            * Wait between increments
        LDAA    #$99            * Start count at 99 and go down
DOWN    BITA    #$0F            * Check for hex number $_F
        BNE     LEAP            * Not $_F then leap else
        SUBA    #$06            * Subtract 6 from count for bcd #s
LEAP    SUBA    #$01            * Subraact 1 from count
        BNE     CHANGE          * Count not= 0 then change else
        BCLR    FLAGS $01               * Clear cntdir flag (count up)
        LDY     #$0013          * Lng dlay cnt bfor changin dir
        JSR     WAIT            * Wait
        BRA     DIRECT          * Branch always to direct
*
* 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
        STAA    BPROT           * Eeprom block protect
        STAA    IODEV
        JSR     VECINIT                 * Initialize interrupt vectors
        LDX     #$0047
        STX     SP              * Default user stack pointer
        LDAA    #$D0
        STAA    UCCR            * Default user CCR
        LDAA    #$00            * Acca = 0
        STAA    EXTDEV          * External device = ACIA
        STAA    IODEV           * I/O thru ACIA
        STAA    HOSTDEV
        INCA
        STAA    AUTOLF          * Auto lf with cr on
        JSR     INIT            * Initialize ACIA
        CLRA    FLAGS           * Clear all 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           *       "
        STAA    PVOC3           *       "
        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 subroutine initializes the timer and oc'
s
*       & 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
        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
*
*UPDATE-        This subroutines outputs the current % duty cycle and
*       converts the BCD number to a hex number, then does the
*       multiplication by the period.
UPDATE  PSHA                    * Save count on stack
        PSHA                    * Save count again on stack
        JSR     OUTLHLF                 * Output left nibble as ascii
        STAA    PERCENT         * Store ascii form of left nibble
        PULA                    * Get copy of count from stack
        JSR     OUTRHLF         * Output right nibble as ascii
        STAA    PERCENT+1               * Store ascii form of rt nibble
        LDAA    #$08            * Ascii bs into acca
        JSR     OUTA            * Output a back space
        JSR     OUTA            * Another bs, ready to output %
        PULA                    * Get count from stack
CONVERT LDX     #PERCENT                * X points ascii bcd % characters
        JSR     BCDHEX          * Convert from ascii bcd to hex
        LDX     #PERIOD         * Multiplier
        JSR     MUL2BY1         * period*percent=tribyts
        JSR     DIV3BYT         * tribyts/100=pwidth(accd)
        STD     PWIDTH          * Store result in PWIDTH
        RTS

*WAIT-  This subroutine provides the delays between increments or
*       decrements in the count in automatic mode.      It also serves
*       to give longer delays at full speed in both forward and
*       reverse directions and at stop. A number in Y indicates
*       how many continious delays there will be.
WAIT    LDX     #REGBAS         * Set up for indexed addressing
        PSHA                    * Save count on stack
AGAIN   LDD     #DELAY          * Delay time for oc3
        ADDD    TCNT,X          * Add timer count to delay
        STD     TOC3,X          * Store in oc3 timer
        BCLR    TFLG1,X %11011111       * Clear the oc3 flag
CIRCLE  BRSET   TFLG1,X %00100000 TSTY  * Oc3 flag set? yes>tsty
        LDAA    #$55            * Reset cop so no time out
        STAA    COPRST          *
        LDAA    #$AA            *
        STAA    COPRST          *
        BRA     CIRCLE          * Poll oc3 flag
TSTY    DEY                     * Decrement Y
        BNE     AGAIN           * Y=0 then return, else loop again
                PULA            * Pull count from stack
        RTS
*
*DSPLYSPD-      This subroutine displays current % duty cycle message then
*       the current %. X should point to the ascii characters
*
DSPLASP PSHX                    * Save X on stack
        LDX     #SPDMSG         * X points to message
        JSR     OTSTRGO         * Out message w/o preceeding crlf
        PULX                    * Set for indexed addressing
        LDAA    0,X             * Get first characer
        JSR     OUTA            * Output character
        LDAA    1,X             * Get 2nd character
        JSR     OUTA            * Output character
        RTS
*
*BCD_HEX-       This subroutine takes the two bytes pointed to by X
*       as ascii two digit bcd number and converts to a hex equiv-
*       alent and returns the result in ACCA.
BCDHEX  LDAA    0,X             * Get hi byte of ascii bcd number
        CMPA    #$20            * If a space then only one digit
        BNE     TUDGITS         * not space then 2 digits
        LDAA    1,X             * 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    1,X             * 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 pointed to by
*       X by 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    1,X             * 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    0,X             * 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 pointed to by Y
*       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
*
**MENUS**
INTRO   FCC     '       MC68HC11/ICePAK MOTOR CONTROL'
        FCB     $0D
        FCB     EOT
FWD     FCC     'FORWARD'
        FCB     EOT
REV     FCC     'REVERSE'
        FCB     EOT
SPDMSG  FCC     'PWM DUTY CYCLE %: '
        FCB     EOT

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.
Resource Listings