Due to personal reasons, it has been a long time since I’ve done something with electronics. Time to start again and have some fun :)
Like you can see on the picture below, I’m experimenting with a pic18f1320, a DS18B20 temperature sensor (1-wire connection) and HD44780 display on a breadboard.
Because of the 1-wire connection the electronic schematic is not very complex.
I’ve written the pic-program in assembly (gputils/gpasm):
; --------------------------------------------------------------------------- ; µC = PIC18F1320 ; --------------------------------------------------------------------------- LIST P=18F1320 #include <p18f1320.inc> ; --------------------------------------------------------------------------- ; Configuration ; --------------------------------------------------------------------------- CONFIG OSC = INTIO2 ; Internal RC, OSC1 as RA7, OSC2 as RA6 CONFIG WDT = OFF ; Watchdog Timer CONFIG BOR = OFF ; Brown-Out Reset CONFIG MCLRE = OFF ; MCLR Enable CONFIG LVP = OFF ; Low Voltage ICSP CONFIG DEBUG = OFF ; Background Debugger Enable ; --------------------------------------------------------------------------- ; Define LCD pins ; --------------------------------------------------------------------------- #DEFINE RS PORTA, 4 ; RS line of LCD #DEFINE E PORTA, 6 ; E line of LCD #DEFINE D4 PORTA, 0 ; #DEFINE D5 PORTA, 1 ; D4-D7 of LCD #DEFINE D6 PORTA, 2 ; #DEFINE D7 PORTA, 3 ; ; --------------------------------------------------------------------------- ; DEFINE DS18B20 pin ; --------------------------------------------------------------------------- #DEFINE DQ 1 ; PORTB PIN 1 ; --------------------------------------------------------------------------- ; MACRO's DS18B20 ; --------------- ; See <http://www.maximintegrated.com/en/app-notes/index.mvp/id/2420> ; --------------------------------------------------------------------------- OW_HIZ: MACRO ; Force the DQ line into a high impedance state. BSF TRISB, DQ ; Make DQ pin High Z ENDM OW_LO: MACRO ; Force the DQ line to a logic low. BCF PORTB, DQ ; Clear the DQ bit BCF TRISB, DQ ; Make DQ pin an output ENDM WAIT: MACRO TIME ; Delay for TIME µs. ; Variable time must be in multiples of 5µs. MOVLW (TIME/5) - 1 ; 1µs to process MOVWF TMP0 ; 1µs to process CALL WAIT5U ; 2µs to process ENDM ; --------------------------------------------------------------------------- ; MACRO wait ms ; --------------------------------------------------------------------------- WAITms MACRO TIME ; Delay for TIME ms movlw TIME call Wachtms ENDM ; --------------------------------------------------------------------------- ; MACRO's LCD ; --------------------------------------------------------------------------- EStrobe MACRO ; Strobe the "E" Bit bsf E bcf E ENDM PRINT MACRO var ; load TBLPTR with string address movlw upper(var) ; for LCD display movwf TBLPTRU movlw high(var) movwf TBLPTRH movlw low(var) movwf TBLPTRL tblrd*+ call printstr ENDM ; --------------------------------------------------------------------------- ; Variables ; --------------------------------------------------------------------------- cblock 0x00 delay Temp dummy ; conv numbers --> char hundreds bin tens_and_ones ; temp.display MEM fraction ; DS18B20 TMP0 PDBYTE IOBYTE COUNT endc ; --------------------------------------------------------------------------- ; START ; --------------------------------------------------------------------------- start movlw B'01100000' ; FREQ = 4Mhz movwf OSCCON CLRF PORTA ; Initialize PORTA by clearing output CLRF PORTB ; Initialize PORTB by clearing output ; data latches MOVLW 0x7F ; Set RB's & RA's as MOVWF ADCON1 ; digital I/O pins clrw movwf TRISA ; PORTA = OUTPUT movwf TRISB ; PORTB = OUTPUT WAITms 10 ; Wait a few ms call initlcd ; setup LCD display lus call cls ; clear LCD display movlw H'80' ; goto line 1 call SendINS PRINT jan ; PRINT jan RETRY CALL OW_RESET BTFSS PDBYTE,0 BRA RETRY ; Retry when there is no pulse of DS18B20 MOVLW H'CC' ; DS18B20 : Skip ROM CALL DSTXBYTE MOVLW H'44' ; DS18B20 : Convert Temp CALL DSTXBYTE WAIT D'800' ; Wait 800 µs CALL OW_RESET BTFSS PDBYTE,0 BRA RETRY ; Retry when there is no pulse of DS18B20 MOVLW H'CC' ; DS18B20 : Skip ROM CALL DSTXBYTE MOVLW H'BE' ; DS18B20 : Read ScratchPad CALL DSTXBYTE movlw H'94' ; goto line 3 call SendINS CALL DSRXBYTE ; Read LTEMP (in IOBYTE) movff IOBYTE, MEM ; MEM = LTEMP CALL DSRXBYTE ; READ HTEMP (in IOBYTE) ;==============================================================; ; IOBYTE = HTEMP ; ; MEM = LTEMP ; ; BTW, we assume that we never meassure negative temperatures ; ;==============================================================; clrf fraction ; fraction = 0 bcf STATUS, C ; clear carry flag rrcf MEM, f rrcf fraction, f rrcf MEM, f rrcf fraction, f ; MEM = MEM/16 , fraction rrcf MEM, f rrcf fraction, f rrcf MEM, f rrcf fraction, f swapf fraction, f swapf IOBYTE, w ; W = IOBYTE * 16 iorwf MEM, w ; W = HTEMP+LTEMP call DispDec ; PRINT XX movlw "." call SendCHAR ; PRINT . ;==============================================================; ; Calculate .X ; ; ------------ ; ; See DS18B20.gnumeric ; ;==============================================================; clrw ; XX.0 btfsc fraction, 3 ; If bit 3 = 1 then ADDLW D'5' ; W = W + 5 btfsc fraction, 2 ; If bit 2 = 1 then ADDLW D'3' ; W = W + 3 btfsc fraction, 1 ; If bit 1 = 1 then ADDLW D'1' ; W = W + 1 btfss fraction, 0 ; If bit 0 = 1 bra ready ; and bit 2 <> 1 then btfss fraction, 2 ; W = W + 1 ADDLW D'1' ready: call SendASCII ; PRINT after . call Wacht1s goto lus ; --------------------------------------------------------------------------- ; LCD subroutine init/cls ; --------------------------------------------------------------------------- initlcd: WAITms D'40' bcf RS ; send an 8 bit instruction movlw 0x03 ; Reset Command call NybbleOut ; Send the Nybble WAITms D'5' ; Wait 5 msecs before Sending Again EStrobe WAIT D'160' ; Wait 160 usecs before Sending 2nd Time EStrobe WAIT D'160' ; Wait 160 usecs before Sending 3rd Time bcf RS ; send an 8 bit instruction movlw 0x02 ; Set 4 Bit Mode call NybbleOut WAIT D'160' movlw 0x028 ; 4 bit, 2 Line, 5x7 font call SendINS movlw 0x010 ; display shift off call SendINS movlw 0x006 ; increment cursor call SendINS movlw 0x00C ; display on cursor off call SendINS cls: movlw 0x001 ; Clear the Display RAM call SendINS WAITms D'5' ; Note, Can take up to 4.1 msecs return ; --------------------------------------------------------------------------- ; LCD subroutine print string ; --------------------------------------------------------------------------- printstr: movf TABLAT, w ; get characters btfsc STATUS, Z ; if character = 0 then ... return ; ... exit call SendCHAR ; display character tblrd*+ ; TABLAT = next character bra printstr ; repeat ; --------------------------------------------------------------------------- ; 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 rlcf hundreds, f btfss hundreds, 0 addlw -0x60 movwf tens_and_ones btfsc bin,7 incf hundreds, f return ; --------------------------------------------------------------------------- ; Display binary value in W in decimal ; --------------------------------------------------------------------------- DispDec: movwf bin call binary_to_bcd ; movf hundreds, W ; Hondertallen zijn niet nodig ; call SendASCII swapf tens_and_ones, W andlw H'F' call SendASCII movf tens_and_ones, W andlw H'F' call SendASCII 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 dummy ; dummy = W bcf D7 ; D7....D4 = dummy[3:0] bcf D6 bcf D5 bcf D4 btfsc dummy, 3 bsf D7 btfsc dummy, 2 bsf D6 btfsc dummy, 1 bsf D5 btfsc dummy, 0 bsf D4 EStrobe ; Strobe out the LCD Data WAIT D'160' ; delay for 160 usec return ;---------------------------------------------------------------------------- ; Delay routines ;---------------------------------------------------------------------------- Wacht1s: WAITms D'250' WAITms D'250' WAITms D'250' WAITms D'250' return Wachtms: movwf delay w2: WAIT D'1000' ; WAIT 1000µs = 1ms decfsz delay, F goto w2 return ; --------------------------------------------------------------------------- ; Subroutines DS18B20 ; see <http://www.maximintegrated.com/en/app-notes/index.mvp/id/2420> ; --------------------------------------------------------------------------- WAIT5U: ;This takes 5µs to complete NOP ; 1µs to process NOP ; 1µs to process DECFSZ TMP0,F ; 1µs if not zero or 2µs if zero GOTO WAIT5U ; 2µs to process RETLW 0 ; 2µs to process OW_RESET: OW_HIZ ; Start with the line high CLRF PDBYTE ; Clear the PD byte OW_LO WAIT .500 ; Drive Low for 500µs OW_HIZ WAIT .70 ; Release line and wait 70µs for PD Pulse BTFSS PORTB,DQ ; Read for a PD Pulse INCF PDBYTE,F ; Set PDBYTE to 1 if get a PD Pulse WAIT .430 ; Wait 430µs after PD Pulse RETLW 0 DSTXBYTE: ; Byte to send starts in W MOVWF IOBYTE ; We send it from IOBYTE MOVLW .8 MOVWF COUNT ; Set COUNT equal to 8 to count the bits DSTXLP: OW_LO NOP NOP NOP ; Drive the line low for 3µs RRCF IOBYTE,F BTFSC STATUS,C ; Check the LSB of IOBYTE for 1 or 0 BSF TRISB,DQ ; HiZ the line if LSB is 1 WAIT .60 ; Continue driving line for 60µs OW_HIZ ; Release the line for pullup NOP NOP ; Recovery time of 2µs DECFSZ COUNT,F ; Decrement the bit counter GOTO DSTXLP RETLW 0 DSRXBYTE: ; Byte read is stored in IOBYTE MOVLW .8 MOVWF COUNT ; Set COUNT equal to 8 to count the bits DSRXLP: OW_LO NOP NOP NOP NOP NOP NOP ; Bring DQ low for 6µs OW_HIZ NOP NOP NOP NOP ; Change to HiZ and Wait 4µs MOVF PORTB,W ; Read DQ ANDLW 1<<DQ ; Mask off the DQ bit ADDLW .255 ; C = 1 if DQ = 1: C = 0 if DQ = 0 RRCF IOBYTE,F ; Shift C into IOBYTE WAIT .50 ; Wait 50µs to end of time slot DECFSZ COUNT,F ; Decrement the bit counter GOTO DSRXLP RETLW 0 ; --------------------------------------------------------------------------- ; Strings used in the program ; --------------------------------------------------------------------------- jan db " - Jan Wagemakers - ",0 ; --------------------------------------------------------------------------- ; END ; --------------------------------------------------------------------------- END