Urgent, Assembly Language PIC16F887, Timer Problem

Thread Starter

zhengkoon8

Joined Nov 28, 2011
10
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.

Rich (BB code):
; Description:                                                                                                                          ;
; -SW simulates door switch, and should allow 3s delay for disarming before triggering the alarm.                                       ;
; -Double click SW simulates the “disarm” switch that allows the legitimate user to avoid the alarm.                                    ;
; -Triple click SW simulate the “arm” switch that starts the armed state after 4s.                                                      ;
; -LEDs show the present state of the system (use separate LED for every state if possible)                                             ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#include "prologue.inc"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Declaring Variable used
     cblock     0x20
Value                                    ; Assign an address 0x20 to label Value
Read                                     ; Assign an address 0x21 to label Read
Value1                                   ; Assign an address 0x22 to label Value1
Read1                                    ; Assign an address 0x23 to label Read1
Delay1                                   ; Assign an address 0x24 to label Delay1
Delay2                                   ; Assign an address 0x25 to label Delay2
Delay3                                   ; Assign an address 0x26 to label Delay3
Counter                                  ; Assign an address 0x27 to label Counter
Direction 
LookingFor
Time
Test
SwitchPressed
LastStableState
Memory
Delay
Mem
     endc


Start:
     bsf       STATUS,RP0                ; select Register Bank 1
     clrf      TRISD                     ; Make PortD all output
     movlw     0x01                      ; Bit one to work register
     movlw     0xFF                      ; b'11111111'
     movwf     TRISA                     ; Make PortA all input
     movwf     TRISB                     ; Make RBO pin input (switch)
     movlw     b'10000010'               ; PortB pull up is disable, Interrupt on rising edge of INT pin, Internal instruction cycle clock (FOSC/4)
     movwf     OPTION_REG                ; Timer0 increment from internal clock with a prescale of 1:16
     bsf       STATUS,RP1                ; select Register Bank 3
     movlw     0x00                      ; move b'00000000' to work register
     movwf     ANSELH                    ; PortB pins are digitial (important as RB0 is switch)
     bcf       STATUS,RP0                ; select Register Bank 2
     bcf       STATUS,RP1                ; select Register Bank 0
     clrf      PORTD                     ; clear value in PORTD
     clrf      Counter                   ; clear value in Counter
     movlw     1
     movwf     LastStableState


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MainLoop:
     clrf      Memory
     btfsc     PORTB,0
     goto      MainLoop
     movlw     b'10000000'
     movwf     PORTD
     call      DelayThreeSecond
     call      PressTwo 
     call      PressThree  
     goto      MainLoop
     
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;     
; Function Delays for Dots and Pause between the dash and dots
DelayThreeSecond:
     clrf      Time
WaitThreeSecond
     clrf      Mem                       ; clear value in Mem register
OneSecondWait:
     clrf      TMR0                      ; clear Timer0
LoopTMR0:
     call      CheckButton
     call      NumberPress
     movf      TMR0,w                    ; move value in TMR0 register to work register
     xorlw     .250                      ; wait for 4ms (250x16us)
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     goto      LoopTMR0                  ; loop back to LoopTMR0
     incf      Mem,f                     ; increase the value of Mem register by 1 and store in counter register
     movlw     .250                      ; wait for 1s (250x4ms)
     xorwf     Mem,w                     ; move value in Mem register to work register
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     goto      OneSecondWait             ; loop back to OneSecondWait
     incf      Time,f                    ; increase the value of Time register by 1 and store in counter register
     movlw     .3                        ; wait for 3s (3x1s)
     xorwf     Time,w                    ; move value in Time register to work register
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     goto      WaitThreeSecond           ; loop back to WaitThreeSecond
     return                              ; return back to the next instruction after function call

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Function Delays for Button Check
CheckButton:
     btfsc      LastStableState,0
     goto       ButtonNotPress
ButtonPress:
     clrw
     btfss     PORTB,0             ; test if the switch is press
     incf      Counter,w           ; if switch press, increase the counter
     movwf     Counter             ; store either the 0 or incremented value
     goto      EndDebounce
ButtonNotPress:
     clrw
     btfsc     PORTB,0
     incf      Counter,w
     movwf     Counter
     goto      EndDebounce
EndDebounce:
     movf      Counter,w           ; have we seen 5 in a row?
     xorlw     5
     btfss     STATUS,Z     
     goto      Delay1mS
     comf      LastStableState,f   ; after 5 straight, reverse the direction
     clrf      Counter
     btfss     LastStableState,0   ; Was it a key-down press?
     goto      Delay1mS            ; no: take no action
     bsf       SwitchPressed,0
 
Delay1mS:
     movlw     .71                 ; delay ~1000uS
     movwf     Delay
     decfsz    Delay,f             ; this loop does 215 cycles
     goto      $-1          
     decfsz    Delay,f             ; This loop does 786 cycles
     goto      $-1
     btfss     LastStableState,0   ; Was it a key-down press?
     return
     goto      CheckButton

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Function Delays for Number Button Press
NumberPress:
     btfss     SwitchPressed,0
     return
     incf      Memory
     clrf      SwitchPressed
     return
     return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Function Delays for Number Button Press 2 times
PressTwo:
     movlw     .3                        ; wait for 1s (250x4ms)
     xorwf     Memory,w                     ; move value in Mem register to work register
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     return
     movlw     b'00000000'
     movwf     PORTD
     return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Function Delays for Number Button Press 3 times
PressThree:
     movlw     .4                        ; wait for 1s (250x4ms)
     xorwf     Memory,w                     ; move value in Mem register to work register
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     return
     movlw     b'00000000'
     movwf     PORTD
     call      DelayFourSecond
     movlw     b'01000000'
     movwf     PORTD
     return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Function Delays for 4 Second
DelayFourSecond:
     clrf      Time
WaitFourSecond
     clrf      Mem                       ; clear value in Mem register
OneSecondDelay:
     clrf      TMR0                      ; clear Timer0
WaitTMR0:
     movf      TMR0,w                    ; move value in TMR0 register to work register
     xorlw     .250                      ; wait for 4ms (250x16us)
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     goto      WaitTMR0                  ; loop back to LoopTMR0
     incf      Mem,f                     ; increase the value of Mem register by 1 and store in counter register
     movlw     .250                      ; wait for 1s (250x4ms)
     xorwf     Mem,w                     ; move value in Mem register to work register
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     goto      OneSecondDelay             ; loop back to OneSecondWait
     incf      Time,f                    ; increase the value of Time register by 1 and store in counter register
     movlw     .4                        ; wait for 4s (4x1s)
     xorwf     Time,w                    ; move value in Time register to work register
     btfss     STATUS,Z                  ; check whether zero present in STATUS
     goto      WaitFourSecond           ; loop back to WaitThreeSecond
     return                              ; return back to the next instruction after function call 
end
 
Last edited by a moderator:

thatoneguy

Joined Feb 19, 2009
6,359
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)
 

Markd77

Joined Sep 7, 2009
2,806
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.
 

Thread Starter

zhengkoon8

Joined Nov 28, 2011
10
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
 

Markd77

Joined Sep 7, 2009
2,806
If processor speed is 4MHz then I think the prescaler should be 16
;wait for 4ms (250x16us)
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.
 

Thread Starter

zhengkoon8

Joined Nov 28, 2011
10
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
 
Top