Sida 1 av 1

Interrupt som bråkar

Postat: 20 juli 2005, 23:19:40
av Nannou
Tjenare.

Har inte stött på detta tidigare, och kan inte komma på något jag gjort annorlunda innan. Det hela gäller en 16F877A@20MHz. När ett interrupt kommer så går den igenom och exekverar alla interrupt.

Kod: Markera allt

void interrupt received(void)
{
	GIE=0;
	PEIE=0;
	
	if(RCIF) //mottaget meddelande på uart
	{
		RCIF = 0;
		
		recived_byte=RCREG;
		
		//blablabla
				
		if(OERR==1) 
		{
			CREN=0;
			CREN=1;
		}
	}
	
	if(CCP1IF)
	{
		CCP1IF = 0;

		//blablabla
								
		CCPR1L+=0xFF; //påhittat tal
		if(CARRY)
			CCPR1H++;
		CCPR1H+=0xFF;
	}
	
	if(CCP2IF)
	{
		CCP2IF = 0;

	   	CCPR2L+=0xFF;
		if(CARRY)
			CCPR2H++;
	   	CCPR2H+=0xFF;
	}	
	
	GIE=1;
	PEIE=1;
}
Timer1 är på och CCP-enheterna är konfigurerade enligt

CCP1CON=0x0A;
CCP1IE=0;
CCP2CON=0x0A;
CCP2IE=0;

Men varje gång det kommer in något på UART så går den även igenom koden för CCP1IF och CCP2IF. :shock: Jag är helt förbluffad, vad kan vara fel?

Postat: 21 juli 2005, 01:27:02
av sodjan
Nu är det här skrivet i C (och du har inte ens orkat ange *vilken* C...), men i alla fall...

GIE sets = 0 automatiskt av processorn när ett interrupt inträffar. Var för gör du det i koden också ? Måste man det i C ??

GIE sets = 1 automatiskt av processorn när när processorn exekverat en RETFIE instruktion (vilken den borde göra även om man skriver i C).

I assembler manipulerar man inte GIE från koden, processorn/RETFIE sköter om det.

För övrigt, utan att veta vad resten av koden gör, så får man väll helt enkelt anta att CCP1IF och CCP2IF är = 1 varje gång som det kommer in något på uarten...

Prova att sätta CCP1IE och CCP2IE = 0, och ändra till :

if (CCP1IF <and> CCP1IE) och
if (CCP2IF <and> CCP2IE) på respektive ställe.

(Jag vet inte hur <and> kodas...)

Då skall den inte köra de två blocken alls oavsett vad som händer med CCP modulerna...

Postat: 21 juli 2005, 10:29:39
av Nannou
sodjan skrev:Nu är det här skrivet i C (och du har inte ens orkat ange *vilken* C...), men i alla fall...

GIE sets = 0 automatiskt av processorn när ett interrupt inträffar. Var för gör du det i koden också ? Måste man det i C ??

GIE sets = 1 automatiskt av processorn när när processorn exekverat en RETFIE instruktion (vilken den borde göra även om man skriver i C).

I assembler manipulerar man inte GIE från koden, processorn/RETFIE sköter om det.

För övrigt, utan att veta vad resten av koden gör, så får man väll helt enkelt anta att CCP1IF och CCP2IF är = 1 varje gång som det kommer in något på uarten...

Prova att sätta CCP1IE och CCP2IE = 0, och ändra till :

if (CCP1IF <and> CCP1IE) och
if (CCP2IF <and> CCP2IE) på respektive ställe.

(Jag vet inte hur <and> kodas...)

Då skall den inte köra de två blocken alls oavsett vad som händer med CCP modulerna...
Ursäkta, glömde bort mig lite. Det hela gäller Hi-tech's PICC compiler. Anledningen att jag satt GIE=0 vid interrupt är att föreläsaren brukade göra det när jag läste Inbyggdasystem i skolan :) Visste inte att den skötte det automatiskt.

Förstår bara inte hur CCPxIF kan sättas när CCPxIE=0..

Postat: 21 juli 2005, 13:05:58
av sodjan
> "Anledningen att jag satt GIE=0 vid interrupt är att föreläsaren brukade göra det när jag läste Inbyggdasystem i skolan. Visste inte att den skötte det automatiskt."

Det förstår jag inte alls, det är hur tydligt som helst på sidan 151 i databladet (DS39582A, det kan finnas en senare och då kan sidnumret vara ett annat...) Vad var det som var otydligt där ?? Har du *läst* delen om interrupt i data bladet ??

> "Förstår bara inte hur CCPxIF kan sättas när CCPxIE=0.."

Varför inte ? Var i data bladet står det att den *inte* skulle göra det ???

Har du överhuvudtaget läst data bladet ?

xxxIF flaggorna sätts så snart "något" (beroende på vilken flagga det är) har inträffat, xxxIE flaggorna hindrar bara att ett interrupt sker, de hindrar inte xxxIF flaggorna att sättas. Och om man har flera iterrupt käller, så måste man ta hänsyn till detta i sin ISR, så som jag visade...

Men som sagt, allt detta står naturligtsvis i data bladet...

Postat: 22 juli 2005, 18:56:51
av Nannou
Ah, funkar nu. Tack för hjälpen. Alltid kul att bemötas med sån professionell vänlighet här.

Postat: 22 juli 2005, 19:07:00
av sodjan
Och vad var problemet ?

Postat: 22 juli 2005, 19:18:58
av Nannou
Som du skrev, hade missat att flaggan sattes även när interruptet var avstängt.

Postat: 22 juli 2005, 20:04:25
av sodjan
OK.

Du har alltså clearat CCP1IE och CCP2IE, men det inträffar i alla fall något som får CCP1IF och CCP2IF att sättas. Det är väll helt OK i sig.

Men, när tar du hand om CCP interrupten ?
Sätter du CCP1IE/CCP2IE = 1 vid ett senare tillfälle ?

Notera att man, om man inte är försiktig när man hanterar IE flaggorna, lätt kan missa ett interrupt om man har IE flaggan = 0 för länge (d.v.s längre än tiden mellan två händelser som får en IF flagga att sättas).

Eller kanske att du inte bryr dig om interrupten från CCP1/CCP2 alls ?

Postat: 22 juli 2005, 20:20:05
av Nannou
sodjan skrev:OK.

Du har alltså clearat CCP1IE och CCP2IE, men det inträffar i alla fall något som får CCP1IF och CCP2IF att sättas. Det är väll helt OK i sig.

Men, när tar du hand om CCP interrupten ?
Sätter du CCP1IE/CCP2IE = 1 vid ett senare tillfälle ?

Notera att man, om man inte är försiktig när man hanterar IE flaggorna, lätt kan missa ett interrupt om man har IE flaggan = 0 för länge (d.v.s längre än tiden mellan två händelser som får en IF flagga att sättas).

Eller kanske att du inte bryr dig om interrupten från CCP1/CCP2 alls ?
CCP1 och CCP2 skall vara på/av beroende på vad som kommer in på UART. Det hela är början på en liten synth där CCP1 har hand om att slå om två gånger per period och togglar en utgång då det kommer in note_on via MIDI på UART. Och skapar en mysig fyrkantsvåg :) Och CCP2 har hand om lite andra saker som arpeggio och envelopes.

Postat: 22 juli 2005, 22:52:39
av Icecap
Man citerar inte inlägget strax innan i detta forum, läs reglerna!

Postat: 22 juli 2005, 23:09:06
av sodjan
Hm, och du sätter CCP1-2 av/på genom CCPxIE ?

Glöm inte bara att cleara CCPxIF innan du sätter CCPxIE !

Om du inte *vill* att de eventuella latenta interrupten skall fyras av direkt, vill säga...