Jag får in en periodisk dataström av ettor och nollor på RB5. Dem vill jag spegla och skicka ut på RB3.
Det jag gör i koden är helt enkelt att i interruptrutinen för PORTB att sätta PORTB.RB3 = PORTB.RB5.
På oscilloscopet så får jag en ganska stabil bild av utdatan på RB3. Men man ser att bitarna hoppar lite, dvs hoppar mellan 0 och 1. Indatan på RB5 ser jag också på oscilloskopet och den är stadig och fin.
Förstår inte riktigt vad det kan bero på? Någon som har ett hum ?
Micke_s:
Grejen är att det är till ett lite större project som jag vill få interrupt på PORTB att funka, så detta är lite testkod... Men tack för förslaget.
Tack Icecap. Det hjälpte, men varför?
Gäller det vid alla typer av interrupt att man skall kvittera flaggan det första man gör? Varför spelar det roll var i interruptrutinen man gör detta?
Är det så att du råkar ha igång en watchdog timer som resettar kretsen med jämna mellanrum så att portarna beter sig underligt?
jag har även en liten fundering kring detta som står i databladet:
"If a change on the I/O pin should occur
when a read operation is being executed
(start of the Q2 cycle), then the RBIF
interrupt flag may not get set."
jag funderar på de övriga PORTB ingångarna 7,6 och 3. Alla dessa kan skapa en interrupt. ex om PORTB.6 ändrar sig lite lite före PORT5, så läser du port 5 för att lägga ut på port 3 och missar förändingen.. känns kanske inte helt genomtänt av mig, men det kanske är värt ett försök att sätta dem om ut-portar istället om det finns en möjlighet till det.
Alltså det Icecap föreslog, att jag skulle nolla INTCON.RBIF det första jag gör, fungerade. Dvs. nu funkar det jättebra. Det jag funderar över varför det hjälpte???
Anledningen till att man ska kvittera flaggan direkt är att själva ISR'n tar sin lilla tid, under den tid kan en interrupt uppstå och när du sedan är klar med din ISR rensar du interruptflaggan.... Alltså kastas det bort en interrupt eller hur?
Jag har vid ett tillfälle varit tvungen att lägga in en 'while(<interruptflagga>)' i en ISR, denna loop rensade flaggan, gjorde sin grej och kollade om flaggan fortfarande var rensat innan den lämnade ISR'n. Det projekt var å andra sidan mycket tungt belastat på en kommunikationsinterrupt så det var ett specialfall (2 st 1Mb/sek synkrona kommunikationslänkar på en 16MHz CPU) men det var vitalt för funktionen.
Bäst är det ju om varje interrupt har egen ISR med vektoriserade hopp och automatisk rensning av flaggorna, snabbare blir det knappast men PIC's sätt kan fungera också.
Ok, men längden på mina ettor och nollor som kommer in på RB5 är ca 900us, dvs. det är 900us innan nästa interrupt på RB5 borde komma. Interruptrutinen tar ju inte så lång tid!?.
Det beror ju på vilken klockhastighet du kör med, själva overheaden på ISR'n är inte speciellt "nådig" heller. Har du ett oscilloskop kan du ju se responstiden vid att kolla fördröjningen men tydligen tar det sin lilla tid när det hjälpte att flytta flagga-rensningen eller hur?
Kolla i .LST-filen, där ser du vilken overhead som finns i en ISR, du blir nog förvånad.
Använder 10MHz.
10MHz ==> 0.4us/instruktion.
HELA (inkl. sparning av register osv.) interruptrutinen består av 36 instruktioner ==> 36*0.4us = 14.4us (+ lite extra för hopp mellan instruktioner).
Hmm. Det borde alltså ej vara något problem med att nollställa flaggan i slutet av rutinen. Eller har jag missuppfattat allt?
Nä, det borde det inte men enl. vad du skrev blev det bättre, alltså är det signaler som är snabbare än 900µs, annars ville det inte vara någon skillnad.
Låt bli C när det gäller snabba saker - kompilatorn gör ofta 50 instruktioner av något som borde (och går göra) på 5....... Tidskritiskt på PIC kör med assambler - gott råd...
Nja... faktisk är overheaden i MikroC inte större än den jag använder i ASM så jag tror att den simpla operation går ganska snabbt men generellt har du rätt, är det kritisk tar man i med järnhandsken!
Men har man såna problem kan det vara läge att skrämma upp processorn lite eller skaffa en kraftigare, går det nätt och jämt på 10MHz kör man den på 15MHz eller mer.