staticvoid interrupt ISR(void){
if (TMR0IE && TMR0IF) // Interrupt från Timer0
{
TMR0IF = 0; // Återställ flagga för Timer0// gör nåt här
}
elseif (INTE && INTF) // Interrupt från INT-pin
{
INTF = 0;
// gör nåt här
}
elseif (RCIE && RCIF) // Seriellt tecken kommit in
{ // RCIF // Denna bit nollställs genom att läsa RCREG// gör nåt här
}
}
En if-else-kedja som betar av interrupt-flaggorna en i taget, ett anrop av interrupt för varje.
Det går också att hitta exempel med fristående if-satser så här:
staticvoid interrupt ISR(void){
if (TMR0IE && TMR0IF) // Interrupt från Timer0
{
TMR0IF = 0; // Återställ flagga för Timer0// gör nåt här
}
if (INTE && INTF) // Interrupt från INT-pin
{
INTF = 0;
// gör nåt här
}
if (RCIE && RCIF) // Seriellt tecken kommit in
{ // RCIF // Denna bit nollställs genom att läsa RCREG// gör nåt här
}
}
Om det då kommer ett interrupt som finns längre ner än det aktuella i listan med if-satser, så utförs det också.
Då borde man kunna ha en slinga som söker av alla aktuella interrupt-flaggor och utför dem, i samma interrupt-anrop. Så här:
staticvoid interrupt ISR(void){
boolean IFfixad = false;
do
{
if (TMR0IE && TMR0IF) // Interrupt från Timer0
{
TMR0IF = 0; // Återställ flagga för Timer0// gör nåt här
IFfixad = true;
}
if (INTE && INTF) // Interrupt från INT-pin
{
INTF = 0;
// gör nåt här
IFfixad = true;
}
if (RCIE && RCIF) // Seriellt tecken kommit in
{ // RCIF // Denna bit nollställs genom att läsa RCREG// gör nåt här
IFfixad = true;
}
}
while (IFfixad );
}
Det bör vara alternativ 2 du vill ha om du vill göra detta.
Om du börjar skriva en loop i en ISR bör du snarast tänka över vad du gör. Principen är att du ska göra så lite som det bara går i din ISR och en loop är nästan alltid fel. Sätt en flagga och gör jobbet utanför ISR.
Det är SVJV väldigt ovanligt att ha en interrupt-rutin till samtliga interrupt.
Alla processorer jag jobbat med tillåter dig att ha egna interrupt-rutiner ("funktioner") för Timer-interrupt, Uart, o.s.v.
Ibland delar dock t.ex. GPIO-pinnarna i en port på en interrupt-rutin men.
Edit2: Vad gäller loopen är det troligen onödigt, så länge Interrupt-flaggan är satt kommer ett interrupt att triggas, så det gör inget om du går ur ISR:en med ett interrupt ohanterat, den kommer köras ögonblickligen igen. Men läs på om processorn och
kolla att den beter sig så.
Min tanke med loopen var att alla interrupten skulle klaras av i ett anrop, för att spara tid.
Där är en del instruktioner som går åt vid anrop och avslut av interrupt-rutinen, men vid praktiskt prov blev det att det gick åt mer tid till loopvarianten.
Jag har inte gjort nån noggrann mätning, men jag hade huvudprogrammet att generera en fyrkantvåg, som inte hade nåt att göra med interrupt.
När jag testade med loop-varianten hörde jag att frekvensen på fyrkantvågen blev lägre.
Så ingen mening med loopen.
Jag är nyfiken på tankegångarna. Vad skulle nyttan med loopen kunna vara?
I vilket läge skulle det vara en god idé att på ett eller annat sätt ligga kvar i en interruptrutin i väntan på nya interrupt? Det går liksom tvärt emot hela syftet med interrupt.
Lämna interruptet ASAP, och låt hårdvaran ta hand om att skicka programmet tillbaka in i interruptrutinen nästa gång ett interrupt sker.
TomasL skrev: ↑9 april 2024, 20:58:22
Dessutom, det första man gör när man går in i en interruptrutin är att stänga av alla interrupt, och slå på dem när man går ur.
Det görs hårdvarumässigt automatiskt. Därför används speciell return, som återgår till adressen som finns sparad på stacken, dessutom slås interrupt på i samma instruktion RETFIE.
Klas-Kenny skrev: ↑9 april 2024, 21:27:02
Jag är nyfiken på tankegångarna. Vad skulle nyttan med loopen kunna vara?
I vilket läge skulle det vara en god idé att på ett eller annat sätt ligga kvar i en interruptrutin i väntan på nya interrupt? Det går liksom tvärt emot hela syftet med interrupt.
Lämna interruptet ASAP, och låt hårdvaran ta hand om att skicka programmet tillbaka in i interruptrutinen nästa gång ett interrupt sker.
Nyttan skulle vara att spara tid, men det var ju inte alls så, det tog längre tid i loopen med alla ifsatser, än gå in och ur interrupt-rutinen.
För att loopen skulle se att alla interrupten blev besvarade måste den gå igenom alla if-satserna utan något "svar".
Nu är väl Int-Flaggorna ENUMADE, och då kanske en "switch-sats "är snabbare, då kompilatorn ofta kan optimera den bättre.
Man servar ett int, sedan hoppar man ur, finns det fler int, så körs funktionen igen, osv.
Om man processorn kan hantera flera vektorer så är det ett bättre val, dvs ha flera int-funktioner.
Varför kolla både IE och IF? Sätter verkligen PIC16 interrupt-flaggor för ett interrupt som inte är aktiverat?
Där kan du ju enkelt ta bort 50% av alla bit-test om ISR:en tar för lång tid.
Om vi tar TMR0 i en 16F1825 som exempel.
TMR0IF sätts när villkoret för interrupt i fråga uppfylls (TMR0 overflow) men genererar bara ett faktiskt interrupt om TMR0IE är satt.
Om man i koden håller på att att slå TMR0IE till och från (och har fler potentiella källor till interrupt än just TMR0) är det lämpligt att polla TMR0IE i ISR, men om man aldrig "stänger av" TMR0IE verkar det onödigt att kolla om den är "till" i varje interrupt.
Senast redigerad av H.O 13 april 2024, 00:08:20, redigerad totalt 1 gång.
Samtidigt brukar man stänga av Int när man går in i servicerutinen, alla kompilatorer gör inte detta.
Men oavsett, man skall alltid kolla om IE-flaggan är satt, för att få en portabel ko.d
Det beror ju på vad du menar med "stänger av Int".
Om man, när man går in i ISR stänger av ALLT vad interrupt heter betyder ju det att inga ytterligare interrupt kan "köas" medan man betjänar nuvarande.
Dvs, om du t.ex har en timer-interrupt och en UART interrupt så är det stor risk att någon av de missas.