Look at the 16F877A datasheet, pages 127, 128, and 135....then look right after DEFINE OSC 20 below...
@ DEVICE PIC16f877a, HS_OSC, PWRT_ON, BOD_ON
include "modedefs.bas"
DEFINE OSC 20
ADCON0=0:ADCON1=6:CMCON=7:I2CDATA VAR PORTC.4:I2CCLK VAR PORTC.3:SerialTX VAR PORTC.6:SerialRX VAR PORTC.7:P_SP_reset VAR PORTE.0:P_zone1 VAR PORTB.3:P_zone2 VAR PORTB.2
P_zone3 VAR PORTB.1:P_zone4 VAR PORTB.0:P_zone5 VAR PORTD.7:P_zone6 VAR PORTD.6:P_zone7 VAR PORTD.5:P_zone8 VAR PORTD.4:P_zone9 VAR PORTC.5:P_zone10 VAR PORTD.3:P_zone11 VAR PORTD.2
P_zone12 VAR PORTD.1:P_zone13 VAR PORTD.0:P_zone14 VAR PORTC.2:P_zone15 VAR PORTC.1:P_zone16 VAR PORTC.0:P_zone17 VAR PORTA.2:P_zone18 VAR PORTA.3:SP_STATUS con $10:SP_NOP CON $00
SP_READ1byte CON $C0:SP_READ2bytes CON $C1:SP_READ3bytes CON $C2:SP_READ5bytes CON $C4:SP_WRITE1byte CON $80:SP_WRITE2bytes CON $81:SP_WRITE5bytes CON $84:SP_RTCADDR con $7f
SP_DAY var byte:SP_HOURS var byte:SP_MINUTES var byte:SP_SECONDS var byte:SP_AMPM var byte:RTC_DAY var byte:RTC_HOURS var byte:RTC_MINUTES var byte:RTC_SECONDS var byte
RTC_AMPM var byte:SP_STARTHOUR con $96:SP_STARTMINUTE con $97:SP_STARTAMPM CON $98:SP_WINTER con $A0:SP_ManualAddr con $83:SP_bstatus var byte:manual_run var bit:timed_run var bit
PREVIOUS_MINUTE var byte:RTC_STATUS VAR WORD:RTC_STATUS = $003F:RTC_TIMEADDR var word:RTC_TIMEADDR = $0030:winter VAR bit:T_zone VAR byte:valve_number var byte:valvetime var byte
current_zone var byte:start_hour var byte:start_minute var byte:start_ampm var byte:i2c_ack VAR BIT:i2c_in var byte:BIN2BCD_TEMP var byte:BIN2BCD_VAL var byte:BCD2BIN_TEMP var byte
BCD2BIN_VAL var byte:TEMP1 var byte:TEMP2 var byte:i var byte:t_zone=0:Current_zone = 0:PREVIOUS_MINUTE = $FF:winter = 0
main:
SEROUT2 SerialTX, 84, [$10]:SERIN2 SerialRX, 84, [SP_bstatus]
if SP_bstatus.7 and SP_bstatus.0 then
Serout2 SerialTX, 84, [SP_READ5bytes, SP_RTCADDR]:SERIN2 SerialRX, 84, [SP_SECONDS, SP_MINUTES, SP_HOuRS, SP_DAY, SP_AMPM]:gosub UPDATE_CURRENT_TIME
endif
if SP_bstatus.7 and SP_bstatus.1 then
SEROUT2 SerialTX,84,[SP_READ3bytes,SP_STARTHOUR]:SERIN2 SerialRX,84,[start_hour,start_minute,start_ampm]:write SP_STARTHOUR,start_hour:write SP_STARTMINUTE,start_minute
write SP_STARTAMPM, start_ampm
endif
if SP_bstatus.7 and SP_bstatus.2 then
for valve_number = 1 to 126:SEROUT2 SerialTX, 84, [SP_READ1byte, valve_number]:SERIN2 SerialRX, 84, [valvetime]:write valve_number, valvetime:next valve_number
endif
if SP_bstatus.7 and SP_bstatus.3 then
Current_zone = 1:manual_run = 1:gosub MANUALRUN
endif
gosub READ_TIME:SEROUT2 SerialTX, 84, [SP_WRITE5bytes, SP_RTCADDR, SP_SECONDS, SP_MINUTES, SP_HOURS, SP_DAY, SP_AMPM]
if current_zone = 0 then PREVIOUS_MINUTE = SP_MINUTES
if SP_MINUTES != PREVIOUS_MINUTE and current_zone > 0 THEN
PREVIOUS_MINUTE = SP_MINUTES:T_zone = T_zone - 1
endif
if T_zone = 255 then T_zone = 0
if SP_HOURS = start_hour and SP_MINUTES = start_minute and current_zone = 0 and winter = 0 and manual_run = 0 then
current_zone = 1:timed_run = 1:gosub GET_CURRENT_VALVE_RUN_TIME
endif
if current_zone > 0 and current_zone < 19 and T_zone = 0 and manual_run = 0 then
current_zone = current_zone + 1:gosub GET_CURRENT_VALVE_RUN_TIME
endif
if current_zone > 0 and current_zone < 19 and T_zone = 0 and manual_run = 1 then
current_zone = current_zone + 1:gosub MANUALRUN
endif
if current_zone > 18 and T_zone = 0 then
current_zone = 0:manual_run = 0:timed_run = 0
endif
if T_zone > 0 then
low p_zone1:low p_zone2:low p_zone3:low p_zone4:low p_zone5:low p_zone6:low p_zone7:low p_zone8:low p_zone9:low p_zone10:low p_zone11:low p_zone12:low p_zone13:low p_zone14:low p_zone15
low p_zone16:low p_zone17:low p_zone18
select case current_zone
case 1
high P_Zone1
case 2
high P_Zone2
case 3
high P_zone3
case 4
high P_zone4
case 5
high P_zone5
case 6
high P_zone6
case 7
high P_zone7
case 8
high P_zone8
case 9
high P_zone9
case 10
high P_zone10
case 11
high P_zone11
case 12
high P_zone12
case 13
high P_zone13
case 14
high P_zone14
case 15
high P_zone15
case 16
high P_zone16
case 17
high P_zone17
case 18
HIGH P_zone18
end select
endif
pause 1000:goto main
UPDATE_CURRENT_TIME:
BIN2BCD_VAL = SP_SECONDS:gosub BIN_TO_BCD:RTC_SECONDS = BIN2BCD_VAL:BIN2BCD_VAL = SP_MINUTES:gosub BIN_TO_BCD:RTC_MINUTES = BIN2BCD_VAL:BIN2BCD_VAL = SP_HOURS:gosub BIN_TO_BCD
RTC_HOURS = BIN2BCD_VAL:RTC_HOURS.7 = 0:RTC_HOURS.5 = SP_AMPM.0:I2CWRITE I2CDATA, I2CCLK, $DE, RTC_STATUS, [$02]:I2CWRITE I2CDATA, I2CCLK, $DE, RTC_STATUS, [$06]
I2CWRITE I2CDATA, I2CCLK, $DE, RTC_TIMEADDR, [RTC_SECONDS, RTC_MINUTES, RTC_HOURS, $00, $00, $00, SP_DAY, $00]ause 10:I2CWRITE I2CDATA, I2CCLK, $DE, RTC_STATUS, [$00]:RETURN
MANUALRUN:
SEROUT2 SerialTX, 84, [SP_READ1byte, SP_ManualAddr+current_zone]:SERIN2 SerialRX, 84, [T_zone]:RETURN
GET_CURRENT_VALVE_RUN_TIME:
read (SP_DAY*18)+current_zone, T_zone:RETURN
READ_TIME:
HIGH I2CDATA:HIGH I2CCLK:LOW I2CDATA:LOW I2CCLK:SHIFTOUT I2CDATA,I2CCLK,1,[$DE]:SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1]:SHIFTOUT I2CDATA,I2CCLK,1,[$00]:SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1]
SHIFTOUT I2CDATA,I2CCLK,1,[$30]:SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1]:HIGH I2CDATA:HIGH I2CCLK:LOW I2CDATA:LOW I2CCLK:SHIFTOUT I2CDATA,I2CCLK,1,[$DF]:SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1]
SHIFTIN I2CDATA,I2CCLK,0,[Sp_SECONDS]:SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]:SHIFTIN I2CDATA,I2CCLK,0,[SP_MINUTES]:SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]:SHIFTIN I2CDATA,I2CCLK,0,[SP_HOURS]
SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]:SHIFTIN I2CDATA,I2CCLK,0,[i2c_in]:SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]:SHIFTIN I2CDATA,I2CCLK,0,[i2c_in]:SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_in]:SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]:SHIFTIN I2CDATA,I2CCLK,0,[SP_DAY]:SHIFTOUT I2CDATA,I2CCLK,1,[%1\1]:LOW I2CDATA:HIGH I2CCLK:HIGH I2CDATA:PAUSE 1
BCD2BIN_VAL = SP_SECONDS:gosub BCD_TO_BIN:SP_SECONDS = BCD2BIN_VAL:BCD2BIN_VAL = SP_MINUTES:gosub BCD_TO_BIN:SP_MINUTES = BCD2BIN_VAL:SP_AMPM = SP_HOURS.5:SP_HOURS.5 = 0
BCD2BIN_VAL = SP_HOURS:gosub BCD_TO_BIN:SP_HOURS = BCD2BIN_VAL:return
BIN_TO_BCD:
BIN2BCD_TEMP = ((BIN2BCD_VAL/10)<<4)+(BIN2BCD_VAL//10):BIN2BCD_VAL = BIN2BCD_TEMP:return
BCD_TO_BIN:
TEMP1=BCD2BIN_VAL & $F:TEMP2=BCD2BIN_VAL & $F0:TEMP2 = TEMP2 >> 4:TEMP2 = TEMP2 * 10:BCD2BIN_VAL = TEMP1 + TEMP2:return
End
Bookmarks