PDA

View Full Version : Clock and Dual Termometer



fratello
- 18th January 2011, 17:51
Hi everyone !
I try to build for my use , in home, one clock with dual termometer, using 16F628A, 2x16 LCD and 2 x DS18B20. I wrote the code, but... at every minute I have a few seconds more...I don't have a clue where it's the mistake. Can help me, please ? Thanks in advance :) !

@ DEVICE pic16F628A, XT_osc, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_ON, LVP_OFF

TRISA= %11111000 ' RA0..3=Outputs RA4=Input
TRISB= %00001111 ' RB0..RB2=Inputs, RB3..RB7=Outputs
CMCON=7 ' Disable comparators
OPTION_REG=%00000111

DEFINE LCD_DREG PORTB ' LCD on port B
DEFINE LCD_DBIT 4 ' Data bits B4..B7
DEFINE LCD_RSREG PORTA ' RS on PORTA
DEFINE LCD_RSBIT 1 ' RS on A1
DEFINE LCD_EREG PORTA ' E on PORTA
DEFINE LCD_EBIT 0 ' E on A0
DEFINE LCD_BITS 4 ' LCD 4 bit mode
DEFINE LCD_LINES 2 ' 2 line LCD display

TempC var word
Float var word
Sign var bit ' +/- sign
DQ var PORTA.4 ' One-wire data pin
TempC2 var word
Float2 var word
Sign2 var BIT ' +/- sign
DQ2 var PORTA.3 ' One-wire data pin
Delay var byte
Mode var byte
semn var word
semn2 var word

DS18B20_1_12bit CON %01111111 ; 750ms, 0.0625°C (default)
DS18B20_2_12bit CON %01111111 ; 750ms, 0.0625°C (default)


Ticks var byte ; Tick count (61 ticks=1 sec)
Hour var byte ; Hour variable
Minute var byte ; Minute variable
Second var byte ; Second variable
ZIUA var byte
LUNA var byte
Disp var byte ; Disp=1 to update display

PAUSE 500 ; Wait 0.5sec for LCD to initialize

Hour=0 : Minute=0 : Second=0
Ticks=0 : ZIUA=01 : LUNA=01

OPTION_REG=$05 ; Set prescaler
ON INTERRUPT GOTO ISR ; ISR routine
INTCON=$A0 ; Enable TMR
LCDOUT $FE, 1 ; Clear LCD

' Init Sensor 1
OWOUT DQ, 1, [$CC, $4E, 0, 0, DS18B20_1_12bit]
OWOut DQ, 1, [$CC, $48]
OWOut DQ, 1, [$CC, $B8]
OWOut DQ, 1, [$CC, $BE]
Pause 50
OWIn DQ, 2, [TempC.byte0, TempC.byte1]
Pause 50
' Init Sensor 2
OWOUT DQ2, 1, [$CC, $4E, 0, 0, DS18B20_2_12bit]
OWOut DQ2, 1, [$CC, $48]
OWOut DQ2, 1, [$CC, $B8]
OWOut DQ2, 1, [$CC, $BE]
Pause 50
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]
Pause 50


LOOP:

If PORTB.0=0 then ' Mode switch preSeconded
Pause 50 ' Debounce
LcdOut $FE, 1
LcdOut $FE, $C0, " SETTING" ' Show that coMinuteand is accepted
PAUSE 500
LcdOut $FE, 1
If PORTB.0=0 then Loop ' Wait until button is released
Mode=Mode+1 ' Increment mode
ENDIF


If Mode=1 then ' SET HOUR
LcdOut $FE, $80, dec2 Hour
LcdOut $FE, $C0, "HOUR SETTING"
if portb.1=0 then
Hour=Hour+1
IF Hour=24 then
Hour=0
ENDIF
Gosub Debounce
endif

if portb.2=0 then
IF Hour = 0 then
Hour=24
ENDIF
Hour=Hour-1
Gosub Debounce
endif
EndIf

If Mode=2 then ' SET MINUTES
LcdOut $FE, $80, dec2 Hour,":",dec2 Minute
LcdOut $FE, $C0, "MINUTES SETTING"

if portb.1=0 then
Second=0
Minute=Minute+1
IF Minute=60 THEN
Minute=0
ENDIF
Gosub Debounce
endif

if portb.2=0 then
Second=0
IF Minute =<0 THEN
Minute=60
ENDIF
Minute=Minute-1
Gosub Debounce
endif
EndIf

If Mode=3 then ' SET DAY
LcdOut $FE, $80, dec2 Hour,":",dec2 Minute,":",dec2 Second," ",DEC2 ZIUA,"/"
LcdOut $FE, $C0, "DAY SETTING"
if portb.1=0 then
ziua=ziua+1
IF LUNA=2 THEN
IF ZIUA > 28 THEN
ZIUA=1
ENDIF
ENDIF
IF LUNA=4 OR LUNA=6 OR LUNA=9 OR LUNA=11 THEN
IF ZIUA > 30 THEN ZIUA=1
ELSE
IF ZIUA > 31 THEN ZIUA=1
ENDIF
Gosub Debounce
endif

if portb.2=0 then
ZIUA=ZIUA-1
IF ZIUA = 0 THEN ZIUA=31
Gosub Debounce
endif
EndIf

If Mode=4 then ' SET MONTH
LcdOut $FE, $80, dec2 Hour,":",dec2 Minute,":",dec2 Second," ",DEC2 ZIUA,"/",DEC2 LUNA
LcdOut $FE, $C0, "MONTH SETTING"
if portb.1=0 then
luna=luna+1
if luna>12 then
luna=1
endif
Gosub Debounce
endif

if portb.2=0 then
luna=luna-1
if luna<1 then
luna=12
endif
Gosub Debounce
endif
EndIf

If Mode > 4 then
LCDOUT $FE, $C0, "END SETTING"
PAUSE 1000
LCDOUT $FE, 1, $FE, $0C
mode=0
EndIf

If Mode > 0 then Loop

IF Disp=1 THEN

LcdOut $FE, $80, DEC2 Hour, ":",DEC2 Minute, ":",DEC2 Second," ",DEC2 ZIUA,"/",DEC2 LUNA

LCDOUT $FE, $C0, semn,DEC ABS TempC/100,".", DEC1 ABS TempC/10, 223,"C ", $FE, $C0 + 9, semn2,DEC ABS TempC2/100,".", DEC1 ABS TempC2/10, 223,"C "

Disp=0
ENDIF

GOTO LOOP

DISABLE
ISR:
Ticks=Ticks + 1
IF Ticks < 61 THEN NoUpdate
Ticks=0
Second=Second + 1 ; Update second
IF Second=60 THEN
Second=0
Minute=Minute + 1 ; Update Minute
IF Minute=60 THEN
Minute=0
Hour=Hour + 1 ; Update Hour
IF Hour=24 THEN
Hour=0
ZIUA=ZIUA+1
IF LUNA=2 THEN
IF ZIUA > 28 THEN
ZIUA=1
LUNA=3
ENDIF
ENDIF

IF LUNA=4 OR LUNA=6 OR LUNA=9 OR LUNA=11 THEN
IF ZIUA > 30 THEN
ZIUA=1
LUNA=LUNA+1
ENDIF
ENDIF

IF LUNA=1 OR LUNA=3 OR LUNA=5 OR LUNA=7 OR LUNA=8 OR LUNA=10 THEN
IF ZIUA > 31 THEN
ZIUA=1
LUNA=LUNA+1
ENDIF
ENDIF

IF LUNA=12 THEN
IF ZIUA > 31 THEN
ZIUA=1
LUNA=1
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
Disp=1 ; Set to update display
Gosub Read_temp

NoUpdate:
INTCON.2=0 ; Re-enable TMR0 interrupts
Resume
ENABLE ; Re-enable interrupts
END


;=================================
;Subrutine

Debounce:
FOR Delay=1 To 200
Pause 1 ; Delay 1ms inside a loop. This way,
NEXT Delay ; timer interrupts are not stopped
Disp=1 ; Set display flag to 1
RETURN
;==================================
Read_Temp:
OWOut DQ, 1, [$CC, $44]
OWOut DQ, 1, [$CC, $BE]
OWIn DQ, 2, [TempC.byte0, TempC.byte1]

Sign = TempC.15
TempC = ABS(TempC)
TempC = ((TempC >> 4)*100) + ((TempC & $F)*100 >> 4)
IF Sign THEN TempC = -TempC
IF TempC.15 THEN
Semn="-"
else
Semn="+"
endif

OWOut DQ2, 1, [$CC, $44]
OWOut DQ2, 1, [$CC, $BE]
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]

Sign2 = TempC2.15
TempC2 = ABS(TempC2)
TempC2 = ((TempC2 >> 4)*100) + ((TempC2 & $F)*100 >> 4)
IF Sign2 THEN TempC2 = -TempC2
IF TempC2.15 THEN
Semn2="-"
else
Semn2="+"
endif
Return
;=====================================

END ; End of program

mackrackit
- 19th January 2011, 05:46
That is one of the problems with ON INTERRUPT. It does not interrupt until the main code gets a break. If, for example the code is in a PAUSE when the interrupt happens, the code will not go to the ISR until the PAUSE is complete.

You will need to use ASM interrupts or DT's instant interrupts.

Acetronics2
- 19th January 2011, 09:25
Hi, Fratello

Even using ON INTERRUPT ... you shouldn't have such a time error ... ( just display " not so regularly " the correct HH:MM:SS )

but maybe you could write the shortest as possible interrupt stubb, not jumping from here to there ...

the problem looks to be your interrupt stubb is longer than the time between two Timer interrupts. ( 1/61 s ? - from your ISR calculations )

Alain

fratello
- 19th January 2011, 14:41
Ok, I think that my previous code it's wrong in his essence...so...
I try another two version, based on codes from : Paul R. Borgmeier, PhD (see EZCLOCK1) and Mr.Bruce (see RENTRON.COM). Still not good precision :( ... Any ideeas ?

@ DEVICE pic16F628A, XT_osc, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_ON, LVP_OFF, CPD_OFF, PROTECT_OFF ' for PBP 2.4
DEFINE OSC 4
INCLUDE "AllDigital.pbp"
TRISA= %11111000 ' RA0..3=Outputs RA4=Input
TRISB= %00001111 ' RB0..RB2=Inputs, RB3..RB7=Outputs
CMCON=7 ' Disable comparators
OPTION_REG=%00000111
INTCON=0

DEFINE LCD_DREG PORTB ' LCD on port B
DEFINE LCD_DBIT 4 ' Data bits B4..B7
DEFINE LCD_RSREG PORTA ' RS on PORTA
DEFINE LCD_RSBIT 1 ' RS on A1
DEFINE LCD_EREG PORTA ' E on PORTA
DEFINE LCD_EBIT 0 ' E on A0
DEFINE LCD_BITS 4 ' LCD 4 bit mode
DEFINE LCD_LINES 2 ' 2 line LCD display


HzTimer Var Word
HH Var Byte
MM Var Byte
SS Var Byte
ZIUA VAR BYTE
LUNA VAR BYTE
X Var Byte
col Var Bit

TempC Var Word
Float Var Word
Sign Var BIT ' +/- sign
DQ Var PORTA.4 ' One-wire data pin
TempC2 Var Word
Float2 Var Word
Sign2 Var BIT ' +/- sign
DQ2 Var PORTA.3 ' One-wire data pin
Delay var byte
Mode VAR BYTE
semn var word
semn2 var word
DS18B20_1_12bit CON %01111111 ; 750ms, 0.0625°C (default)
DS18B20_2_12bit CON %01111111 ; 750ms, 0.0625°C (default)

HzTimer = $7A12
HH=00 : MM=00 : SS=00 : ZIUA=01 : LUNA=01 : col=0 : Mode=0

Pause 500
LCDOUT $FE, 1, $FE, $0C ' Clear display, cursor off
Pause 100

'====================================
' Init Sensor 1
OWOUT DQ, 1, [$CC, $4E, 0, 0, DS18B20_1_12bit]
OWOut DQ, 1, [$CC, $48] ' Start temperature conversion
OWOut DQ, 1, [$CC, $B8]
OWOut DQ, 1, [$CC, $BE]
Pause 50
OWIn DQ, 2, [TempC.byte0, TempC.byte1]
Pause 50
' Init Sensor 2
OWOUT DQ2, 1, [$CC, $4E, 0, 0, DS18B20_2_12bit]
OWOut DQ2, 1, [$CC, $48] ' Start temperature conversion
OWOut DQ2, 1, [$CC, $B8]
OWOut DQ2, 1, [$CC, $BE]
Pause 50
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]
Pause 50


OPTION_REG.7=1
TMR0=0
INTCON.2=0

'====================================

Pause 500
LCDOUT $FE, 1, $FE, $0C ' Clear display, cursor off
Pause 250

LCDOUT $FE, $80, " TERMO-CLOCK "
LcdOut $FE, $C0, "By NICULESCU DAN"
PAUSE 3000
LCDOUT $FE, 1, $FE, $0C


'====================================

MainLoop:
If PORTB.0=0 then ' Mode switch pressed
Pause 50 ' Debounce
LcdOut $FE, 1
LcdOut $FE, $C0, " SETTING" ' Show that command is accepted
PAUSE 500
LcdOut $FE, 1
If PORTB.0=0 then MainLoop ' Wait until button is released
Mode=Mode+1 ' Increment mode

ENDIF


If Mode=1 then ' SET HOUR
LcdOut $FE, $80, dec2 HH
LcdOut $FE, $C0, "HOUR SETTING"
if portb.1=0 then
HH=HH+1
IF HH=24 then
HH=0
ENDIF
Gosub Debounce
endif

if portb.2=0 then
IF HH = 0 then
HH=24
ENDIF
HH=HH-1
Gosub Debounce
endif
EndIf

If Mode=2 then ' SET MINUTES
LcdOut $FE, $80, dec2 HH,":",dec2 MM
LcdOut $FE, $C0, "MINUTES SETTING"

if portb.1=0 then
SS=0
MM=MM+1
IF MM=60 THEN
MM=0
ENDIF
Gosub Debounce
endif

if portb.2=0 then
SS=0
IF MM =<0 THEN
MM=60
ENDIF
MM=MM-1
Gosub Debounce
endif
EndIf

If Mode=3 then ' SET DAY
LcdOut $FE, $80, dec2 HH,":",dec2 MM,":",dec2 ss," ",DEC2 ZIUA,"/"
LcdOut $FE, $C0, "DAY SETTING"
if portb.1=0 then
ziua=ziua+1
IF LUNA=2 THEN
IF ZIUA > 28 THEN
ZIUA=1
ENDIF
ENDIF
IF LUNA=4 OR LUNA=6 OR LUNA=9 OR LUNA=11 THEN
IF ZIUA > 30 THEN ZIUA=1
ELSE
IF ZIUA > 31 THEN ZIUA=1
ENDIF
Gosub Debounce
endif

if portb.2=0 then
ZIUA=ZIUA-1
IF ZIUA = 0 THEN ZIUA=31
Gosub Debounce
endif
EndIf

If Mode=4 then ' SET MONTH
LcdOut $FE, $80, dec2 HH,":",dec2 MM,":",dec2 ss," ",DEC2 ZIUA,"/",DEC2 LUNA
LcdOut $FE, $C0, "MONTH SETTING"
if portb.1=0 then
luna=luna+1
if luna>12 then
luna=1
endif
Gosub Debounce
endif

if portb.2=0 then
luna=luna-1
if luna<1 then
luna=12
endif
Gosub Debounce
endif
EndIf

If Mode > 4 then
LCDOUT $FE, $C0, "END SETTING"
PAUSE 1000
LCDOUT $FE, 1, $FE, $0C
mode=0
EndIf

If Mode > 0 then Mainloop

'====================================
Main :
ClockLoop : IF INTCON.2=0 THEN ClockLoop
INTCON.2=0


if portb.0=0 then Gosub MainLoop

HzTimer = HzTimer - $1000 'decrement timer
IF HzTimer<$1000 THEN
IF Col=1 THEN 'update time'
SS=SS+1
IF SS=60 THEN
SS=0
MM=MM+1
IF MM=60 THEN
MM=0
HH=HH+1
IF HH=24 THEN
HH=0
ZIUA=ZIUA+1
IF LUNA=2 THEN
IF ZIUA > 28 THEN
ZIUA=1
LUNA=3
ENDIF
ENDIF
IF LUNA=4 OR LUNA=6 OR LUNA=9 OR LUNA=11 THEN
IF ZIUA > 30 THEN
ZIUA=1
LUNA=LUNA+1
ENDIF
ENDIF
IF LUNA=1 OR LUNA=3 OR LUNA=5 OR LUNA=7 OR LUNA=8 OR LUNA=10 THEN
IF ZIUA > 31 THEN
ZIUA=1
LUNA=LUNA+1
ENDIF
ENDIF
IF LUNA=12 THEN
IF ZIUA > 31 THEN
ZIUA=1
LUNA=1
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF


'==================================== display time with :

LcdOut $FE, $80, dec2 HH,":",dec2 MM,":",dec2 ss," ",DEC2 ZIUA,"/",DEC2 LUNA

ELSE
'==================================== display time without :
LcdOut $FE, $80, dec2 HH,":",dec2 MM," ",dec2 ss," ",DEC2 ZIUA,"/",DEC2 LUNA

ENDIF
Col=Col+1
HzTimer=HzTimer+$7A12
else
gosub ReadTemp
ENDIF


goto Main



' SUBROUTINES:
'====================================
ReadTemp:
OWOut DQ, 1, [$CC, $44]
OWOut DQ, 1, [$CC, $BE]
OWIn DQ, 2, [TempC.byte0, TempC.byte1]

Sign = TempC.15
TempC = ABS(TempC)
TempC = ((TempC >> 4)*100) + ((TempC & $F)*100 >> 4)
IF Sign THEN TempC = -TempC
IF TempC.15 THEN
Semn="-"
else
Semn="+"
endif

OWOut DQ2, 1, [$CC, $44]
OWOut DQ2, 1, [$CC, $BE]
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]

Sign2 = TempC2.15
TempC2 = ABS(TempC2)
TempC2 = ((TempC2 >> 4)*100) + ((TempC2 & $F)*100 >> 4)
IF Sign2 THEN TempC2 = -TempC2
IF TempC2.15 THEN
Semn2="-"
else
Semn2="+"
endif
LCDOUT $FE, $C0, semn,DEC ABS TempC/100,".", DEC1 ABS TempC/10, 223,"C ", $FE, $C0 + 9, semn2,DEC ABS TempC2/100,".", DEC1 ABS TempC2/10, 223,"C "
Return
'====================================
Debounce :
For Delay= 1 to 200
Pause 1
next Delay
Return
'====================================
END ' Of program


and

@ DEVICE pic16F628A, XT_osc, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_ON, LVP_OFF
DEFINE OSC 4 ' using a 4MHz crystal

TRISA= %11111000 ' RA0..3=Outputs RA4=Input
TRISB= %00001111 ' RB0..RB2=Inputs, RB3..RB7=Outputs
DEFINE OSC 4 ' using a 4MHz crystal

DEFINE LCD_DREG PORTB ' LCD on port B
DEFINE LCD_DBIT 4 ' Data bits B4..B7
DEFINE LCD_RSREG PORTA ' RS on PORTA
DEFINE LCD_RSBIT 1 ' RS on A1
DEFINE LCD_EREG PORTA ' E on PORTA
DEFINE LCD_EBIT 0 ' E on A0
DEFINE LCD_BITS 4 ' LCD 4 bit mode
DEFINE LCD_LINES 2 ' 2 line LCD display
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us


TempC var word
Float var word
Sign var bit ' +/- sign
DQ var PORTA.4 ' One-wire data pin
TempC2 var word
Float2 var word
Sign2 var BIT ' +/- sign
DQ2 var PORTA.3 ' One-wire data pin
Delay var byte
Mode var byte
semn var word
semn2 var word

DS18B20_1_12bit CON %01111111 ; 750ms, 0.0625°C (default)
DS18B20_2_12bit CON %01111111 ; 750ms, 0.0625°C (default)



' setup vars for clock
Time VAR BYTE ' accumulates TMR2 to PR2 match counts
Minutes VAR BYTE ' minutes
Hours VAR BYTE ' hours
Seconds VAR BYTE
Match VAR PIR1.1 ' TMR2 to PR2 match interrupt flag bit

CMCON = 7 ' disable comparators
INTCON = 0 ' not using interupts. Just monitoring int flag bits

Time = 0 ' clear TMR2 to PR2 match counter
Hours = 00 ' set clock starting hour here
Minutes = 00 ' set clock starting minutes here
Seconds = 0

PR2 = 249 ' 249 +1 extra cycle for TMR2 reset = 250*5*16*1uS=20mS
Match = 0 ' clear match flag


' setup & start TMR2
T2CON = %00100110 ' 1:5 postscale, 1:16 prescale, TMR2 on


Main:
' every 20mS the TMR2IF flag is set, and this routine is entered.
' Plenty of time to do other stuff.
IF Match THEN ' has TMR2 matched PR2? (should happen every 20mS)
Match = 0 ' yes. clear TMR2 to PR2 match flag bit
Time = Time + 1 ' increment 20mS count
IF Time = 50 THEN ' 50 x 20mS = 1 second
Time = 0 ' show time in 1 second intervals
LcdOut $FE, $80, DEC2 Hours, ":",DEC2 Minutes, ":",DEC2 Seconds,13,10
LCDOUT $FE, $C0, semn,DEC ABS TempC/100,".", DEC1 ABS TempC/10, 223,"C ", $FE, $C0 + 9, semn2,DEC ABS TempC2/100,".", DEC1 ABS TempC2/10, 223,"C "
Gosub readtemp
Seconds = Seconds + 1
ENDIF
IF Seconds = 60 THEN ' has 60 seconds passed?
Seconds = 0
Minutes = Minutes + 1 ' increment minute count
IF Minutes = 60 THEN ' have 60 minutes passed?
Minutes = 0 ' yes. roll-over minutes 00
Hours = Hours + 1 ' update hours
IF Hours = 24 THEN Hours = 0 ' roll-over hours from 24 to 00
ENDIF ' end IF Minutes = 60
ENDIF ' end IF Seconds = 60
ENDIF ' end IF Match

GOTO Main


ReadTemp:
OWOut DQ, 1, [$CC, $44]
OWOut DQ, 1, [$CC, $BE]
OWIn DQ, 2, [TempC.byte0, TempC.byte1]

Sign = TempC.15
TempC = ABS(TempC)
TempC = ((TempC >> 4)*100) + ((TempC & $F)*100 >> 4)
IF Sign THEN TempC = -TempC
IF TempC.15 THEN
Semn="-"
else
Semn="+"
endif

OWOut DQ2, 1, [$CC, $44]
OWOut DQ2, 1, [$CC, $BE]
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]

Sign2 = TempC2.15
TempC2 = ABS(TempC2)
TempC2 = ((TempC2 >> 4)*100) + ((TempC2 & $F)*100 >> 4)
IF Sign2 THEN TempC2 = -TempC2
IF TempC2.15 THEN
Semn2="-"
else
Semn2="+"
endif
Return

END

Sorry for long post... It's a proof of hard ( useless :( ) work...

mackrackit
- 19th January 2011, 15:05
http://www.darreltaylor.com/DT_INTS-14/elapsed.html

cncmachineguy
- 19th January 2011, 15:18
First thing I would try is take out the gosub readtemp. Just for testing purpose. Then report back, tell us exactly how it is not precision. is it losing 1 second per min. is it gaining 1? what is the output you are seeing?

BTW, I am looking at the second program

fratello
- 19th January 2011, 15:26
Thanks for atention ! All three programs are - without read_temperature - verry accurate !
I try, in all three cases, to put the "read_temp" code in other places... the results are inadequates !

Acetronics2
- 19th January 2011, 15:39
@ first you can try your program with a 9 bits resolution, to have the quickest sensor conversion time ...

THEN you will know where is something wrong ...

Alain

malc-c
- 19th January 2011, 18:40
Not checked the data sheet so can't confirm if this is an option, but for the sake of a couple of ££ why not use a DS1307 RTC chip ??

cncmachineguy
- 19th January 2011, 19:12
I try, in all three cases, to put the "read_temp" code in other places... the results are inadequates !

Still waiting to hear what the results are. Is it slow, fast, sometimes right, sometimes wrong? Is it close or all over the place?

fratello
- 19th January 2011, 19:25
The clock run ok without read_temp, in all cases and run faster ( strange for me :( ) if use this subroutine.
I try now with 9 bits resolution of DS18B20, wait for result !
Thanks for support !

fratello
- 20th January 2011, 06:17
If DS18B20 it's in 9 bit mode, the clock run faster (!) with ~ 2 sec/hour (5 sec in 3 hours).

ardhuru
- 20th January 2011, 08:43
Thats about .055%; you ARE using a crystal, not a resonator, right?

Anand

fratello
- 20th January 2011, 09:15
Yes, I use a crystal. But, without code for DS18B20, the clock run correct (~ 1 sec/day). :confused:

HenrikOlsson
- 20th January 2011, 10:11
Hi,
If I read this correctly you have an interrupt frequency of 61.035Hz (prescaler 1:64, 256*64=16384, 1/0.016384=61.035Hz) when you ideally should have 61Hz - that's 0.057% off and as Anand says 2 seconds over one hour is 0.055%.

I currently have no idea why it starts running correct when you remove the DS1820 code - are you sure that's the case?

ardhuru
- 20th January 2011, 12:09
that's 0.057% off and as Anand says 2 seconds over one hour is 0.055%.

Closer to .056, actually since its .055555.. So, you might me spot on..

Anand

fratello
- 20th January 2011, 18:47
Somebody, in a forum of my country, propose this code. It' work ok, just 1 sec/hour faster !

@ __config _XT_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF

define OSC 4
TRISA= %11111000 ' RA0..3=Outputs RA4=Input
TRISB= %00001111 ' RB0..RB2=Inputs, RB3..RB7=Outputs
CMCON=7 ' Disable comparators
OPTION_REG=%00000111


DEFINE LCD_DREG PORTB ' LCD on port B
DEFINE LCD_DBIT 4 ' Data bits B4..B7
DEFINE LCD_RSREG PORTA ' RS on PORTA
DEFINE LCD_RSBIT 1 ' RS on A1
DEFINE LCD_EREG PORTA ' E on PORTA
DEFINE LCD_EBIT 0 ' E on A0
DEFINE LCD_BITS 4 ' LCD 4 bit mode
DEFINE LCD_LINES 2 ' 2 line LCD display

wsave VAR BYTE $70 SYSTEM
TempC var word
Float var word
Sign var bit ' +/- sign
DQ var PORTA.4 ' One-wire data pin
TempC2 var word
Float2 var word
Sign2 var BIT ' +/- sign
DQ2 var PORTA.3 ' One-wire data pin
Delay var byte
Mode var byte
semn var word
semn2 var word

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System ; Attention ! Modified file !
INCLUDE "ReEnterPBP.bas"

DS18B20_1_12bit CON %00011111 ' NOW 9 BIT
DS18B20_2_12bit CON %00011111 ' NOW 9 BIT


Ticks var byte ; Tick count (61 ticks=1 sec)
Hour var byte ; Hour variable
Minute var byte ; Minute variable
Second var byte ; Second variable
ZIUA var byte
LUNA var byte
Disp var BIt ; Disp=1 to update display

PAUSE 500 ; Wait 0.5sec for LCD to initialize

Hour=0 : Minute=0 : Second=0
Ticks=0 : ZIUA=01 : LUNA=01






' Init Sensor 1
OWOUT DQ, 1, [$CC, $4E, 0, 0, DS18B20_1_12bit]
OWOut DQ, 1, [$CC, $48]
OWOut DQ, 1, [$CC, $B8]
OWOut DQ, 1, [$CC, $BE]
Pause 50
OWIn DQ, 2, [TempC.byte0, TempC.byte1]
Pause 50
' Init Sensor 2
OWOUT DQ2, 1, [$CC, $4E, 0, 0, DS18B20_2_12bit]
OWOut DQ2, 1, [$CC, $48]
OWOut DQ2, 1, [$CC, $B8]
OWOut DQ2, 1, [$CC, $BE]
Pause 50
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]
Pause 50
OPTION_REG=$05 ; Set prescaler
INTCON=$A0 ; Enable TMR
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, _ISR, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR0_INT

LCDOUT $FE, 1 ; Clear LCD
LOOP:

If PORTB.0=0 then ' Mode switch preSeconded
Pause 50 ' Debounce
LcdOut $FE, 1
LcdOut $FE, $C0, " SETTING" ' Show that coMinuteand is accepted
PAUSE 500
LcdOut $FE, 1
If PORTB.0=0 then Loop ' Wait until button is released
Mode=Mode+1 ' Increment mode
ENDIF


If Mode=1 then ' SET HOUR
LcdOut $FE, $80, dec2 Hour
LcdOut $FE, $C0, "HOUR SETTING"
if portb.1=0 then
Hour=Hour+1
IF Hour=24 then
Hour=0
ENDIF
Gosub Debounce
endif

if portb.2=0 then
IF Hour = 0 then
Hour=24
ENDIF
Hour=Hour-1
Gosub Debounce
endif
EndIf

If Mode=2 then ' SET MINUTES
LcdOut $FE, $80, dec2 Hour,":",dec2 Minute
LcdOut $FE, $C0, "MINUTES SETTING"

if portb.1=0 then
Second=0
Minute=Minute+1
IF Minute=60 THEN
Minute=0
ENDIF
Gosub Debounce
endif

if portb.2=0 then
Second=0
IF Minute =<0 THEN
Minute=60
ENDIF
Minute=Minute-1
Gosub Debounce
endif
EndIf

If Mode=3 then ' SET DAY
LcdOut $FE, $80, dec2 Hour,":",dec2 Minute,":",dec2 Second," ",DEC2 ZIUA,"/"
LcdOut $FE, $C0, "DAY SETTING"
if portb.1=0 then
ziua=ziua+1
IF LUNA=2 THEN
IF ZIUA > 28 THEN
ZIUA=1
ENDIF
ENDIF
IF LUNA=4 OR LUNA=6 OR LUNA=9 OR LUNA=11 THEN
IF ZIUA > 30 THEN ZIUA=1
ELSE
IF ZIUA > 31 THEN ZIUA=1
ENDIF
Gosub Debounce
endif

if portb.2=0 then
ZIUA=ZIUA-1
IF ZIUA = 0 THEN ZIUA=31
Gosub Debounce
endif
EndIf

If Mode=4 then ' SET MONTH
LcdOut $FE, $80, dec2 Hour,":",dec2 Minute,":",dec2 Second," ",DEC2 ZIUA,"/",DEC2 LUNA
LcdOut $FE, $C0, "MONTH SETTING"
if portb.1=0 then
luna=luna+1
if luna>12 then
luna=1
endif
Gosub Debounce
endif

if portb.2=0 then
luna=luna-1
if luna<1 then
luna=12
endif
Gosub Debounce
endif
EndIf

If Mode > 4 then
LCDOUT $FE, $C0, "END SETTING"
PAUSE 100
LCDOUT $FE, 1, $FE, $0C
mode=0
EndIf
If Mode > 0 then Loop
IF Disp=1 THEN

LcdOut $FE, $80, DEC2 Hour, ":",DEC2 Minute, ":",DEC2 Second," ",DEC2 ZIUA,"/",DEC2 LUNA

LCDOUT $FE, $C0, semn,DEC ABS TempC/100,".", DEC1 ABS TempC/10, 223,"C ", $FE, $C0 + 9, semn2,DEC ABS TempC2/100,".", DEC1 ABS TempC2/10, 223,"C "

Disp=0
ENDIF

GOTO LOOP

@ INT_DISABLE TMR0_INT
ISR:
Ticks=Ticks + 1
IF Ticks < 61 THEN NoUpdate
Ticks=0
Second=Second + 1 ; Update second
IF Second=60 THEN
Second=0
Minute=Minute + 1 ; Update Minute
IF Minute=60 THEN
Minute=0
Hour=Hour + 1 ; Update Hour
IF Hour=24 THEN
Hour=0
ZIUA=ZIUA+1
IF LUNA=2 THEN
IF ZIUA > 28 THEN
ZIUA=1
LUNA=3
ENDIF
ENDIF

IF LUNA=4 OR LUNA=6 OR LUNA=9 OR LUNA=11 THEN
IF ZIUA > 30 THEN
ZIUA=1
LUNA=LUNA+1
ENDIF
ENDIF

IF LUNA=1 OR LUNA=3 OR LUNA=5 OR LUNA=7 OR LUNA=8 OR LUNA=10 THEN
IF ZIUA > 31 THEN
ZIUA=1
LUNA=LUNA+1
ENDIF
ENDIF

IF LUNA=12 THEN
IF ZIUA > 31 THEN
ZIUA=1
LUNA=1
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
Gosub Read_temp
Disp=1 ; Set to update display


NoUpdate:
INTCON.2=0 ; Re-enable TMR0 interrupts
@ INT_RETURN ; Re-enable interrupts
END


;=================================
;Subrutine

Debounce:
FOR Delay=1 To 200
Pause 1 ; Delay 1ms inside a loop. This way,
NEXT Delay ; timer interrupts are not stopped
Disp=1 ; Set display flag to 1
RETURN
;==================================
Read_Temp:
OWOut DQ, 1, [$CC, $44]
OWOut DQ, 1, [$CC, $BE]
OWIn DQ, 2, [TempC.byte0, TempC.byte1]

Sign = TempC.15
TempC = ABS(TempC)
TempC = ((TempC >> 4)*100) + ((TempC & $F)*100 >> 4)
IF Sign THEN TempC = -TempC
IF TempC.15 THEN
Semn="-"
else
Semn="+"
endif

OWOut DQ2, 1, [$CC, $44]
OWOut DQ2, 1, [$CC, $BE]
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]

Sign2 = TempC2.15
TempC2 = ABS(TempC2)
TempC2 = ((TempC2 >> 4)*100) + ((TempC2 & $F)*100 >> 4)
IF Sign2 THEN TempC2 = -TempC2
IF TempC2.15 THEN
Semn2="-"
else
Semn2="+"
endif
Return
;=====================================

END ; End of program

HenrikOlsson
- 21st January 2011, 06:26
Great - as long as it works for your needs.

But you can't get away from the fact that you're interrupting at 61.035Hz while it ideally should be 61Hz. That little difference WILL make it run fast.

Let's see.... For a duration of 100.000 interrupts a time of 100,000/61.035=1638.40 seconds have passed. Your code, because it divides by 61, will "display" 1639.34 seconds (the clock runs fast).

Here's an idea... If you keep a second WORD sized tick counter incrementing in your ISR and when it hits 1754 you reset it to zero and skip updating your normal Ticks variable for that interrupt only. This way, in 100,000 interrupts you'll only increment your Ticks variable 100,000 - (100,000/1754) = 99943 times, resulting in "time" of 99943/61 = 1638.40 seconds - pretty darn close to ideal. The clock will zig-zag a little bit but the period is only about 28 seconds so I don't think you'll notice.

It's still early here, I may have made some terrible misstake in the math (doesn't have to be early for that). Anyway, it's an idea you may want to look into.

/Henrik.

fratello
- 25th January 2011, 16:40
I re-re-re-read all the topics on this forum (searching for "timer") and I found one code (Josepino's code) for HIGH-accuracy clock.
I try to compile them, but I have errors. What I do wrong ?

DEFINE NO_CLRWDT
Define OSC 4

DEFINE LCD_DREG PORTB ' LCD Data Port
DEFINE LCD_DBIT 4 ' Starting Data Bit
DEFINE LCD_RSREG PORTA ' Register Select Port
DEFINE LCD_RSBIT 1 ' Register Select Bit
DEFINE LCD_EREG PORTA ' Enable Port
DEFINE LCD_EBIT 0 ' Enable Bit
DEFINE LCD_BITS 4 ' Data Bus Size
DEFINE LCD_LINES 2 ' Number of Lines on LCD

DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50



TRISA= %11111000 ' RA0..3=Outputs RA4=Input
TRISB= %00001111 ' RB0..RB2=Inputs, RB3..RB7=Outputs

CMCON = 7

pushButton1 var portb.0 'switch
pushButton2 var portb.1
pushButton3 Var portb.2
pushButton4 Var portb.3

pressed con 0 ;value of button pressed
notPressed con 1 ;value of button not pressed

dhour var byte ' Define display hour variable

i var byte ' Debounce loop variable

ticks var byte ' Define pieces of seconds variable
Seconds var byte
Minutes var byte
Hours var byte
Days var byte
Months var BYTE

TempC var word
Float var word
Sign var bit ' +/- sign
DQ var PORTA.4 ' One-wire data pin
TempC2 var word
Float2 var word
Sign2 var bit ' +/- sign
DQ2 var PORTA.3 ' One-wire data pin
semn var word
semn2 var word
DS18B20_1 CON %01011111
DS18B20_2 CON %01011111


;DS18B20_9bit CON %00011111 ; 93.75ms, 0.5°C
;DS18B20_10bit CON %00111111 ; 187.5ms, 0.25°C
;DS18B20_11bit CON %01011111 ; 375ms, 0.125°C

SecondsChanged var bit
MinutesChanged var bit
HoursChanged var bit
DaysChanged var bit
SecondsChanged = 1
MinutesChanged = 1


Seconds = 0
Minutes = 0
Hours = 12
Days = 1
Months = 1
SecondsChanged = 1
MinutesChanged = 1
HoursChanged = 1
DaysChanged = 1



include "timp.pbp.txt"

Pause 200 ' Wait for LCD to Initialize

' Init Sensor 1
OWOUT DQ, 1, [$CC, $4E, 0, 0, DS18B20_1]
OWOut DQ, 1, [$CC, $48]
OWOut DQ, 1, [$CC, $B8]
OWOut DQ, 1, [$CC, $BE]
Pause 50
OWIn DQ, 2, [TempC.byte0, TempC.byte1]
Pause 50
' Init Sensor 2
OWOUT DQ2, 1, [$CC, $4E, 0, 0, DS18B20_2]
OWOut DQ2, 1, [$CC, $48]
OWOut DQ2, 1, [$CC, $B8]
OWOut DQ2, 1, [$CC, $BE]
Pause 50
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]
Pause 50


mainloop:
if tick.0=1 then
tick.0=0
Seconds = Seconds + 1
SecondsChanged = 1
if Seconds = 60 then
Minutes = Minutes + 1
MinutesChanged = 1
Seconds = 0
endif
if Minutes = 60 then
Hours = Hours + 1
HoursChanged = 1
Minutes = 0
endif
if Hours = 24 then
Days = Days + 1
DaysChanged = 1
Hours = 0
endif
if Days = 32 then
Months = Months + 1
Days = 1
endif
if months = 13 then
months = 1
endif
endif


' Check button pressed to set time
if pushbutton1 = pressed Then
gosub set_minutes
endif
if pushbutton2 = pressed then
gosub set_hours
endif
if pushbutton4 = pressed then
gosub set_days
endif
if pushbutton3 = pressed then
gosub set_Months
endif
' Check for time to update screen

If SecondsChanged = 1 Then
SecondsChanged = 0 ' Display time as hh:mm:ss
LCDout $FE, $80, dec2 Hours,":",dec2 Minutes,":",dec2 Seconds," ",DEC2 Days,"/",DEC2 Months
LCDOUT $FE, $C0, semn,DEC ABS TempC/100,".", DEC1 ABS TempC/10, 223,"C ", $FE, $C0 + 9, semn2,DEC ABS TempC2/100,".", DEC1 ABS TempC2/10, 223,"C "
' pauseus 1386
Endif

Goto mainloop ' Do it all forever



set_minutes:
Minutes = Minutes + 1
if Minutes = 60 then
Minutes = 0
endif
gosub debounce
return

set_hours:
Hours = Hours + 1
if Hours = 24 then
Hours = 0
endif
gosub debounce
return

set_days:
Days = Days + 1
if Days = 32 then
Days = 1
endif
gosub debounce
return

set_months:
Months = Months +1
if Months = 13 then
Months = 1
endif
gosub debounce
return
debounce:
For i = 1 To 100 ' Debounce and delay for 100ms
Pause 1 ' 1ms at a time so no interrupts are lost
Next i
SecondsChanged = 1
return

;================================================= ==
Read_Temp:
' Skip ROM search & do temp conversion
OWOut DQ, 1, [$CC, $BE]
OWIn DQ, 2, [TempC.byte0, TempC.byte1]

Sign = TempC.15
TempC = ABS(TempC)
TempC = ((TempC >> 4)*100) + ((TempC & $F)*100 >> 4)
IF Sign THEN TempC = -TempC
IF TempC.15 THEN
Semn="-"
else
Semn="+"
endif
OWOut DQ2, 1, [$CC, $BE]
OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]

Sign2 = TempC2.15
TempC2 = ABS(TempC2)
TempC2 = ((TempC2 >> 4)*100) + ((TempC2 & $F)*100 >> 4)
IF Sign2 THEN TempC2 = -TempC2
IF TempC2.15 THEN
Semn2="-"
else
Semn2="+"
endif
Return
;================================================= ==
End


and timp.pbp.txt

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, int_handler, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor

INT_ENABLE TMR0_INT ; Enable Timer 1 Interrupts
ENDASM
OPTION_REG = %00001000 ' Set TMR0 configuration
INTCON = %10100000 ' Enable TMR0 interrupts


bres_hi VAR BYTE bank0 system ' hi byte of our 24bit variable
bres_mid VAR BYTE bank0 system ' ; mid byte
bres_lo VAR BYTE bank0 system '; lo byte
'; (we only need 3 bytes for this system)
bres_hi = $0F
bres_mid= $42
bres_lo= $40
tick VAR BYTE bank0 system

ASM
;************************************************* *****************************
; INTERRUPT HANDLER (runs this code each timer0 interrupt)
;************************************************* *****************************
;
;------------------
int_handler ;
;------------------

;-------------------------------------------------



;-------------------------------------------------
; Note! we get here every 256 instructions, we
; can now do our special one second timing system.

; This consists of three main steps;
; * subtract 256 counts from our 24bit variable
; * test if we reached the setpoint
; * if so, add 1,000,000 counts to 24bit variable and generate event.
;-------------------------------------------------
; * optimised 24 bit subtract here
; This is done with the minimum instructions.
; We subtract 256 from the 24bit variable
; by just decrementing the mid byte.

tstf bres_mid ; first test for mid==0
skpnz ; nz = no underflow needed
decf bres_hi,f ; z, so is underflow, so dec the msb

decfsz bres_mid,f ; dec the mid byte (subtract 256)

; now the full 24bit optimised subtract is done!
; this is about 4 times faster than a "proper"
; 24bit subtract.

goto int_exit ; nz, so definitely not one second yet.
; in most cases the entire 'fake" int takes
; only 9 instructions.
;------------------------
; * test if we have reached one second.
; only gets here when mid==0, it MAY be one second.
; only gets to here 1 in every 256 times.
; (this is our best optimised test)
; it gets here when bres_mid ==0.

tstf bres_hi ; test hi for zero too
skpz ; z = both hi and mid are zero, is one second!
goto int_exit ; nz, so not one second yet.

;-------------------------------------------------
; Only gets to here if we have reached one second.

; now we can generate our one second event, like add
; one second to our clock or whatever.
; (in this example we toggle a led)

; The other thing we need to do is add 1,000,000 counts
; to our 24bit variable and start all over again.
;-------------------------------------------------
; Add the 1,000,000 counts first.
; One second = 1,000,000 = 0F 42 40 (in hex)

; As we know hi==0 and mid==0 this makes it very fast.
; This is an optimised 24bit add, because we can
; just load the top two bytes and only need to do
; a real add on the bottom byte. This is much quicker
; than a "proper" 24bit add.

movlw 0x0F ; get msb value
movwf bres_hi ; load in msb

movlw 0x42 ; get mid value
movwf bres_mid ; load in mid

movlw 0x40 ; lsb value to add
addwf bres_lo,f ; add it to the remainder already in lsb
skpnc ; nc = no overflow, so mid is still ok

incf bres_mid,f ; c, so lsb overflowed, so inc mid
; this is optimised and relies on mid being known
; and that mid won't overflow from one inc.

; that's it! Our optimised 24bit add is done,
; this is roughly twice as quick as a "proper"
; 24bit add.
;-------------------------
; now we do the "event" that we do every one second.

; Note! for this example we toggle a led, which
; will give a flashing led which is on for a second
; and off for a second.
; Add your own code here for your one second event.

; Note! My led is on porta,3
; your led may be on a different pin.
movlw b'00000001' ; mask for bit 3
xorwf tick,f ; toggle PORTA,bit3 (toggle the led)

;-------------------------------------------------
; now our one second event is all done, we can exit the
; interrupt handler.
;-------------------------------------------------
; finally we restore w and status registers.
; also clears TMRO int flag now we are finished.

int_exit
INT_RETURN
ENDASM

ScaleRobotics
- 25th January 2011, 17:09
I have not tested it, but me thinks:



INT_Handler TMR0_INT, int_handler, ASM, yes

is a NO NO.

Try using a unique name to name your handler.

fratello
- 25th January 2011, 17:50
Thanks for support ! I changed the name, but...

HenrikOlsson
- 25th January 2011, 18:51
Hi,
It compiles here. I renamed the interrupt handler to ISR (changed the label) and adjusted the DT-Ints declaration accordingly:

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, ISR, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE TMR0_INT ; Enable Timer 0 Interrupts
ENDASM

And

ASM
;************************************************* *****************************
; INTERRUPT HANDLER (runs this code each timer0 interrupt)
;************************************************* *****************************
;------------------
ISR
;------------------

I compiled it for a 16F628A for which I had to add

INCLUDE DT_Ints-14.bas
wsave VAR BYTE $70 SYSTEM
wsave1 VAR BYTE $A0 SYSTEM
wsave2 var BYTE $120 SYSTEM

Make sure your compiling "from" the main source file and not from within the timp.pbp.txt file.

/Henrik.

fratello
- 26th January 2011, 12:44
Thanks for support ! Yes, in this way I compiled the code. Unfortunately the result are so strange ...the display show random numbers - quickly changed, the errors messages are without end :(

fratello
- 27th January 2011, 15:08
OK, now the code for clock works fine now.
Let's return to my sheeps :) ...How can I put in "timp.pbp.txt" the code for reading the two DS18B20 ? The author say : "Add your own code here for your one second event". How can I make this ? I don't have a clue...

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_HANDLER TMR0_INT, PISR, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor

INT_ENABLE TMR0_INT ; Enable Timer 1 Interrupts

ENDASM


OPTION_REG = %00001000 ' Set TMR0 configuration
INTCON = %10100000 ' Enable TMR0 interrupts


bres_hi VAR BYTE bank0 system ' hi byte of our 24bit variable
bres_mid VAR BYTE bank0 system ; mid byte
bres_lo VAR BYTE bank0 system ; lo byte

bres_hi = $0F
bres_mid= $42
bres_lo= $40

tick VAR BYTE bank0 system

ASM
;************************************************* *****************************
; INTERRUPT HANDLER (runs this code each timer0 interrupt)
;************************************************* *****************************
;
;------------------
PISR ;
;------------------

tstf bres_mid ; first test for mid==0
skpnz ; nz = no underflow needed
decf bres_hi,f ; z, so is underflow, so dec the msb

decfsz bres_mid,f ; dec the mid byte (subtract 256)
goto int_exit ; nz, so definitely not one second yet.
;------------------------
tstf bres_hi ; test hi for zero too
skpz ; z = both hi and mid are zero, is one second!
goto int_exit ; nz, so not one second yet.
movlw 0x0F ; get msb value
movwf bres_hi ; load in msb

movlw 0x42 ; get mid value
movwf bres_mid ; load in mid

movlw 0x40 ; lsb value to add
addwf bres_lo,f ; add it to the remainder already in lsb
skpnc ; nc = no overflow, so mid is still ok

incf bres_mid,f ; c, so lsb overflowed, so inc mid
; now we do the "event" that we do every one second.

; Note! for this example we toggle a led, which
; will give a flashing led which is on for a second
; and off for a second.
; Add your own code here for your one second event

; Note! My led is on porta,3
; your led may be on a different pin.

movlw b'00000001' ; mask for bit 3
xorwf tick,f ; toggle PORTA,bit3 (toggle the led)

int_exit
INT_RETURN
ENDASM

fratello
- 3rd February 2011, 17:17
This is my solution. Maybe not correct, but...accuracy is VERY good !
I read the sensors (each) twice in a minute ; i add the timex variable, for increase 'the duration' of seconds when PIC read sensors, in step of 200 us. From various tests (many guys from one romanian electronics forum) , with 800 us the clock run correct !
Every advice it's wellcome !

if seconds=20 or seconds=50 then 'read first DS18B20
intcon.7=0
gosub temp_1
for i=1 to timpx
pauseus 200
next i
intcon.7=1
endif
if seconds=25 or seconds=55 then 'read second DS18B20
intcon.7=0
gosub temp_2
for i=1 to timpx
pauseus 200
next i
intcon.7=1
endif