; PROGRAM balloontemp.asm 7/6/2005 ;This program works. ; ; Performs temperature measurement using DS1820 and 12F508. ; Data from DS1820, pin 2, communicates with 12F508 GPIO,0. ; The data line to the DS1820 must be pulled high w/ 4.7K resistor. ; The tone out to a speaker is GPIO,1. LIST P=12F508 ;Configuration: ; MCLR enabled ; Code Protection off ; Watchdog timer disabled ; Internal RC oscillator PCL EQU 0x02 STATUS EQU 0x03 OSCAL EQU 0x05 GPIO EQU 0x06 C EQU 0 Constant BAS_VAR=0x07 WARMUP EQU BAS_VAR+0 TEMP_F EQU BAS_VAR+1 TEMP_F_W EQU BAS_VAR+2 _N EQU BAS_VAR+3 TONE_L EQU BAS_VAR+4 TONE_P EQU BAS_VAR+5 LOOP1 EQU BAS_VAR+6 LOOP2 EQU BAS_VAR+7 LOOP3 EQU BAS_VAR+8 O_BYTE EQU BAS_VAR+9 I_BYTE EQU BAS_VAR+9 TEMP EQU BAS_VAR+10 TENS EQU BAS_VAR+10 ;Option: bit 7, 1=no interrupts, bit 6, 1=no pullups, ;bit 5, 0=internal clock, bit 4, edge select, ;bit 3, 1=prescaler to WDT, bits 0-2, prescaler. ;GPIO set all all output except bit 3. ;TRIS set as low except for DS1820, bit 0. org 0x00 movwf OSCAL movlw b'11011111' option ;see OPTION note above movlw b'00001000' TRIS GPIO ;set GPIO as output, except MCLR movlw b'00001001' movwf GPIO ;set speaker, MCLR high movlw .30 ;set at 30 for 5 minutes, sets movwf WARMUP ;10 second reports for 5 minutes goto Begin ;skip tables and subroutines ;TABLES------------------------------------------------------- ;Sensor returns temperature in .5 degree increments. ;thus value of 200 means reading of 100 degress Celcius TEMP_TABLE ;Converts sensor reading to F degrees addwf PCL, f retlw .140 ;offset 0 or 60C or 120 from sensor retlw .145 ;offset 1 retlw .145 ;offset 2 retlw .150 ;offset 3 retlw .155 ;offset 4 retlw .160 ;offset 5 retlw .160 ;offset 6 retlw .165 ;offset 7 retlw .170 ;offset 8 retlw .175 ;offset 9 retlw .175 ;offset 10 retlw .180 ;offset 11 retlw .180 ;offset 12 retlw .185 ;offset 13 retlw .190 ;offset 14 retlw .195 ;offset 15 retlw .195 ;offset 16 retlw .200 ;offset 17 retlw .205 ;offset 18 retlw .205 ;offset 19 retlw .210 ;offset 20 retlw .215 ;offset 21 retlw .215 ;offset 22 retlw .220 ;offset 23 retlw .225 ;offset 24 retlw .230 ;offset 25 retlw .235 ;offset 26 retlw .235 ;offset 27 retlw .240 ;offset 28 retlw .245 ;offset 29 retlw .250 ;offset 30 retlw .250 ;offset 31 retlw .255 ;offset 32 retlw .255 ;offset 33 ;tables MorseCt and MorseT translate the number of 10's into tones. ;for example, assume temperature of 160 which has 6 tens. MorseCt ; will return the value ".10". MorseT will then go down 10 rows ;to the last Dah before the goto command. One Dah will be sent. MorseCt addwf PCL, f ;Translates numbers into dits and dahs retlw .6 ;number 0 retlw .4 ;number 1 retlw .3 ;number 2 retlw .2 ;number 3 retlw .1 ;number 4 retlw .0 ;number 5 retlw .10 ;number 6 retlw .9 ;number 7 retlw .8 ;number 8 retlw .7 ;number 9 MorseT ;sounds Dits and Dahs based on table MorseCt, above addwf PCL, f call Dit ;number 5, offset 0 call Dit ;number 4, offset 1 call Dit ;number 3, offset 2 call Dit ;number 2, offset 3 call Dit ;number 1, offset 4 goto MorseRet call Dah ;number 0, offset 6 call Dah ;number 9, offset 7 call Dah ;number 8, offset 8 call Dah ;number 7, offset 9 call Dah ;number 6, offset 10 goto MorseRet ;SUBROUTINES-------------------------------------------------- ; Routines for "1-Wire" serial data transfers. INIT: ;initializes DS1820 call PIN_HI call PIN_LO movlw .70 ;enter 50 for 500 microsecond delay movwf LOOP1 call DELAY_10USEC call PIN_HI movlw .50 ;enter 50 for 500 microsecond delay movwf LOOP1 call DELAY_10USEC retlw 0 IN_BYTE: ;returns byte in w movlw .8 ;8 bits make a byte movwf _N ;_N is bit counter clrf I_BYTE ;this is reported temperature IN_BYTE_1: call PIN_LO NOP call PIN_HI movlw b'00001001' ;Set pin to receive data tris GPIO ;from DS1820. NOP ;wait to allow Ds1820 to stabilize NOP NOP NOP movf GPIO, w ;move gpio pins to w, to read bit 0 movwf TEMP ;move gpio pins to temp btfss TEMP, 0 ;test the data_pin; set = 0 bcf STATUS, C ;if so clear status bit c btfsc TEMP, 0 ;test data-pin; clear = 1 bsf STATUS, C ;if so set status bit c rrf I_BYTE, f ;rotate for next bit; carry in c movlw .7 ;ENTER 6 FOR 60 USEC DELAY movwf LOOP1 call DELAY_10USEC movlw b'00001000' ;finished reading bit from DS1820 TRIS GPIO ;allow PIC to transit to DS1820 decfsz _N, f ;count down counter _N goto IN_BYTE_1 ;return for next bit retlw 0 OUT_BYTE: ;sends byte out the data_pin movlw .8 ;8 bits make a byte movwf _N ;_N is bit counter OUT_BYTE_1: rrf O_BYTE, f ;rotate the byte, picking up bits btfss STATUS, C ;test determines 0 or 1 bit out goto OUT_0 goto OUT_1 OUT_BYTE_2: decfsz _N, f ;count down counter for 8 bits goto OUT_BYTE_1 ;get next bit retlw 0 OUT_0: ;sends out a 0 bit call PIN_LO ;sets data_pin low movlw .7 ;ENTER 6 FOR 60 USEC DELAY movwf LOOP1 call DELAY_10USEC call PIN_HI ;sets data_pin high goto OUT_BYTE_2 OUT_1: ;sends out a 1 bit call PIN_LO ;sets data_pin low call PIN_HI ;sets data_pin high movlw .7 ;ENTER 6 FOR 60 USEC DELAY movwf LOOP1 call DELAY_10USEC goto OUT_BYTE_2 PIN_HI ;sets data_pin high bsf GPIO,0 retlw 0 PIN_LO ;sets data_pin low bcf GPIO,0 retlw 0 ;Dit and Dah are same code except for timing ;tone is created by setting and clearing pin. ;this creates square wave whose frequency is ;determined by time high and low. Dit movlw .30 ;set time of each tone swing-30 movwf TONE_L movlw .254 ;each sound 254 cycles long movwf TONE_P ToneC bsf GPIO, 1 ;tone goes out this pin movf TONE_L, w movwf LOOP1 call DELAY_10USEC bcf GPIO, 1 movf TONE_L, w movwf LOOP1 call DELAY_10USEC decfsz TONE_P, f goto ToneC movlw .1 ;creates 1/4 second space after dit movwf LOOP1 call Delay retlw 0 Dah movlw .100 ;set time of each tone swing-100 movwf TONE_L movlw .150 ;each sound 150 cycles long movwf TONE_P ToneC1 bsf GPIO, 1 ;tone goes out this pin movf TONE_L, w movwf LOOP1 call DELAY_10USEC bcf GPIO, 1 movf TONE_L, w movwf LOOP1 call DELAY_10USEC decfsz TONE_P, f goto ToneC1 movlw .1 ;creates 1/4 second space after dah movwf LOOP1 call Delay retlw 0 DELAY_10USEC: ;sets delay of 10usec for each increment of loop1 nop nop nop nop nop nop nop decfsz LOOP1, f goto DELAY_10USEC retlw 0 Delay Outer ;Loop1 sets 1/4 second per increment movlw .250 ;make 250 for about .25 seconds movwf LOOP2 Middle movlw .110 ;make 110 for 1 millisecond movwf LOOP3 Inner nop nop nop nop nop nop decfsz LOOP3,F goto Inner decfsz LOOP2,F goto Middle decfsz LOOP1,F goto Outer retlw 0 ;MAIN PROGRAM------------------------------------------------- Begin nop nop nop call INIT ;initialize the DS1820 movlw 0xcc ;cch is command for 1820 to skip rom movwf O_BYTE call OUT_BYTE movlw 0x44 ;44h is command to read and store temperature movwf O_BYTE call OUT_BYTE movlw .3 ;time to read and store temperature movwf LOOP1 call Delay call INIT ;initialize the DS1820 movlw 0xcc ;cch is command for 1820 to skip rom movwf O_BYTE call OUT_BYTE movlw 0xbe ;beh is command to transmit out temperature movwf O_BYTE call OUT_BYTE call IN_BYTE ;read the temperature, only the 1st. call INIT ;initialize the DS1820 ;I_BYTE now holds value of degrees Celcius times 2. ;------------------------------------------------ ;This section takes the DS1820 output ;which is celcius temperature times 2. ;thus 100 celcius reports out as 200 ;binary. That number is divided by 4. ;Then 30 is subtracted from the result. ;This allows a simple table to convert ;celcius into F degrees, with about ;5 degrees F resolution. A converted ;value of 0 represents 140F. The table ;then increments to 255F. movf I_BYTE, w ;copy into working storage bcf STATUS, C ;clear C so rrf is correct rrf I_BYTE, f ;divide the value bcf STATUS, C ;clear C so rrf is correct rrf I_BYTE, f ;by 4 movlw .30 ;decrement by 30 to index subwf I_BYTE, w ;table read to 0 btfss STATUS, C ;C bit reports 140 degrees or less goto TooLow ;temp is below 140 degrees send dah dit call TEMP_TABLE ;temp above 140F report temp as audio movwf TEMP_F movwf TEMP_F_W ;------------------------------------------------ ;This section breaks the F temp ;down into three bytes. The first ;is the number of 100's, the second ;is the number of 10's, and the ;third is the remaining five's. clrf TENS ;clear counter for number of tens movlw .200 ;check for no 100's subwf TEMP_F_W, f btfss STATUS, C ;neg result =200+, pos =100+ goto OneHund ;result was 100+ call Dit ;200 means two dits of audio call Dit movlw .3 ;creates space before audio tens movwf LOOP1 call Delay movlw .200 subwf TEMP_F, f ;subtract 200 for 10's calculation goto TenPro OneHund call Dit ;100 means one dit movlw .3 ;creates space before audio tens movwf LOOP1 call Delay movlw .100 subwf TEMP_F, f ;subtract 100 for 10's calculation TenPro ;determine # of 10's by sucessive subtraction movlw .10 ; 10 is unit of decrement subwf TEMP_F, f ;subtract 10 from number = 0 to 99 btfss STATUS, C ;negative result means too much sub goto NegRes incf TENS, f ;positive result means another 10's goto TenPro ;repeat subtracting 10's NegRes addwf TEMP_F, f ; neg result means 1 too many 10's taken ;so add back 10 nop ;-------------------------------------------------------- TestSt ;This section translates hundreds, tens, ;and fives into morse code calls for dits ;and dahs. MorseT sends the dits and ;dahs. Relative addressing, set by ;MorseCt sets the number of dits and ;dahs for the numbers. The Five ;is sent as a dit for five and ;no sound for zero. ;100's were sent in preceding section movf TENS, w ;Number of 10's call MorseCt ;get index for number of 10's nop goto MorseT ;apply index to sound send table MorseRet movlw .3 ;creates space before fives report movwf LOOP1 call Delay TestFive movlw .5 ;Test for fives subwf TEMP_F, f ;subtract 5 from remaining number 0 through 9 btfss STATUS, C ;test of 0 or 1 fives goto Wait ;no fives exist call Dit ;sound Dit because five exists goto Wait ;yes this instruction is redundant. Wait ;5 minutes of 10 second reporting then 1 minute decfsz WARMUP, f ;Warmup counts down for 5 minutes goto DlayS ;go to 10 second delay incf WARMUP, f ;warmup is 0, add 1 to keep from starting over movlw .240 ;Count for 1 minute delay movwf LOOP1 call Delay goto Begin DlayS movlw .40 ;wait 10 seconds before next report. movwf LOOP1 call Delay goto Begin TooLow ;less than 140 degrees, sound Dah-Dit movlw .40 ;repeat every 10 seconds movwf LOOP1 nop call Dah call Dit movlw .40 movwf LOOP1 call Delay goto Begin END