PIC16F870 vill inte snurra ordentligt efter sleep.

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

PIC16F870 vill inte snurra ordentligt efter sleep.

Inlägg av StRob »

Jag har skrivit ett program för en 16F870. Programmet tar emot ett meddelande på UARTen, kontrollerar meddelandet och räknar ut hur länge den ska ligga i sleep beroende på vad som står i meddelandet. tiden är upp till 2 timmar vilket jag realiserar genom att använda en 32kHz osc till TIMER1. Timeravbrotten väcker µP var 10:e sekund och räknar upp variabeln delay. Allt fungerar bra hit. MEN till problemet:
När delay räknats ned och programmet ska gå ur loopen så väntar den på att ett nytt meddelande tas emot på UARTen men när den gått ur sleep så hinner den bara sätta en utgång hög sen lägger den sig i sleep igen. Det borde enligt mej vara helt omöjligt, men icke! Klipper in Sleep-rutinen och relevanta delar av avbrottsrutinen:

Kod: Markera allt

void PWRDown(void)
{
	byte temp, CCP1Temp, PIETemp, CCPTempH, CCPTempL, a, b;

	PIETemp = PIE1;
	temp = T1CON;
	CCP1Temp = CCP1CON;
	T1OSCEN = 1;				//Starta 32kHz-osc. 
	ms = 103;					//OSC-start up delay
RC2 = !RC2;
	while(ms>1);
RC2 = !RC2;
	TMR1L = TIOSEKL;
	TMR1H = TIOSEKH;
	CCP1CON = 0x00;
	T1CON = 0b00111111;			//Prescaler = 1/8, enable ext osc, ej synk, T1 på EXTERN osc, TMR1ON = ON. 
	Sleep = 1;					//Sleepflagga.
	PIE1 = 0x00000001;			//Endast TIMER1 Overflow Interrupt Enable.

	a = 0x35 - CommandBuff[16];		//50 - Min10.
	a *= 10;
	b = 0x3A - CommandBuff[17];		//10 - Min1.
	a += b;							//a = Minuter i decimalform.
	delay = 0;
	delay = (uns16)a * 6;					//antal minutrar uttryckt i 10-sekunders enheter.	
	delay -= 42;					//dra ifrån 7 min för DCF och offset.
//	if(!(CommandBuff[15] & 0b00000001))	//Om jämn timma, lägg till en timma sleep.
//		delay += 360;

//	delay = 3;		//TEST TEST TEST TEST TEST TEST TEST!????????????????????????????????????????????
	PORTB = 0x00;	
RC3 = !RC3;			//TEST TEST TEST TEST TEST TEST TEST!????????????????????????????????????????????
	while(delay >= 1)				//Ligg i Sleep tills nästa jämna timmomslag.
	{
		sleep();					//God natt..
		nop();						//Denna rad exekveras ALLTID vid wake up, SEN avbrottet.
	}
RC3 = !RC3;			//TEST TEST TEST TEST TEST TEST TEST!????????????????????????????????????????????
	Sleep = 0;						//Nolla Sleep-flaggan.
	CCP1CON = CCP1Temp;				
	T1CON = temp;
	PIR1 = 0b00000000;
	PIE1 = PIETemp;
	DCF = 0;		//TEST TEST TEST TEST TEST TEST TEST!????????????????????????????????????????????
}
Avbrottsrutinen:

Kod: Markera allt

//SLEEP-RÄKNAREN

	}
	if(Sleep)
	{
		TMR1L = TIOSEKL;		//Ladda om TIMER1 för 10sek-avbrott.
		TMR1H = TIOSEKH;	
		if(delay == 0)
			return;
		delay--;				//TEST TEST TEST TEST!!!!!!!!!!  10 sekunder !!!!!!!!!!!!!!!!!!!!!
		DCF = !DCF;				
	}
	TMR1IF = 0;
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Inlägg av v-g »

Verkar vara skrivet i något konstigt språk :wink:

Efter du gått ur avbrottsrutinen kanske du skulle stoppa timern och se till så att alla vilkor inom själva "main" loopen inte kan uppfyllas direkt IGEN efter att den just vaknat från sleep. Är dock inte 100% då jag icke kodar i annat än .ASM
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

Ja det är skrivet i det konstiga språket C. ;)
Jag nollställer ju flaggorna men jag ska prova att stoppa timern innan jag drar igång den med 8MHz-oscillatorn (Fosc/4) igen..
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Den sista gången som avbrottsrutinen körs så hoppar du ur med hjälp av en "return" och den sista raden "TMR1IF = 0;" körs då inte... kan det ha något med saken att göra?
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

Oj! vad tänkte jag med där!? "return" är nog inte att rekommendera över huvud taget i avbrottsrutinen.. :oops:
Det verkar fungera nu. Tack! :D
Senast redigerad av StRob 15 maj 2007, 16:23:21, redigerad totalt 1 gång.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

DEFINITIVT INGEN "return" I ISR!!!!
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

Nä, ja vet. Flåt, ska inte hända igen. :wink:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Nä, det är ju kanske bra, men löste det problemet ??
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

sodjan skrev:Nä, det är ju kanske bra, men löste det problemet ??
Som jag sa: Det verkar fungera nu.
En hårdtest tar flera timmar ioma den ska ligga i sleep och vakna varje jämn timma. Men om jag "fuskar" och skriver t.ex "delay = 3;" innan den går in i while-loopen för sleep så fungerar det. Problemet är bara att det gjorde det IBLAND förut också, det betedde sig som sagt skumt. Men det slutgiltiga svaret kommer i morgon. patience my friend.. :wink:
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Såja Icecap, inte skrika! :ajabaja:

För att att göra din testprocedur cirka åtta gånger snabbare så kan du ju låta bli att sätta prescaler=8 för din 32kHz-kristall.
Eller så skalar du ner TIOSEKL/H med faktor x...
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

Men då behöver jag trimma mitt ur som skickar ut tiden också, för det är hela idén att den ska vakna på just urets jämna timmar, vilket jag sett att den inte gör som den ska. Och mätningen blev apa, logikanalysatorn avbröts efter en halvtimma. Har kanske missat att ställa in att den ska packa mätvärdena. Ska titta på det nu.. Men tackar så mkt för tipsen!
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

Nu fungerar det utmärkt! Den vaknar så fint ur sleep och tar emot meddelanden och behandlar dem som väntat. Tack för hjälpen!
Skriv svar