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+
file: /Techref/piclist/roundweather.htm, 52KB, , updated: 2004/5/17 22:02, local time: 2024/11/24 16:13,
owner: AR-telus-,
3.15.34.50:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://ecomorder.com/techref/piclist/roundweather.htm"> Adrian Round's PIC Weather Station</A> |
Did you find what you needed? |
Welcome to ecomorder.com! |
Welcome to ecomorder.com! |
.