Ik probeer nu een klok te maken voor m'n pic18f4550. Daarvoor heb ik een 32768Hz kristal aangesloten op Timer1.
Daaruit haal ik dan met Timer1 een stabiel 1Hz signaal. Maar het probleem is nu dat ik niet 1Hz bekom maar slechts _ongeveer_ de helft. Mijn klok loopt nu dus ongeveer aan halve snelheid.

Dit is de code die ik gebruik om de timer te initialiseren:



	INTCONbits.GIEL = 1;		//Global interrupt enable inschakelen
	INTCONbits.GIEH = 1;		//Global interrupt enable inschakelen
	INTCONbits.PEIE = 1;		//enable peripheral interrupts
	RCONbits.IPEN = 1;

	TMR1L = 0;
	TMR1H = 0x80;
	T1CON = 0b01001111;

	IPR1bits.TMR1IP = 1;  //Timer1 high interrupt
	PIE1bits.TMR1IE = 1;  
	PIR1bits.TMR1IF = 0;  //Timer1 interrupts mogelijk maken

En dit is mijn interrupt routine:


#pragma interrupt HighInterrupt
void HighInterrupt(void)
{
	//////////////////////////////////////////////////
	// TIMER 1		                                //
	//////////////////////////////////////////////////
	if (PIR1bits.TMR1IF == 1) // controlleren ofdat de interrupt van Timer1 komt
	{
		TMR1H = 0x80;
		PIR1bits.TMR1IF=0; //clear interrupt flag, om volgende interrupt terug mogelijk te maken

		time.s++;
		if (time.s >= 60) {time.s = 0; time.m++;};
		if (time.m >= 60) {time.m = 0; time.h++;};
	}
}

Wat doe ik verkeerd?

En ondertussen heb ik gevonden wat het probleem was. Blijkbaar moest de timer in 8-bit mode staan.
Maar nu loopt de tijd nog steeds niet heel perfect.
Nu loopt hij 1.0186 * de normale snelheid. En dat maakt toch al snel vele minuten fout per dag.
Iemand die ziet wat er foutloopt?

[Bericht gewijzigd door Memorex op (85%)]

Vind het op zich al vreemd dat de timer in 8-bits modus moet staan.. zou perfect moeten werken in 16-bits modus.

Nu goed, als die in 8-bits modus staat, vermoed ik dat het probleem in het volgende zit; heb je bij je reload waarde rekening gehouden met de overhead van je interrupt?

Dwz wanneer de interrupt getriggerd wordt wordt eerst de instructie die bezig was afgewert, dan de ISR aangeroepen, registers gesaved ed.

Vandaar dat je in 16-bit modus enkel de hoogste byte waarde aanpast, en de laagste byte onaangeroerd laat, zodat de timer blijft doortellen tijdens het aanroepen van de interrupt.

Het probleem is dat als Timer1 in 16-bit mode staat, dat de hoogste byte enkel wordt overgenomen bij het schrijven van de laagste byte. Dus de hoogste byte alleen updaten lukt niet.

En zou de tijd op de pic dan niet trager moeten gaan ipv sneller?

Zijn de condensators die je bij het kristal moet zetten eigelijk erg kritisch? Nu heb ik er 2x 20pF bijstaan.

Ik heb ongeveer hetzelfde probleem met een 16F636.

In de datasheet van de 18F4550(DS39632D-page131) worden condensatoren van 33pF gebruikt, met deze waarde loopt mijn 16F636 goed, en volgens mij zijn deze oscillatoren vergelijkbaar.

Ik kan nergens iets vinden over Timer1 in 8-bits mode, maar ga voorzichtig dit projectje weer eens afstoffen

[Bericht gewijzigd door Hunter op (17%)]

Zijn de condensators die je bij het kristal moet zetten eigelijk erg kritisch? Nu heb ik er 2x 20nF bijstaan.

Neem aan (hoop) dat dat een typfout is? Je bedoelt waarschijnlijk 20pF...
Datasheet adviseert 33pF of hoger. Hoger is stabieler, maar er is dan een langere start-up tijd nodig voor de oscillator. Ook afhankelijk van het kristal.

Op 27 februari 2009 03:02:31 schreef Arco:
[...]
Neem aan (hoop) dat dat een typfout is? Je bedoelt waarschijnlijk 20pF...
Datasheet adviseert 33pF of hoger. Hoger is stabieler, maar er is dan een langere start-up tijd nodig voor de oscillator. Ook afhankelijk van het kristal.

Inderdaad typfoutje. Nu staan er 20pF condensatoren erbij. Waarschijnlijk is dat dan ook de reden waarom m'n timer niet juist loopt.

Niet alle kristallen zijn even nauwkeurig wat betreft de opgegeven frequentie. Ik heb het met 2 verschillende 32768 getest en daar zat best verschil tussen. Je kunt in plaats van 1 van de condensatoren een trimmertje proberen.
Een manier om de instructies tijdens de interrupt te negeren is aan het begin van de interrupt de timer uit te zetten en aan het eind weer aan te zetten. Verder kun je experimenteren door aan het eind van de interrupt de timerregisters te "preloaden".
Uiteindelijk kwam ik uit op een onnauwkeurigheid van 1 seconde per 3 dagen. Good enough for me.

Meeste tuning-fork kristallen hebben een afwijking van max. 10 of 20 ppm. Dat is zo'n 0.85 / 1.70 seconde per dag...

Of, als je echt leuke/goede precisie wilt kan je zo iets nemen:

http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2940

Ik heb er drie van, nog niet getest.

Ondertussen de condensatortjes vervangen door 47pF die ik had liggen. De tijd loopt nu al veel corrector. Ik heb het nu enkele uurtjes laten draaien en de tijd op de pic gaat nu 0.00015 * de werkelijke tijd.
Misschien kan het nog precieser door 33pF te nemen?

Op 26 februari 2009 22:23:34 schreef Memorex:
Het probleem is dat als Timer1 in 16-bit mode staat, dat de hoogste byte enkel wordt overgenomen bij het schrijven van de laagste byte. Dus de hoogste byte alleen updaten lukt niet.

Misverstand mijnentwege.

Timer1 is altijd een 16-bits timer, maar je kan deze in 16 bits read/write modus zetten.

In dat geval klopt het dat je hoge byte pas geschreven wordt bij het schrijven van de lage byte, en is idd niet gewenst.

Waar ik op doelde was dat je enkel de TMR1H waarde gaat invullen (dus in dit geval 0x80) en de TMR1L op de waarde laat die ie heeft, hij overflowt, geeft een interrupt, maar blijft wel doortellen.

In de datasheet, pg.135, example12-1. Hier wordt zelfs gebruik gemaakt van een BSF ipv movlw en movwf 0x80 om de delay nog korter te houden.