PDA

View Full Version : Pulse Width Modulation with HC11


MLCarter
08-03-00, 12:54 AM
I was wondering if anyone has info on PWM using the NM HC11. I am wanting to regulate solar array charging of a battery bank.<br>Thanks.

rob
08-03-00, 12:49 PM
PWM on the 68HC11 is a pain since you have to use interrupts to make<br> it work. Here is a chunk of code used to control eight different<br> joints on a robot with 8 PWM channels. The interrupt just outputs<br> the bytes from the legs array. Different joints are activated by<br> setting bits within the array with SET-BITS and CLEAR-BITS. This<br> is more then you probably need but it is good for multiple PWM<br> outputs. (I've removed the code that deals with input sensors.)<p> Rob<p>COLD<br>( remove all previous software<p>( Four limb crabot controller Rob Chapman Apr 11, 1999 )<p>HEX<br>( 7F00 S0 ! SP! ( increase data stack size<br>( 7E00 R0 ! QUIT ( increase return stack size<p>( ==== Timer control registers ==== )<br> B023 CONSTANT TFLG1 ( timer interrupt flag register 1<br> B025 CONSTANT TFLG2 ( timer interrupt flag register 2<br> B021 CONSTANT TCTL2 ( timer control register 2<br> B020 CONSTANT TCTL1 ( timer control register 1<br> B010 CONSTANT TIC1 ( timer input capture register 1<br> B012 CONSTANT TIC2 ( timer input capture register 2<br> B01E CONSTANT TOC5 ( timer output capture register 5<br> B026 CONSTANT PACTL ( port A control register<br> B009 CONSTANT DDRD ( port D data direction register<br> B022 CONSTANT TMSK1 ( timer interrupt mask1<p>( ==== Leg states array ==== )<br>VARIABLE legs.out ( points to state output<br>VARIABLE legs.end ( points to last legs state<br>CREATE legs 200 ALLOT ( 256 possible states of A and D outputs<br>HERE 2 - legs.end ! legs legs.out ! ( set pointer and limit<p>( Map indices to state table and limit them<br>: &gt;LEGS ( i \ j -- a \ b ) 2 0 DO 0 MAX FF MIN 2* legs + SWAP LOOP ;<p>( ==== Tools ==== )<br>: C@+ ( a -- c \ a+ ) COUNT SWAP ;<br>: C!+ ( c \ a -- a+ ) SWAP OVER C! 1 + ;<p>( Bits in the state output array are two bytes. The bytes are the same<br>( but the second byte is shifted left by two. The first byte is used to<br>( output to the A port and the second byte is used to output to the D port.<br>( Each port uses a nibble.<br>: SET-BITS ( start \ end \ mask -- ) &gt;R SWAP &gt;LEGS<br> BEGIN DUP C@ R@ OR SWAP C!+ DUP C@ R@ 2* 2* OR SWAP C!+ 2DUP U&lt;<br> UNTIL 2DROP R&gt; DROP ;<br>: CLEAR-BITS ( start \ end \ mask -- ) NOT &gt;R SWAP &gt;LEGS<br> BEGIN DUP C@ R@ AND SWAP C!+ DUP C@ R@ 2* 2* AND SWAP C!+ 2DUP U&lt;<br> UNTIL 2DROP R&gt; DROP ;<p>( ==== 68HC11 deployment ==== )<br>( port A bits 4,5,6,7 and port D bits 2,3,4,5 are used to<br>( drive eight actuators<p>( Binding of joint actuators to port bits: usage: 20 RRO 45 RRI )<br>: JOINT ( bit-mask -- ) &lt;BUILDS 0 C, C,<br> ( bend -- ) DOES&gt; 2DUP C@+ C@ &gt;R 2DUP &lt;<br> IF R&gt; CLEAR-BITS ELSE SWAP R&gt; SET-BITS THEN C! ;<p>( ==== Separate joints ==== )<br> 80 JOINT RRI ( rear right inner<br> 40 JOINT RLO ( rear left outer<br> 20 JOINT FLO ( front left outer<br> 10 JOINT RLI ( rear left inner<br> 8 JOINT FRI ( front right inner<br> 4 JOINT RRO ( rear right outer<br> 2 JOINT FRO ( front right outer<br> 1 JOINT FLI ( front left inner<p>( ==== Leg macros ==== )<br>: RR ( n -- ) DUP RRI RRO ;<br>: RL ( n -- ) DUP RLI RLO ;<br>: FR ( n -- ) DUP FRI FRO ;<br>: FL ( n -- ) DUP FLI FLO ;<br>: ALL ( n -- ) DUP RR DUP RL DUP FR FL ;<p>( ==== Assembler branching ==== )<br>: fwd HERE 0 C, ;<br>: fwd: HERE OVER - 1 - SWAP C! ;<p>( ==== Output ports to actuators ==== )<br>B000 CONSTANT portA<br>B008 CONSTANT portD<p>( ==== PWM parameters ==== )<br> VARIABLE TIME 200 TIME ! ( length of of period<p>CODE SIR-PWM ( servicing interrupt routine for time to next transition )<br> ( each time a wraparound counter is the same as a count, this interrupt )<br> ( routine is called. It revises the count and acknowledges the interrupt )<br> FE C, legs.out , ( ldx legs.out ; get state output pointer<br> EC C, 0 C, ( ldd 0,x ; state outputs<br> BC C, legs.end , ( cpx legs.end ; compare to state array end<br> 27 C, fwd ( beq fwd ; same so reset<br> 08 C, 08 C, ( inx inx ; next state output<br> 20 C, fwd ( bra fwd ; continue later<br>SWAP fwd:<br> CE C, legs , ( ldx #legs ; first state output<br>fwd:<br> FF C, legs.out , ( stx legs.out ; update state output pointer<br> CE C, B000 , ( LDX #$B000 : base address of registers<br> A7 C, portA C, ( staa portA,X ; upper quad<br> E7 C, portD C, ( stab portD,X ; lower quad<br> 1D C, TFLG1 C, F7 C, ( BCLR TFLG1,X $F7 : clear interrupt flag<br> FC C, TIME , ( LDD TIME : half period time )<br> E3 C, TOC5 C, ( ADDD TOC5,X : add the current transition time )<br> ED C, TOC5 C, ( STD TOC5,X : and store it back for next time )<br> 3B C, ( RTI : return to normal processing )<br>END-CODE<p>CODE-SUB +INT 0E C, 39 C, END-CODE ( enable interrupts )<br>CODE-SUB -INT 0F C, 39 C, END-CODE ( disable interrupts )<p>: COLD -INT COLD ; ( redefine cold to turn off interrupts )<p>( ==== Actuator control ==== )<br>: OFF TCTL1 C@ 3 NOT AND TCTL1 C! 0 ALL 0 portA C! 0 portD C! ;<br> ( turn off the signal )<p>: ON ( turn on the signal )<br> 0 ALL ( all legs are at zero<br> legs 200 ERASE ( all state outputs to zero<br> 0 portA C! 0 portD C! ( all outputs to zero<br> PACTL C@ 80 OR PACTL C! ( ddrA7 is an output<br> 3C DDRD C! ( ddrD2-5 are outputs<br> -INT ['] SIR-PWM @ 100 /MOD<br> 7E B7CE EEC! ( jmpe opcode )<br> B7CF EEC! B7D0 EEC! ( install sir )<br> 01 TCTL1 C! ( toggle output )<br> 08 TMSK1 C! ( enable 1 interrupt ) +INT ;<br>

MLCarter
08-27-00, 05:17 PM
Here is code I have come up with to regulate power flow to a battery bank. You can change the % time set with the ratio of INC1:(INC1+INC2)<br>HEX<p>: IS CONSTANT ;<p>B000 IS PORTA<br>B020 IS TCTL1<br>B022 IS TMSK1<br>B023 IS TFLG1<br>B01E IS TOC5<p>1002 IS INC1<br>1004 IS INC2<p>2000 INC1 ! ( time set<br>1000 INC2 ! ( time clear<p>CODE SIR-PWM<br>B6 C, PORTA , ( LDAA porta<br>85 C, 8 C, ( BITA test PA3 set<br>27 C, B C, ( BEQ branch if set, 11 locs forward<br>FC C, INC1 , ( LDDA inc1, time PA3 set<br>F3 C, TOC5 , ( ADDD add to TOC5<br>FD C, TOC5 , ( STDA back into TOC5<br>20 C, 9 C, ( BRA branch 9 locs forward<p>FC C, INC2 , ( LDDA inc2, time PA3 cleared<br>F3 C, TOC5 , ( ADDD add to TOC5 )<br>FD C, TOC5 , ( STDA TOC5 )<p>86 C, 08 C, ( LDAA #08 $08 to clear bit<br>B7 C, TFLG1 , ( STAA store at TFLG1<br>3B C, ( RTI return from interupt)<br>END-CODE<p>CODE-SUB +INT 0E C, 39 C, END-CODE<br>CODE-SUB -INT 0F C, 39 C, END-CODE<p>: ON -INT<br>['] SIR-PWM @ 100 /MOD<br>7E B7CE EEC!<br> B7CF EEC!<br> B7D0 EEC!<br>01 TCTL1 C!<br>08 TMSK1 C!<br>+INT<br>.&quot; INTERUPT ON &quot; CR ;<p><br>: TEST ON .&quot; PRESS ANY KEY TO END &quot; CR<br> BEGIN<br> ?TERMINAL UNTIL<br>.&quot; End &quot; CR<br>-INT<br>0 TCTL1 C!<br>ABORT ;<p>