please dont rip this site

;----------------------------------------------------------------------;
; WKTIM4M.ASM  Pushbutton toggles clock on and off, time on LCD  4 MHz ;                    
;----------------------------------------------------------------------;

;  Note: must add additional time digit to run over 99 hrs.

;                            .-----------.
;                           -|RA2     RA1|----[LCD E]       
;                           -|RA3     RA0|----[LCD RS]      
;                           -|RA4    OSC1|--|X|-||--- gnd    
;                      V+ ---|MCLR   OSC2|--|X|-||--- gnd  
;                     gnd ---|Vss     Vdd|--- V+   
;                [LCD D4]----|RB0     RB7|-   X = 4.096 MHz xtal 20 pfd
;                [LCD D5]----|RB1     RB6|-   V+ = 4.5 or 5 Volts
;                [LCD D6]----|RB2     RB5|-       
;                [LCD D7]----|RB3     RB4|---[PB]--- gnd        
;                            '-----------'         
;                               PIC16F84      -[PB]- pushbutton

;     LCD pin connections:
;      1 - gnd     ground    2 - Vcc V+    3 - contrast 10K pot V+ & gnd
;      4 - RS  RA0 PIC(17)   5 - RW  gnd   6 - E   RA1 PIC(18) 
;      7 - D0   gnd      8 - D1  gnd       9 - D2 gnd        10 - D3 gnd       
;      11 - D4  RB0 (6)  12 - D5 RB1 (7)   13 - D6 RB2 (8)   14 - D7 (9)

           LIST P=16F84           ;  16F84 Runs at 4.096 MHz
           INCLUDE "p16f84.inc"
           __CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF  
           ERRORLEVEL -224        ;  supress annoying message from tris



;  Define Information
     #DEFINE RS PORTA, 0
     #DEFINE E  PORTA, 1
     #DEFINE TOGGLESW PORTA, 4

;  Macro

EStrobe MACRO                   ;  Strobe the "E" Bit
  bsf    E
  bcf    E
 ENDM

            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
                highlim         ; high limit + 1 of digit
                w_temp          ; holds W during interrupt
                status_temp     ; holds STATUS during interrupt
                fsr_temp        ; holds FSR during interrupt
                Dlay            ; 8 Bit Delay Variable
                working         ; working flag 0 not working, 1 working
                ptr             ; used in displaying message
                Temp            ; a temporary variable
                bin             ; a temporary variable
                oset            ; offset of time register
                oldtime         ; holds last value of sec
                cntmsec         ; used in counting milliseconds
                isrcnt          ; used in isr to stretch time to 1 sec
               ENDC
          
            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'A'

;----------------------------------------------------------------------;
;                    Data for message to be output                     ;
;----------------------------------------------------------------------;
shomsg                          ;  Message to Output
  addwf  PCL, f                 ;  Output the Characters
  dt     "Working Time:", 0

;----------------------------------------------------------------------;
; ISR, increments time by one second, (BCD), every 125th time through  ;
;----------------------------------------------------------------------;
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 isrcnt, f         ; count down to zero before incr.
            goto restore
            movlw D'125'             ; reset isr count
            movwf isrcnt
            movf working, f          ; check working flag
            btfsc STATUS, Z          ; if not zero then increment time
            goto restore             ; else get out of interrupt routine            

            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
            goto newdigit            ; no, increment the next digit
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

;----------------------------------------------------------------------;
;                       Initialize the ports                           ;
;----------------------------------------------------------------------;
init:
            clrf   PORTA
            clrf   PORTB

            movlw B'00010000'          ;  RA4 input, others outputs
            tris PORTA
            movlw B'00000000'          ;  all outputs on port B
            tris PORTB
            movlw B'00000011'          ;  pull-ups enabled                                    
                                       ;  prescaler assigned to TMR0
                                       ;  prescaler set to 1:16
                                       ;  rolls over each 125th second
            option                
 
            movlw 0                    ;  zero out all registers
            movwf hr10
            movwf hr
            movwf min10                
            movwf mins
            movwf sec10
            movwf sec
            clrf working               ;  working flag to zero

            movlw B'10100000'          ;  GIE set T0IE set, T0IF cleared
            movwf INTCON
   return

;----------------------------------------------------------------------;
;                 Initialize the LCD                                   ;
;----------------------------------------------------------------------;
initlcd:
  movlw D'40'
  call   nmsec                  ;  Wait 40 msecs before Reset
  bcf    RS                     ;  send an 8 bit instruction
  movlw  0x03                   ;  Reset Command
  call   NybbleOut              ;  Send the Nybble
  call   Dlay5                  ;  Wait 5 msecs before Sending Again
  EStrobe
  call Dlay160                  ;  Wait 160 usecs before Sending 2nd Time
  EStrobe
  call Dlay160                  ;  Wait 160 usecs before Sending 3rd Time
  bcf    RS                     ;  send an 8 bit instruction
  movlw  0x02                   ;  Set 4 Bit Mode
  call   NybbleOut              
  call Dlay160
  movlw  0x028                  ;  4 bit, 2 Line, 5x7 font
  call   SendINS
  movlw  0x010                  ;  display shift off
  call   SendINS
  movlw  0x001                  ;  Clear the Display RAM
  call   SendINS
  call   Dlay5                  ;  Note, Can take up to 4.1 msecs
  movlw  0x006                  ;  increment cursor
  call   SendINS
  movlw  0x00C                  ;  display on cursor off
  call   SendINS
  return

;----------------------------------------------------------------------;
;              Send the character in W out to the LCD                  ;
;----------------------------------------------------------------------;
SendASCII
  addlw '0'                     ;  Send nbr as ASCII character
SendCHAR                        ;  Send the Character to the LCD
  movwf  Temp                   ;  Save the Temporary Value
  swapf  Temp, w                ;  Send the High Nybble
  bsf    RS                     ;  RS = 1
  call   NybbleOut
  movf   Temp, w                ;  Send the Low Nybble
  bsf    RS
  call   NybbleOut
  return

;----------------------------------------------------------------------;
;              Send an instruction in W out to the LCD                 ;
;----------------------------------------------------------------------;
SendINS                         ;  Send the Instruction to the LCD
  movwf  Temp                   ;  Save the Temporary Value
  swapf  Temp, w                ;  Send the High Nybble
  bcf    RS                     ;  RS = 0
  call   NybbleOut
  movf   Temp, w                ;  Send the Low Nybble
  bcf    RS
  call   NybbleOut
  return

;----------------------------------------------------------------------;
;              Send the nibble in W out to the LCD                     ;
;----------------------------------------------------------------------;
NybbleOut                       ;  Send a Nybble to the LCD
  movwf  PORTB                            
  EStrobe                       ;  Strobe out the LCD Data
  call Dlay160                  ;  delay for 160 usec
  return

;----------------------------------------------------------------------;
;                   Output the message on the LCD                      ;
;----------------------------------------------------------------------;
OutMessage:
  movwf  FSR                    ;  Point at first letter
OutLoop:
  movf   FSR, w                 ;  Get pointer into W
  incf   FSR, f                 ;  Set up for next letter
  call   shomsg                 ;  Get character to output
  iorlw  0                      ;  At the End of the Message?
  btfsc  STATUS, Z              ;  Skip if not at end
  return                        ;  Yes - Equal to Zero
  call   SendCHAR               ;  Output the ASCII Character
  goto   OutLoop                ;  Get the next character


;----------------------------------------------------------------------;
;                Wait until button is released                         ;
;----------------------------------------------------------------------;
waitup:    
            btfss TOGGLESW           ; test toggle switch
            goto $ -1                ; ck again if pressed
            movlw 20                 ; wait 20 msec for debounce
            call nmsec              
            btfss TOGGLESW           ; check again, still up?
            goto $ -4                ; no start over
            return                   ; yes, finished

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

Dlay160:    movlw D'41'                ;  delay about 160 usec
micro4      addlw H'FF'                ;  subtract 1 from 'W'
            btfss STATUS,Z             ;  skip when you reach zero
            goto micro4                ;  more loops
            return                     

Dlay5:      movlw 5                    ;  delay for 5 milliseconds
            goto $ + 2
msec250:    movlw D'250'               ;  delay for 250 milliseconds
                ;*** N millisecond delay routine ***
nmsec:      movwf cntmsec              ; delay for N (in W) millisec
msecloop:   movlw D'254'               ; load takes .9765625 microsec
            call micro4                ; by itself CALL takes ...
                                       ; 2 + 253 X 4 + 3 + 2 = 1019 
                                       ; 1019 * .977 = 995 microsec
            nop                        ; .98 microsec 
            decfsz cntmsec, f          ; .98 skip not taken, else 1.95
            goto msecloop              ; 1.95 here: total ~1000 / loop
            return                     ; final time through ~999 to here
                                       ; overhead in and out ignored

;----------------------------------------------------------------------;
;                       Display the Time                               ;
;----------------------------------------------------------------------;
DispTime
              MOVLW H'C0'       ;  position at beginning of second line
              CALL SendINS
              MOVF hr10, W      ;  tens of hours
              CALL SendASCII
              MOVF hr, W        ;  hours
              CALL SendASCII
              MOVLW ":"         
              CALL SendCHAR
              MOVF min10, W     ;  tens of minutes
              CALL SendASCII
              MOVF mins, W      ;  minutes
              CALL SendASCII
              MOVLW ":"
              CALL SendCHAR
              MOVF sec10, W     ;  tens of seconds
              CALL SendASCII
              MOVF sec, W       ;  seconds
              CALL SendASCII
              RETURN
 
;----------------------------------------------------------------------;
;                            Toggle Work Flag                          ;
;----------------------------------------------------------------------;
togglewk:
            movf working, f   ; set zero flag if zero
            btfss STATUS, Z   ; skip if working is zero
            goto turnoff
            incf working, f   ; set working to 1
            call waitup       ; wait for button release
            return
turnoff:
            clrf working      ; working set to zero
            call waitup       ; wait for button to be released
            return

;----------------------------------------------------------------------;
;                           The Main routine                           ;
;----------------------------------------------------------------------;
main:
       call init               ; initialize ports, set up timer
       call initlcd            ; initialize the LCD
       movlw 0                 ; display 'Working Time:'
       call OutMessage
ckbutton:                      ; check for a press of the TOGGLE button
       btfss TOGGLESW          ; skip if not pressed
       call togglewk           ; else change the mode of timer
       movf oldtime, W         ; is oldtime the same as sec?
       subwf sec, W
       btfsc STATUS, Z         ; if not, skip over next instruction
       goto ckbutton           ; else continue checking
       call DispTime           ; sec has changed, display the time
       movf sec, W             ; make sec and oldsec the same
       movwf oldtime
       goto ckbutton           ; and continue checking

       end 

; Note:  You could use 4 mhz crystal and change the isr count to 
; 125 * 0.98 = 122 but timing would not be exact.  You could also use 
; a 4 mhz ceramic resonator, just to see if the program works


file: /Techref/piclist/cheapic/wktim4m.htm, 15KB, , updated: 2005/10/14 13:08, local time: 2024/10/31 18:28,
TOP NEW HELP FIND: 
3.147.36.61:LOG IN
©2024 PLEASE DON'T RIP! THIS SITE CLOSES OCT 28, 2024 SO LONG AND THANKS FOR ALL THE FISH!

 ©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/wktim4m.htm"> Pushbutton toggles clock on and off, time on LCD</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?