please dont rip this site

Piclist Cheapic BINCLK4M.ASM

;----------------------------------------------------------------------;
; BINCLK4M.ASM          A clock that displays in bcd numbers           ;
;----------------------------------------------------------------------;

;                            .-----------.
;                           -|RA2     RA1|-       V+ = 4.5 or 5 Volts
;                           -|RA3     RA0|-       X = 4.096 MHz xtal
;                           -|RA4    OSC1|--|X|-||--- gnd  20 pf caps 
;   -{r}- = 470 ohm    V+ ---|MCLR   OSC2|--|X|-||--- gnd  
;   -|<- = LED        gnd ---|Vss     Vdd|--- V+
;            gnd ---|<--{r}--|RB0     RB7|-         
;            gnd ---|<--{r}--|RB1     RB6|-         
;            gnd ---|<--{r}--|RB2     RB5|---[PB]--- gnd  <- SET PB     
;            gnd ---|<--{r}--|RB3     RB4|---[PB]--- gnd  <- SHOW PB      
;                            '-----------'         
;                               PIC16F84      -[PB]- pushbutton

        LIST P=16F84           ;  tells which processor is used
        INCLUDE "p16f84.inc"   ;  defines various registers etc. Look 
        ERRORLEVEL -224        ;  supress annoying message from tris
        __CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF   ;  config. switches

            CBLOCK     0CH
                sec             ; seconds digit
                sec10           ; 10's of second digit
                mins            ; minutes digit
                min10           ; 10's of minutes digit
                hr              ; hours digit
                hr10            ; 10's of hours digit
                w_temp          ; holds W during interrupt
                status_temp     ; holds STATUS during interrupt
                fsr_temp        ; holds FSR during interrupt
                digit           ; holds digit position
                cntmsec         ; used to count milliseconds
                counter         ; used to stretch isr out to 1 sec
                flashcnt        ; counter for flashing LED
              ENDC
          
;----------------------------------------------------------------------;
;  Here are some DEFINEs which give 'names' to pushbutton port bits    ;
;----------------------------------------------------------------------;
            #DEFINE SHOWPB PORTB, 4
            #DEFINE SETPB PORTB, 5

            ORG 0               ; start at location 0

            goto main           ; jump over to main routine       

            ORG 4
             
            goto isr            ; jump to interrupt routine

;----------------------------------------------------------------------;
;                  High limit + 1 of digits at position W              ;
;----------------------------------------------------------------------;
sethi:
            addwf PCL, f
         dt H'A',H'6',H'A',H'6',H'A',H'3'

;----------------------------------------------------------------------;
;                        time delay routines                           ;
;----------------------------------------------------------------------;

micro4      addlw H'FF'                ;  subtract 1 from 'W'
            btfss STATUS,Z             ;  skip when you reach zero
            goto micro4                ;  more loops
            return                     

msec250:    movlw D'250'               ;  delay for 250 milliseconds
                ;*** N millisecond delay routine ***
nmsec:      movwf cntmsec              ;  delay for N (in W) millisec
msecloop:   movlw D'248'               ;  1 usec for load
            call micro4                ;  this instruction is 995 usec
            nop                        ;  1 usec 
            decfsz cntmsec,f           ;  1 usec, (2 if skip taken)
            goto msecloop              ;  2 usec, loop = 995+5 = 1 msec
            return 

;----------------------------------------------------------------------;
;                        Delay for one second                          ;
;----------------------------------------------------------------------;
onesecond:                     ; a subroutine that delays for 1 seconds
         call msec250
         call msec250
         call msec250
         call msec250
         return

;----------------------------------------------------------------------;
;                   Put value in W on LEDs for 1 second                ;
;----------------------------------------------------------------------;
sendnbr:
         btfsc STATUS, Z      ; skip if not zero
         movlw H'0F'          ; else all on for a zero
         movwf PORTB          ; light LEDs
         call onesecond       ; wait 1 second
         clrf PORTB           ; clear the LEDs
         movlw D'100'         ; pause for 0.1 sec
         call nmsec
         return 

;----------------------------------------------------------------------;
;                   Send the current time out LEDs                     ;
;----------------------------------------------------------------------;

disptime:              
             movf hr10, W
             call sendnbr
             movf hr, W
             call sendnbr
             movf min10, W
             call sendnbr
             movf mins, W
             call sendnbr
             return

;----------------------------------------------------------------------;
;                 Wait until set button is released                    ;
;----------------------------------------------------------------------;
waitsetup:                           ; wait for set pushbutton up
            btfss SETPB              ; skip if set button released
            goto waitsetup
            movlw D'10'
            call nmsec               ; wait 10 msec for debounce
            btfss SETPB              ; check again for release
            goto waitsetup           ; false alarm, start over
            return                   ; yes, finished

;----------------------------------------------------------------------;
;                       Initialization Subroutine                      ;
;----------------------------------------------------------------------;
init:
            movlw B'0000000'           ; all outputs port A
            tris PORTA                 
            movlw B'00110000'          ; RB4, RB5 inputs, others outputs
            tris PORTB                 ; on port B
            movlw H'0'                 ; all low (off)
            movwf PORTB
            movlw B'00000100'          ; pull-ups enabled                                    
                                       ; prescaler assigned to TMR0
                                       ; prescaler set to 1:16
                                       ; rolls over each 1/125 th second
            option                
            movlw 0
            movwf hr10
            movlw H'9'                 ; initialize hrs, mins and secs
            movwf hr                   ; Do this before interrupts are
            movlw H'5'                 ; turned on because isr also acts
            movwf min10                ; on these registers
            movlw H'0'
            movwf mins
            movwf sec10
            movwf sec
            movlw D'125'               ; initialize isr counter
            movwf counter
            movlw B'10100000'          ; GIE & T0IE set, T0IF cleared
            movwf INTCON
            return

;----------------------------------------------------------------------;
;  Interrupt routine, increments time by one second  (BCD)             ;
;----------------------------------------------------------------------;
isr:
            movwf w_temp             ; save W
            swapf STATUS,W           ; save status
            movwf status_temp        ; without changing flags
            swapf FSR,W              ; save FSR
            movwf fsr_temp           ; without changing flags


            decfsz counter, f        ; skip on 125th time thru
            goto restore             ; else exit
            movlw D'125'              ; reset interrupt counter
            movwf counter              
            movlw sec                ; point at sec register
            movwf FSR
newdigit:   incf INDF, f             ; current digit up one
            movlw sec                ; get difference sec and FSR
            subwf FSR, W
            call sethi               ; use to get high limit + 1
            subwf INDF, W            ; reached that number yet?
            btfss STATUS, Z          ; skip over if yes
            goto restore             ; else exit isr
            clrf INDF                ; set current digit to 0
            incf FSR, f               ; point at next digit
            btfss hr10, 1            ; has hr10 reached 2?
            goto newdigit            ; no, increment the next digit
            btfss hr, 2              ; has hr reached 4?
            goto newdigit            ; no
            clrf hr                  ; yes, set hour to 00
            clrf hr10                ; and hour 10
restore: 
            swapf status_temp,W      ; get original status back
            movwf STATUS             ; into status register
            swapf fsr_temp,W         ; get original fsr back
            movwf FSR                ; into status register
            swapf w_temp,f           ; old no flags trick again
            swapf w_temp,W           ; to restore W
            bcf INTCON,T0IF          ; clear the TMR0 interrupt flag
            retfie                   ; finished reset GIE

;----------------------------------------------------------------------;
;           Increment and display digit pointed to by FSR              ;
;----------------------------------------------------------------------;
updigit:
            incf INDF, f          ; selected digit up one
            movlw mins            ; set up to subtract mins address
            subwf FSR, W          ; from address of current digit
            call sethi            ; get maximum of digit + 1 into W
            subwf INDF, W         ; is it = to current digit value?
            btfsc STATUS, Z       ; gives zero if yes, skip if no
            clrf INDF             ; reset value of digit to zero
            movf INDF, W          ; get current value and ..
            movwf PORTB           ; display it
            call onesecond        ; pause for 1 second
            return

;----------------------------------------------------------------------;
;              flash  LED representing digit position                  ;
;----------------------------------------------------------------------;
setnext:
            movwf digit           ; save digit position
flashloop:
            clrf PORTB            ; all LEDs off
            movf digit, W         ; restore digit position
            btfss flashcnt, 0     ; leave off on odd #'s of counter
            movwf PORTB           ; flash digit on even #'s
            movlw 50              ; delay for 50 msec
            call nmsec
            incf flashcnt, f      ; flip LSB of flashcnt
            btfss SHOWPB          ; skip over if SHOW not pressed
            call updigit          ; else increment current digit
            btfsc SETPB           ; skip over if set pressed
            goto flashloop        ; continue until pressed again
            incf FSR, f           ; set up for next digit
            call waitsetup        ; wait for release
            return

;----------------------------------------------------------------------;
;                        Increment and set digits                      ;
;----------------------------------------------------------------------;
setdigits:
            bcf INTCON, GIE       ; no interrupts while setting time
            movlw mins            ; point at minutes register
            movwf FSR
            call waitsetup        ; wait on set pushbutton up
            movlw B'00000001'     ; light right LED (mins)
            call setnext
            movlw B'00000010'     ; light min10 LED
            call setnext
            movlw B'00000100'     ; light hr LED
            call setnext
            movlw B'00001000'     ; hr10 LED on
            call setnext
            clrf PORTB            ; clear LEDs
            bsf INTCON, GIE       ; enable interrupts again
            return

;----------------------------------------------------------------------;
;                          The main routine                            ;
;----------------------------------------------------------------------;

main:      
            call init             ; set up initial conditions
loop:       
            btfss SHOWPB          ; check for show pushbutton
            call disptime         ; display the time
            btfss SETPB           ; check for setting of time
            call setdigits
            goto loop             ; do forever

            end

;  Note:  A 4.096 MHz xtal is needed for accurate timing over long
;  periods.  You press the SHOW pushbutton to show the time, digit by
;  digit.  Zeros are shown as all lights on.  To set the time you press
;  SET.  The right most digit will blink indicating minutes are to
;  be set.  Pressing SET again chooses tens of minutes etc. After tens
;  of hours, the LEDs blank and the clock is timing again.  While any
;  LED is blinking, pressing SHOW will display that digit value and
;  increment it every second.  Release SHOW when the digit value is what
;  you want.



file: /Techref/piclist/cheapic/binclk4m.asm, 13KB, , updated: 2000/12/8 11:59, local time: 2024/11/17 14:01,
TOP NEW HELP FIND: 
3.12.108.69:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://linistepper.com/techref/piclist/cheapic/binclk4m.asm"> piclist cheapic binclk4m</A>

Did you find what you needed?