;----------------------------------------------------------------------;
; TMR04M.ASM Show TMR0 in decimal on LCD after counting 1 second ;
;----------------------------------------------------------------------;
; 555 V+ PIC16F84
; .----------. | .-----------.
; gnd ---|gnd Vcc|--- V+ [R] -|RA2 RA1|----[LCD E]
; .-|trig dis|----------| -|RA3 RA0|----[LCD RS]
; RA4<--|-|out thres|--.--{r}--' in>-|RA4 OSC1|--|X|__ gnd
; V+ --|-|rst cont| |--|<---' V+--|MCLR OSC2|--|X| X = 4 MHz
; | '----------' | gnd--|Vss Vdd|--- V+ cer. res.
; '---------------' [LCD D4]----|RB0 RB7|-
; | C [LCD D5]----|RB1 RB6|- V+ = 4.5 or 5V
; '---||---gnd [LCD D6]----|RB2 RB5|---[PB]--- gnd
; C = 0.001-0.1 mfd [LCD D7]----|RB3 RB4|---[PB]--- gnd
; -{r}- = 33K '-----------'
; -|<- = 1n4148 [R] = 10K variable resistor -[PB]- = pushbutton
; LCD pin connections:
; 1 - gnd ground 2 - Vcc V+ 3 - cont. 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 MHz
INCLUDE "p16f84.inc"
__CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF
ERRORLEVEL -224 ; suppress annoying message from tris
ERRORLEVEL -302 ; suppress message from page change
; Define Information
#DEFINE RS PORTA, 0 ; RA0 is RS line of LCD
#DEFINE E PORTA, 1 ; RA1 is E line of LCD
; RB0-RB3 are D4-D7 of LCD
#DEFINE upbutton PORTB, 4 ; RB4 is the up button
#DEFINE dnbutton PORTB, 5 ; RB5 is the down button
; Macro
EStrobe MACRO ; Strobe the "E" Bit
bsf E
bcf E
ENDM
CBLOCK 0CH
Temp ; a temporary variable
count ; counter
precount ; holds value for prescalar
bin ; binary number to be converted to BCD
hundreds ; BCD hundreds result
tens_and_ones ; BCD tens and ones result
cntmsec ; used in counting milliseconds
ENDC
ORG 0 ; start at location 0
goto main ; jump over to main routine
;----------------------------------------------------------------------;
; Data for message to be output ;
;----------------------------------------------------------------------;
shomsg: ; Message to Output
addwf PCL, f ; Output the Characters
m0 dt "TMR0 Value:", 0
m1 dt "Multiply by:", 0
;----------------------------------------------------------------------;
; Ratios of Prescaler ;
;----------------------------------------------------------------------;
preratio:
addwf PCL, f ; select offset using W
dt D'2',D'4',D'8',D'16',D'32',D'64',D'128'
;----------------------------------------------------------------------;
; Initialize the ports ;
;----------------------------------------------------------------------;
Init:
clrf PORTA
clrf PORTB
movlw B'00010000' ; RA4 input, others outputs
tris PORTA
movlw B'00110000' ; RB4, RB5 input, others outputs
tris PORTB
movlw B'00100001' ; pull-ups enabled
; prescaler assigned to RA4
; prescaler set to 1:4
option
clrf precount
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 msec
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
;----------------------------------------------------------------------;
; Change binary nbr in bin to BCD ;
;----------------------------------------------------------------------;
binary_to_bcd ; by Scott Dattalo
clrf hundreds ; found at http://www.piclist.com
swapf bin, W
addwf bin, W
andlw B'00001111'
skpndc
addlw 0x16
skpndc
addlw 0x06
addlw 0x06
skpdc
addlw -0x06
btfsc bin,4
addlw 0x16 - 1 + 0x6
skpdc
addlw -0x06
btfsc bin,5
addlw 0x30
btfsc bin, 6
addlw 0x60
btfsc bin,7
addlw 0x20
addlw 0x60
rlf hundreds, f
btfss hundreds, 0
addlw -0x60
movwf tens_and_ones
btfsc bin,7
incf hundreds, f
return
;----------------------------------------------------------------------;
; time delay routines ;
;----------------------------------------------------------------------;
Dlay160 movlw D'40' ; 160 usec delay entry point
micro4 addlw H'FF' ; subtract 1 from 'W'
btfss STATUS,Z ; skip when you reach zero
goto micro4 ; more loops
return
Dlay5: movlw D'5' ; 5 msec delay entry point
goto nmsec
msec250: ; a subroutine to delay 250 msec
movlw D'250'
;*** 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 here 995+5 = 1 msec
return
;----------------------------------------------------------------------;
; Display binary value in W in decimal ; ;
;----------------------------------------------------------------------;
DispDec
movwf bin
call binary_to_bcd
movf hundreds, W
call SendASCII
swapf tens_and_ones, W
andlw H'F'
call SendASCII
movf tens_and_ones, W
andlw H'F'
call SendASCII
return
;----------------------------------------------------------------------;
; Return the prescalar ratio setting in W ;
;----------------------------------------------------------------------;
getpre:
bsf STATUS, RP0 ; change to page 1
movf OPTION_REG, W ; get OPTION register
bcf STATUS, RP0 ; back to page 0
andlw 7 ; get 1st 3 bits in W
return
;----------------------------------------------------------------------;
; Check pushbuttons and increment or decrement prescalar ;
;----------------------------------------------------------------------;
ckbuttons:
call getpre ; get prescalar ratio # in Temp
movwf Temp
btfss upbutton ; Skip if up button not pressed
goto preup ; increment prescalar
btfss dnbutton ; Skip if down button not pressed
goto predown ; decrement prescalar
return ; no buttons pressed, return
preup:
incf Temp, f ; up one
btfsc Temp, 3 ; if reach 8, go back to zero
clrf Temp
goto newpre ; and fix new ratio
predown:
decf Temp, f ; down one
movlw H'FF' ; check for underflow
subwf Temp, W
btfss STATUS, Z ; skip if underflow
goto newpre ; and fix new ratio
movlw 7 ; reset to 7
movwf Temp
newpre:
bsf STATUS, RP0 ; change to page 1
movlw B'11111000' ; mask out low three bits
andwf OPTION_REG, W ; result in W
bcf STATUS, RP0 ; back to page 0
iorwf Temp, W ; add in new prescalar ratio #
option ; update OPTION
return ; no debounce necessary because it
; will be one second till you get
; baclk to this routine, even if the
; button is still pressed.
;----------------------------------------------------------------------;
; The Main routine ;
;----------------------------------------------------------------------;
main:
call Init ; initialize ports, set up timer
call initlcd ; initialize the LCD
movlw H'80' ; position at 1st line column 0
call SendINS
movlw m0 -2 ; send 'TMR0 Value:' message
call OutMessage
movlw H'C0'
call SendINS ; position at 2nd line column 0
movlw m1 -2 ; send 'Multiply by:' message
call OutMessage
sholoop:
call ckbuttons ; update prescalar if buttons pushed
movlw H'CD' ; position at 2nd line column 13
call SendINS
call getpre ; get prescalar ratio # in binary
call preratio ; change to prescalar ratio
call DispDec ; put it on LCD
movlw H'8C' ; position at 1st line column 12
call SendINS
bcf INTCON, T0IF ; clear timer zero interrupt flag
clrf TMR0 ; zero TMR0
call msec250 ; wait a total of one second
call msec250
call msec250
call msec250
movf TMR0, W ; retrieve timer zero
btfsc INTCON, T0IF ; check if timer overflowed
goto overload ; yes, display 'OVR'
call DispDec ; display TMR0 value
goto sholoop ; repeat forever
overload
movlw 'O' ; output 'OVR'
call SendCHAR
movlw 'V'
call SendCHAR
movlw 'R'
call SendCHAR
goto sholoop ; and continue
end