; Program name: Example 10 The motor ; Function description: ; (1) The motor rotates in a
clockwise direction at first. ; (2) The number of revolutions is
displayed on Display 0 (the rightmost 7-segment display). ; The display only shows up to nine
revolutions and then resets. ; (3) The motor sensor is connected
to P3.5, which receives the external clock source for timer 1. ; Timer 1 is put into event
counting mode, so it increments by 1 once every motor revolution. ; The value in timer 1 low byte is
moved to Acc, which together with the data pointer (DPH and DPL) ; are used to get a
7-segment code from the program memory. ; The seven-segment
code is then sent to P1 to show the number of revolutions on Display 0. ; (4) The motor can be changed from
clockwise to anti-clockwise by pressing SW0, which connects P2.0 to GND. ; (5) The motor direction is stored
in F0 (1 for clockwise, 0 for anti-clockwise). ; The value in F0 is sent to
Display 0's decimal point (P1.7). ; So, if the
decimal point is lit, the motor is rotating anti-clockwise; ; if it is not lit, the motor is
rotating clockwise. ; (6) The value in F0 is compared
with the value of SW0. ; If they are the same, the motor
direction does not need to be changed. ; If they are not the same, it means the
user has pressed SW0 and the motor direction must be reversed. ; When this
happens the new motor direction is then stored in F0. ; (7) In summary: Current
direction: F0 = 1 for CW, = 0 for CCW
; Next
direction: SW0 = 1 for
CW, = 0 for CCW ; (8) The motor rotation is
controlled by P3.1 and P3.0 in the following manners: ; P3.1
P3.0
Motor ;
------
------
--------- ; 0
0
Off ; 0
1
On, CW ; 1
0
On, CCW ; 1
1 Off ;
Timer 1 will be used to count the number of rotations. MOV TMOD,
#50H ;
Put timer 1 in event counting mode. SETB TR1 ;
Start timer 1. ;
LEDcodes is the label of the 7-segment code table. MOV
DPL,
#LOW(LEDcodes) ;
Put the low byte of LEDcodes into DPL. MOV
DPH,
#HIGH(LEDcodes) ;
Put the high byte of LEDcodes into DPH. CLR
P3.4 ;
| CLR
P3.3 ;
| Enable Display 0 (of the 7-segment display). again: CALL
setDirection ;
Set the motor's direction. MOV A,
TL1 ;
Move timer 1 low byte to A. CJNE
A,
#10, skip ;
If the number of revolutions is not 10, skip next instruction. CALL
clearTimer ;
If the number of revolutions is 10, reset timer 1. skip: MOVC A, @A+DPTR ;
Get 7-segment code from code table: ;
The index into the table is decided by the value in Acc. ;
(Example: The data pointer points to the start of the table ; - if the
motor is in the second revolutions, Acc should contain two, ; and the second code in the table will
be copied to Acc.) MOV
C,
F0 ;
Move the current motor direction value to the carry and from there to ACC.7 . MOV
ACC.7,
C ;
(This will ensure Display 0's decimal point will indicate the motor's
direction.). MOV P1,
A ;
| Move the 7-seg code for the number of revolutions and ; | motor direction indicator to
Display 0. JMP
again ;
Do it all again. ; ==== Subroutine: setDirection
=============================================== setDirection: PUSH
ACC ;
Save value of A on stack. PUSH
20H ;
Save value of location 20H (first bit-addressable location in RAM) on stack CLR
A ;
Clear A. MOV
20H, #0 ;
Clear location 20H. MOV
C, P2.0 ;
Let Acc.0 contains the value of P2.0. MOV
ACC.0, C ;
MOV
C, F0 ;
Let 20H.0 contain the value of F0, i.e., the current motor direction. MOV
0, C ;
( "MOV
0,C" is equivalent to "MOV 20H.0,C" .) ;
In summary: Acc.0 =
SW0 = Next direction; 20H.0 = F0 = Current direction. CJNE
A, 20H, changeDir ;
| Compare SW0 (LSB of A) with F0 (LSB of 20H) ;
| - if they are not the same, the motor's direction needs to be reversed. notChangeDir: JMP
finish ;
If they are the same, motor's direction does not need to be changed changeDir: CLR
P3.0 ;
| CLR
P3.1 ;
| Stop motor. CALL
clearTimer ;
Reset timer 1 (revolution count restarts when motor direction changes). MOV
C, P2.0 ;
Move SW0 value to carry, MOV
F0, C ;
and then to F0 - this is the new motor direction. MOV
P3.0, C ;
Move SW0 value (in carry) to motor control bit 1. CPL
C ;
Invert the carry, MOV
P3.1, C ;
| and move it to motor control bit 0 (it will therefore have the opposite ;
| value to control bit 1 and the motor will start ;
| again in the new direction). finish: POP 20H ;
Get original value for location 20H from the stack. POP
ACC ;
Get original value for A from the stack. RET ;
Return from subroutine. ; ========= Subroutine: clearTimer
=================================================== clearTimer: CLR
A ;
Reset revolution count in A to zero. CLR
TR1 ;
Stop timer 1. MOV
TL1, #0 ;
Reset timer 1 low byte to zero. SETB
TR1 ;
Start timer 1. RET ;
Return from subroutine. ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>> The
7-segment COde Table
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< LEDcodes: ;
| This label points to the start address of the 7-segment code table which is
;
| stored in program memory using the DB command below. DB
11000000B, 11111001B, 10100100B, 10110000B, 10011001B, 10010010B, 10000010B,
11111000B, 10000000B, 10010000B |
;
Program name: ICP-A08-01 = motor direction control with simplified
instruction sequence ;
Description: This ICP performs the same function as Example 10 does. ; However,
in the subroutine "setDirection", a
tedious instruction sequence is simplified. ;
Function of "setDirection" subroutine: ; This
subroutine test whether P2.0 == F0. ; If
P2.0 =\= F0, change F0 to P2.0 and change the motor rotation direction. ;
Summary: ; ; Direction SW0 P2.0 F0 P3.1 P3.0 ;
------------ ----- ----- --- ------ ----- ; CW Open 1 1 0 1 ; CCW Close 0 0 1 0 ; ; ; Note: These PURPLE
instructions can be simplified to about 4 GREEN instructions. ;
Timer 1 will be used to count the number of rotations. MOV TMOD,
#50H ;
Put timer 1 in event counting mode. SETB TR1 ;
Start timer 1. ;
LEDcodes is the label of the 7-segment code table. MOV
DPL,
#LOW(LEDcodes) ;
Put the low byte of LEDcodes into DPL. MOV
DPH,
#HIGH(LEDcodes) ;
Put the high byte of LEDcodes into DPH. CLR
P3.4 ;
| CLR
P3.3 ;
| Enable Display 0 (of the 7-segment display). again: CALL
setDirection ;
Set the motor's direction. MOV A,
TL1 ;
Move timer 1 low byte to A. CJNE
A,
#10, skip ;
If the number of revolutions is not 10, skip next instruction. CALL
clearTimer ;
If the number of revolutions is 10, reset timer 1. skip: MOVC A, @A+DPTR ;
Get 7-segment code from code table: ;
The index into the table is decided by the value in Acc. ;
(Example: The data pointer points to the start of the table ; - if the
motor is in the second revolutions, Acc should contain two, ; and the second code in the table will
be copied to Acc.) MOV
C,
F0 ;
Move the current motor direction value to the carry and from there to ACC.7 . MOV
ACC.7,
C ;
(This will ensure Display 0's decimal point will indicate the motor's
direction.). MOV P1,
A ;
| Move the 7-seg code for the number of revolutions and ; | motor direction indicator to
Display 0. JMP
again ;
Do it all again. ; ==== Subroutine: setDirection
=============================================== setDirection: ;---------------- The
following instructions are deleted. ---------------------------------- ;delete PUSH ACC ;
save value of A on stack ;delete PUSH 20H ;
save value of location 20H (first bit-addressable ;delete ; location
in RAM) on stack ;delete CLR A ;
clear A ;delete MOV 20H, #0 ;
clear location 20H ;delete MOV C, P2.0 ;
put SW0 value in carry ;delete MOV ACC.0, C ;
then move to ACC.0 ;delete MOV C, F0 ;
move current motor direction in carry ;delete MOV 0, C ;
and move to LSB of location 20H (which has bit address 0) ;delete CJNE A, 20H,
changeDir ;
| compare SW0 (LSB of A) with F0 (LSB of 20H) ;delete ;
| - if they are not the same, the motor's direction needs to be reversed ;------------- The
deleted instruction sequence is replaced with the instruction sequence BELOW
--------------- ??? ???, ??? ???: ??? ???, ??? ??? ??? ???: ??? ???, ??? ;------------- The
deleted instruction sequence is replaced with the instruction sequence ABOVE
--------------- notChangeDir: JMP
finish ;
If they are the same, motor's direction does not need to be changed changeDir: CLR
P3.0 ;
| CLR
P3.1 ;
| Stop motor. CALL
clearTimer ;
Reset timer 1 (revolution count restarts when motor direction changes). MOV
C, P2.0 ;
Move SW0 value to carry, MOV
F0, C ;
and then to F0 - this is the new motor direction. MOV
P3.0, C ;
Move SW0 value (in carry) to motor control bit 1. CPL
C ;
Invert the carry, MOV
P3.1, C ;
| and move it to motor control bit 0 (it will therefore have the opposite ;
| value to control bit 1 and the motor will start ;
| again in the new direction). finish: ;delete POP 20H ;
get original value for location 20H from the stack ;delete POP ACC ;
get original value for A from the stack RET ;
Return from subroutine ; ========= Subroutine: clearTimer
=================================================== clearTimer: CLR
A ;
Reset revolution count in A to zero. CLR
TR1 ;
Stop timer 1. MOV
TL1, #0 ;
Reset timer 1 low byte to zero. SETB
TR1 ;
Start timer 1. RET ;
Return from subroutine. ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>> The
7-segment COde Table
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< LEDcodes: ;
| This label points to the start address of the 7-segment code table which is
;
| stored in program memory using the DB command below. DB
11000000B, 11111001B, 10100100B, 10110000B, 10011001B, 10010010B, 10000010B,
11111000B, 10000000B, 10010000B |