16F690, TMR0, Internal timer

Status
Not open for further replies.

ibwev

Member
I am trying to complete a project that lights an led on one second and then off for one second and on the fifth second lights a separate led. I am using a PIC16F690 and the code line "btfss STATUS,2" apparently never goes to 0 because the program never skips the next instruction. Please help.

list p=16F690 ; list directive to define processor
#include <p16F690.inc> ; processor specific variable definitions

errorlevel -302 ; suppress message 302 from list file

__CONFIG _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF

;declarations

INT_VAR UDATA_SHR
Marker125 res 1
Post125 res 1
fivSEC res 1

RESET_VECTOR CODE 0x0000 ; processor reset vector
goto start ; go to beginning of program

INT_VECTOR CODE 0x0004 ; interrupt vector location

Init
;initialize PORTA example 4-1 in datasheet
BCF STATUS,RP1
CLRF PORTA
BSF STATUS,RP1
CLRF ANSEL
BSF STATUS,RP0
BCF STATUS,RP1
MOVLW 0Ch ;set RA<5:4,1:0>;as outputs
MOVWF TRISA
BCF STATUS,RP0

;8 Mhz internal timer oscillates 2,000,000 times a second
;2,000,000/256(prescaler)=15,625 cycles to 1 second after prescaler
;125(Marker)x125(Post)=15,625

movlw b'00000000' ;disable TMR0 interrupt
movwf INTCON

movlw b'00000110' ;internal instruction cycle,prescaler assigned to TMR0
movwf OPTION_REG ;Prescaler 1:128 for even numbers on "Mark125" and "Post125"

movlw d'125' ;move decimal 125 in GPF called Marker125
movwf Marker125

movlw d'125' ;move decimal 125 in GPF called Post125
movwf Post125

movlw d'5' ;move decimal 5 in GPF called fivSEC
movwf fivSEC

TimeLoop
movfw Marker125 ;move number from Marker125 into working register
subwf TMR0,0 ;As TMR0 counts up, the decimal in Marker125 will
;subtract and store the number in the w register
;this leaves the number in TMR0 unchanged
btfss STATUS,2 ;When the above number reaches 0 the next
;instructions will be skipped
goto TimeLoop ;loop until Marker125 - TMR0 = 0

movlw d'125' ;add 125 to Marker125 and store in Marker125
addwf Marker125,1

decfsz Post125,1 ;Decrement the postscaler and store in Post125
goto TimeLoop ;this line is skipped once Post125 = 0

;when the Timeloop reaches this point 1 second has passed

movlw d'125' ;add 125 to Post125 and store in Post125
movwf Post125

retlw 0


MAIN_PROG CODE

start
call Init

Main

decfsz fivSEC,1 ;decrements fivSEZ by 1 and stores contents in fivSEC
;register
goto toggle ; skips of 0
bsf PORTA,4 ;sets high bit 4 of PORTA once fivSEC reaches 0

movlw d'5' ;move number 5 into fivSEC register
movwf fivSEC

goto TimeLoop ;repeat timeloop

toggle
bcf PORTA,4 ;turn bit 4 off

movlw b'100000' ;toggles RA5 and stores contents in w register
xorwf PORTA,0

goto TimeLoop ;repeat timeloop

END ; directive 'end of program'
 
hi,
I have reformatted your listing, use the '#' on the menu when you post code, it keeps the formatting, makes easier for us to see and help.
Code:
    list    p=16F690    ; list directive to define processor
#include <p16F690.inc>         ; processor specific variable definitions

    errorlevel -302        ; suppress message 302 from list file

    __config _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF

;declarations 

INT_VAR    udata_shr 
Marker125 res    1
Post125    res    1
fivSEC    res    1

RESET_VECTOR code 0x0000    ; processor reset vector
    goto    start        ; go to beginning of program

INT_VECTOR code    0x0004        ; interrupt vector location

Init
;initialize PORTA example 4-1 in datasheet  
    bcf    STATUS,RP1
    clrf    PORTA
    bsf    STATUS,RP1
    clrf    ANSEL
    bsf    STATUS,RP0
    bcf    STATUS,RP1
    movlw    0Ch        ;set RA<5:4,1:0>;as outputs
    movwf    TRISA
    bcf    STATUS,RP0

;8 Mhz internal timer oscillates 2,000,000 times a second  
;2,000,000/256(prescaler)=15,625 cycles to 1 second after prescaler  
;125(Marker)x125(Post)=15,625  

    movlw    b'00000000'    ;disable TMR0 interrupt
    movwf    INTCON

    movlw    b'00000110'    ;internal instruction cycle,prescaler assigned to TMR0
    movwf    OPTION_REG    ;Prescaler 1:128 for even numbers on "Mark125" and "Post125"

    movlw    d'125'        ;move decimal 125 in GPF called Marker125
    movwf    Marker125

    movlw    d'125'        ;move decimal 125 in GPF called Post125
    movwf    Post125

    movlw    d'5'        ;move decimal 5 in GPF called fivSEC
    movwf    fivSEC

TimeLoop 
    movfw    Marker125    ;move number from Marker125 into working register
    subwf    TMR0,0        ;As TMR0 counts up, the decimal in Marker125 will
;subtract and store the number in the w register  
;this leaves the number in TMR0 unchanged  
    btfss    STATUS,2    ;When the above number reaches 0 the next
;instructions will be skipped  
    goto    TimeLoop    ;loop until Marker125 - TMR0 = 0

    movlw    d'125'        ;add 125 to Marker125 and store in Marker125
    addwf    Marker125,1

    decfsz    Post125,1    ;Decrement the postscaler and store in Post125
    goto    TimeLoop    ;this line is skipped once Post125 = 0

;when the Timeloop reaches this point 1 second has passed  

    movlw    d'125'        ;add 125 to Post125 and store in Post125
    movwf    Post125

    retlw    0


MAIN_PROG code

start
    call    Init

Main

    decfsz    fivSEC,1    ;decrements fivSEZ by 1 and stores contents in fivSEC
;register 
    goto    toggle        ; skips of 0
    bsf    PORTA,4        ;sets high bit 4 of PORTA once fivSEC reaches 0

    movlw    d'5'        ;move number 5 into fivSEC register
    movwf    fivSEC

    goto    TimeLoop    ;repeat timeloop

toggle
    bcf    PORTA,4        ;turn bit 4 off

    movlw    b'100000'    ;toggles RA5 and stores contents in w register
    xorwf    PORTA,0

    goto    TimeLoop    ;repeat timeloop

    end            ; directive 'end of program'
 
I don't think you ever actually turned on Timer0.

I don't know why you aren't making this interrupt driven. IMO, what you are doing is fairly uncoventional.

Also, I never use MOVFW. I've seen it before, but I always use "MOVF FILENAME,W"
 
Try this build as absolute code
Code:
   #include <p16F690.inc>
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

     cblock     0x20
Display
     endc

     org 0
     bsf       STATUS,RP0
     movlw     b'00000111'    ; configure Timer0.  Sourced from the Processor clock;
     movwf     OPTION_REG     ; Maximum Prescaler
     clrf      TRISC          ; Make PortC all output
     clrf      Display
     bcf       STATUS,RP0
     
ForeverLoop:
     btfss     INTCON,T0IF    ; wait here until Timer0 rolls over
     goto      ForeverLoop
     bcf       INTCON,T0IF    ; flag must be cleared in software
     incf      Display,f      ; increment display variable
     movf      Display,w      ; send to the LEDs
     movwf     PORTC
     goto      ForeverLoop
     
     
     end
 
Last edited:
I don't think you ever actually turned on Timer0.

I don't know why you aren't making this interrupt driven. IMO, what you are doing is fairly uncoventional.

Also, I never use MOVFW. I've seen it before, but I always use "MOVF FILENAME,W"

How do I turn on Timer0?
How do I make the code interrupt driven?
 
There you a little better code to play with
Code:
#include <p16F690.inc>
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

     cblock     0x20
count
flags
     endc

     org 0
     banksel   OPTION_REG
     movlw     b'00000111'    ; configure Timer0.  Sourced from the Processor clock;
     movwf     OPTION_REG     ; Maximum Prescaler
     banksel   ANSEL
     clrf      ANSEL
     banksel   TRISC
     clrf      TRISC          ; Make PortC all output
     banksel   PORTC
     clrf      PORTC
     clrf      count
     clrf      flags
	
start
	movlw     D'250'    ;preload count higher faster toggle time
	movwf	   count    ;lower longer toggle time 
     
ForeverLoop: 
     btfss     INTCON,T0IF    ; wait here until Timer0 rolls over
     goto      ForeverLoop
     bcf       INTCON,T0IF    ; flag must be cleared in software
     incfsz    count      ; increment count variable
     goto      ForeverLoop 
	 call      toggle
	 goto      start
toggle:
	movlw 	   0x01  ;sets the port pin    
	xorwf      PORTC,f ; set the port
	return	
     
     end
 
Last edited:

I am new at programming. What is the purpose of "bsf STATUS,RP0"? Does this direct the code to Bank 1 and allow access to OPTION_REG and TRISC?
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…