Urgent, Assembly Language PIC16F887, Timer Problem

Discussion in 'Embedded Systems and Microcontrollers' started by zhengkoon8, Dec 2, 2011.

  1. zhengkoon8

    Thread Starter New Member

    Nov 28, 2011
    10
    0
    Hi, I have a timing problem on my coding. My code want to have exact 3 second for testing and 4 second for delay. But at the end come out with the problem the timing not accurate. Can someone point out my mistake. Thank you very much. Below is my coding.

    Code ( (Unknown Language)):
    1.  
    2. ; Description:                                                                                                                          ;
    3. ; -SW simulates door switch, and should allow 3s delay for disarming before triggering the alarm.                                       ;
    4. ; -Double click SW simulates the “disarm” switch that allows the legitimate user to avoid the alarm.                                    ;
    5. ; -Triple click SW simulate the “arm” switch that starts the armed state after 4s.                                                      ;
    6. ; -LEDs show the present state of the system (use separate LED for every state if possible)                                             ;
    7. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    8. #include "prologue.inc"
    9. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    10. ; Declaring Variable used
    11.      cblock     0x20
    12. Value                                    ; Assign an address 0x20 to label Value
    13. Read                                     ; Assign an address 0x21 to label Read
    14. Value1                                   ; Assign an address 0x22 to label Value1
    15. Read1                                    ; Assign an address 0x23 to label Read1
    16. Delay1                                   ; Assign an address 0x24 to label Delay1
    17. Delay2                                   ; Assign an address 0x25 to label Delay2
    18. Delay3                                   ; Assign an address 0x26 to label Delay3
    19. Counter                                  ; Assign an address 0x27 to label Counter
    20. Direction
    21. LookingFor
    22. Time
    23. Test
    24. SwitchPressed
    25. LastStableState
    26. Memory
    27. Delay
    28. Mem
    29.      endc
    30.  
    31.  
    32. Start:
    33.      bsf       STATUS,RP0                ; select Register Bank 1
    34.      clrf      TRISD                     ; Make PortD all output
    35.      movlw     0x01                      ; Bit one to work register
    36.      movlw     0xFF                      ; b'11111111'
    37.      movwf     TRISA                     ; Make PortA all input
    38.      movwf     TRISB                     ; Make RBO pin input (switch)
    39.      movlw     b'10000010'               ; PortB pull up is disable, Interrupt on rising edge of INT pin, Internal instruction cycle clock (FOSC/4)
    40.      movwf     OPTION_REG                ; Timer0 increment from internal clock with a prescale of 1:16
    41.      bsf       STATUS,RP1                ; select Register Bank 3
    42.      movlw     0x00                      ; move b'00000000' to work register
    43.      movwf     ANSELH                    ; PortB pins are digitial (important as RB0 is switch)
    44.      bcf       STATUS,RP0                ; select Register Bank 2
    45.      bcf       STATUS,RP1                ; select Register Bank 0
    46.      clrf      PORTD                     ; clear value in PORTD
    47.      clrf      Counter                   ; clear value in Counter
    48.      movlw     1
    49.      movwf     LastStableState
    50.  
    51.  
    52. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    53. MainLoop:
    54.      clrf      Memory
    55.      btfsc     PORTB,0
    56.      goto      MainLoop
    57.      movlw     b'10000000'
    58.      movwf     PORTD
    59.      call      DelayThreeSecond
    60.      call      PressTwo
    61.      call      PressThree  
    62.      goto      MainLoop
    63.      
    64. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    
    65. ; Function Delays for Dots and Pause between the dash and dots
    66. DelayThreeSecond:
    67.      clrf      Time
    68. WaitThreeSecond
    69.      clrf      Mem                       ; clear value in Mem register
    70. OneSecondWait:
    71.      clrf      TMR0                      ; clear Timer0
    72. LoopTMR0:
    73.      call      CheckButton
    74.      call      NumberPress
    75.      movf      TMR0,w                    ; move value in TMR0 register to work register
    76.      xorlw     .250                      ; wait for 4ms (250x16us)
    77.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    78.      goto      LoopTMR0                  ; loop back to LoopTMR0
    79.      incf      Mem,f                     ; increase the value of Mem register by 1 and store in counter register
    80.      movlw     .250                      ; wait for 1s (250x4ms)
    81.      xorwf     Mem,w                     ; move value in Mem register to work register
    82.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    83.      goto      OneSecondWait             ; loop back to OneSecondWait
    84.      incf      Time,f                    ; increase the value of Time register by 1 and store in counter register
    85.      movlw     .3                        ; wait for 3s (3x1s)
    86.      xorwf     Time,w                    ; move value in Time register to work register
    87.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    88.      goto      WaitThreeSecond           ; loop back to WaitThreeSecond
    89.      return                              ; return back to the next instruction after function call
    90.  
    91. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    92. ; Function Delays for Button Check
    93. CheckButton:
    94.      btfsc      LastStableState,0
    95.      goto       ButtonNotPress
    96. ButtonPress:
    97.      clrw
    98.      btfss     PORTB,0             ; test if the switch is press
    99.      incf      Counter,w           ; if switch press, increase the counter
    100.      movwf     Counter             ; store either the 0 or incremented value
    101.      goto      EndDebounce
    102. ButtonNotPress:
    103.      clrw
    104.      btfsc     PORTB,0
    105.      incf      Counter,w
    106.      movwf     Counter
    107.      goto      EndDebounce
    108. EndDebounce:
    109.      movf      Counter,w           ; have we seen 5 in a row?
    110.      xorlw     5
    111.      btfss     STATUS,Z    
    112.      goto      Delay1mS
    113.      comf      LastStableState,f   ; after 5 straight, reverse the direction
    114.      clrf      Counter
    115.      btfss     LastStableState,0   ; Was it a key-down press?
    116.      goto      Delay1mS            ; no: take no action
    117.      bsf       SwitchPressed,0
    118.  
    119. Delay1mS:
    120.      movlw     .71                 ; delay ~1000uS
    121.      movwf     Delay
    122.      decfsz    Delay,f             ; this loop does 215 cycles
    123.      goto      $-1          
    124.      decfsz    Delay,f             ; This loop does 786 cycles
    125.      goto      $-1
    126.      btfss     LastStableState,0   ; Was it a key-down press?
    127.      return
    128.      goto      CheckButton
    129.  
    130. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    131. ; Function Delays for Number Button Press
    132. NumberPress:
    133.      btfss     SwitchPressed,0
    134.      return
    135.      incf      Memory
    136.      clrf      SwitchPressed
    137.      return
    138.      return
    139.  
    140. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    141. ; Function Delays for Number Button Press 2 times
    142. PressTwo:
    143.      movlw     .3                        ; wait for 1s (250x4ms)
    144.      xorwf     Memory,w                     ; move value in Mem register to work register
    145.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    146.      return
    147.      movlw     b'00000000'
    148.      movwf     PORTD
    149.      return
    150.  
    151. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    152. ; Function Delays for Number Button Press 3 times
    153. PressThree:
    154.      movlw     .4                        ; wait for 1s (250x4ms)
    155.      xorwf     Memory,w                     ; move value in Mem register to work register
    156.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    157.      return
    158.      movlw     b'00000000'
    159.      movwf     PORTD
    160.      call      DelayFourSecond
    161.      movlw     b'01000000'
    162.      movwf     PORTD
    163.      return
    164.  
    165. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    166. ; Function Delays for 4 Second
    167. DelayFourSecond:
    168.      clrf      Time
    169. WaitFourSecond
    170.      clrf      Mem                       ; clear value in Mem register
    171. OneSecondDelay:
    172.      clrf      TMR0                      ; clear Timer0
    173. WaitTMR0:
    174.      movf      TMR0,w                    ; move value in TMR0 register to work register
    175.      xorlw     .250                      ; wait for 4ms (250x16us)
    176.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    177.      goto      WaitTMR0                  ; loop back to LoopTMR0
    178.      incf      Mem,f                     ; increase the value of Mem register by 1 and store in counter register
    179.      movlw     .250                      ; wait for 1s (250x4ms)
    180.      xorwf     Mem,w                     ; move value in Mem register to work register
    181.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    182.      goto      OneSecondDelay             ; loop back to OneSecondWait
    183.      incf      Time,f                    ; increase the value of Time register by 1 and store in counter register
    184.      movlw     .4                        ; wait for 4s (4x1s)
    185.      xorwf     Time,w                    ; move value in Time register to work register
    186.      btfss     STATUS,Z                  ; check whether zero present in STATUS
    187.      goto      WaitFourSecond           ; loop back to WaitThreeSecond
    188.      return                              ; return back to the next instruction after function call
    189. end
    190.  
     
    Last edited by a moderator: Dec 3, 2011
  2. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    You can use the stopwatch function in the MPLAB simulator to get an idea of the number of cycles your code is taking.

    Otherwise, count your instructions, all of them are 1 cycle (Fosc/4) except for instructions that change the instruction pointer (goto, positive tests, etc)
     
    zhengkoon8 likes this.
  3. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    I'm going to assume you are using a 4MHz clock speed.
    You have the timer0 prescaler set to 8 which I don't think is what you intended.
    Also the instructions in between checking if TMR0 = 250 take more than 8 instruction cycles so sometimes when it gets to the test it will be 249 and then the next time it gets to the test it will be 251 so it just carries on counting without incrementing your time variable.
    Better to test for TMR0 > 250 and then for better accuracy, subtract 250 from the TMR0 value instead of simply setting it to 0. It's still not perfect, but good enough for most purposes.
     
    zhengkoon8 likes this.
  4. zhengkoon8

    Thread Starter New Member

    Nov 28, 2011
    10
    0
    how to use it stopwatch?

    i use prescaler 8 is because the time got up and down. so it is 16 right? correct if i am mistake

    so just substrat it? i trying first. hope it work
     
  5. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    If processor speed is 4MHz then I think the prescaler should be 16
    Just noticed that in one of your delay routines there is debouncing code which has a delay of a millisecond. You can probably remove that because the debounce code only gets called every 4ms anyway.
     
    zhengkoon8 likes this.
  6. zhengkoon8

    Thread Starter New Member

    Nov 28, 2011
    10
    0
    so i just need to change the prescale and delete ;wait for 4ms (250x16us)right? ok i try and see got problem or not. thanks
     
Loading...