meerdere interrupt sources in een programma PIC16F877

Voor mijn maaksel zou in een interrupt moeten kunnen genereren op het binnen komen van data via usart
en ook een interrupt tot het maken van een timer van 10ms

het eerste lukt perfect via interrupt, maar kan ik dat combineren met een tweede ineterrupt source, bijvoorbeeld deze van TIMER0 voor het maken van een 10ms timer

ik programmeer in JAL maar stukken ASM lukt ook wel

Geen idee waar je het momenteel over hebt Sp3ci3S maar in het algemeen kan ik zeggen dat interrupts, in wat voor processor dan ook, een priority hebben. Deze priority bepaalt welke interrupt eerst wordt afgehandeld. Met de uC's (die ik ken) heeft de timer meestal de laagste priority. Een interrupt van 1 van de poorten van je uC (normaal de hoogste priority) wordt eerst afgehandeld. Andere, lagere interrupts worden, als die mogelijkheid enabled is, tijdelijk opgeslagen en pas uitgevoerd wanneer de hogere interrupt z'n routine heeft afgemaakt.

Hoe bedoel je het precies?

Wil je 2 losse interrupts? Of moet je die timer interrupt krijgen nadat de 1e interrupt is geweest?

2 losse interrupts

interrupt via de USART komt wanneer een byte in het FIFO zit, op de interrupt wordt deze byte in een ringbuffer gewipt, die dan geleegd wordt eens het programma in zijn normale wijze verderloopt

de andere zou om de 10ms iets moeten uitvoeren (een interrupt op TMR0 dacht ik). Het is de bedoeling om een schuifregister in te lezen onafhankelijk van de lengte van de code. Ik heb dit geprobeerd om met een delay te werken, maar de afwijkingen zijn onaanvaardbaar, dus is een interrupt via TMR0 de laatste optie denk ik

@ altlantis: is niet echt belangrijk welke eerst komt als de interupts werken ben ik al tevreden

Dat kan gewoon, dan moet je beide interrupts aanzetten en je moet de interruptvectoren/routines maken.

Op 11 september 2004 18:54:29 schreef Bastiaan:
Dat kan gewoon, dan moet je beide interrupts aanzetten en je moet de interruptvectoren/routines maken.

ok dus in JAL

procedure interrupt
pragma interrupt
...
end procedure

waar de ... staan moet ik gewoon kijken welke flag de interrupt heeft gegenereerd en zo de acties uitvoeren die moeten gedaan worden.

Een bijkomstige vraag
wat gebeurd er als de andere interrupt ook gegenereerd wordt terwijl ie aan de andere bezig is?
wordt deze in de stack geplaatst?? en uitgevoerd nadat de andere is uitgevoerd

Waarschijnlijk veroorzaken beide een interrupt met dezelfde vector. Ze worden dan dus door dezelfde routine afgehandeld. Wat je dan moet doen is het statusregister van de mogelijke oorzaken van de interrupt (de UART of de timer) uitlezen en kijken van welke het interrupt-bit is geset. Op basis daarvan maak je binnen de interrupt service routine een sprong naar de juiste afhandelingsroutine.

Wat je dus moet doen in de IRQ afhandelingsroutine is dit:

>IRQ service routine (waar de IRQ-vector naar wijst)
lees UART-status
IRQ-bit geset?
Ja: spring naar UART-routine
lees Timer-status
IRQ-bit geset?
Ja: spring naar TIMER-routine
>einde service routine

>UART-routine
.
.
.
>einde UART-routine

>TIMER-routine
.
.
.
>einde TIMER-routine

Is het een beetje duidelijk?

foutje hier (:))

[Bericht gewijzigd door Atlantis op ]

Vergeet niet te controleren of de µC de registers op de stack zet voor de afhandeling van de ISR en ze er terug afhaalt nà de ISR.

Sommige processoren hebben daar een beperking.
Desnoods moet je dit zelf doen.

Voor de 877 zul je de registers zelf moeten opslaan. Het gaat daarbij om het 'W' register en het status register. Doe je dit niet, dan kan er wel eens iets fout gaan nadat je de interrupt hebt afgehandeld.

Dus opslaan op het moment dat je interrupt wordt aangeroepen en weer terugzetten vlak voordat je interrupt afgehandeld is.

- Edit -
Voor de 870, en volgens mij voor de 877 ook, is dit een mogelijkheid:


	ORG 0x04			;Interrupt vector
	MOVWF WTemp			;W opslaan in Wtemp
	SWAPF STATUS,0 			;Status swappen
	CLRF STATUS	 		;Bank 0
	MOVWF StatusTemp		;Geswapte status opslaan in StatusTemp
	
	...
	...
	
	SWAPF StatusTemp,0		;Opgeslagen geswapte Status terug swappen in W
	MOVWF STATUS			;Zet dit weer in Status
	SWAPF WTemp,1			;Wtemp wordt geswapt, dit veranderd het status register niet
	SWAPF WTemp,0			;Weer terug geswapt in W, zonder status bits te veranderen.
	RETFIE				;Terug van de Interrupt

[Bericht gewijzigd door KillerB the Supreme op ]

Op 11 september 2004 19:11:35 schreef Sp3ci3S:
wat gebeurd er als de andere interrupt ook gegenereerd wordt terwijl ie aan de andere bezig is?

In de interrupt routine staat de global interupt flag uit, dus die tweede interrupt ontstaat wel maar wordt pas afgehandeld nadat de IRET de global interrupt flag weer aan heeft gezet. Je interrupt routine wordt dus meteen na de eerste keer weer aangeroepen.

De interrupts worden blijkbaar niet genest uitgevoerd.
Zwak van die µC's.
Kun je in een lopende interrupt nieuwe interrupts disabelen ?

> De interrupts worden blijkbaar niet genest uitgevoerd.

dat kan je wel bewerkstelligen door binnen de interrupt de GIE aan te zetten, maar het wordt erg lastig om dan correcte 'context save / restore' code te maken

> Zwak van die µC's.

kweenie hoe het op andere uC's werkt, dit gaat over PICs (en dan nog alleen over 14-bit cores, de 18F's en de 30F's werken weer anders)

> Kun je in een lopende interrupt nieuwe interrupts disabelen ?

Je kan per interrupt bron altijd het interrupt enable bit voor die bron uitzetten.

Nog zwakker, als je ISR tijdkritisch is, moet je voor alle bronnen de interrupts uitschakelen.
Het ware beter als dat met één instructie kon.

> Nog zwakker, als je ISR tijdkritisch is, moet je voor alle bronnen de interrupts uitschakelen.

Binnen een interrupt staat de GIE uit, dus alle interrupts zijn geblokkeerd.

> Het ware beter als dat met één instructie kon.

Als je alle individuele interrupt sources apart zou willen uitzetten kan dat met 1 of 2 CLRF instructies, maar ik zie daar de zin niet van in.

Op 11 september 2004 20:55:43 schreef Wim P.:
Nog zwakker, als je ISR tijdkritisch is, moet je voor alle bronnen de interrupts uitschakelen.
Het ware beter als dat met één instructie kon.

Als je tijdkritische software schrijft, moet je ook geen PIC nemen, maar een echte microcontroller. Er zijn legio mogelijkheden voor microcontrollers met interruptprioriteit in de hardware ingebakken.

Dàt is nu net wat ik wil zeggen.

> Als je tijdkritische software schrijft, moet je ook geen PIC nemen, maar een echte microcontroller.

ploink

Mijn docent digitale technieken gaf eens een demonstratie van een eenvoudig PIC-programmaatje.
Het ding had maar één opdracht: een LED doen knipperen op 3Hz.
Het ding voerde 5 Hz uit.

Belachelijk.

lekkere docent dan, kan ie niet echt goed proggen. of werkte hij op een LDR en C basis :P

edit: la maar

[Bericht gewijzigd door Bastiaan op ]

Een PIC of µP in het algemeen is dan ook niet geschikt om als oscillator te gebruiken.
Je moet op zijn minst de uitvoertijden van elke instructie incalculeren en dan kan het nog mislopen als de µP in hold gaat of een interrupt ontvangt enz...

Op 11 september 2004 23:31:21 schreef Bastiaan:
edit: la maar

Straks ga je nog beweren dat het aan de LED ligt, Bastiaan.

Op 11 september 2004 23:34:24 schreef Wim P.:
[...]
Straks ga je nog beweren dat het aan de LED ligt, Bastiaan.

Hehe, nou dat was nog een mogelijkheid die ik was vergeten, maar dat zou idd ook nog kunnen. Misschien was het wel gewoon een knipperled (zo'n ding waar al electronica inzit) en die helemaal niet aan die PIC zat maar gewoon op de voeding :D