;********************************************************** ; OREGON INSTITUTE OF TECHNOLOGY ; COMPUTER HARDWARE DEPARTMENT ; ; REMOTE WEATHER STATION JUNIOR PROJECT ; WEATHER STATION SOFTWARE ; ; Team Leader: Stefan Lever ; Team Members: James Conley ; Derek Purdy ; Khanh Nguyen ; ; Date Completed: May 13, 2004 ; ; This software was designed and written by the above ; students at Oregon Institute of Technology for Junior ; Project. This software was written for the Weather ; Station. It may be modified, copied, or used for ; any purpose. However, it is only guaranteed to work ; for the system it was specifically designed for. ;********************************************************** ;*************** INTERRUPT HANDLERS *********************** ORG 00H ; Reset LJMP main ORG 03H ; INT0 RETI ; do nothing ORG 0BH ; Timer 0 RETI ; do nothing ORG 13H ; INT1 RETI ; do nothing ORG 1BH ; Timer 1 JMP isr_t1 ORG 23H ; Serial port RETI ; do nothing ;************************ EQUATES ************************** th_clk EQU P1.0 th_data EQU P1.1 ;******************* BIT SEGMENT*************************** BSEG at 20h wspd_dn: dbit 1 write_err: dbit 1 ;**************** DATA SEGMENT************************ DSEG at 60h temph: ds 1 templ: ds 1 hum: ds 1 ws: ds 4 stp_addr: ds 1 ;*************** WEATHER STATION SOFTWARE********************* CSEG at 64h main: start: CALL s_init ; Initialize data CALL wind_spd ; Measure wind speed 1 MOV ws, A CALL wind_spd ; Measure wind speed 2 MOV ws+1, A CALL temp_hum ; Measure temperature and humidity CALL wind_spd ; Measure wind speed 3 MOV ws+2, A CALL wind_dir ; Measure wind direction CALL wind_spd ; Measure wind speed 4 MOV ws+3, A CALL cal_wind_spd ; Calculate wind speed and gust CALL trans_data ; Transmit Data to Display Station CLR P1.3 ; Input to PLD for Power Down MOV R3, #80 CALL delay_any JMP start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; INITIALIZATION ; PASSED - nothing ; RETURNS - nothing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; s_init: SETB P1.3 CLR P1.2 ; Clear bit to stop transmission MOV TMOD, #01h ; Initialize Timer 0 Mode 1 SETB ET0 ; Enable Timer 0 Interrupt SETB PT0 ; Set priority of Timer 0 Int. SETB ET1 ; Enable Timer 1 Interrupt SETB PT1 ; Set priority of Timer 1 Int. SETB EA ; Global Enable USING 3 MOV temph, #0FFh ; Initialize all data to FFh MOV templ, #0FFh MOV hum, #0FFh MOV AR0, #0FFh MOV AR1, #0FFh MOV AR2, #0FFh MOV AR3, #0FFh MOV AR4, #0FFh CLR wspd_dn ; Clear wind speed done bit CLR write_err ; Clear write error bit USING 0 CALL delay ; Delay 125 ms RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TEMPERATURE AND HUMIDITY ; PASSED - nothing ; RETURNS - Temp in AR0 - bank 3 ; - Humidity in AR1 - bank3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; temp_hum: MOV R7, #00h ; Load 0 in R7 for 16 bit temp. measurement CALL write_reg ; Write 00h to register in sensor JB write_err, skip_conv_t ; Skip measure temperature if write error MOV R4, #03h ; 3 is for measuring temperature MOV R5, #0FFh ; Initialize low byte to FFh MOV R6, #0FFh ; Initialize high btye to FFh CALL measure ; Measure Temperature MOV A, R5 CJNE A, #0FFh, store_temp ; Check to see if low byte changed MOV A, R6 CJNE A, #0FFh, store_temp ; Check to see if high byte changed JMP skip_conv_t ; If neither byte changed, skip conversion store_temp: MOV temph, R5 ; Store high and low byte in memory MOV templ, R6 CALL temp_conv ; Convert Temperature USING 3 MOV AR0, A ; Store in register 0 bank 3 USING 0 skip_conv_t: MOV R7, #01h ; Load 1 into R7 for 8 bit humidity measurement CALL write_reg ; Write 01h to register in sensor JB write_err, skip_conv_h ; Skip measure humidity if write error MOV R4, #05h ; 5 is for measuring humidity MOV R6, #0FFh ; Initialize byte to FFh CALL measure ; Measure Humidity MOV A, R6 CJNE A, #0FFh, store_hum ; Check to see if byte changed JMP skip_conv_h ; If byte didn't change, skip conversion store_hum: MOV hum, R6 ; Store measured data in memory CALL hum_conv ; Convert Humidity USING 3 MOV AR1, A ; Store in register 1 bank 3 USING 0 skip_conv_h: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEASURE TEMP/HUMIDITY ; PASSED - 5 bit code in R4 ; RETURNS - High Byte in R5 ; - Low Byte in R6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; measure: CALL srt_trans ; Start Transmission to sensor MOV A, R4 ; Load 5 bit code in register A CALL snd_code ; Send Code CALL delay JB th_data, measure_done ; Check Acknowledge from sensor, quit if no acknowledge CALL clk_pulse CALL get_data ; Get first byte of data from sensor MOV R5, A ; Store byte in R5 CALL give_ack ; Give Acknowledge to sensor that first byte was received CALL get_data ; Get second byte of data from sensor MOV R6, A ; Store byte in R6 measure_done: CALL clk_pulse RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TEMPERATURE COVERSION ; PASSED - temph and templ ; RETURNS - converted temp in A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; temp_conv: MOV R0, #00h ; Initialize registers MOV R1, #00h MOV R2, #-40 check_high: MOV A, R1 ; Load R1 in register A CJNE A, temph, add_high ; Check if value in A equals measured high byte JMP check_low ; If so, go to check_low add_high: INC R2 ; Add one to temperature MOV A, R0 ; Load R0 into A CJNE A, #00h, skip1 ; If A != 0, then go to skip1 ADD A, #1Ch ; Otherwise, add 1Ch to value in A JMP skip2 ; Go to skip2 skip1: ADD A, #38h ; Add 38h to value in register skip2: MOV R0, A ; Load A into R0 JNC check_high ; If no carry from add, then go to jump high INC R1 ; Otherwise, add one to R1 for carry JMP check_high ; Go to check_high check_low: MOV A, templ ; Load low byte of temperature into A CLR C ; Clear carry SUBB A, R0 ; Subtract R0 from A JC check ; If a carry, jump to check SUBB A, #1Dh ; Otherwise, Subtract 1Dh from A JNC add_low ; If no carry, jump to add_low JMP check ; Go to check add_low: INC R2 ; Add one to temperature MOV A, R0 ; Load R0 into A CJNE A, #00h, skip3 ; If A != 0, then go to skip3 SUBB A, #1Ch ; Subtract 1Ch from A skip3: ADD A, #38h ; Add 38h to A MOV R0, A ; Load A into R0 JMP check_low check: MOV A, templ ; Move low byte of temperature into A CLR C ; Clear carry SUBB A, R0 ; Subtract R0 from A SUBB A, #1Ch ; Subtract 1Ch from A JC done_conv ; If carry go to done_conv DEC R2 ; Otherwise, subtract one from temperature done_conv: MOV A, R2 JNB ACC.7, exit ; If bit 7 is not set, exit CPL A ; Otherwise, complement A ADD A, #01h ; And add one to A (two's complement) SETB ACC.7 ; Set bit 7 for negative temperature exit: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; HUMIDITY COVERSION ; PASSED - hum ; RETURNS - converted humidity in A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hum_conv: MOV A, hum ; Load humidity reading into A CLR C ; Clear carry SUBB A, #6Ch ; Subtract 108d from reading JNC above107 ; If no carry, jump to above 107 below108: MOV B, #143 ; Load 143d into B MOV R1, #0FEh ; Load FEh into R1 MOV R0, #00h ; Load 00h into R0 JMP start_calc above107: MOV B, #111 ; Load 111d into B MOV R1, #0Bh ; Load 0Bh into R1 MOV R0, #40h ; Load 40h into R0 start_calc: MOV A, hum ; Load humidity reading into A MUL AB ; Multiply A and B (A * (143 or 111)) ADD A, R0 ; Add R0 to A (A + (0 or 64)) MOV A, B ; Load B into A ADDC A, R1 ; Add with carry A and R1 (A + (254 or 11)) RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; WRITE TO REGISTER (T/H sensor) ; PASSED - value to write in R7 ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; write_reg: CLR write_err ; Initialize error to false CALL srt_trans ; Start Transmission MOV A, #06h CALL snd_code ; Send bit code to write CALL delay JB th_data, write_error ; Check acknowledge, exit if error CALL clk_pulse MOV A, R7 CALL snd_code ; Send data to write to register CALL delay JB th_data, write_error ; Check acknoledge, exit if error JMP write_done write_error: SETB write_err ; If error, set write_err bit write_done: CALL clk_pulse RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; START TRANSMISSION (T/H sensor) ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; srt_trans: CALL clk_low CALL clk_high CALL data_low CALL clk_low CALL clk_high CALL data_high CALL clk_low RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SEND BYTE TO T/H sensor ; PASSED - Byte in A ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; snd_code: MOV R3, #08h begin: JB ACC.7, one1 zero0: CALL data_low JMP send one1: CALL data_high send: CALL clk_pulse RL A DJNZ R3, begin CALL data_high RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GIVE ACKNOWLEDGE (T/H sensor) ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; give_ack: CALL delay CALL delay CALL data_low CALL clk_high CALL clk_low CALL data_high RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GET ONE BYTE FROM T/H sensor ; PASSED - none ; RETURNS - Received byte in A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_data: MOV A, #00h MOV R3, #08h loop8: CALL clk_high JB th_data, one CLR C RLC A JMP done one: SETB C RLC A done: CALL clk_low DJNZ R3, loop8 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CLOCK PULSE - High then Low ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clk_pulse: CALL clk_high CALL clk_low RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CLOCK LINE HIGH (T/H sensor) ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clk_high: SETB th_clk CALL delay RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CLOCK LINE LOW (T/H sensor) ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clk_low: CLR th_clk CALL delay RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DATA LINE HIGH (T/H sensor) ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data_high: SETB th_data CALL delay10 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DATA LINE LOW (T/H sensor) ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data_low: CLR th_data CALL delay10 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEASURE WIND SPEED ; PASSED - none ; RETURNS - Wind Speed A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wind_spd: MOV R7, #00h ; Initialize # of pulses to 0 MOV R0, #235 ; Counter 0 - 235 * 30 * 255 * 540 ns = .971s = 1s MOV R1, #30 ; Counter 1 -(c0) * (c1) * (timer cycles) * (mach. cycle) CLR wspd_dn ; Clear 1 sec done flag ;Initialize Timer MOV TMOD, #20h ; Set timer 1 to mode 2, auto-reload MOV TH1, #00h ; Load high byte with 0 MOV TL1, #00h ; Load low byte with 0 SETB TR1 ; Turn timer 1 on JB P3.5, wspd_h ; Jump if initially high wspd_l: JB wspd_dn, wspd_convert ; Check if 1 sec is up JNB P3.5, wspd_l ; Jump back up one line if still low INC R7 ; Increment if line goes from 0 to 1 wspd_h: JB wspd_dn, wspd_convert ; Check if 1 sec is up JB P3.5, wspd_h ; Jump back up one line if still high JMP wspd_l ; Jump to low if line goes from 1 to 0 wspd_convert: CLR TR1 ; Turn timer 1 off MOV A, R7 ; Move count into accumulator MOV B, #0AH ; Move 10 dec into reg b DIV AB ; Divide #pulses by 10 MOV R6, B ; Move remainder into R6 MOV B, #07H MUL AB ; Multiply dividend by 7 ADD A, R7 ; Add original number pulses MOV R7, A ; Move accumulated value to r7 MOV A, R6 ; Move remainder into accumulator MOV B, #07H ; Multiply by 7 MUL AB MOV B, #0AH ; Move divisor 10 into b DIV AB ; Divide remainder by 10 ADD A, R7 ; Add R7 value for final value RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CALCULATE WIND SPEED AND GUST ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cal_wind_spd: MOV R0, #ws MOV A, @R0 MOV R1, A MOV stp_addr, #ws+3 loop: INC R0 ; Determine highest measured wind speed MOV A, @R0 MOV B, A MOV A, R1 CLR C SUBB A, B JNC less more: MOV A, @R0 MOV R1, A less: MOV A, R0 CJNE A, stp_addr, loop USING 3 MOV AR3, R1 ; Store highest wind speed as wind gust USING 0 MOV A, ws ; Average 4 wind speed measurements ADD A, ws+1 RR A CLR ACC.7 MOV ws, A MOV A, ws+2 ADD A, ws+3 RR A CLR ACC.7 MOV ws+1, A MOV A, ws ADD A, ws+1 RR A CLR ACC.7 USING 3 MOV AR2, A ; Store average speed as wind speed USING 0 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEASURE WIND DIRECTION ; PASSED - none ; RETURNS - Wind Dir. in AR3 - bank 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wind_dir: SETB P3.0 ; Set clock pin to high for upper nibble CLR P3.1 ; Set the wind direction OE signal active (low active) CALL delay ; Allow tri state time to opperate MOV R1, P0 ; Read in port data CLR P3.0 ; Set clock pin to low for lower nibble CALL delay MOV R2, P0 ; Read in port data SETB p3.1 ; Set wind direction OE signal inactive (low active) MOV A, R1 ; Move upper nibble from temp location in register to accumulator MOV R0, #0Fh ; Move 00001111 into register 0 ANL A, R0 ; AND accumulator with 00001111 to force upper nibble in accumulator to become 0's RL A ; Rotate accumulator left one bit 00001111 -> 00011110 RL A ; 00001111 -> 00111100 RL A ; 00001111 -> 01111000 lower nibble has now been repositioned RL A ; 00001111 -> 11110000 to appropirate upper nibble location MOV R1, A ; Store adjusted upper nibble back into register 1 MOV A, R2 ; Move lower nibble into accumulator ANL A, R0 ; AND accumulator with 00001111 to force upper nibble in accumulator to become 0's ORL A, R1 ; OR lower and upper nibble together to make 8 bit number USING 3 MOV AR4, A ; Store 8 bit result into register 4 USING 0 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TRANSMIT MEASURED DATA ; R0 - Temp, R1 - Hum, R2 - Wsp, ; R3 - Wgst, R4 - Wdir ; PASSED - Data in R0-R3, bank 3 ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; trans_data: MOV P2, #00h CALL trans_one ; Transmit inital byte 00h MOV P2, #0A5h CALL trans_one ; Transmit second byte to confirm new transmission USING 3 MOV P2, AR0 MOV A, AR0 USING 0 CALL trans_one ; Transmit temperature USING 3 MOV P2, AR1 ADD A, AR1 USING 0 CALL trans_one ; Transmit humidity USING 3 MOV P2, AR2 ADD A, AR2 USING 0 CALL trans_one ; Transmit wind speed USING 3 MOV P2, AR3 ADD A, AR3 USING 0 CALL trans_one ; Transmit wind gust USING 3 MOV P2, AR4 ADD A, AR4 USING 0 CALL trans_one ; Transmit wind direction MOV P2, A CALL trans_one ; Transmit checksum RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TRANSMIT ONE BYTE ; PASSED - byte to transmit in R3 ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; trans_one: SETB P1.2 MOV R3, #2h CALL delay_any CLR P1.2 MOV R3, #2h CALL delay_any RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DELAY_ANY ; PASSED - num of delays in R3 ; - # of delays * 125 ms = delay ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delay_any: CALL delay DJNZ R3, delay_any RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DELAY 125 ms ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delay: USING 0 PUSH AR0 PUSH AR1 PUSH AR2 MOV R0, #255 loop1: MOV R1, #100 loop2: MOV R2, #3 loop3: DJNZ R2, loop3 DJNZ R1, loop2 DJNZ R0, loop1 POP AR2 POP AR1 POP AR0 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DELAY 10 ms ; PASSED - none ; RETURNS - none ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delay10: USING 0 PUSH AR0 PUSH AR1 MOV R0, #95 loop11: MOV R1, #100 loop22: DJNZ R1, loop22 DJNZ R0, loop11 POP AR1 POP AR0 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Timer 1 ISR ; PASSED - count variables in R0 and R1 ; RETURNS - Sets wspd_dn bit when ; countrs are both 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; isr_t1: CLR TF1 DJNZ R1, wdsp_nt_done DJNZ R0, wdsp_skip JMP wdsp_done wdsp_skip: MOV R1, #30 JMP wdsp_nt_done wdsp_done: SETB wspd_dn wdsp_nt_done: RETI END