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 23:02, local time: 2025/10/26 07:01,
owner: AR-telus-,
216.73.216.188,10-3-157-36:LOG IN
|
| ©2025 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! |
|
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! |
.