;----------------------------------------------------------------------;
; THERM4M.ASM Shows Temperature from Thermistor on LCD, 4 MHz clock ;
;----------------------------------------------------------------------;
; 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.03 mfd [LCD D7]----|RB3 RB4|---[PB]--- gnd
; -{r}- = 33K '-----------'
; -|<- = 1n4148 [R] = Thermistor -[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 MHz
INCLUDE "p16f84.inc"
__CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF ; uses 4 MHz crystal
ERRORLEVEL -224 ; supress annoying message from tris
ERRORLEVEL -302 ; supress 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
; Macro
EStrobe MACRO ; Strobe the "E" Bit
bsf E
bcf E
ENDM
CBLOCK 0CH
Temp ; a temporary variable
count ; counter
cntmsec ; used in counting milliseconds
bin ; binary number to be converted to BCD
hundreds ; BCD hundreds result
tens_and_ones ; BCD tens and ones result
savetmr0 ; used to save value of tmr0
dispvalue ; used to hold temperature displayed
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 "Temperature", 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'00100011' ; pull-ups enabled
; prescaler assigned to RA4
; prescaler set to 1:16
option
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
;----------------------------------------------------------------------;
; Change binary nbr in bin to BCD ;
;----------------------------------------------------------------------;
binary_to_bcd ; by Scott Dattalo
clrf hundreds
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' ; delay about 160 usec,(4/loop )
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'248' ; 1 usec for load
call micro4 ; this instruction takes 995 usec
nop ; 1 usec
decfsz cntmsec,f ; 1 usec, (2 if skip taken)
goto msecloop ; 2 usec here makes 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
;----------------------------------------------------------------------;
; 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 'Temperature:' message
call OutMessage
sholoop:
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
movwf savetmr0 ; save the value
btfsc INTCON, T0IF ; check if timer overflowed
goto overload ; yes, display 'OVR'
call DispDec ; display TMR0 value
movlw H'CD' ; position at 2nd line column 13
call SendINS
movlw 2 ; set up PCLATH to page 2
movwf PCLATH
movlw D'32' ; 1st table value is for tmr0 = 32
subwf savetmr0, W ; subtract 32 from tmr0 value
call temptable ; get temperature
movwf dispvalue ; save it in display value
swapf dispvalue, W ; get hi nibble in W
andlw H'0F' ; lowest 4 bits
call SendASCII ; display it
movf dispvalue, W ; get lo nibble in W
andlw H'0F' ; lowest 4 bits
call SendASCII ; display it
goto sholoop ; repeat forever
overload
movlw 'O' ; output 'OVR'
call SendCHAR
movlw 'V'
call SendCHAR
movlw 'R'
call SendCHAR
goto sholoop ; and continue
org H'200'
temptable: ; get temperature to display
addwf PCL, f
dt 11,12,12,13,14,14,15,16,16,17,18,18,19,20,20,21,22,22,23,24,24,25
dt 26,26,27,27,28,29,29,30,31,31,32,32,33,34,34,35,35,36,36,37,38,38
dt 39,39,40,40,41,41,42,42,43,44,44,45,45,46,46,47,47,48,48,49,49,50
dt 50,51,51,52,52,53,53,54,54,54,55,55,56,56,57,57,58,58,59,59,59,60
dt 60,61,61,62,62,63,63,63,64,64,65,65,65,66,66,67,67,68,68,68,69,69
dt 70,70,70,71,71,71,72,72,73,73,73,74,74,75,75,75,76,76,76,77,77,78
dt 78,78,79,79,79,80,80,81,81,81,82,82,82,83,83,83,84,84,84,85,85,85
dt 86,86,87,87,87,88,88,88,89,89,89,90,90,90,91,91,91,92,92,92,93,93
dt 93,94,94,95,95,95,96,96,96,97,97,97,98,98,98,99,99,99,00,00,00,01
dt 01,01,02,02,03,03,03,04,04,04,05,05,05,06,06,06,07,07,08,08,08,09
dt 09,09,10,10
end