; 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