Delay problems with assembly code and pic

Thread Starter

hunterage2000

Joined May 2, 2010
487
I have tried to create a delay to blink an led on and off using the below code but the led remains on. Can anyone see the prob.

Rich (BB code):
#include "p16F690.inc"

 __CONFIG H'30F0'

TMR0 equ 01
STATUS equ 03
PORTB equ 06
TRISB equ 86

RES_VECT  CODE    0x0000            
                 
GOTO START

MAIN_PROG CODE
                 
;DELAY
DELAY1 CLRF TMR0 ;START TMR0.
LOOPA MOVF TMR0,W ;READ TMR0 INTO W.
SUBLW D'32' ;TIME - 32
BTFSS STATUS,2 ; Check TIME-W¼0
GOTO LOOPA ;Time is not¼32.
RETLW 0 ;Time is 32, return.

START
BCF STATUS,RP0 ;Bank 0
BCF STATUS,RP1 ;
CLRF PORTB ;Init PORTB
BSF STATUS,RP0 ;Bank 1
MOVLW 0x00 
MOVWF TRISB ;
BCF STATUS,RP0 ;Bank 0
LOOP BSF PORTB,6
    CALL DELAY1
BCF PORTB,6
CALL DELAY1
    GOTO LOOP                          ; loop forever

    END
 

Thread Starter

hunterage2000

Joined May 2, 2010
487
I have used a 555 timer at 25Hz (EC) and a 32kHz small oscillator (LP). I have usee a 20MHz Epson crystal osc (XT) but not sure if I set it properly. Its pins is (1) OE, (2) GND, (3) OUT and (4) Vcc with OUT going to CLKIN. I wasn't sure about the decimal time used, I have seen D'32' and .32.
 

JohnInTX

Joined Jun 26, 2012
4,787
You have several problems here.

First, you have to determine the flash rate and then how many Tcyc (Tosc/4) that is then determine how many TMR0 counts you have to accumulate. You haven't specified a prescaler using the OPTION register so its running so fast that you may not be able to see your LED blink at all.

As an example at 4MHz Tcyc is 1uS. To blink the LED at 50ms on/off you need to count to 50,000 (50ms/1us). Using a prescaler of 256 with the internal clock source (OPTION= xx0x0111) you need to count 195.3 counts in the timer. So set OPTION and reload the timer to .256-.195 as shown in the code below. .256-.195=.61 i.e. set the counter to 61 and it will count up from there 195counts * 256prescaler * 1usTcyc ~= 50ms

You are currently testing for zero (STATUS,2) i.e. testing for a timer value of exactly 32. That will be difficult to catch exactly when the timer is running very fast. A better way would be to count up from a value that is a number of counts from overflow then monitor TOIF.:
Rich (BB code):
 movlw .256-.195 ; init the timer
 movwf TMR0
 bcf INTCON,T0IF ; clear the overflow flag
loop:
 btfss INTCON,T0IF
 goto loop
 return
That way you can miss a couple of counts and still catch the overflow.

This is not a particularly good way to get timer generated delays but its a start.

Finally, you shouldn't define the PORTs, TRIS etc. That is done for you in the header file. As for _CONFIG, you should use the method called out in the header file and MPASM's help file. Using a hard-coded value is very error prone and virtually impossible to read.

For value settings, I use . for decimal i.e. .10 and h for hex i.e. 0ah. MPASM accepts different ways as you have seen. The rule is be consistent and always specify the radix (hex, decimal, binary) explicitly for clarity and to guard against different defaults in various assembler configurations.

Lastly, try to use STATUS,Z instead of STATUS,2 . That's easier to read. Even better is to use the built in macros i.e.
skpz ; skip if STATUS,Z is set (zero result). Others are skpnz, skpc (skip on carry set), skpnc etc.

Good luck.

EDIT:
Here's a starting point with some cleanups. You'll still need to determine the oscillator type/freq etc.
Rich (BB code):
#include "p16F690.inc"

 ;__CONFIG H'30F0'
 __CONFIG _LP_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_OFF &_FCMEN_OFF

RES_VECT  CODE    0x0000            
                 
        GOTO    START

MAIN_PROG CODE
                 
;DELAY
DELAY1: 
        movlw    .256-.195  ; 50ms on, 50ms off at 4MHz
        movwf    TMR0
        bcf        INTCON,T0IF
LOOPA:    
        btfss    INTCON,T0IF
        GOTO    LOOPA
        RETLW 0 

START:
        ;BCF STATUS,RP0     ;Bank 0
        ;BCF STATUS,RP1 
        banksel PORTB
        CLRF PORTB            ;Init PORTB
        
        ;BSF STATUS,RP0     ;Bank 1
        banksel TRISB
        MOVLW 0x00 
        MOVWF TRISB ;
        movlw    B'10000111'    ; RBPU off, PS=256, internal source
        movwf    OPTION_REG

        ;BCF STATUS,RP0     ;Bank 0
        banksel    PORTB

LOOP:
        BSF PORTB,6
        CALL DELAY1
        BCF PORTB,6
        CALL DELAY1
        GOTO LOOP                          ; loop forever

    END
 
Last edited:
Top