Code:
;****************************************************************************** ; ; Weather Station Software ; ; This program links a homemade weather station to a PIC 16F628A with display ; and logger functions. Wind direction, wind speed and a lightening detector ; use Dallas One-Wire bus chips and a one-wire protocol. An SMT11 ; relative humidity and temperature chip is also used and communicates using ; a 2-wire protocol. ; ; The data is displayed on a 2x24 LCD module using two screens. ; Display 1 shows temp, humidity, wind speed and wind direction. ; Display 2 shows max/min temperature and lightning strikes. The display ; toggles when the Display Toggle button is pushed. The weather data is ; sampled every second for wind direction and lightning strikes, and every 2 seconds for ; temperature, relative humidity, wind speed. The data is also output on an RS-232 ; serial link (9600 baud) every minute. The PIC 16F628A pin layout: ; ; ; RA0 LCD Data ; RA1 LCD Data ; RA2 LCD Data ; RA3 LCD Data ; RA4 ; RA5 ; RA6 LCD RS ; RA7 LCD EN ; ; RB0 Switch input - Display Toggle ; RB1 RS232 RX ; RB2 RS232 TX ; RB3 One-wire bus ; RB4 2-wire Clock ; RB5 2-wire Data ; RB6 ; RB7 ; ; Routines for SHT11 temperature and humidity calculations were modified ; from original code by Claudiu Chiculita http://www.ac.ugal.ro/staff/ckiku/software/sht11.htm ; ;****************************************************************************** ; ; Filename: weather.asm ; Date: 18 November 2003 ; File Version: 1.0 ; ; Author: A.Round ; Company: ; ; ;****************************************************************************** ; ; Files required: "m_lcd.h" ; ;****************************************************************************** ; ; Notes: Version 1.0 - Initial Baseline ; ; ; ;***************************************************************************** list p=16f628A ; list directive to define processor #include <p16F628A.inc> ; processor specific variable definitions __CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT ; '__CONFIG' directive is used to embed configuration word within .asm file. ; The lables following the directive are located in the respective .inc file. ; See data sheet for additional information on configuration word settings. ;***** LCD HARDWARE DECLARATION ***** LCD_DATA EQU PORTA LCD_DATA_TRIS EQU TRISA #define R_S LCD_DATA,6 ; LCD Register Select control line RA6 #define EN LCD_DATA,7 ; LCD Enable control line RA7 ;***** IC2 HARDWARE DECLARATION ***** IC2 EQU PORTB IC12_TRIS EQU TRISB #define IC2_CLOCK IC2,6 ; IC2 clock line #define IC2_DATA IC2,7 ; IC2 data line ;***** TWO WIRE HARDWARE DECLARATION ***** TWO_WIRE EQU PORTB TWO_WIRE_TRIS EQU TRISB #define TWO_WIRE_CLOCK TWO_WIRE,4 ; Two Wire Serial Clock line RB4 #define TWO_WIRE_DATA TWO_WIRE,5 ; Two Wire Serial Data line RB5 ;***** 1-WIRE HARDWARE DECLARATION ***** D1WIRE_PORT EQU PORTB D1WIRE_TRIS EQU TRISB #define D1WIRE D1WIRE_PORT,3 ; 1-Wire Bus RB0 ;***** VARIABLE DECLARATION ***** CBLOCK 0X20 TEMP1 ; Used in LCD subroutines, SHT-11 Time Out subroutine TEMP2 ; Used in LCD_Hex subroutine, SHT-11 Time Out subroutine TEMP3 ; Used in 1-Wire Reset subroutine, SHT-11 Time Out subroutine CNTR ; Used in 1-Wire WB/RB, 1-Wire Reset subroutines CNTR1 ; Used in 1-Wire RB, Read DS2423 subroutines CNTR2 ; Used in 1-Wire Read DS2423 subroutine COUNT ; Used in RCOUNT macro START_COUNT ; Used to determine wind speed STORE ; Used in 16 Bit CRC subroutine CRC8 ; Used for 8 bit CRC subroutine CRC16_HI ; Used for 16 bit CRC subroutine CRC16_LO ; Used for 16 bit CRC subroutine DELAY1 ; Used in Delay macros DELAY2 ; Used in Delay macros HALF_SEC_COUNT ; Used for Timer1 ISR routines TWO_SEC_COUNT ; Used for Timer1 ISR routines TA1 ; Low byte DS2423 counter memory page address TA2 ; High byte DS2423 counter memory page address WSPEED_VALUE ; Latest Wind Speed value FLAGS ; B0=0 Start Display B0=1 Second Display B1=0 call DS2423 table ; B1=1 call DS2450 table TEST ; Used for keyboard de-bounce DATAH ; MS byte from SHT11 DATAL ; LS byte from SHT11 CALCH ; Working temperature/RH/WD/LS MS byte CALCL ; Working temperature/RH/WD/LS LS byte TDATAHMAX ; Maximum temperature reading MS byte TDATALMAX ; Maximum temperature reading LS byte TDATAHMIN ; Minimum temperature reading MS byte TDATALMIN ; Minimum temperature reading LS byte NEG ; Temperature sign register T10 ; ASCII Temperature 10's T1 ; ASCII Temperature 1's T01 ; ASCII Temperature 0.1's TSIGN_MAX_VALUE ; maximum temperature sign (pos or neg) TSIGN_MIN_VALUE ; minimum temperature sign (pos or neg) T10MAX_VALUE ; ASCII Temperature 10's maximum value T10MIN_VALUE ; ASCII Temperature 10's minimum value T1MAX_VALUE ; ASCII Temperature 1's maximum value T1MIN_VALUE ; ASCII Temperature 1's minimum value T01MAX_VALUE ; ASCII Temperature 0.1's maximum value T01MIN_VALUE ; ASCII Temperature 0.1's minimum value R100 ; ASCII Relative Humidity 100's R10 ; ASCII Relative Humidity 10's R1 ; ACSII Relative Humidity 1's WD100 ; ASCII Wind direction 100's WD10 ; ASCII Wind direction 10's WD1 ; ASCII Wind direction 1's WS10 ; ASCII Wind speed 10's WS1 ; ASCII Wind speed 1's LS100 ; ASCII Lightning Strikes 100's LS10 ; ASCII Lightning Strikes 10's LS1 ; ASCII Lightning Strikes 1's RH_32 ; Raw Relative Humidity divided by 32 RH_128 ; Raw Relative Humidity divided by 128 RH ; Calculated Relative Humidity SHT_ERROR1 ; ASCII SHT11 Error code SHT_ERROR2 ; ASCII SHT11 Error code D1WIRE_ERROR ; 1 Wire Error code CHANNELC ; 8 bit ADC reading from Channel C pot in wind vane CHANNELD ; 8 bit ADC reading from Channel D pot in wind vane HIGH_ADDRESS ; temp register to pass table read address information LOW_ADDRESS ; temp register to pass table read address information SUBH ; Used in 16BIT subtraction routine SUBL ; Used in 16BIT subtraction routine DIGIT ; Used in binary to ASCII temperature conversion ENDC CBLOCK 0X70 W_TEMP STATUS_TEMP ENDC ;********************************************************************** ORG 0x000 ; processor reset vector GOTO MAIN ; go to beginning of program ORG 0x004 ; interrupt vector location GIE_CLEAR BCF INTCON, GIE ; turn off interupts BTFSC INTCON, GIE ; make sure they are really turned off GOTO GIE_CLEAR MOVWF W_TEMP ; save off current W register contents MOVF STATUS, W ; move status register into W register MOVWF STATUS_TEMP ; save off contents of STATUS register MOVLW ' ' ; clear 1 Wire error code MOVWF D1WIRE_ERROR BTFSC INTCON, INTF ; test to see if Display Change button has been pushed GOTO DISPLAY_CHANGE : if yes, go to the display change routine BTFSC PIR1, TMR1IF ; test to see if Timer1 overflow GOTO HALF_SEC ; if yes, go to time counting routine GOTO ISR_OVER ; if no, go to ISR_OVER HALF_SEC BCF PIR1, TMR1IF ; Clear Timer1 interrupt flag INCF HALF_SEC_COUNT,F ; increment half seconds count MOVFW HALF_SEC_COUNT BTFSS HALF_SEC_COUNT, 0 ; check to see if this was a whole second GOTO HALF_SEC1 ; If yes, go to HALF_SEC1 GOTO ISR_OVER ; If no, go to ISR_OVER and wait for next interrupt HALF_SEC1 MOVFW HALF_SEC_COUNT ; check to see if 2 seconds has elapsed ANDLW b'00011111' SUBLW b'00000100' SKPNZ GOTO HALF_SEC2 ; If yes, update wspeed, wdir, temp, rh CALL WDIR_UPDATE ; If no, update wdir and lightning strikes CALL LSTRIKE_UPDATE GOTO ISR_OVER ; Go to ISR_OVER and wait for next interrupt HALF_SEC2 CLRF HALF_SEC_COUNT ; Clear half seconds count CALL WSPEED_UPDATE ; update wspeed, wdir, temp, rh, lstrike CALL WDIR_UPDATE CALL TEMP_RH_UPDATE CALL LSTRIKE_UPDATE INCF TWO_SEC_COUNT,F ; increment ten second count MOVFW TWO_SEC_COUNT SUBLW b'00011110' ; Check to see if one minute has past SKPNZ GOTO HALF_SEC3 ; If yes, go to HALF_SEC3 GOTO ISR_OVER ; If no, go to ISR_OVER and wait for next interrupt HALF_SEC3 CLRF TWO_SEC_COUNT ; Clear 2 second counter CALL RS232_TX ; Send current readings to RS232 GOTO ISR_OVER WSPEED_UPDATE MOVLW 0xC0 ; Load low byte counter memory page address MOVWF TA1 MOVLW 0x01 ; Load high byte counter memory page address MOVWF TA2 CALL RCOUNT ; Read the counter value from the DS2423 MOVF START_COUNT,W ; Move previous counter value into W SUBWF COUNT,W ; Subtract previous counter value from latest counter value MOVWF WSPEED_VALUE ; Store result in WSPEED_VALUE MOVF COUNT,W ; Overwrite previous counter value with latest counter value MOVWF START_COUNT MOVF WSPEED_VALUE,W MOVWF CNTR MOVLW HIGH WIND_SPEED MOVWF PCLATH MOVLW LOW WIND_SPEED + 1 ADDWF CNTR,W BTFSC STATUS,C INCF PCLATH,F CALL WIND_SPEED ; get BCD wind speed from look-up table CALL WS_BCD_ASCII ; convert BCD table value to ASCII RETURN WDIR_UPDATE CALL DS2450_READ ; read value of two 360 degree potentiometers converted to BCF STATUS,C ; eight bit readings MOVLW 0X0F SUBWF CHANNELD,W BTFSS STATUS,C ; if set, CHANNELD is greater than 0x0F GOTO WD_CC ; if not set, CHANNELD is less that 0x0F and use CHANNELC BCF STATUS,C MOVLW 0XF0 SUBWF CHANNELD,W BTFSC STATUS,C ; if clear, CHANNELD is less than 0x0F GOTO WD_CC ; use Channel C pot as Channel D is near deadband GOTO WD_CD ; use Channel D pot as Channel D is clear of deadband WD_CC MOVLW 0X80 ; add 180 degrees to the reading of Channel C pot ADDWF CHANNELC,W GOTO CALC_WD D_CD MOVF CHANNELD,W CALC_WD MOVWF CALCL ; calculate degrees from Channel C/D ADC converter values CLRF CALCH MOVLW D'14' ; multiply CHANNELD reading by 14 to give degrees*10 CLRF CNTR BSF CNTR, 3 RRF CALCL,F LOOP SKPNC ADDWF CALCH,F RRF CALCH,F RRF CALCL,F DECFSZ CNTR,F GOTO LOOP CALL WD_ASCII ; convert degrees*10 into ASCII RETURN TEMP_RH_UPDATE ; Routines for SHT11 temperature and humidity calculations were modified ; from original code by Claudiu Chiculita MOVLW ' ' ; clear SHT11 error codes MOVWF SHT_ERROR1 MOVWF SHT_ERROR2 CALL SHT_CONNECTION_RESET ; reset SHT11 serial interface MOVLW 0x03 ; temperature conversion command CALL SHT_DATA_ACQUIRE ; get temperature data. W will be 1 if an error was detected ADDLW D'0' BTFSS STATUS,Z ; check for errors GOTO ISR_OVER ; if yes, go to ISR_OVER MOVF DATAL,W ; if no, move temperature reading LS byte to CALCL MOVWF CALCL MOVF DATAH,W ; move temperature reading MS byte to CALCH MOVWF CALCH MOVLW HIGH(D'4000') ; calculate temperature by subtracting 4000 MOVWF SUBH MOVLW LOW(D'4000') MOVWF SUBL CLRF NEG CALL SUB16 BC POS_TEMP ; if no carry then temperature is positive MOVLW HIGH(D'1') ; if carry, then temperature is negative MOVWF SUBH MOVLW LOW(D'1') MOVWF SUBL CALL SUB16 COMF CALCH,F COMF CALCL,F INCF NEG,F ; increment NEG to indicate negative temperature POS_TEMP CALL TEMP_ASCII ; convert temperature into ASCII and store in T10, T1, T01 CALL SHT_CONNECTION_RESET ; reset SHT11 serial interface MOVLW 0x05 ; relative humidity conversion command CALL SHT_DATA_ACQUIRE ; get relative humidity data. W is 1 if an error was detected ADDLW D'0' BTFSS STATUS,Z ; check for errors GOTO ISR_OVER ; if yes, go to ISR_OVER MOVF DATAL,W ; if no, move relative humidity reading LS byte to CALCL MOVWF CALCL MOVF DATAH,W ; move relative humidity reading MS byte to CALCH MOVWF CALCH MOVLW D'5' MOVWF CNTR ; number of right shifts for RH calculations LIN_RH1 BCF STATUS,C ; 5 right shifts to CALCH, CALCL to give raw reading/32 RRF CALCH,F RRF CALCL,F DECFSZ CNTR,F GOTO LIN_RH1 MOVF CALCL,W MOVWF RH_32 ; raw RH reading divided by 32 MOVLW D'2' MOVWF CNTR LIN_RH11 BCF STATUS,C ; 2 right shifts to CALCH, CALCL to give raw reading/128 RRF CALCH,F RRF CALCL,F DECFSZ CNTR,F GOTO LIN_RH11 MOVF CALCL,W MOVWF RH_128 ; raw RH reading divided by 128 MOVF DATAL,W ; move relative humidity reading LS byte to CALCL MOVWF CALCL MOVF DATAH,W ; move relative humidity reading MS byte to CALCH MOVWF CALCH MOVLW HIGH(D'1024') MOVWF SUBH MOVLW LOW(D'1024') MOVWF SUBL CALL SUB16 BTFSS STATUS,C ; is relative humidity reading RH<1024 GOTO LIN_RH2 ; if yes, use RH% = RH_32 + RH_128 -3 MOVLW HIGH(D'1546') MOVWF SUBH MOVLW LOW(D'1546') MOVWF SUBL CALL SUB16 BTFSS STATUS,C ; is relative humidity reading 1024<RH<2560? GOTO LIN_RH3 ; if yes, use RH% = RH_31 + 4 MOVF RH_128,W ; if no, then use RH% = RH_32 - RH_128 + 24 SUBWF RH_32,W ADDLW D'24' MOVWF RH SUBLW D'100' BTFSS STATUS,C ; is result greater than 100%? GOTO LIN_RH_HUN ; yes, limit value to 100% GOTO LIN_RH_OVER ; no, finished LIN_RH_HUN MOVLW D'100' ; limit RH to 100% MOVWF RH GOTO LIN_RH_OVER LIN_RH2 MOVF RH_32,W ; RH% = RH_32 + RH_128 -3 ADDWF RH_128,W ADDLW -D'3' BTFSS STATUS,C ; is result less than 0%? GOTO LIN_RH_ZERO ; yes, limit value to 0% MOVWF RH GOTO LIN_RH_OVER ; no, finished LIN_RH_ZERO MOVLW D'0' ; limit RH to 0% MOVWF RH GOTO LIN_RH_OVER LIN_RH3 MOVF RH_32,W ; RH% = RH_31 + 4 ADDLW D'4' MOVWF RH LIN_RH_OVER CLRF CALCH MOVF RH,W MOVWF CALCL CALL RH_ASCII ; convert RH into ASCII and store in R100, R10, R1 RETURN LSTRIKE_UPDATE MOVLW 0xE0 ; Load low byte counter memory page address MOVWF TA1 MOVLW 0x01 ; Load high byte counter memory page address MOVWF TA2 CALL RCOUNT ; Read the counter value from the DS2423 MOVF COUNT,W MOVWF CALCL CLRF CALCH CALL LS_ASCII RETURN DISPLAY_CHANGE BTFSC FLAGS,0 ; is start screen displayed? GOTO DISPLAY_CHANGE1 ; if no, go to DISPLAY_CHANGE1 BSF FLAGS,0 ; if yes, set display flag CALL SECOND_SCREEN ; put screen two on LCD GOTO DISPLAY_CHANGE2 DISPLAY_CHANGE1 BCF FLAGS,0 ; clear display flag CALL START_SCREEN ; put start screen on LCD DISPLAY_CHANGE2 MOVF PORTB, W ; read PORTB MOVWF TEST ; store PORTB in TEST BTFSS TEST, 0 ; has display key been released? GOTO DISPLAY_CHANGE2 ; no, go to DISPLAY_CHANGE2 CALL DELAY_KB ; 10 ms Keyboard debounce MOVF PORTB, W ; read PORTB MOVWF TEST ; store PORTB in TEST BTFSS TEST, 0 ; has display key been released? GOTO DISPLAY_CHANGE2 ; no, go to DISPLAY_CHANGE2 BCF INTCON, INTF ; clear RB0 interupt flag GOTO ISR_OVER ISR_OVER CALL DISPLAY_UPDATE ; Update display MOVF STATUS_TEMP,W ; retrieve copy of STATUS register MOVWF STATUS ; restore pre-isr STATUS register contents SWAPF W_TEMP,F SWAPF W_TEMP,W ; restore pre-isr W register contents RETFIE ; return from interrupt ;***** INCLUDE FILES ***** #include "m_lcd.h" ;*************************************** TABLES ************************************* ;***** 1-WIRE DEVICE ROM CODE TABLE ***** ; This needs to be modified should any of the 1-Wire devices be changed DS2423 MOVWF PCL DT 0x1D,0x56,0xA7,0x04,0x00,0x00,0x00,0x33 DS2450 MOVWF PCL DT 0x20,0x1B,0xAD,0x00,0x00,0x00,0x00,0x93 ;***** SCREEN TABLES ***** SCREEN1 MOVWF PCL DT "TEMP . ",0xDF,"C RELH %",0x00 SCREEN2 MOVWF PCL DT "WSPD KTS WDIR ",0xDF,"T",0x00 SCREEN3 MOVWF PCL DT "TMIN . ",0xDF,"C TMAX . ",0xDF,"C",0x00 SCREEN4 MOVWF PCL DT "LSTRIKES ",0x00 ;***** WIND SPEED LOOK-UP TABLE ***** WIND_SPEED MOVWF PCL DT 0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x05,0x05,0x05,0x06 DT 0x06,0x07,0x07,0x07,0x08,0x08,0x09,0x09,0x09,0x10,0x10,0x11,0x11,0x12,0x12,0x12 DT 0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x18,0x18,0x18,0x19 DT 0x19,0x20,0x20,0x20,0x21,0x21,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x25,0x25,0x25 DT 0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x29,0x29,0x29,0x30,0x30,0x31,0x31,0x31,0x32 DT 0x32,0x33,0x33,0x33,0x34,0x34,0x35,0x35,0x36,0x36,0x36,0x37,0x37,0x38,0x38,0x38 DT 0x39,0x39,0x40,0x40,0x40,0x41,0x41,0x42,0x42,0x42,0x43,0x43,0x44,0x44,0x44,0x45 DT 0x45,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x49,0x49,0x49,0x50,0x50,0x51,0x51,0x51 DT 0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x57,0x57,0x58,0x58 DT 0x58,0x59,0x59,0x60,0x60,0x60,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x64,0x64,0x64 DT 0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x68,0x68,0x69,0x69,0x69,0x70,0x70,0x71,0x71 DT 0x71,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x75,0x75,0x75,0x76,0x76,0x77,0x77,0x77 DT 0x78,0x78,0x79,0x79,0x80,0x80,0x80,0x81,0x81,0x82,0x82,0x82,0x83,0x83,0x84,0x84 DT 0x84,0x85,0x85,0x86,0x86,0x86,0x87,0x87,0x88,0x88,0x88,0x89,0x89,0x90,0x90,0x91 DT 0x91,0x91,0x92,0x92,0x93,0x93,0x93,0x94,0x94,0x95,0x95,0x95,0x96,0x96,0x97,0x97 DT 0x97,0x98,0x98,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99 ;*************************************** DELAY MACROS ************************************* ;***** SHORT DELAY MACRO ***** D10USEC MACRO TCNST ; provides a delay equal to TCNST * 10 usecs MOVLW TCNST MOVWF DELAY1 CALL D10USEC1 ENDM D10USEC1 NOP NOP NOP NOP NOP NOP NOP DECFSZ DELAY1, F GOTO D10USEC1 RETURN ;***** LONG DELAY MACRO ***** DLONG MACRO TCNST ; provided a delay of TCNST * msec MOVLW TCNST MOVWF DELAY1 CALL OUTER ENDM OUTER MOVLW D'110' ; close to 1.0 msec delay when set to 110 MOVWF DELAY2 INNER NOP NOP NOP NOP NOP NOP DECFSZ DELAY2, F GOTO INNER DECFSZ DELAY1, F GOTO OUTER RETURN ;*************************************** DELAY SUBROUTINES ************************************* DELAY_KB DLONG D'10' RETURN ;*************************************** LCD MODULE SUBROUTINES ************************************* ; For KS0066U controller chips ; Note that lower bits of Port are being used ;***** LCD MODULE INITALIZATION SUBROUTINE ***** LCD_Init BANKSEL LCD_DATA_TRIS CLRF LCD_DATA_TRIS BANKSEL LCD_DATA CLRF LCD_DATA BCF R_S ; write to the KS0066U IR. MOVLW b'00000011' ; Command for 8-bit interface MOVWF LCD_DATA BSF EN NOP NOP BCF EN DLONG D'5' ; have to wait 5ms here BSF EN NOP NOP BCF EN D10USEC D'12' ; have to wait 100us here BSF EN NOP NOP BCF EN D10USEC D'10' ; have to wait 100us here MOVLW FUNC_SET ; Function Set CALL LCD_Cmd MOVLW DISP_OFF ; Display Off CALL LCD_Cmd MOVLW CLR_DISP ; Clear the Display CALL LCD_Cmd MOVLW ENTRY_INC ; Entry Cursor Increment CALL LCD_Cmd MOVLW DISP_ON ; Display On, No Cursor CALL LCD_Cmd RETURN ;***** LCD_Nbl SUBROUTINE ***** LCD_Nbl MOVWF TEMP1 ; Character to be sent is in ; W so put in Temp1 DLONG D'2' ; Wait 2ms instead of Busy Check SWAPF TEMP1, W ANDLW 0x0F ; Get upper nibble into lower half port MOVWF LCD_DATA ; Send data to LCD BSF R_S ; Set LCD to data mode CALL LCDtglclk ; Toggle EN MOVF TEMP1, W ANDLW 0x0F ; Get lower nibble into upper half port MOVWF LCD_DATA ; Send data to LCD BSF R_S ; Set LCD to data mode CALL LCDtglclk ; Toggle EN RETURN LCDtglclk BSF EN ; Toggle EN for LCD NOP NOP BCF EN RETURN ;***** LCD_Cmd SUBROUTINE ***** LCD_Cmd MOVWF TEMP1 ; Command to be sent is in ; W so put in Temp1 DLONG D'2' SWAPF TEMP1, W ANDLW 0x0F ; Get upper nibble into lower half port MOVWF LCD_DATA ; Send data to LCD BCF R_S ; Set LCD to command mode CALL LCDtglclk ; Toggle EN MOVF TEMP1, W ANDLW 0x0F ; Get lower nibble into lower half port MOVWF LCD_DATA ; Send data to LCD BCF R_S ; Set LCD to command mode CALL LCDtglclk ; Toggle EN RETURN ;***** LCD_Hex SUBROUTINE ***** LCD_Hex MOVWF TEMP2 ; Character to be sent is in ; W so put in Temp2 SWAPF TEMP2, W ANDLW 0x0F ; Get upper nibble into lower half port CALL LCD_Hex1 ; Convert upper nybble to ASCII CALL LCD_Nbl ; Output ASCII on LCD display MOVF TEMP2, W ANDLW 0x0F ; Get lower nibble into lower half port CALL LCD_Hex1 ; Convert lower nybble to ASCII CALL LCD_Nbl ; Output ASCII on LCD display RETURN LCD_Hex1 ADDLW 0xF6 ; This routine converts a number in w to an BTFSC STATUS, C ; ASCII hex number. Result in W ADDLW 0x07 ADDLW 0x3A RETURN ;***** LCD_Clear SUBROUTINE ***** LCD_Clear MOVLW CLR_DISP CALL LCD_Cmd RETURN ;***************************************LCD MODULE MACROS ************************************* ;***** LCD_Move Macro ***** LCD_Move MACRO Address MOVLW Address ;(Address|0x80) CALL LCD_Cmd ENDM ;*************************************** 1-WIRE SUBROUTINES ************************************* ;***** 1-WIRE MATCH ROM SUBROUTINE ***** MATCH_ROM MOVLW 0X55 ; MATCH ROM Command MOVWF TEMP1 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW D'8' ; 8 bytes of ROM ID data long MOVWF CNTR2 MATCH_ROM1 MOVLW D'8' ; 8 bits long MOVWF CNTR MOVF HIGH_ADDRESS,W MOVWF PCLATH INCF LOW_ADDRESS,W ADDWF CNTR1,W BTFSC STATUS,C INCF PCLATH,F BTFSS FLAGS,1 ; is FLAGS,1 set? GOTO CALL_DS2423 ; no, call DS2423 table CALL DS2450 ; yes, call DS2450 table GOTO NEXT CALL_DS2423 CALL DS2423 NEXT MOVWF TEMP1 ; and output to 1820 CALL WB ; One-Wire Write Byte subroutine DECFSZ CNTR2,F ; decrement count and skip next if=0 GOTO MATCH_ROM2 ; else increment address and read again GOTO MATCH_ROM3 ; done sending ROM ID MATCH_ROM2 INCF CNTR1,F GOTO MATCH_ROM1 MATCH_ROM3 RETURN ;***** 1-WIRE Reset SUBROUTINE ***** RESET BANKSEL D1WIRE_PORT BCF D1WIRE ; Set 1-Wire Bus low BANKSEL D1WIRE_TRIS BCF D1WIRE ; 1-Wire Bus direction = output, 1-wire forced low D10USEC D'50' ; 500 µs DELAY BSF D1WIRE ; 1-Wire Bus direction = input, 1-wire pulled up BANKSEL D1WIRE_PORT D10USEC D'6' ; 60 µs DELAY CLRF TEMP3 ; Initialize samples register=0 MOVLW D'36' ; 36 counts (180 µs) MOVWF CNTR ; Put 36 into count register CALL RESET1 RETURN RESET1 BTFSS D1WIRE ; Skip next if 1-wire is high INCF TEMP3,F ; Low so increment samples register DECFSZ CNTR,F ; Decrement count and skip next if=0 GOTO RESET1 ; Else go back, sample, decrement again D10USEC D'24' ; 240 µs DELAY RETURN ; Done (TEMP3 contains sampled low count) ;***** 1-WIRE WRITE SUBROUTINE ***** ; Input: Byte to write in TEMP1 ; : Number of bits to send in CNTR ; WB CALL WB0 RETURN WB0 RRF TEMP1,F ; Rotate LSBit data into carry BTFSS STATUS,C ; Skip next if carry (data)=1 GOTO WB2 ; Else jump to data=0 routine WB1 CALL W1S ; Call the write-1 time slot GOTO WB3 ; Go on WB2 CALL W0S ; Call the write-0 time slot WB3 DECFSZ CNTR,1 ; Decrement count and skip next if=0 GOTO WB0 ; Else go back and do another bit RETURN ; Done sending all bits W1S BANKSEL D1WIRE_PORT BCF D1WIRE ; Force 1-wire I/O bit low BANKSEL D1WIRE_TRIS BCF D1WIRE ; I/O direction=output, 1-wire forced low D10USEC D'1' BSF D1WIRE ; I/O direction=input, 1-wire pulled up BANKSEL D1WIRE_PORT D10USEC D'10' ; 100 µs DELAY RETURN ; Done sending bit W0S BANKSEL D1WIRE_PORT BCF D1WIRE ; Force 1-wire I/O bit low BANKSEL D1WIRE_TRIS ; Point to Bank1 (direction control) BCF D1WIRE ; I/O direction=output, 1-wire forced low D10USEC D'6' ; 60 µs DELAY BSF D1WIRE ; I/O direction=input, 1-wire pulled up BANKSEL D1WIRE_PORT D10USEC D'1' RETURN ; Done sending bit ;***** 1-WIRE READ SUBROUTINE ***** ; Input: number of bits to read in CNTR ; Output: read byte in TEMP1 ; RB CALL RB0 RETURN RB0 CALL RS ; Call the read time slot MOVF TEMP2,1 ; Get the sampled low count BCF STATUS,C ; Clear carry (read data=0 setup) BTFSC STATUS,Z ; Skip next if sampled count <>0 BSF STATUS,C ; Set carry (read data=1) RRF TEMP1,1 ; Rotate data into the MSBit DECFSZ CNTR,1 ; Decrement count and skip next if=0 GOTO RB0 ; Else go back and do another bit RETURN ; Done reading all bits RS BANKSEL D1WIRE_PORT BCF D1WIRE ; Force 1-wire I/O bit low BANKSEL D1WIRE_TRIS ; Point to Bank1 (direction control) BCF D1WIRE ; I/O direction=output, 1-wire forced low D10USEC D'1' ; 10 µs DELAY BSF D1WIRE ; I/O direction=input, 1-wire pulled up BANKSEL D1WIRE_PORT MOVLW D'3' ; 3 count (15 µs) MOVWF CNTR1 ; into count register CLRF TEMP2 ; Initialize sample count=0 RS2 BTFSS D1WIRE ; Skip next if 1-wire input=1 INCF TEMP2,1 ; Low so increment samples register DECFSZ CNTR1,1 ; Decrement count and skip next if=0 GOTO RS2 ; Else go back and decrement again D10USEC D'5' ; 50 µs DELAY RETURN ; Done receiving bit ;***** 16 bit CRC SUBROUTINE ***** ; Input: Byte for CRC in TEMP1 ; Output: Original byte in TEMP1, ; CRC16_HI and CRC16_LO new value of CRC16 ; DSCRC16 MOVLW D'8' ; 8 bits MOVWF CNTR ; store counter MOVF TEMP1,W MOVWF STORE ; Store TEMP1 Crc_Get_Bit RRF TEMP1,F ; Bit in C MOVF TEMP1,W ; Value to W SKPNC GOTO Crc_In_1 BTFSS CRC16_LO,0 ; Lowest bit set ? GOTO Crc_Cont ; Go to count with C=0 SETC GOTO Crc_Cont ; Go to count with C=1 Crc_In_1 BTFSC CRC16_LO,0 ; Lowest bit zero ? CLRC ; If no, C=0 = complement Crc_Cont SKPC GOTO Crc_Shift ; If C=0 only shift BTFSC CRC16_HI,6 ; Complement 15th bit of CRC GOTO Crc1 BSF CRC16_HI,6 ; If clear, set GOTO Crc2 Crc1 BCF CRC16_HI,6 ; If set, clear Crc2 BTFSC CRC16_LO,1 ; Complement 2nd bit of CRC GOTO Crc3 BSF CRC16_LO,1 GOTO Crc_Shift Crc3 BCF CRC16_LO,1 Crc_Shift RRF CRC16_HI,F ; 16bit rotate RRF CRC16_LO,F MOVF TEMP1,W DECFSZ CNTR,F GOTO Crc_Get_Bit MOVF STORE,W MOVWF TEMP1 ; Restore TEMP1 RETURN ;***************************************READ DS2423 SUBROUTINE************************************* ; Reads DS2423 Counter ; Input:TA1 is low byte address, TA2 is high byte address ; Output: counter value in COUNT RCOUNT CLRF CRC16_LO CLRF CRC16_HI CLRF CNTR1 CLRF COUNT CALL RESET MOVF TEMP3,W ; Move data into W SKPNZ ; Check to see if it is zero GOTO ERROR_TRAP ; If it is zero, go to ERROR_TRAP MOVLW HIGH DS2423 ; send Match Rom command using ID of DS2423 MOVWF HIGH_ADDRESS MOVLW LOW DS2423 ; send Match Rom command using ID of DS2423 MOVWF LOW_ADDRESS BCF FLAGS,1 ; clear FLAGS,1 to indicate DS2423 table read CALL MATCH_ROM MOVLW 0XA5 ; READ COUNTER Command MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVF TA1,W ; COUNTER Low Address Command MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVF TA2,W ; COUNTER High Address Command MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW D'32' MOVWF CNTR2 SKIPD32 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 DECFSZ CNTR2,F GOTO SKIPD32 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 MOVF TEMP1,W MOVWF COUNT ; transfer value to COUNT. Only interested in last byte of ; counter MOVLW D'3' MOVWF CNTR2 READD MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 DECFSZ CNTR2,F GOTO READD MOVLW D'4' MOVWF CNTR2 SKIPD2 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 DECFSZ CNTR2, 1 GOTO SKIPD2 READCRC MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine COMF CRC16_LO,F MOVF CRC16_LO,W SUBWF TEMP1,W SKPZ GOTO ERROR_TRAP MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine COMF CRC16_HI,F MOVF CRC16_HI,W SUBWF TEMP1,W SKPZ GOTO ERROR_TRAP GOTO CRC_OVER ERROR_TRAP MOVLW 'E' MOVWF D1WIRE_ERROR RETURN CRC_OVER RETURN ;***************************************DS2450 INITIALIZATION SUBROUTINE************************* ; Initialize DS2450 to do 8 bit conversions on Channel A,B,C,D with Vcc available (0X40 written to ; Memory location 1C) DS2450_INIT CLRF CRC16_LO CLRF CRC16_HI CLRF CNTR1 CALL RESET MOVF TEMP3,W ; Move data into W SKPNZ ; Check to see if it is zero GOTO ERROR_TRAP ; If it is zero, go to ERROR_TRAP MOVLW HIGH DS2450 ; send Match Rom command using ID of DS2450 MOVWF HIGH_ADDRESS MOVLW LOW DS2450 ; send Match Rom command using ID of DS2450 MOVWF LOW_ADDRESS BSF FLAGS,1 ; set FLAGS,1 to indicate DS2450 table read CALL MATCH_ROM MOVLW 0X55 ; Write Command MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x0C ; Page 1 Channel C Control/Status Low Address MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x00 ; Page 1 Channel C Control/Status High Address MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x08 ; Channel C Control, 8 bit conversion MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine CALL READCRC MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine MOVLW 0x08 SUBWF TEMP1,W BTFSS STATUS,Z CALL ERROR_TRAP1 CLRF CRC16_LO CLRF CRC16_HI MOVLW 0x0D MOVWF CRC16_LO MOVLW 0x00 MOVWF CRC16_HI MOVLW 0x01 ; Channel C Status, 5.12 Volts MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine CALL READCRC MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine MOVLW 0x01 SUBWF TEMP1,W BTFSS STATUS,Z CALL ERROR_TRAP2 CLRF CRC16_LO CLRF CRC16_HI MOVLW 0x0E MOVWF CRC16_LO MOVLW 0x00 MOVWF CRC16_HI MOVLW 0x08 ; Channel D Control, 8 bit conversion MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine CALL READCRC MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine MOVLW 0x08 SUBWF TEMP1,W BTFSS STATUS,Z CALL ERROR_TRAP3 CLRF CRC16_LO CLRF CRC16_HI MOVLW 0x0F MOVWF CRC16_LO MOVLW 0x00 MOVWF CRC16_HI MOVLW 0x01 ; Channel D Status, 5.12 Volts MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine CALL READCRC MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine MOVLW 0x01 SUBWF TEMP1,W BTFSS STATUS,Z CALL ERROR_TRAP4 CALL RESET CLRF CRC16_LO CLRF CRC16_HI CLRF CNTR1 CALL MATCH_ROM MOVLW 0X55 ; Write Command MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x1C ; Page 4 Low Address MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x00 ; Page 4 High Address MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x40 ; VCC available alwyas MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine CALL READCRC MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine MOVLW 0x40 SUBWF TEMP1,W BTFSS STATUS,Z CALL ERROR_TRAP5 CALL RESET RETURN ERROR_TRAP1 MOVLW '1' MOVWF D1WIRE_ERROR RETURN ERROR_TRAP2 MOVLW '2' MOVWF D1WIRE_ERROR RETURN ERROR_TRAP3 MOVLW '3' MOVWF D1WIRE_ERROR RETURN ERROR_TRAP4 MOVLW '4' MOVWF D1WIRE_ERROR RETURN ERROR_TRAP5 MOVLW '5' MOVWF D1WIRE_ERROR RETURN ;***************************************READ DS2450 SUBROUTINE************************* ; Read results of 8 bit conversions on Channel C,D DS2450_READ CLRF CRC16_LO CLRF CRC16_HI CLRF CNTR1 CALL RESET MOVF TEMP3,W ; Move data into W SKPNZ ; Check to see if it is zero GOTO ERROR_TRAP ; If it is zero, go to ERROR_TRAP MOVLW HIGH DS2450 ; send Match Rom command using ID of DS2450 MOVWF HIGH_ADDRESS MOVLW LOW DS2450 ; send Match Rom command using ID of DS2450 MOVWF LOW_ADDRESS BSF FLAGS,1 ; set FLAGS,1 to indicate DS2450 table read CALL MATCH_ROM MOVLW 0X3C ; Convert Command MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x0C ; input select mask MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x00 ; read out control byte MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine CALL READCRC CONVER_WAIT MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine MOVLW 0xFF SUBWF TEMP1,W BTFSS STATUS,Z GOTO CONVER_WAIT CALL RESET CLRF CRC16_LO CLRF CRC16_HI CLRF CNTR1 CALL MATCH_ROM MOVLW 0XAA ; Read Command MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x04 ; Channel C Result Low Address MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW 0x00 ; Channel C Result High Address MOVWF TEMP1 CALL DSCRC16 MOVLW D'8' ; 8 bits long MOVWF CNTR CALL WB ; One-Wire Write Byte subroutine MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 ; Channel C LS Byte MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 ; Channel C MS Byte MOVF TEMP1,W MOVWF CHANNELC MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 ; Channel D LS Byte MOVLW D'8' ; 8 bits long MOVWF CNTR CALL RB ; One-Wire Read Byte subroutine CALL DSCRC16 ; Channel D MS Byte MOVF TEMP1,W MOVWF CHANNELD CALL READCRC CALL RESET RETURN ;*************************************** SHT11 SUBROUTINES ************************************* ;***** SHT11 TRANSMISSION START SUBROUTINE ***** ; Leaves DATA as input at end of subroutine SHT_TX_START BANKSEL TWO_WIRE BCF TWO_WIRE_CLOCK ; set Clock line low BCF TWO_WIRE_DATA ; set Data line low BANKSEL TWO_WIRE_TRIS BCF TWO_WIRE_CLOCK ; set Clock line as output BCF TWO_WIRE_DATA ; set Data line as output BANKSEL TWO_WIRE BSF TWO_WIRE_DATA ; set Data line high BSF TWO_WIRE_CLOCK ; set Clock line high BCF TWO_WIRE_DATA ; set Data line low BCF TWO_WIRE_CLOCK ; set Clock line low BSF TWO_WIRE_CLOCK ; set Clock line high BSF TWO_WIRE_DATA ; set Data line high BCF TWO_WIRE_CLOCK ; set Clock line low BANKSEL TWO_WIRE_TRIS BSF TWO_WIRE_DATA ; set Data line as input BANKSEL TWO_WIRE RETURN ;***** SHT11 WRITE BYTE SUBROUTINE ***** ; Input: Byte to write in TEMP1 ; : Number of bits to send in CNTR ; Output: Carry=1 if no ACK was received ; Leaves DATA as input at end of subroutine SHT_WRITE_BYTE BANKSEL TWO_WIRE BCF TWO_WIRE_CLOCK ; set Clock line low BCF TWO_WIRE_DATA ; set Data line low BANKSEL TWO_WIRE_TRIS BCF TWO_WIRE_CLOCK ; set Clock line as output BCF TWO_WIRE_DATA ; set Data line as output BANKSEL TWO_WIRE SHT_WRITE_BYTE1 BCF TWO_WIRE_CLOCK ; set Clock line low RLF TEMP1,F ; rotate MSB into Carry BTFSS STATUS,C ; is bit 1? BCF TWO_WIRE_DATA ; no, set Data line low BTFSC STATUS,C ; is bit 0? BSF TWO_WIRE_DATA ; no. set Data line high BSF TWO_WIRE_CLOCK ; set Clock line high DECFSZ CNTR,F ; have all bits been sent? GOTO SHT_WRITE_BYTE1 ; no, go to SHT_WRITE_BYTE BANKSEL TWO_WIRE_TRIS BSF TWO_WIRE_DATA ; set Data line as input BANKSEL TWO_WIRE BCF TWO_WIRE_CLOCK ; set Clock line low BSF TWO_WIRE_CLOCK ; set Clock line high BCF STATUS,C ; clear Carry flag BTFSC TWO_WIRE_DATA ; is Data line low? BSF STATUS,C ; no, set Carry bit to indicate no ACK received BCF TWO_WIRE_CLOCK ; yes, set Clock line low RETURN ;***** SHT11 READ BYTE SUBROUTINE ***** ; Input: Number of bits to read in CNTR ; Output: Read byte in TEMP1 SHT_READ_BYTE BANKSEL TWO_WIRE CLRF TEMP1 BCF TWO_WIRE_CLOCK BCF TWO_WIRE_DATA BANKSEL TWO_WIRE_TRIS BCF TWO_WIRE_CLOCK BSF TWO_WIRE_DATA BANKSEL TWO_WIRE SHT_READ_BYTE1 BSF TWO_WIRE_CLOCK BCF STATUS,C BTFSC TWO_WIRE_DATA BSF STATUS,C RLF TEMP1,F BCF TWO_WIRE_CLOCK DECFSZ CNTR,F GOTO SHT_READ_BYTE1 BANKSEL TWO_WIRE_TRIS BCF TWO_WIRE_DATA BANKSEL TWO_WIRE BCF TWO_WIRE_DATA BSF TWO_WIRE_CLOCK BCF TWO_WIRE_CLOCK RETURN ;***** SHT11 WAIT FOR DATA SUBROUTINE ***** ; WAIT_FOR_DATA MOVLW D'195' ; this gives a maximum 250 msec delay while waiting for the SHT-11 MOVWF TEMP1 ; to finish the reading WAIT_FOR_DATA1 CLRF TEMP2 ; inner nested counting loop WAIT_FOR_DATA2 BTFSS TWO_WIRE_DATA ; is the data line low (SHT-11 signal that reading is finished) RETLW D'0' ; if yes, return with w egual to 0 DECFSZ TEMP2,F ; if no, continue counting GOTO WAIT_FOR_DATA2 DECFSZ TEMP1,F ; is TEMP1 now zero GOTO WAIT_FOR_DATA1 ; if no, continue counting RETLW D'1' ; if yes, SHT-11 has timed out. Return with W equal to 1 ;***** SHT11 CONNECTION RESET SUBROUTINE ***** SHT_CONNECTION_RESET BANKSEL TWO_WIRE BCF TWO_WIRE_CLOCK BCF TWO_WIRE_DATA BANKSEL TWO_WIRE_TRIS BCF TWO_WIRE_CLOCK BCF TWO_WIRE_DATA BANKSEL TWO_WIRE MOVLW D'9' MOVWF CNTR BSF TWO_WIRE_DATA SHT_CONNECTION_RESET1 BSF TWO_WIRE_CLOCK BCF TWO_WIRE_CLOCK DECFSZ CNTR,F GOTO SHT_CONNECTION_RESET1 RETURN ;***** SHT11 DATA ACQUISITION SUBROUTINE ***** ; Input: Command in W ; Output: Data in DATAH, DATAL ; 0 in W if data received ; 1 in W if communication timeout SHT_DATA_ACQUIRE MOVWF TEMP1 CALL SHT_TX_START MOVLW D'8' MOVWF CNTR CALL SHT_WRITE_BYTE BTFSC STATUS,C ; has the SHT-11 issued an ACK for the command GOTO ERROR_NO_ACK ; if no, go to error routine CALL WAIT_FOR_DATA ; if yes, wait for end of reading XORLW D'1' ; did the SHT-11 timeout BTFSC STATUS,Z GOTO ERROR_TIMEOUT ; if yes, go to error routine MOVLW D'8' ; if no, read first data byte MOVWF CNTR CALL SHT_READ_BYTE MOVF TEMP1,W MOVWF DATAH ; store first data byte in DATAH MOVLW D'8' ; read second data byte MOVWF CNTR CALL SHT_READ_BYTE MOVF TEMP1,W MOVWF DATAL ; store second data byte in DATAL RETLW D'0' ; return with W equal to 0 to indicate success ERROR_NO_ACK MOVLW '1' ; set ASCII error code 1 for no ack MOVWF SHT_ERROR2 GOTO SHT_ERROR ERROR_TIMEOUT MOVLW '2' ; set ASCII error code 2 for timeout MOVWF SHT_ERROR2 GOTO SHT_ERROR ERROR_CRC MOVLW '3' ; set ASCII error code 3 for wrong CRC MOVWF SHT_ERROR2 GOTO SHT_ERROR SHT_ERROR MOVLW 'E' ; set ASCII error code E for error detected MOVWF SHT_ERROR1 CALL SHT_CONNECTION_RESET ; reset SHT-11 serial interface RETLW D'1' ; return with W equal to 1 to indicate error ;***************************************LCD SCREEN SUBROUTINES ************************************* ;***** START SCREEN ***** START_SCREEN CALL LCD_Clear CLRF CNTR START_SCREEN1 MOVLW HIGH SCREEN1 MOVWF PCLATH MOVLW LOW SCREEN1 + 1 ADDWF CNTR,W BTFSC STATUS,C INCF PCLATH,F CALL SCREEN1 ANDLW 0xFF BTFSC STATUS, Z GOTO START_SCREEN2 CALL LCD_Nbl INCF CNTR,F GOTO START_SCREEN1 START_SCREEN2 LCD_Move 0xC0 CLRF CNTR START_SCREEN3 MOVLW HIGH SCREEN2 MOVWF PCLATH MOVLW LOW SCREEN2 + 1 ADDWF CNTR,W BTFSC STATUS,C INCF PCLATH,F CALL SCREEN2 ANDLW 0xFF BTFSC STATUS, Z GOTO START_SCREEN4 CALL LCD_Nbl INCF CNTR,F GOTO START_SCREEN3 START_SCREEN4 RETURN ;***** SECOND SCREEN ***** SECOND_SCREEN CALL LCD_Clear CLRF CNTR SECOND_SCREEN1 MOVLW HIGH SCREEN3 MOVWF PCLATH MOVLW LOW SCREEN3 + 1 ADDWF CNTR,W BTFSC STATUS,C INCF PCLATH,F CALL SCREEN3 ANDLW 0xFF BTFSC STATUS, Z GOTO SECOND_SCREEN2 CALL LCD_Nbl INCF CNTR,F GOTO SECOND_SCREEN1 SECOND_SCREEN2 LCD_Move 0xC0 CLRF CNTR SECOND_SCREEN3 MOVLW HIGH SCREEN4 MOVWF PCLATH MOVLW LOW SCREEN4 + 1 ADDWF CNTR,W BTFSC STATUS,C INCF PCLATH,F CALL SCREEN4 ANDLW 0xFF BTFSC STATUS, Z GOTO SECOND_SCREEN4 CALL LCD_Nbl INCF CNTR,F GOTO SECOND_SCREEN3 SECOND_SCREEN4 RETURN ;***** DISPLAY UPDATE ***** DISPLAY_UPDATE BTFSC FLAGS,0 GOTO DISPLAY_UPDATE2 LCD_Move 0x84 MOVF NEG,W CALL LCD_Nbl MOVF T10,W CALL LCD_Nbl MOVF T1,W CALL LCD_Nbl LCD_Move 0x88 MOVF T01,W CALL LCD_Nbl LCD_Move 0X8C MOVF SHT_ERROR1,W CALL LCD_Nbl MOVF SHT_ERROR2,W CALL LCD_Nbl LCD_Move 0x94 MOVF R100,W CALL LCD_Nbl MOVF R10,W CALL LCD_Nbl MOVF R1,W CALL LCD_Nbl LCD_Move 0xC5 MOVF WS10,W CALL LCD_Nbl MOVF WS1,W CALL LCD_Nbl LCD_Move 0xCC MOVF D1WIRE_ERROR,W CALL LCD_Nbl LCD_Move 0xD3 MOVF WD100,W CALL LCD_Nbl MOVF WD10,W CALL LCD_Nbl MOVF WD1,W CALL LCD_Nbl GOTO DISPLAY_UPDATE3 DISPLAY_UPDATE2 LCD_Move 0x84 MOVF TSIGN_MIN_VALUE,W CALL LCD_Nbl MOVF T10MIN_VALUE,W CALL LCD_Nbl MOVF T1MIN_VALUE,W CALL LCD_Nbl LCD_Move 0x88 MOVF T01MIN_VALUE,W CALL LCD_Nbl LCD_Move 0x91 MOVF TSIGN_MAX_VALUE,W CALL LCD_Nbl MOVF T10MAX_VALUE,W CALL LCD_Nbl MOVF T1MAX_VALUE,W CALL LCD_Nbl LCD_Move 0x95 MOVF T01MAX_VALUE,W CALL LCD_Nbl LCD_Move 0xC9 MOVF LS100,W CALL LCD_Nbl MOVF LS10,W CALL LCD_Nbl MOVF LS1,W CALL LCD_Nbl DISPLAY_UPDATE3 RETURN ;***************************************MATH SUBROUTINES ************************************* ;***** 16 BIT SUBTRACTION ***** ; Input: CALCH, CALCL , SUBH, SUBL ; Output: CALCH=CALCH-SUBH, CALCL=CALCL-SUBL SUB16 BCF STATUS,C MOVF SUBL,W SUBWF CALCL,F MOVF SUBH,W BTFSS STATUS,C ADDLW D'1' SUBWF CALCH,F RETURN ;***** 16 BIT ADDITION ***** ; Input: CALCH, CALCL , SUBH, SUBL ; Output: CALCH=CALCH+SUBH, CALCL=CALCL+SUBL ADD16 MOVF SUBL,W ADDWF CALCL,F MOVF SUBH,W BTFSC STATUS,C ADDLW D'1' ADDWF CALCH,F RETURN ;***** 16 BIT MACRO ***** ; Loads SUBH, SUBL with ARGL LOADS MACRO ARGL MOVLW HIGH(ARGL) MOVWF SUBH MOVLW LOW(ARGL) MOVWF SUBL ENDM ;***** BINARY TO ASCII CONVERSION MACRO***** ; Input: CALCH, CALCL, ARGL ; Output: ASCII value in DIGIT based on CALCH,CALCL divided by ARGL DODIGIT MACRO ARGL LOADS ARGL CALL DOSUB ENDM DOSUB MOVLW '0'-1 MOVWF DIGIT ; tracks ASCII value of count DOSUB1 INCF DIGIT,F ; increment ASCII character CALL SUB16 BTFSC STATUS,C ; any carry? GOTO DOSUB1 ; no, keep subtracting CALL ADD16 ; yes, reverse the last subtraction MOVF DIGIT,W ; place ASCII value of count in W RETURN ;***** TEMP DATA TO ASCII CONVERSION ***** ; Input: Temp data is CALCH, CALCL ; Output: ASCII characters in T10,T1,T01 (leading spaces removed and leading minus if req'd) TEMP_ASCII DECFSZ NEG,F GOTO TEMP_SIGN1 ; temperature is positive, no sign required MOVLW '-' ; temperature is negative, sign required MOVWF NEG GOTO TEMP_SIGN2 TEMP_SIGN1 MOVLW ' ' ; temperature is positive, replace negative sign with space MOVWF NEG TEMP_SIGN2 DODIGIT D'1000' ; count 10's of degrees MOVWF T10 ; store result in T10 DODIGIT D'100' ; count 1's of degrees MOVWF T1 ; store result in T1 DODIGIT D'10' ; count 0.1's of degrees MOVWF T01 ; store result in T01 BCF STATUS,C ; is temperature a new TMAX? MOVF DATAL,W SUBWF TDATALMAX,W MOVF DATAH,W BTFSS STATUS,C ADDLW D'1' SUBWF TDATAHMAX,W BTFSC STATUS,C GOTO OVER MOVF DATAH,W ; yes, update TDATAHMAX, TDATALMAX MOVWF TDATAHMAX MOVF DATAL,W MOVWF TDATALMAX MOVF T10,W MOVWF T10MAX_VALUE ; update T10MAX_VALUE MOVF T1,W MOVWF T1MAX_VALUE ; update T1MAX_VALUE MOVF T01,W MOVWF T01MAX_VALUE ; update T01MAX_VALUE MOVF NEG,W MOVWF TSIGN_MAX_VALUE ; update sign of maximum temperature OVER BCF STATUS,C ; is temperature a new TMIN? MOVF DATAL,W SUBWF TDATALMIN,W MOVF DATAH,W BTFSS STATUS,C ADDLW D'1' SUBWF TDATAHMIN,W BTFSS STATUS,C GOTO OVER1 MOVF DATAH,W ; yes, update TDATAHMIN, TDATALMIN MOVWF TDATAHMIN MOVF DATAL,W MOVWF TDATALMIN MOVF T10,W MOVWF T10MIN_VALUE ; update T10MIN_VALUE MOVF T1,W MOVWF T1MIN_VALUE ; update T1MIN_VALUE MOVF T01,W MOVWF T01MIN_VALUE ; update T01MIN_VALUE MOVF NEG,W MOVWF TSIGN_MIN_VALUE OVER1 BCF STATUS,RP0 ; check for leading zero MOVLW '0' XORWF T10,W SKPZ GOTO ZERO_END ; no leading zero MOVLW ' ' ; leading zero found, replace with space MOVWF T10 ZERO_END RETURN ;***** RH DATA TO ASCII CONVERSION ***** ; Input: RH data is in CALCH, CALCL ; Output: ASCII characters in R100,R10,R1 (leading zeros removed) RH_ASCII DODIGIT D'100' ; count 100's of relative humidity MOVWF R100 ; store result in R100 DODIGIT D'10' ; count 10's of relative humidity MOVWF R10 ; store result in R10 DODIGIT D'1' ; count 1's of relative humidity MOVWF R1 ; store result in R1 BCF STATUS,RP0 ; check for leading zeros MOVLW '0' XORWF R100,W SKPZ GOTO RH_ZERO_END MOVLW ' ' ; 100's leading zero found, replace with space MOVWF R100 MOVLW '0' XORWF R10,W SKPZ GOTO RH_ZERO_END MOVLW ' ' ; 10's leading zero found, replace with space MOVWF R10 RH_ZERO_END RETURN ;***** WIND SPEED TO ASCII CONVERSION ***** ; Input: WIND_SPEED look-up table value in W (BCD) ; Output: ASCII characters in WS10,WS1 WS_BCD_ASCII MOVWF TEMP1 SWAPF TEMP1,W ANDLW 0x0F ADDLW 0x30 MOVWF WS10 BCF STATUS,RP0 ; check for leading zeros MOVLW '0' XORWF WS10,W SKPZ GOTO WS_ZERO_END MOVLW ' ' ; 10's leading zero found, replace with space MOVWF WS10 WS_ZERO_END MOVF TEMP1,W ANDLW 0x0F ADDLW 0x30 MOVWF WS1 RETURN ;***** WIND DIRECTION TO ASCII CONVERSION ***** ; Input: WD data is in CALCH, CALCL ; Output: ASCII characters in W100,W10,W1 WD_ASCII DODIGIT D'1000' ; count 100's of relative humidity MOVWF WD100 ; store result in W100 DODIGIT D'100' ; count 10's of relative humidity MOVWF WD10 ; store result in W10 DODIGIT D'10' ; count 1's of relative humidity MOVWF WD1 ; store result in W1 RETURN ;***** LIGHTING STRIKES TO ASCII CONVERSION ***** ; Input: LS data is in CALCH, CALCL ; Output: ASCII characters in LS100,LS10,LS1 (leading zeros removed) LS_ASCII DODIGIT D'100' ; count 100's of relative humidity MOVWF LS100 ; store result in LS100 DODIGIT D'10' ; count 10's of relative humidity MOVWF LS10 ; store result in LS10 DODIGIT D'1' ; count 1's of relative humidity MOVWF LS1 ; store result in LD1 BCF STATUS,RP0 ; check for leading zeros MOVLW '0' XORWF LS100,W SKPZ GOTO LS_ZERO_END MOVLW ' ' ; 100's leading zero found, replace with space MOVWF LS100 MOVLW '0' XORWF LS10,W SKPZ GOTO LS_ZERO_END MOVLW ' ' ; 10's leading zero found, replace with space MOVWF LS10 LS_ZERO_END RETURN ;***************************************RS232 SUBROUTINES ************************************* ;***** TX WEATHER DATA ***** RS232_TX MOVLW 'T' CALL TX_DATA MOVF NEG,W CALL TX_DATA MOVF T10,W CALL TX_DATA MOVF T1,W CALL TX_DATA MOVLW '.' CALL TX_DATA MOVF T01,W CALL TX_DATA MOVLW 'C' CALL TX_DATA MOVLW ' ' CALL TX_DATA MOVLW 'R' CALL TX_DATA MOVLW 'H' CALL TX_DATA MOVLW ' ' CALL TX_DATA MOVF R100,W CALL TX_DATA MOVF R10,W CALL TX_DATA MOVF R1,W CALL TX_DATA MOVLW 0X25 CALL TX_DATA MOVLW ' ' CALL TX_DATA MOVLW 'W' CALL TX_DATA MOVLW 'S' CALL TX_DATA MOVLW ' ' CALL TX_DATA MOVF WS10,W CALL TX_DATA MOVF WS1,W CALL TX_DATA MOVLW 'K' CALL TX_DATA MOVLW 'T' CALL TX_DATA MOVLW 'S' CALL TX_DATA MOVLW ' ' CALL TX_DATA MOVLW 'W' CALL TX_DATA MOVLW 'D' CALL TX_DATA MOVLW ' ' CALL TX_DATA MOVF WD100,W CALL TX_DATA MOVF WD10,W CALL TX_DATA MOVF WD1,W CALL TX_DATA MOVLW 'T' CALL TX_DATA MOVLW ' ' CALL TX_DATA MOVLW 'L' CALL TX_DATA MOVLW 'S' CALL TX_DATA MOVLW ' ' MOVF LS100,W CALL TX_DATA MOVF LS10,W CALL TX_DATA MOVF LS1,W CALL TX_DATA MOVLW 0x0A CALL TX_DATA MOVLW 0X0D CALL TX_DATA RETURN TX_DATA BANKSEL PIR1 BTFSC PIR1,TXIF ;check if transmitter busy GOTO TX_DATA1 GOTO TX_DATA TX_DATA1 MOVWF TXREG RETURN ;************** MAIN ************** MAIN ;***** INITALIZE ***** CLRF PORTA CLRF PORTB CLRF HALF_SEC_COUNT CLRF TWO_SEC_COUNT CLRF WSPEED_VALUE CLRF FLAGS MOVLW 0xFF MOVWF TDATAHMIN MOVWF TDATALMIN MOVLW 0x00 MOVWF TDATAHMAX MOVWF TDATALMAX MOVLW ' ' MOVWF SHT_ERROR1 MOVWF SHT_ERROR2 MOVWF D1WIRE_ERROR MOVWF NEG MOVWF T10 MOVWF T1 MOVWF T01 MOVWF T10MIN_VALUE MOVWF T1MIN_VALUE MOVWF T01MIN_VALUE MOVWF T10MAX_VALUE MOVWF T1MAX_VALUE MOVWF T01MAX_VALUE MOVWF TSIGN_MAX_VALUE MOVWF TSIGN_MIN_VALUE MOVWF R100 MOVWF R10 MOVWF R1 MOVWF WD100 MOVWF WD10 MOVWF WD1 MOVWF WS10 MOVWF WS1 MOVWF LS100 MOVWF LS10 MOVWF LS1 BANKSEL OPTION_REG MOVLW b'00000000' ; Port B pullups, int falling edge RB0 MOVWF OPTION_REG BANKSEL INTCON MOVLW b'11010000' ; GIE, PIE, RBIE enabled MOVWF INTCON BANKSEL PIE1 MOVLW b'00000001' ; RCI, TXI, TMR1I enabled MOVWF PIE1 BANKSEL CMCON MOVLW b'00000111' ; Comparators off MOVWF CMCON BANKSEL T1CON MOVLW b'00110000' ; 1:8 pre-scale, Internal Clock, Timer1 disabled MOVWF T1CON BANKSEL SPBRG MOVLW D'25' ; 9600 baud MOVWF SPBRG MOVLW 0x06 ; set tris bits for TX and RX IORWF TRISB,F MOVLW 0x24 MOVWF TXSTA ; TX endabled and BRGH=1 BANKSEL RCSTA MOVLW 0x80 ; enable serial port MOVWF RCSTA MOVLW '0' MOVWF TXREG DLONG D'200' ; LCD power up delay CALL LCD_Init ; Initialize LCD Module CALL START_SCREEN ; display first screen CALL DS2450_INIT CALL DISPLAY_UPDATE BANKSEL T1CON BSF T1CON, TMR1ON ; Turn Timer1 on WAIT GOTO WAIT ; Wait for interrupts END