;----------------------------------------------------------------------;
; 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.asm, 15KB, , updated: 2005/10/14 12:03, local time: 2024/11/17 13:32,
|
| ©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? <A HREF="http://linistepper.com/techref/piclist/cheapic/wktim4m.asm"> piclist cheapic wktim4m</A> |
Did you find what you needed?
|