ON 20040506@8:15:29 AM at page:
http://www.piclist.compiclist/questions.htm#38113.0308217593
James Newton[JMN-EFP-786] published post 38113.0308217593
chin_kok_leong@yahoo.com asks: "
pls, help me here!!!!!!!!
how can i connect my pic to my pc. i cant load my hex file to my pic.Y??????"
|Delete 'P-' before: '' but after: 'nanawash5@aol.com asks:
I want know how to control two stepper motors for mobile robots;and make them slave to each other. Without affecting the torque and stepping sequences.|Delete 'P-' before: '' but after: 'gerrett@globetrotter.net asks:
does anyone have assembler code to enable me to have a 32bit varable that is stored in eeprom of a pic 16f877 - add a 16 bit variable to it and then store this 32 bit sum again. therefore read - add - write|Delete 'P-' before: '' but after: 'Fabio silveira Moura of Sinteck electronics asks: " Please,
I wander there is any way to establish a 4 bits paralel interface between pic and LCD. I want to put a 64 frequency devider to increase the masured frequency. I need a pine from the pic to set it high if the frequency devider is in use, and low if is not. Any idea...?|Delete 'P-' before: '' but after: 'pastapora@hotmail.com asks: " fpp how to use? , please urgent!!!"
Thenks for your atention! Radu
;******************************************************************************
;
; 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
|Delete 'P-' before: '' but after: 'researcher@freemail.it asks: I would like to use this frequency counter in an ancient radio receiver so does anybody know how I can subtract a constant value? ex: it should be interesting subtract 10.7MHz or 455KHz from the red value.|Delete 'P-' before: '' but after: '