ERRORLEVEL -302 TITLE "Temperature Data Logger (c) 2000 Doug Jackson." ;******************************************************************** ; ; TempLog - A temperature logger using a PIC 16F84 and DS1820 ; ; Copyright (c) Jan 2000 ; Doug Jackson ; doug@stillhq.com ; ; Usage: ; Revision: 0.1 ; Date: 05 Jan, 2000 ; Source: \\win95\My Documents\articles\04_Temperature Logger\ ; templog.asm ; Notes: None ; ;******************************************************************** ; Revision History ;******************************************************************** ; Date By What ;******************************************************************** ; 20000105 DRJ Initial Creation ; ;******************************************************************** ; ; Dip Switch Settings ; ; DS1 - 1 = Deg C, 0 = Raw Data (Continuous mode only) ; DS2 - 1 = Log Mode 0 = Continuous Mode ; DS3 - Sample Rate 0 ; DS4 - Sample Rate 1 ; ; Sample Rates; ; ; 11 - 5 Sec / Sample (Approx 5.5 Hours Memory) ; 10 - 1 Min / Sample (Approx 2.8 Days Memory) ; 01 - 5 Min / Sample (Approx 14 Days Memory) ; 00 - 30 Min / Sample (Approx 85 Days Memory) ; ;********************************************************************* ; ; The unit draws approx 3.1mA continuously. A set of AA batteries (2500ma/H) ; should last approx 800 Hours = 33 days. This means that the unit needs to ; have larger capacity to fill the memory on the lowest sample rate. ; ;********************************************************************** Page ; ; CPU configuration ; (It's a 16F84, HS (10 Mhz) oscillator, ; watchdog timer off, power-up timer on) processor 16f84 include __config _HS_OSC & _WDT_OFF & _PWRTE_ON FALSE EQU 0 TRUE EQU 1 J EQU 0x030 K EQU 0x031 L EQU 0x032 textptr EQU 0x033 ; a pointer into a sent text string TXreg EQU 0x034 RXreg EQU 0x034 BitCtr EQU 0x036 T_Val EQU 0x037 T_Sign EQU 0x038 T_Hi EQU 0x039 T_Lo EQU 0x03A T_CountRem EQU 0x03B T_CountPerDegC EQU 0x03C HexChar EQU 0x03D ByteSave EQU 0x03E WRITEHI EQU 0x03F ; storage for our current position WRITELO EQU 0x040 ; in eeprom. READHI EQU 0x041 ; storage for reading the values in READLO EQU 0x042 ; eeprom. w_temp EQU 0x043 status_temp EQU 0x044 LoopCTR EQU 0x045 RESETFLAG EQU 0x046 msCount EQU 0x047 PAGE org 0x0000 RESET GOTO START ; Reset vector location org 0x0004 Interrupt GOTO IntVec ; do the interrupt code. ;*** The tables go into the code early so they don't have any word ; boundary problems. ( remember, we add to PCL, not PC..) Page CopyrightMessage: addwf PCL, f retlw 'P' retlw 'i' retlw 'c' retlw ' ' retlw 'T' retlw 'e' retlw 'm' retlw 'p' retlw 'e' retlw 'r' retlw 'a' retlw 't' retlw 'u' retlw 'r' retlw 'e' retlw ' ' retlw 'L' retlw 'o' retlw 'g' retlw 'g' retlw 'e' retlw 'r' retlw 0x0d retlw 0x0a retlw '(' retlw 'C' retlw ')' retlw 'M' retlw 'a' retlw 'r' retlw ' ' retlw '2' retlw '0' retlw '0' retlw '0' retlw ',' retlw ' ' retlw 'V' retlw 'K' retlw '1' retlw 'Z' retlw 'D' retlw 'J' retlw '.' retlw 0x0d retlw 0x0a retlw 0x0d retlw 0x0a retlw 'D' retlw 'S' retlw '1' retlw ' ' retlw '-' retlw ' ' retlw '0' retlw '=' retlw 'R' retlw 'a' retlw 'w' retlw ',' retlw ' ' retlw '1' retlw '=' retlw 'D' retlw 'e' retlw 'g' retlw 'C' retlw 0x0d retlw 0x0a retlw 'D' retlw 'S' retlw '2' retlw ' ' retlw '-' retlw ' ' retlw '0' retlw '=' retlw 'C' retlw 'o' retlw 'n' retlw 't' retlw 'i' retlw 'n' retlw 'o' retlw 'u' retlw 's' retlw ',' retlw ' ' retlw '1' retlw '=' retlw 'L' retlw 'o' retlw 'g' retlw ' ' retlw 0x0d retlw 0x0a retlw 'D' retlw 'S' retlw '3' retlw ' ' retlw '-' retlw ' ' retlw 'S' retlw 'a' retlw 'm' retlw 'p' retlw 'l' retlw 'e' retlw ' ' retlw 'R' retlw 'a' retlw 't' retlw 'e' retlw ' ' retlw '0' retlw 0x0d retlw 0x0a retlw 'D' retlw 'S' retlw '4' retlw ' ' retlw '-' retlw ' ' retlw 'S' retlw 'a' retlw 'm' retlw 'p' retlw 'l' retlw 'e' retlw ' ' retlw 'R' retlw 'a' retlw 't' retlw 'e' retlw ' ' retlw '1' retlw 0x0d retlw 0x0a retlw 0x0d retlw 0x0a retlw 'S' retlw 'a' retlw 'm' retlw 'p' retlw 'l' retlw 'e' retlw ' ' retlw 'r' retlw 'a' retlw 't' retlw 'e' retlw 's' retlw ':' retlw 0x0d retlw 0x0a retlw 0x0d retlw 0x0a retlw '1' retlw '1' retlw '=' retlw '5' retlw 'S' retlw 'e' retlw 'c' retlw '(' retlw '5' retlw '.' retlw '5' retlw ' ' retlw 'H' retlw 'r' retlw 's' retlw ' ' retlw 'M' retlw 'a' retlw 'x' retlw ')' retlw 0x0d retlw 0x0a retlw '1' retlw '0' retlw '=' retlw '1' retlw 'M' retlw 'i' retlw 'n' retlw '(' retlw '2' retlw '.' retlw '8' retlw ' ' retlw 'D' retlw 'a' retlw 'y' retlw 's' retlw ')' retlw 0x0d retlw 0x0a retlw '0' retlw '1' retlw '=' retlw '5' retlw 'M' retlw 'i' retlw 'n' retlw '(' retlw '1' retlw '4' retlw ' ' retlw 'D' retlw 'a' retlw 'y' retlw 's' retlw ')' retlw 0x0d retlw 0x0a retlw '0' retlw '0' retlw '=' retlw '3' retlw '0' retlw 'M' retlw 'i' retlw 'n' retlw '(' retlw '8' retlw '5' retlw ' ' retlw 'D' retlw 'a' retlw 'y' retlw 's' retlw ')' retlw 0x0d retlw 0x0a retlw 00 Page ;******************************************************************** ; IntVec: ; Do something because the button was pressed. ; ;******************************************************************** BUTTON EQU 0 LED EQU 1 IntVec movwf w_temp ; save off current W register movf STATUS,w ; move status register into W movwf status_temp ; save off contents of STATUS movfw PORTB ; do a dummy read of port b clrf INTCON ; Dissable interrupts clrf LoopCTR ; clear our loop counter clrf RESETFLAG ; and the reset flag bcf PORTB, LED ; Ensure that the LED is off. IntBLoop ; loop while the button is down ; if the button has been down for ; 5 seconds; clear EEPROM and ; start reading again btfsc PORTB, BUTTON ; Is the button down? goto IntButtonUp ; no, bail out movlw d'100' call VarMsDly ; do a delay for 100ms incf LoopCTR,f ; increment our loop counter movfw LoopCTR ; get the value addlw 0 - d'50' ; subtract 50 btfss STATUS,Z ; if the result is zero, the ; number was = 50.. so we set the ; flag that enforces a reset goto IntBLoop ; no carry, loop again movlw 0xFF ; carry - load an FF into the reset movwf RESETFLAG ; flag. bsf PORTB, LED ; turn on the LED to indicate that ; a reset is iminent goto IntBLoop ; and loop again. Page IntButtonUp btfss RESETFLAG,0 ; is the reset flag set? goto DoDump ; no.. dump the current memory buffer clrf WRITELO clrf WRITEHI ; start writing from 0 again. movlw 0x00 movwf EEADR ; save the current value for WRITEHI movfw WRITEHI movwf EEDATA call WriteEE movlw 0x01 movwf EEADR ; save the current value for WRITELO movfw WRITELO movwf EEDATA call WriteEE bcf PORTB, LED ; turn off the LED clrf LoopCTR ; reset the loop counter goto RESET goto IntEnd DoDump movlw 'W' call SendChar movlw 'r' call SendChar movlw 'i' call SendChar movlw 't' call SendChar movlw 'e' call SendChar movlw '=' call SendChar movf WRITEHI,w call PrintHex movf WRITELO,w call PrintHex Page movlw 0x0d call SendChar movlw 0x0a call SendChar movlw 'T' call SendChar movlw 'E' call SendChar movlw 'M' call SendChar movlw 'P' call SendChar movlw '_' call SendChar movlw 'D' call SendChar movlw 'A' call SendChar movlw 'T' call SendChar movlw 'A' call SendChar movlw 0x0d call SendChar movlw 0x0a call SendChar ; ; test to see if there is any data to dump. ; if no data, display a "no data" message and continue ; movfw WRITEHI addlw 0x00 btfsc STATUS,Z goto w1 goto w3 w1 movfw WRITELO addlw 0x00 btfss STATUS,Z goto w3 movlw 'N' call SendChar movlw 'O' call SendChar movlw ' ' call SendChar movlw 'D' call SendChar movlw 'A' call SendChar movlw 'T' call SendChar movlw 'A' call SendChar movlw 0x0d call SendChar movlw 0x0a call SendChar goto IntEnd w3 call Seqread ; do the sequential read of ; the 24c64 IntEnd movf status_temp,w ; retrieve copy of STATUS reg movwf STATUS ; restore pre-isr STATUS movlw B'10010000' ; Turn the GIE bit on. ; and enable INT (PB0) interrupts. movwf INTCON ; set the interrupt reg. ; register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register retfie ; return from interrupt Page ;******************************************************************** ; Start: ; Set up all inputs and outputs as designed. ; and do a self test. ;******************************************************************** START clrf INTCON ; Dissable interrupts bsf STATUS, RP0 ; Select Bank 1 ; note! 0 = output, 1 = input.. movlw b'11111101' ; all of port b, ; except bit 1 are inputs movwf TRISB movlw b'00000000' ; and all of port A are outputs movwf TRISA movlw b'00111111' ; 0 = enable weak pull ups. movwf OPTION_REG bcf STATUS, RP0 ; select bank 0 again.. movlw 0x00 call ReadEE movwf WRITEHI ; get the last value for write Hi movlw 0x01 call ReadEE movwf WRITELO ; get the last value for write Lo call Flash ; the flash of the LED adds another 10mS call WriteCopyright call Flash ; the flash of the LED adds another 10mS movlw B'10010000' ; Turn the GIE bit on. ; and enable INT (PB0) interrupts. movwf INTCON ; set the interrupt reg. goto MAINLOOP Page MAINLOOP ; ; start the main loop by seeing if we have filled ; all available data memory with samples ; If we have, stop logging and enter sleep mode ; to conserve batteries. ; movfw WRITEHI ; look at the High byte of the number of ; samples. if it is 0x20, we have filled ; the memory buffer, so stop sampling addlw 0 - 0x20 btfss STATUS,Z ; if a zero was generated, the ; number was = 20h.. so we stop ; recording samples goto SampleMore ; no, continue counting ; yes. Enable interrupts, and sleep movlw B'10010000' ; Turn the GIE bit on. ; and enable INT (PB0) interrupts. movwf INTCON ; set the interrupt reg. sleep ; yes... lets sleep. SampleMore ; ; Check to see if we want to operate in continuous mode ; (i.e. Stream temp data out the serial port constantly) ; btfsc PORTB,5 ; if the Continuous Switch is on, goto goto ContDump ; a routine to dump data constantly ; movlw 'T' ; ; call SendChar ; movlw 'i' ; call SendChar ; movlw 'm' ; call SendChar ; movlw 'e' ; call SendChar ; movlw 'r' ; call SendChar ; movlw '=' ; call SendChar Page ; ; We are here because we want to log the data as it ; is read.. ; ; Sample the delay value and do an inter-reading delay ; as appropriate ; movfw PORTB ; read the current speed settings andlw b'11000000' addlw 0 btfss STATUS,Z ; if the result is zero, do a 5 sec delay goto aaaa ; movlw '5' ; call SendChar ; movlw 's' ; call SendChar call Dly5s aaaa movfw PORTB ; read the current speed settings andlw b'11000000' addlw 0 - b'10000000' ; subtract the value for 1 Minute btfss STATUS,Z ; if the result is zero, do a goto bbbb ; movlw '1' ; call SendChar ; movlw 'm' ; call SendChar call Dly1m ; 1 minute delay bbbb movfw PORTB ; read the current speed settings andlw b'11000000' addlw 0 - b'01000000' ; subtract the value for 5 Minutes btfss STATUS,Z ; if the result is zero, do a goto cccc ; movlw '5' ; call SendChar ; movlw 'm' ; call SendChar call Dly5m ; 5 minute delay cccc movfw PORTB ; read the current speed settings andlw b'11000000' addlw 0 - b'11000000' ; subtract the value for 30 Minutes btfss STATUS,Z ; if the result is zero, do a goto dddd ; movlw '3' ; call SendChar ; movlw '0' ; call SendChar ; movlw 'm' ; call SendChar call Dly30m ; 30 minute delay dddd ; ; We have now waited long enough, lets do the sampling ; of the Temp sensor. ; call OneWReset ; send a reset pulse to the temp sensor movlw 0xcc ; start conversion by sending a 0xcc, 0x44 call OneWTx ; pattern to the sensor. movlw 0x44 call OneWTx movlw d'250' call VarMsDly movlw d'240' call VarMsDly ; wait 500ms for the conversion call Flash ; the flash of the LED adds another 10mS Page call OneWReset ; send a reset pulse movlw 0xcc ; send a 0xcc, 0xbe call OneWTx ; to start data read movlw 0xbe call OneWTx clrf INTCON ; Dissable interrupts during this section call OneWRx ; get value byte movwf T_Val call SaveByte ; save it away call OneWRx ; get sign byte movwf T_Sign call SaveByte ; save it away ; movlw ':' ; output a ':' char ; call SendChar ; call PrintDecTemp ; send it out rs232 ; movlw 0x0d ; output a char ; call SendChar ; movlw 0x0a ; output a char ; call SendChar movlw 0x00 movwf EEADR ; save the current value for WRITEHI movfw WRITEHI movwf EEDATA call WriteEE movlw 0x01 movwf EEADR ; save the current value for WRITELO movfw WRITELO movwf EEDATA call WriteEE movlw B'10010000' ; Turn the GIE bit on. ; and enable INT (PB0) interrupts. movwf INTCON ; set the interrupt reg. call OneWReset ; send a reset to terminate read. goto MAINLOOP Page ContDump ; dump data continuously call OneWReset ; send a reset pulse to the temp sensor movlw 0xcc ; start conversion by sending a 0xcc, 0x44 call OneWTx ; pattern to the sensor. movlw 0x44 call OneWTx movlw d'250' call VarMsDly movlw d'240' call VarMsDly ; wait 500ms for the conversion call Flash ; the flash of the LED adds another 10mS call OneWReset ; send a reset pulse movlw 0xcc ; send a 0xcc, 0xbe call OneWTx ; to start data read movlw 0xbe call OneWTx ; ; Check to see if we want to dump raw data, or decode ; the data to Degrees C. ; btfsc PORTB,4 ; if the Raw switch is set, do the raw dump goto RawDump ; ; ; We want the data as decoded ascii (deg C) ; call OneWRx ; get value byte movwf T_Val call OneWRx ; get sign byte movwf T_Sign call PrintDecTemp ; send it out rs232 movlw 0x0d ; output a char call SendChar movlw 0x0a ; output a char call SendChar call OneWReset ; send a reset to terminate read. goto MAINLOOP Page RawDump ; ; We want tha data as a raw dump ; call OneWRx ; get value byte movwf T_Val call OneWRx ; get sign byte movwf T_Sign call OneWRx ; get TempHigh byte; movwf T_Hi call OneWRx ; get TempLo byte movwf T_Lo call OneWRx ; skip over the 2 reserved bytes call OneWRx ; call OneWRx ; get count remaining byte movwf T_CountRem call OneWRx ; get count per degree C byte movwf T_CountPerDegC call OneWReset ; send a reset to terminate read. ; ; Now, Dump the data that we read ; movlw 'D' call SendChar movlw 'a' call SendChar movlw 't' call SendChar movlw 'a' call SendChar movlw ':' call SendChar Page movf T_Sign, W call PrintHex movlw ',' call SendChar movf T_Val, W call PrintHex movlw ',' call SendChar movf T_Hi, W call PrintHex movlw ',' call SendChar movf T_Lo, W call PrintHex movlw ',' call SendChar movf T_CountRem, W call PrintHex movlw ',' call SendChar movf T_CountPerDegC, W call PrintHex movlw 0x0d call SendChar movlw 0x0A call SendChar goto MAINLOOP Page ;******************************************************************** ; OneWHi: Provide a logic 1 to a one wire interface. ; Input: ; Output: ; Comments: none ;******************************************************************** OneWHi bsf STATUS, RP0 ; select page 1 bsf TRISA, 0 ; make Port A bit 1 an input ; the external pull up will make it high bcf STATUS, RP0 ; reselect page 0 return OneWLo bcf PORTA, 0 ; port A, bit 1 low. bsf STATUS, RP0 ; page 1 bcf TRISA, 0 ; make the pin an output bcf STATUS, RP0 ; back to page 0 return OneWSlotLo call OneWLo ; take the wire low goto Delay80uS ; and keep it there. OneWSlotHi call OneWLo call OneWHi Delay80uS movlw 0x14 call delay4us call OneWHi ; make sure that we always end with ; the one wire interface high. return OneWReset call OneWLo ; push a low. movlw 0x96 ; delay for 600 uS call delay4us call OneWHi ; push a high movlw 0x64 call delay4us ; delay for 400 uS return Page OneWTx movwf TXreg ; Store W in the tx register movlw 8 ; we need to send 8 bits movwf BitCtr ; store this in the bit counter OneWTxLp rrf TXreg, f ; put the next bit to send into the carry btfsc STATUS, C ; if carry=0, send a zero. goto OneWHiBit ; otherwise, send a one call OneWSlotLo ; make the bit go low. goto OneWDone ; test to see if there are more bits to send OneWHiBit call OneWSlotHi ; make the interface go high OneWDone decfsz BitCtr, f ; have we sent all of the bits? goto OneWTxLp ; no, send more return ; yes, return to sender. OneWRx movlw 8 ; we are expecting 8 bits of data movwf BitCtr ; save this in the bit counter OneWRxLp Call OneWLo call OneWHi ; pulse the wire to get the next nop ; bit of data nop nop nop nop nop nop nop nop nop nop nop nop nop nop bsf STATUS, C ; store a 1 in the carry bit btfss PORTA, 0 ; read Port A bit 0, and skip the ; next bcf STATUS, C ; we read a 0, so make carry a 0. rrf RXreg, f ; move the carry bit into the ; recieve register. movlw 0x14 ; delay for 80 uS. call delay4us decfsz BitCtr, f ; decrement the number of bits that ; we now expect goto OneWRxLp ; get more bits if we have to movf RXreg,W return Page ;******************************************************************** ; Flash: Flash the LED to re-assure the user that we are working. ; Input: ; Output: ; Comments: none ;******************************************************************** Flash bsf PORTB, 1 movlw d'10' ; delay for 10 mS. call VarMsDly bcf PORTB, 1 return Page ;******************************************************************** ; Internal EEProm routines ; Input: ; Output: ; Comments: none ;******************************************************************** ReadEE movwf EEADR ; Setup EEPROM address from ; 'w' bsf STATUS, RP0 ; change to page 1 bsf EECON1, RD ; set the read bit bcf STATUS, RP0 ; back to page 0 movf EEDATA, W ; return value in 'W' return WriteEE bsf STATUS, RP0 ; setup eeAddr and EEDATA first clrf EECON1 ; bsf EECON1, WREN ; enable writes. movlw 0x55 ; movwf EECON2 movlw 0xaa movwf EECON2 bsf EECON1, WR ; set the write bit EEloop btfsc EECON1, WR ; wait for the write bit to drop goto EEloop bsf EECON1, WREN ; bcf EECON1, EEIF ; clear the interrupt flag bcf STATUS, RP0 ; back to page 0 return Page ;************************************************************************************* ; SDA routines ; Input: ; Output: ; Comments: none ;************************************************************************************* sda equ 3 ; the 24C64 data line is on bit 3 sck equ 2 ; the 24C64 clock line is on bit 2 SClock_Hi bsf PORTA,sck ;make ra2 a 1 return SClock_Lo bcf PORTA,sck ;make ra2 a 0 return SData_Hi bsf STATUS,RP0 ;go to bank 1 bsf TRISA,sda ;make pa3 an input bcf STATUS,RP0 ;back to page 0 return SData_Lo bcf PORTA,sda ;sda low bsf STATUS,RP0 ;bank 1 bcf TRISA,sda ;make ra3 an output bcf STATUS,RP0 ;bank 0 return Page Pulse_Clock call SClock_Hi ;clock high call delay4us call delay4us ; stay high for 8us call SClock_Lo ;bring back low call delay4us call delay4us ; stay low for 8us return SStart call SClock_Lo ;make sure clock low call SData_Hi ;make sure high while clock low call SClock_Hi ;start with high clock call SData_Lo ;bring sda low while clock high call SClock_Lo ;bring clock back low call delay4us ;stay low for a while return SStop call SClock_Lo ;make sure it's low call SData_Lo ;make sure low while clock low call SClock_Hi ;start with high clock call SData_Hi ;bring sda high while clock high call SClock_Lo ;bring clock back low call delay4us ;stay low for a while return SNack call SData_Hi ;make sure sda is high call Pulse_Clock ;and clock return SAck call SData_Lo ;sda low ( clock should be low ) call Pulse_Clock ;and clock return Page Stxbyte2 movwf TXreg ;put w into transmit register movlw 0x08 ;eight bits of data movwf BitCtr ;a counter for bits Stx2loop bcf STATUS,C ;clear carry rlf TXreg,f ;roll leftmost bit into carry btfsc STATUS,C ;if carry 0 want low bit output goto Shibit2 ;else send a 1 call SData_Lo ;output a low bit ( ra1 ) call Pulse_Clock call SData_Hi goto Sdone2 ;are we finished? Shibit2 call SData_Hi ;output a high bit ( ra1 ) call Pulse_Clock Sdone2 decfsz BitCtr,f ;1 less data bit, skip when 0 goto Stx2loop ;more bits left call SNack ;allow memory to acknowledge return Srxbyte2 movlw 0x08 ;eight bits of data movwf BitCtr ;a counter for bits call SData_Hi ;make sure sda is high Srx2loop call SClock_Hi ;clock high call delay4us ; wait a while btfss PORTA,sda ;test sda bit goto Szeroin ;must be a zero bsf STATUS,C ;set carry to 1 goto Scont_in ;and check for more bits Szeroin bcf STATUS,C ;zero into carry Scont_in rlf RXreg,f ;roll into receive register call SClock_Lo ;bring clock low nop ;wait a while nop nop nop decfsz BitCtr,f ;1 less data bit, skip when zero goto Srx2loop ;more bits left movf RXreg,w return Page SaveByte movwf ByteSave ;enter with byte to save in w call SStart movlw 0xa0 ;control byte write into w call Stxbyte2 ;i2c transmit byte movf WRITEHI,W ;high byte of address in w call Stxbyte2 movf WRITELO,W ;low byte of address call Stxbyte2 movf ByteSave,W ;recall saved byte call Stxbyte2 ;and send it out call SStop ;end the save movlw 0x14 ;20 msec delay to 'burn in' call VarMsDly incf WRITELO,f ;bump address up one btfsc STATUS,Z ;rolled over to zero? incf WRITEHI,f ;yes, bump high byte return Seqread movlw 0x0d ; output a char call SendChar movlw 0x0a ; output a char call SendChar movf WRITEHI,W movwf READHI movf WRITELO,w movwf READLO ; start from addr 0 incf READHI,f ; bodgie. inc ReadHI, so that the dec test later will work. call SStart ;addr & # reads set before entry movlw 0xA0 ;control byte write into w call Stxbyte2 ;i2c transmit byte movlw 0x00 ;Start at zero call Stxbyte2 movlw 0x00 ;low byte of address call Stxbyte2 call SStart ;another start pulse movlw 0xA1 ;control byte read into w call Stxbyte2 ;i2c transmit byte Readone call Srxbyte2 ;get byte from memory movwf T_Val call SAck call Srxbyte2 movwf T_Sign call PrintDecTemp ;send it out rs232 Page decfsz READLO,f ;check low byte of count goto decagain ;not finished, get another decfsz READHI,f ;check hi byte goto decagain ;not finished goto decexit decagain decfsz READLO,f ;check low byte of count goto Nextout ;not finished, get another decfsz READHI,f ;check hi byte goto Nextout ;not finished decexit call SNack ;we are finished, stop reading call SStop movlw 0x0d ; output a char call SendChar movlw 0x0a ; output a char call SendChar return Nextout call SAck ;pic acknowledges byte movlw 0x0d ; output a char call SendChar movlw 0x0a ; output a char call SendChar goto Readone Page ;******************************************************************** ; WriteCopyright: Displays a copyright message ; Input: ; Output: ; Comments: none ;******************************************************************** WriteCopyright movlw 0x0d ; output a char call SendChar movlw 0x0a ; output a char call SendChar movlw 0 ; send the first message movwf textptr TextLoop movf textptr, W call CopyrightMessage addlw 0 btfsc STATUS, Z return call SendChar incf textptr, f goto TextLoop Page ;******************************************************************** ; PrintDecTemp: Dump The temp as a decimal number. ; Input: ; Output: ; Comments: ;******************************************************************** PrintDecTemp movlw HIGH DigitTable movwf PCLATH movlw '-' ; assume the sign is -ve btfss T_Sign,0 ; get the sign of the temperature movlw '+' ; reset the sign if we stuffed up call SendChar ; print the sign movf T_Val,w btfsc T_Sign,0 ; get the sign of the temperature comf T_Val,w ; add 128 to the temp if it is -ve to display it correctly. andlw 0x7f movwf T_Val ; isolate the .0 / .5 Deg bit movf T_Val,W ; get the temperature value andlw b'00000001' ; isolate the last bit movwf T_Hi ; and save the result away rrf T_Val,w ; rotate out the .5 deg bit andlw 0x7f movwf T_Val disp111 movf T_Val,W ; get the temperature value addlw 0 - d'100' ; subtract 100. btfss STATUS, C ; are we now less than 100 goto PrintTens ; yes, do the tens test movwf T_Val movlw '1' ; no, display a 1 call SendChar PrintTens movf T_Val,W ; re-get the temp clrf J ; zero a counter PrintTenslp incf J,f addlw 0 - d'10' ; subtract 10 from the tens counter btfsc STATUS,C goto PrintTenslp addlw d'10' ; add 10 to the result, as we took off ; too much. decf J,f movwf T_Val ; save the remaining units movf J, W ; get the number of tens call DigitTable call SendChar ; and print them. movf T_Val,W ; get the units call DigitTable call SendChar ; and print them. movlw '.' call SendChar ; output the decimal point movlw '5' ; assume the digit is -ve btfss T_Hi,0 ; get the Previously saved LSB movlw '0' ; reset the digit if we stuffed up call SendChar ; print the last digit return ; return Page ;******************************************************************** ; PrintHex: Dump a hexadecimal character ; Input: ; Output: ; Comments: ;******************************************************************** PrintHex movwf HexChar ; save the byte provided movlw HIGH DigitTable movwf PCLATH swapf HexChar, 0 andlw 0x0f ; get the first nibble call DigitTable ; use W as an offset into a character Table call SendChar movf HexChar, W ; get the byte back andlw 0x0f ; get the second nibble call DigitTable ; use W as an offset into a character Table call SendChar return DigitTable: addwf PCL, f retlw '0' retlw '1' retlw '2' retlw '3' retlw '4' retlw '5' retlw '6' retlw '7' retlw '8' retlw '9' retlw 'a' retlw 'b' retlw 'c' retlw 'd' retlw 'e' retlw 'f' retlw 'X' Page ;******************************************************************** ; SendChar: Send a serial character ; Input: ; Output: ; Comments: ;******************************************************************** SendChar movwf TXreg movlw 8 movwf BitCtr bsf PORTA, 1 SendLoop movlw d'49' call delay4us rrf TXreg, f btfsc STATUS, C goto Clearbit bsf PORTA, 1 goto Senddone Clearbit bcf PORTA, 1 nop Senddone decfsz BitCtr, f ; are all bits sent? goto SendLoop ; no, send more movlw 0x34 ; delay for 208 uS now. call delay4us bcf PORTA, 1 ; send the stop bit. movlw 0x68 ; delay for 104uS call delay4us return Page ;******************************************************************** ; var_delay: variable delay routine ; Input: ; Output: ; Comments: ;******************************************************************** var_delay movwf J jloop2 movwf K kloop2 decfsz K,f goto kloop2 decfsz J,f goto jloop2 return ;******************************************************************** ; Dly5m: Delay for 30 Minutes (including time to read sensor etc..) ; Input: none ; Output: none ; Comments: none ;******************************************************************** Dly30m movlw d'30' movwf J m30loop call Dly1m decfsz J,f goto m30loop movlw d'196' ; fudge so that total delay (inc temp read) call VarMsDly ; = 30 Minutes. return Page ;******************************************************************** ; Dly5m: Delay for 5 Minutes (including time to read sensor etc..) ; Input: none ; Output: none ; Comments: none ;******************************************************************** Dly5m movlw d'71' movwf K m5dloop call Dly5s decfsz K,f goto m5dloop movlw d'44' movwf L m5da movlw d'100' call VarMsDly decfsz L,f goto m5da movlw d'77' ; fudge so that total delay (inc temp read) call VarMsDly ; = 300 Seconds. movlw d'1' call delay4us ; fine tune return ;******************************************************************** ; Dly1m: Delay for 1 Minute (including time to read sensor etc..) ; Input: none ; Output: none ; Comments: none ;******************************************************************** Dly1m movlw d'13' movwf K m1dloop call Dly5s decfsz K,f goto m1dloop movlw d'20' movwf L m1da movlw d'250' call VarMsDly decfsz L,f goto m1da movlw d'201' ; fudge so that total delay (inc temp read) call VarMsDly ; = 5 Seconds. movlw d'150' call delay4us ; fine tune return Page ;******************************************************************** ; Dly5s: Delay for 5 Seconds (including time to read sensor etc..) ; Input: none ; Output: none ; Comments: none ;******************************************************************** Dly5s movlw d'16' movwf L s5dloop movlw d'250' call VarMsDly decfsz L,f goto s5dloop movlw d'155' ; fudge so that total delay (inc temp read) call VarMsDly ; = 5 Seconds. movlw d'152' call delay4us ; fine tune return ;******************************************************************** ; VarMsDly: Variable millisecond based delay loop ; Input: none ; Output: Various Dice patterns ; Comments: none ;******************************************************************** VarMsDly movwf msCount ; save w in a millisecond counter register vmsloop movlw 0xf9 call delay4us nop nop decfsz msCount,f goto vmsloop return Page ;******************************************************************** ; Delay1ms: Delay for 1 millisecond ; Input: ; Output: ; Comments: none ;******************************************************************** delay1ms movlw 0xf9 nop ; add a nop to allow for the use of a call instruction in the ; same delay loop. delay4us addlw 0xff ; subtract 1 from W reg nop ; add 2.4uS of delays at 10Mhz clock speed nop nop nop nop nop btfss STATUS,Z; is it zero? goto delay4us; no, more looping required return ; yes, return to the caller routine end