Går inte att "nolla" avbrottsflaggor

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

Går inte att "nolla" avbrottsflaggor

Inlägg av StRob »

Det gäller en PIC16F870 som snurrar med en ICD2 i MPLAB med C-kompilatorn CC5X. Programmet startar TIMER1 och väntar på OF-avbrott samt incapture på CCP1 från signal utifrån. Jag har valt rätt device och configurationbitsen ska vara satta som sig bör.

i main() ligger jag i en evighetsloop och väntar på avbrott och de kommer men jag kan inte släcka avbrottsflaggorna, varken för TMR1IF eller CCP1IF. Jag har även provat att skriva direkt till hela PIR1 men ingen skillnad. Vad kan det vara för fel??
MVH Robert

Kod: Markera allt

#pragma origin 4
extern interrupt isr (void)
{
	clrwdt();
	char save_FSR;
	int_save_registers		//Spara viktiga register
	save_FSR = FSR;

	byte i, a;			//ändrat från char till byte (byte = unsigned char).

	if(TMR1IF)
	{
		TMR1IF = 0;
		overflow = ++overflow;
		if(overflow > 100)
		{
			main();				//Starta om
		}
	}

	if(CCP1IF)
	{
		PIR1 = (0b11111011 & PIR1);
		tidh[period] = CCPR1H;	//Spara räknarens höga register.
		tidl[period] = CCPR1L;	//Spara räknarens låga register.
		uti = 1;				//Flagga för UTI-avbrott.
		CCP1IF = 0;				//Viktig! Annars kan avbrott ligga och vänta och genereras osynkront med flanken.
	}

	FSR = save_FSR;
	int_restore_registers	//Hämta sparade register
}
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Re: Går inte att "nolla" avbrottsflaggor

Inlägg av björn »

Säkert inte svar på ditt problem men....
StRob skrev:

Kod: Markera allt


	int_save_registers		//Spara viktiga register
	
	int_restore_registers	//Hämta sparade register
}
Vad är detta? Är det något som finns med i kompilatorn? är det rop efter en funktion så har du glömt "()".

EDIT: Funktion istället för rutin
Senast redigerad av björn 31 maj 2007, 17:08:55, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Jag vet inte vad din kompilator accepter, men normnalt skriver man väl
PIR1.TMR1IF = 0.

Dssutom, hur *vet* du att de inte nollas ??

> clrwdt();

Stäng av WDT istället !

Är det inte lite konstigt at anropa main() inne från ISR'en ?
Hur blir det med stacken o.s.v ?
henkebenke
Inlägg: 521
Blev medlem: 31 maj 2003, 10:42:37
Ort: Helsingborg

Inlägg av henkebenke »

> overflow = ++overflow;

Detta är lite onödigt, (++)-operatorn ökar själva variabeln. Och att anropa main() kan nog inte bli annat än fel. Vill du starta om så får du göra en reset istället.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Vill du starta om

Det intressanta är *vad* StRob *igentligen* vill göra.
Min *gissning* är att vissa initieringar ska köras om...

Oavsett det är det i alla lägen fel att anropa main() från en ISR.
ISR'en kan/ska sätta någon flagga och sedan får main() se till att
applikationen kör om lämpliga delar.

Notera också att PIC18 serien har en RESET instruktion som fungerar
på samma sätt som en hårdvaru-reset. *Den* kan köras var
som helst, även från en ISR...
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Re: Går inte att "nolla" avbrottsflaggor

Inlägg av StRob »

björn skrev:Säkert inte svar på ditt problem men....
StRob skrev:

Kod: Markera allt


	int_save_registers		//Spara viktiga register
	
	int_restore_registers	//Hämta sparade register
}
Vad är detta? Är det något som finns med i kompilatorn? är det rop efter en funktion så har du glömt "()".

EDIT: Funktion istället för rutin
Det är nåt kompilatorn har om man har med en include-fil som heter INT16CXX.h.
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

sodjan skrev:Jag vet inte vad din kompilator accepter, men normnalt skriver man väl
PIR1.TMR1IF = 0.

Dssutom, hur *vet* du att de inte nollas ??

> clrwdt();

Stäng av WDT istället !

Är det inte lite konstigt at anropa main() inne från ISR'en ?
Hur blir det med stacken o.s.v ?
Att skriva TMR1IF = 0 brukar fungera utmärkt, annars borde kompilatorn dessutom klaga på att variabeln inte är deklarerad om det inte accepteras.
Jag "vet" att de inte nollas denom att jag stegar mig igenom programmet med debuggern och tittar på de aktuella registerna.
Jag har stängt av WD, det är bara en grej som ligger kvar från min felsökning.
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

henkebenke skrev:> overflow = ++overflow;

Detta är lite onödigt, (++)-operatorn ökar själva variabeln. Och att anropa main() kan nog inte bli annat än fel. Vill du starta om så får du göra en reset istället.
Hur gör man en reset? Kan man hoppa till resetvektorn på något sätt? Hur skriver man?
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

sodjan skrev:> Vill du starta om

Det intressanta är *vad* StRob *igentligen* vill göra.
Min *gissning* är att vissa initieringar ska köras om...

Oavsett det är det i alla lägen fel att anropa main() från en ISR.
ISR'en kan/ska sätta någon flagga och sedan får main() se till att
applikationen kör om lämpliga delar.

Notera också att PIC18 serien har en RESET instruktion som fungerar
på samma sätt som en hårdvaru-reset. *Den* kan köras var
som helst, även från en ISR...
Blir overflow > än 100 så har mitt program fastnat i en loop den inte ska fastna i och då vill jag starta om programmet. Jag skulle vilja göra en reset. initiera om processorn och starta om från början.

Att hoppa till main från ISR är givetvis helt galet! Det är en gammal grej som ligger kvar som jag missat :oops: Men det har tyvär inte med problemet att göra..
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Jag "vet" att de inte nollas denom att jag stegar mig igenom
> programmet med debuggern och tittar på de aktuella registerna.

Jag vet inte hur din debugger jobbar, men du är säker på att timern
inte går i bakgrunden ? Den har ju i sig inget med "instruktionerna"
att göra...

Vad menar du med "instruktioner" förresten ? C eller asm ?

> det är bara en grej som ligger kvar från min felsökning....

OK, men problemet är att det gör att man inte litar på att du har kollat
övrig kod bättre heller. Se till att koden är rensad från skräp innan
du postar den, om inte så för att undvika denna typ av diskussion... :-)
Hur ska *vi* veta vad du bara har lämnat kvar p.g.a slarv och vad
som faktiskt *ska* vara med ?

> Hur gör man en reset?

Är det verkligern en "hard reset" du vill göra ?
Vill du inte veta vad som har hänt också ?

> Kan man hoppa till resetvektorn på något sätt?
> Hur skriver man?

GOTO h'0000'
(På PIC18 serien kommandot RESET)

Men notera att det inte är detsamma som att cycla MCLR ner/upp !
Bl.a så *kan* stacken vara i fel läge om detta görs från fel ställe i koden.

> initiera om processorn och starta om från början.

Ja, men det är en helt annan sak!
Och det skrev jag i ett tidigare inlägg :

> ISR'en kan/ska sätta någon flagga och sedan får main() se till att
> applikationen kör om lämpliga delar.

I princip bara att anropa samma rutiner/funktioner
som vid en "vanlig" reset.
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

> ISR'en kan/ska sätta någon flagga och sedan får main() se till att
> applikationen kör om lämpliga delar.
Problemet är att när overflow > 100 så har jag som sagt fastnat i en loop där jag ligger och väntar på flanker från en mätkanal som jag MUXar in och då har det blivit fel i multiplexeringen. Detta gör att jag inte kan kolla någon flagga på något bra sätt. då måste jag kolla den på massa ställen nämligen. Om jag på något smidigt sätt bara kunde starta om programmet från början i avbrottet vore det bättre.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

När "felet" upptäcks (var det än sker) sätts en flagga.
Denna flagga kollas på *ett* ställe i main-loopen och du gör
vad som måste göras för att "starta om".
Varför ska den kollas på en massa ställen ?

Om detta inte fungerar så har du större problem med din
applikation än vad du tror... :-) :-)
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

Jag får strukturera om programmet lite så går det att göra så.. Det jag menar är att hjag ligger i en av flera loopar liknande:
while(flanker < 5)
{
//så ligger den här tills den fått 5 flanker, SEN återgår den till main.
}
då hjälper det inte att kolla flagga i main för den kommer inte dit om flankerna uteblir.. Men jag ska strukturera om programmet lite så kommer det gå bra.. Det här är det första PIC-programmet jag gjort och det var ett halvår sedan jag skrev på det och jag har lärt mig lite sedan dess iaf. Men upplägget på det är för att uttrycka det på ren svenska, helt åt helvete ;)

Men en annan fråga: Visst ska man väl alltid kunna se interruptflaggornas statur i debuggern när ma nanvänder ICD2 ("pucken")? Jag är 99% säker på att jag alltid gjort det förut i andra program jag skrivit.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Bara så att vi är helt överens:
Dessa "while(flanker < 5){}" ligger självklart i main och INTE i en ISR eller hur? Om du har lagt dom i en ISR förstår jag definitivt varför du får problem....

(ISR = Interrupt Service Routine)
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Inlägg av StRob »

De ligger inte i ISRen och inte i main. den ligger i en rutin som anropas från main:

Kod: Markera allt

void main (void)
{
GIE = 0;
GIE = 0;
vFirstInit();			//Initiera µP
UARTinit();				//Initiera UART
timer1init();			//Initiera Timer1


RC4 = 1;
PORTB = 0b00000001;		//Börjar med mätkanal 0.		
delay(10);
RC4 = 0;
INTCON = 0b11000000;	//Enabla interrupt.
TMR1ON = 1;				//Starta timer1
	while(1)				//Evighetsloop. Ligger och väntar på avbrott.
	{
		if(uti)
		{
			uti = 0;
			berakna();
		}
	}
}
Skriv svar