Realtids klocka?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
SweLogan
Inlägg: 550
Blev medlem: 29 januari 2006, 23:36:15
Ort: Jönköping

Realtids klocka?

Inlägg av SweLogan »

Hej, undrar hur man ska bygga en klocka som håller tiden. Byggde en idag.
typ sek = sek + 1 osv sedan hade jag en pause 1000. Men efter några minuter så började klockan gå fel med någon sek. Jag har mina aningar varför, om porgrammet tar 1 hundradel så måste man ju ha en pause på 999. Men i vilket fall hur gör man detta smidigast?
Användarvisningsbild
Icecap
Inlägg: 26736
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Man börjar med en stabil oscillator. Dallas har DS32KHZ om man vill vara noga men mindre kan göra det.

Sen ställer man en timer till att ge avbrott med lämpligt intervall, baserat på den klocka.

Dessa avbrott lyftar egentligen bara en flagga och en huvudrutin räknar upp den egentliga räkningen. Jag hade gjort så att timer-interrupten ville inkrementa en variabel och när den variabel överstiger ett visst värde kommer main-rutinen att reagerar på det, räkna upp tiden och subtrahera det "viss värde" från variablen.

Kod: Markera allt

Pseudokod:
Flagga: 1 byte
Timme: 1 byte
Minut: 1 byte
Sekund: 1 byte

#define Value 10

interrupt-rutin:
  Flagga = Flagga + 1;
return-from-interrupt

main:
  Kör Initialiserings-rutin;
Loop-Evigt:
  if(Flagga >= Value)
    {
    Flagga = Flagga - Value;
    Sekund = Sekund + 1;
    if(Sekund > 59)
      {
      Sekund = 0;
      Minut = Minut + 1;
      if(Minut > 59)
        {
        Minut = 0;
        Hour = Hour + 1:
        if(Hour > 23) Hour = 0;
        }
      }
    }
goto Loop-Evigt

Initialiserings-rutin:
Ställ timer till att ge 'Value' interrupts/sek
Såklart kan man även koppla in en RTC-krets men den biten kan du nog själv klura ut.
sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> pause 1000...

Det fungerar inte i MPASM, så du kanska ska tala om vad det är du kör i.

Vad betyder "hålla tiden" för dig ?

Sen, som Icecap redan har förklarat, så fungerar det aldrig att göra så där...

*Timers* är vad du ska läsa på om i databladet.
Det är normalt inget större problem att få en "klocka" som har i alla fall
lika stort "fel" som kristallen (eller hur nu processorn körs).
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Här är ett exempel på en sekund-räknare som använder 4Mhz kristallen som bas utan att använda interrupt.
Otestad Pseudokod skriven av en trött Chribbe:

Kod: Markera allt


Dim TimerTmp as Word
Dim TimerOld as Word
Dim TimerDiff as Word
Dim TimerTot as 24bitars signed
Dim TidBasen as 24bitars signed eller unsigned (kan vara en konstant)
;TMR1 har 16bitar och ska initieras för att räkna cycler
TidBasen=1000000 (antal steg som TMR1 räknar per sekund)


Denna rutin ska anropas så ofta som möjligt, minst 30gånger/sekund.

	TimerTmp=TMR1
	TimerDiff=TimerTmp-TimerOld	;denna beräkning måste kunna "slå runt"
	TimerTot=TimerTot-TimerDiff
	TimerOld=TimerTmp

	if TimerTot<0 then
		TimerTot=TimerTot+TidBasen
		Sekund=Sekund+1
	endif
Om man inte kan ha 24-bitars variabler går det bra med 32bitars.
Har man inte tillgång till en 16-bitars timer går det bra med 8bitars timer och valfri prescaler men programmeringen blir inte lika enkel.
Om man inte kan använda 24/32bitars tal i ditt programspråk så är det dags att byta språk.
Användarvisningsbild
bengt-re
EF Sponsor
Inlägg: 4829
Blev medlem: 4 april 2005, 16:18:59
Skype: bengt-re
Ort: Söder om söder
Kontakt:

Inlägg av bengt-re »

Assamber använder 8-bitar och det räcker för det mesta. Det går att göra allt ändå...

Och varför inte inte använda timerinterupt? I 80% av alla program så kan man göra det utan problem. Och i de fall man inte kan det på grund av att man vekligen behöver us timing i sin huvudloop och man ändå behöver en klocka så är det väl lika bra att använda en RTC? Du kan bygga en egen RTC med en PIC10f629 - kör den med INTOSC för programmet och sätt dit en klockkristall (32kHz) som osc till TIMER1. Skriv sedan en egen RTC i programmet. Lite onödigt eftersom det finns billiga färdiga RTC, men en 12F629 är också billlig och ger dig friheten att designa din rtc som du vill ha den.
sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Chribbes kod skulle jag inte vilja ha i en större applikation.
Hur ska man garantera att det anropas "minst 30 gånger/sekund"
på ett snyggt/praktiskt sätt utan att använda timer-interrupt ?
Och med 24/32 bitars signed beräkningar blir det lite onödigt
mycket beräkningar "minst 30 gånger/sekund". Dessutom håller
den bara reda på hela sekunder, min/tim/osv beräkningen tillkommer
utöver koden i exemplet Normalt har man 8-bitars register som
håller reda på sek/min/timmar/o.s.v och justerar alla register i RTC-
rutinen.

Men, så snart man kommer upp på datumhantering så är nog en
separat RTC krets att föredra där men får hantering av t.ex veckodagar,
månadernas längd och skottår "på köpet" så att säga...
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Vad du vill bryr iaf inte jag mig om.
Alla mina projekt har alltid haft en Mainloop som sysslar med lite av varje och har aldrig varit långsammare än 100 varv/sekund.
Jag använder interrupt till det som är absolut tidskritiskt och vill inte ha fler interruptkällor än nödvändigt för då fördröjer man viktiga processer.

Visst ser koden lite klumpig ut men i assembler(om man modifierar metoden lite) blir det riktigt bra.
Jag läser bara höga delen av TMR1 så låga delen agerar bara prescaler.
Otestad kod ihopsläng på några minuter.

Kod: Markera allt

;TimerTotL,TimerTotH,TimerTotU är ett 24bitars tal
;TidBasenL,TidBasenH,TidBasenU är en 24bitars konstant

	movf	TMR1H,w
	movwf	TimerTmp

	movf	TimerOld,w
	subwf	TimerTmp,w
	movwf	TimerDiff

	movf	TimerTmp,w
	movwf	TimerOld

	movf	TimerDiff,w
	subwf	TimerTotH
	btfss	STATUS,C
	decf	TimerTotU

	btfss	TimerTotU,7
	goto	InteMinus

	movf	TidBasenL,w
	addwf	TimerTotL
	movf	TidBasenH,w
	btfsc	STATUS,C
	incfsz	TidBasenH,w
	addwf	TimerTotH
	movf	TidBasenU,w
	btfsc	STATUS,C
	incfsz	TidBasenU,w
	addwf	TimerTotU 

	incf	Sekund
InteMinus:


sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Jag använder interrupt till det som är absolut tidskritiskt

OK, det är ett sätt att se på det.

Andra använder interrupt som ett verktyg för att få välstrukturerad kod
som är lätt att underhålla. Man slipper till stor del snårig kod i main.
D.v.s att man använder interrupt till allt där det *går* att använda
interrupt för att t.ex slippa pollning eller liknande i main.

> ...inte ha fler interruptkällor än nödvändigt för då fördröjer man viktiga processer.

Om man har några "viktiga processer" som inte får avbrytas så är det
enkelt att tillfälligt stänga av interrupt.

Olika designfilosofier bara... :-)
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Jag skulle kunna sluta här men jag vill ändå säga......

Jag tycker inte att några call (där varje rutin pollar om vad som ska hända) i main är snårig kod.
Det är lika snårigt med en interrupt-rutin som måste göra många tester för att styra programmet till rätt ställe.

"Om man har några "viktiga processer" som inte får avbrytas så är det
enkelt att tillfälligt stänga av interrupt. "

Jag menar att viktiga interrupt kan stå väntande för att ett mindre viktigt interrupt har "lagt beslag på execveringen", det är svårt att lösa genom att stänga av interrupt.

Finns den någon annan designfilosofi än maximal prestanda?! 8) :wink:
sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Jag skulle kunna sluta här

Detsamma, men... :-)

> Finns den någon annan designfilosofi än maximal prestanda?!

*Rätt* prestanda kanske ?
Eller *tillräcklig* prestanda ?
Och "prestanda" är sällan den *enda* designparametern...
Skriv svar