Jonathan
"Theorie is alleen te rechtvaardigen als 'n vorm van praktijk. De praktijk staat niet terecht voor 't hooggerechtshof van de theorie" (Stephan Toulmin)
ben wat aan het spelen met een RGB-ledje (hmmmmm)
ik heb een progje geschreven dat drie poorten stuurt in PWM om de led te sturen. ik gebruikt hiervoor wat tellers en een interrupt op TMR2. verder gebruik ik een interrupt op TMR0 voor een algemene timer in het hoofdprogramma en NOG een interrupt om data te ontvangen via RS232 en deze direct in een ringbuffer te plaatsen
blijkt nu de data niet altijd correct aan te komen. kan dit zijn doordat de interrupts met elkaar vechten??
progje in JAL (interrupt-procedure) rest van het programma is redelijk triviaal
procedure isr is
pragma interrupt
if intcon_t0if then -- Tmr0_overflow
... "wat teller gedoe"
asm bcf intcon_t0if
end if
if tmr2if then -- Tmr2_match_PR2
... "poorten sturen PWM (100Hz)afh van presetvalue en 3 tellers
asm bcf tmr2if
end if
if RCIF then
... "inlezen rx-regiter en naar ringbuffer sturen
B_RX_Last = rx_data
asm bcf RCIF
end if
end procedure
is dit de juiste manier om meerdere interrupts te verwerken, of geeft dit toch problemen?
Begin is goed, uitwerking alleen niet:
Wat je al doet is in je interrupt ruotine kijken wie er nou eigenlijk de interrupt gegenereerd heeft. Uitstekend!
Maarrrr... Op het moment dat je een controle doet, laat je meteen de code uitvoeren als je de juiste oorzaak van de interrupt gevonden hebt. Mooier is als je een jump-table maakt: alleen maar achtereenvolgens kijken wie er een interrupt heeft veroorzaakt en indien gevonden: een sprong maken naar de code die de verdere afhandeling verzorgt.
procedure isr is
...blokkeer ontvangen van nieuwe interrupts!
...
pragma interrupt
if intcon_t0if then call TMR0_IR -- Tmr0_overflow
if tmr2if then call TMR2_IR -- Tmr2_match_PR2
if RCIF then call SER_IR -- RS232
...geef ontvangen van interrupts weer vrij, want blijbaar zat onze interrupt er niet bij.
end procedure
procedure TMR0_IR is
...code
...
...geef ontvangen van interrupts weer vrij
end procedure
procedure TMR2_IR is
...code
...
...geef ontvangen van interrupts weer vrij
end procedure
procedure SER_IR is
...code
...
...geef ontvangen van interrupts weer vrij
end procedure
In Jal mag de 'overhead' van de ISR niet te groot zijn, houd het simpel, zet een vlag in je ISR en laat de afhandeling aan je hoofdprogramma over.
Jonathan
"Theorie is alleen te rechtvaardigen als 'n vorm van praktijk. De praktijk staat niet terecht voor 't hooggerechtshof van de theorie" (Stephan Toulmin)
leuk 
alleen dit nog.
je typt "blokkeer ontvangen nieuwe interrupts en ontvangen opnieuw vrijgeven."
waarschijnlijk doe je dat met de interrupt af te zetten dus
asm bsf intcon_gie -- enable interrupts
...
asm bcf intcon_gie -- disable all interrupts
echter, al er in die tussenperiode een interrupt op de proppen komt is deze dan toch verloren of wordt deze in "wachtrij gezet" ( of kan je ze in wachtrij zetten)
alleszins bedankt
Als het goed is, komt die IRQ idd in een soort wachtrij te staan. Zoiets kan ik me iig wel herinneren uit mijn 68HC11 periode. 
Maar buiten dat is dit dus precies een van de hoofdredenen om je "zoektocht naar wie de IRQ heeft veroorzaakt" zo kort mogelijk te houden.
Jonathan
"Theorie is alleen te rechtvaardigen als 'n vorm van praktijk. De praktijk staat niet terecht voor 't hooggerechtshof van de theorie" (Stephan Toulmin)
Op 14 december 2005 22:26:06 schreef MNM(tm):
Als het goed is, komt die IRQ idd in een soort wachtrij te staan. Zoiets kan ik me iig wel herinneren uit mijn 68HC11 periode.
Maar buiten dat is dit dus precies een van de hoofdredenen om je "zoektocht naar wie de IRQ heeft veroorzaakt" zo kort mogelijk te houden.
ik heb al veel opgezocht en gelezen over dergelijk maar 100% duidelijk wordt het me niet.
als ik versta wat je bedoeld: is het enkel de ISR die wordt uitgevoerd op de interrupt vector in de PIC. als ik via deze een twee procedure (de verwerking na zoektocht) uitvoer, gebeurd deze reeds opnieuw op de main-program vector, en zo opnieuw....
ik probeer deze oplossing en dan zien we wel
Op 14 december 2005 22:33:15 schreef Jonathan:
[...]ik heb al veel opgezocht en gelezen over dergelijk maar 100% duidelijk wordt het me niet.
als ik versta wat je bedoeld: is het enkel de ISR die wordt uitgevoerd op de interrupt vector in de PIC. Als ik via deze een twee procedure (de verwerking na zoektocht) uitvoer, gebeurd deze reeds opnieuw op de main-program vector, en zo opnieuw....
Dit begrijp ik ff niet...
De interrupts komen niet in een echte wachtrij te staan. Als GIE uit staat worden de xxxIF nog wel gewoon geset als er iets gebeurd. Wanneer je later GIE weer aan zet wordt meteen de ISR aangeroepen voor die xxxIF vlaggen.
GIE moet je NIET zelf uitzetten in de ISR, dat is al voor je gedaan.
Die "asm bcf RCIF" is niet nodig. RCIF is een read only bit en wordt uitgezet zodra je het ontvangen karakter uit de buffer leest.
De methode van MNM zou ik niet gebruiken. Hij is eleganter maar langzamer dan de originele code omdat er een extra CALL instructie moet worden uitgevoerd.
.. maar waarom je data niet correct aankomt zou ik niet weten. Wat bedoel je met "niet correct", niet alle data of niet de verwachtte data?
Wouter van Ooijen
Wouter van Ooijen: VOTI webwinkel, docent HvU (Technische Informatica); C++ on mictrocontrollers blog
Op 14 december 2005 21:50:25 schreef Jonathan:
blijkt nu de data niet altijd correct aan te komen. kan dit zijn doordat de interrupts met elkaar vechten??
De opbouw van je interrupt routine lijkt me prima. Doe vooral niet meer call levels dan nodig is, dat is niet alleen voor Jal maar altijd als je een 14-bit core PIC programmeert.
Maar heb je wel uitgerekend of je altijd snel genoeg alle interrupts afhandelt? MAW heb je wel genoeg CPU tijd? Stel dat er een char binnenkomt, en de andere twee interrupt bronnen moeten ook net afgehandeld worden?
Op 14 december 2005 23:14:35 schreef Brem:
De interrupts komen niet in een echte wachtrij te staan. Als GIE uit staat worden de xxxIF nog wel gewoon geset als er iets gebeurd. Wanneer je later GIE weer aan zet wordt meteen de ISR aangeroepen voor die xxxIF vlaggen.
Dat is eigenlijk ook wat ik bedoel. Vandaar dus ook dat ik zei "een soort wachtrij". 
GIE moet je NIET zelf uitzetten in de ISR, dat is al voor je gedaan.
Verder niet bekend mee. Bij de 'HC11 was dat namelijk wèl noodzakelijk (ook bij de 6809 en de 6502/6510 trouwens...).
Die "asm bcf RCIF" is niet nodig. RCIF is een read only bit en wordt uitgezet zodra je het ontvangen karakter uit de buffer leest.
Bij vrijwel alle periferieën is het zo dat het interrupt bit automatisch gecleared wordt na het uitlezen van het status register van de betreffende periferie (Timer / Serial I/O / ...).
De methode van MNM zou ik niet gebruiken. Hij is eleganter maar langzamer dan de originele code omdat er een extra CALL instructie moet worden uitgevoerd.
Mjah, GOTO's hadden ook gekund. Zijn sneller, hoewel ik ook wel weet dat ook daar weer een extra aantal cycli voor nodig zijn.
Jonathan
"Theorie is alleen te rechtvaardigen als 'n vorm van praktijk. De praktijk staat niet terecht voor 't hooggerechtshof van de theorie" (Stephan Toulmin)
Op 14 december 2005 23:24:08 schreef Wouter van Ooijen:
Maar heb je wel uitgerekend of je altijd snel genoeg alle interrupts afhandelt? MAW heb je wel genoeg CPU tijd? Stel dat er een char binnenkomt, en de andere twee interrupt bronnen moeten ook net afgehandeld worden?
hoe kan ik dat berekenen?? (instructies tellen van de ISR?,... en zo ja waar vind het aantal instructies van JAL-operaties -> bv if byte > 0 then ... end if )
ik vrees er een beetje voor dat ze dikwijls samen afgehandeld worden
Op 14 december 2005 23:14:35 schreef Brem:
De interrupts komen niet in een echte wachtrij te staan. Als GIE uit staat worden de xxxIF nog wel gewoon geset als er iets gebeurd. Wanneer je later GIE weer aan zet wordt meteen de ISR aangeroepen voor die xxxIF vlaggen.GIE moet je NIET zelf uitzetten in de ISR, dat is al voor je gedaan.
dus aanzetten hoeft ook niet, dit gebeurd dan waarschijnlijk bij verlaten van de ISR
.. maar waarom je data niet correct aankomt zou ik niet weten. Wat bedoel je met "niet correct", niet alle data of niet de verwachtte data?
ik verzend serieen van 5 bytes, deze worden direct na inlezen via indirect adresseren in een ringbuffer geladen (grootte 16 bytes). In het hoofdprogramma controleer grootte ringbuffer, vanaf er 5 bytes aanwezig zijn worden deze direct uitgelezen naar 5 variabelen. via controle gebeurd een actie, indien geen juiste data in de variabelen bounce ik de 5 bytes terug naar de PC en dan krijg ik maar eentje binnen.....????? . deze actie gebeurd af en toe
vb ik zend karakters: sr255 ( set red 255 )
controler + berekening
if buffercount > 4 then
data1 = B_RX_prior -- haal eerste byte uit buffer
...
data5 = B_RX_prior
if data1 == "s" & data2 == "r" then
R_value = 100*( data3 - "0" ) +
10 * ( data4 - "0" ) +
1 * ( data5 - "0")
else
B_RX_clear -- procedure waarbij buffer wordt geleegd
async_tx (data1)
...
async_tx (data5)
end if
end if
Wouter van Ooijen
Wouter van Ooijen: VOTI webwinkel, docent HvU (Technische Informatica); C++ on mictrocontrollers blog
Op 15 december 2005 07:47:00 schreef Jonathan:
[...]hoe kan ik dat berekenen?? (instructies tellen van de ISR?,... en zo ja waar vind het aantal instructies van JAL-operaties -> bv if byte > 0 then ... end if )
bekijke de gegenereerde assembler en tel instructies (goto etc. tellen voor twee).
Jonathan
"Theorie is alleen te rechtvaardigen als 'n vorm van praktijk. De praktijk staat niet terecht voor 't hooggerechtshof van de theorie" (Stephan Toulmin)
Op 15 december 2005 07:50:47 schreef Wouter van Ooijen:
bekijke de gegenereerde assembler en tel instructies (goto etc. tellen voor twee).
geen vaste regel voor omdat dit via JAL gemakkelijk te berekenen?
Wouter van Ooijen
Wouter van Ooijen: VOTI webwinkel, docent HvU (Technische Informatica); C++ on mictrocontrollers blog
Op 15 december 2005 07:52:08 schreef Jonathan:
geen vaste regel voor omdat dit via JAL gemakkelijk te berekenen?
nee.
je zou ook de gegenereerde code kunnen simuleren, maar dat kost wrsch. veel tijd om alles goed te zetten (hardware vlaggen enzo).
R_value = 100*( data3 - "0" ) +
10 * ( data4 - "0" ) +
1 * ( data5 - "0")
Vermenigvuldigen is erg zwaar werk voor een PIC zonder hardware multiplier. Kun je de data niet HEX verzenden, of zelfs gewoon binair?
Maar ja, je probleem ligt bij het zenden van PIC naar PC, de ISR en de ringbuffer hebben er dus waarschijnlijk niets mee te maken. Ik zou het programma helemaal uitkleden: ISR eruit , ringbuffer eruit, en eerst concentreren op 5 bytes sturen en correct ontvangen. Daarna weer voorzichtig opbouwen..
Op 14 december 2005 23:14:35 schreef Brem:
De methode van MNM zou ik niet gebruiken. Hij is eleganter maar langzamer dan de originele code omdat er een extra CALL instructie moet worden uitgevoerd.
Nu weet ik niet precies wat JAL voor taal is, maar zo ongeveer alles hoger dan assembler wordt gecompileerd.
Een beetje compiler optimaliseert dit en vervangt die preocedure-aanroep door de procedure zelf, zeker als deze enkel en alleen daar aangeroepen wordt 
Zit ik me net te bedenken: doe je met je seriële poort ook aan flow control? Dus als de PIC een byte ontvangen heeft, dat 'ie dan via bijv. de CTS ofsow tegen de PC kan zeggen: "ff wachten met de rest van je zooi, ben momenteel BEZIG!". Pas als je dan dmv. de ISR afhandelingsroutine de byte uit het receive-register hebt gelezen, kun je dan via CTS aan de PC doorgeven: "Yo, kom maar op met je zooi!".
Ps.: op de PC moet je dus hetzelfde doen, maar dan met bijv. de DTR-lijn.
Op 15 december 2005 11:43:44 schreef MNM(tm):
Zit ik me net te bedenken: doe je met je seriële poort ook aan flow control? Dus als de PIC een byte ontvangen heeft, dat 'ie dan via bijv. de CTS ofsow tegen de PC kan zeggen: "ff wachten met de rest van je zooi, ben momenteel BEZIG!". Pas als je dan dmv. de ISR afhandelingsroutine de byte uit het receive-register hebt gelezen, kun je dan via CTS aan de PC doorgeven: "Yo, kom maar op met je zooi!".Ps.: op de PC moet je dus hetzelfde doen, maar dan met bijv. de DTR-lijn.
Of stuur gewoon een byte terug als "acknowledge". Als enorme snelheden geen rol spelen gaat dat prima en hoef je nog steeds maar twee lijntjes te gebruiken.
Jonathan
"Theorie is alleen te rechtvaardigen als 'n vorm van praktijk. De praktijk staat niet terecht voor 't hooggerechtshof van de theorie" (Stephan Toulmin)
Op 15 december 2005 11:43:44 schreef MNM(tm):
Zit ik me net te bedenken: doe je met je seriële poort ook aan flow control? Dus als de PIC een byte ontvangen heeft, dat 'ie dan via bijv. de CTS ofsow tegen de PC kan zeggen: "ff wachten met de rest van je zooi, ben momenteel BEZIG!". Pas als je dan dmv. de ISR afhandelingsroutine de byte uit het receive-register hebt gelezen, kun je dan via CTS aan de PC doorgeven: "Yo, kom maar op met je zooi!".
kan ik gerust, echter wel softwarematig, zoals DIY zegt byte heen, byte terug indien goed ontvangen en klaar om volgende te ontvangen.
zenden gebeurd nu via hyperterminal, dus ik toets de karakters gewoon in. echt snel komen die dingen dus niet na elkaar (ik typ zeker niet vlugger dan dat de interrupt zou afgewerkt zijn
)
@ Brem: dit is een antwoord op jou opmerking: de drie databytes die de waarde voorstellen worden inderdaad later vervangen door één byte die de waarde voorstelt. ik ken nu echter niet de hele ascii-tabel vanbuiten om zo het karakter te typen die de waarde voorstelt die ik wil hebben in de µP 
Het probleem: twee mogelijke problemen zat ik te denken
1: uitlezen ringbuffer gebeurd in de main loop (inlezen in ISR en ze komen altijd alle 5 toe). deze procedure kan dus gestoord worden door een interrupt en aangezien dit indirect gebeurd loopt daar misschien een en ander mis bij terugzetten van de program counter??
2: aantal stopbits bij verzenden. raar maar het werkt met zowel 1 als 2 stopbits en het geeft in beide gevallen "foute dataoverdracht"
Wouter van Ooijen
Wouter van Ooijen: VOTI webwinkel, docent HvU (Technische Informatica); C++ on mictrocontrollers blog
Op 15 december 2005 21:55:11 schreef Jonathan:
kan ik gerust, echter wel softwarematig, zoals DIY zegt byte heen, byte terug indien goed ontvangen en klaar om volgende te ontvangen.
Als je de communicatie met deze 'byte level software handshake' doet (check eens mijn oude WBus protocol!) dan is er geen enkele reden om dit in de interrupt te doen. Er uit halen dus, gewoon in de main afhandelen.
Jonathan
"Theorie is alleen te rechtvaardigen als 'n vorm van praktijk. De praktijk staat niet terecht voor 't hooggerechtshof van de theorie" (Stephan Toulmin)
Op 15 december 2005 21:58:42 schreef Wouter van Ooijen:
Als je de communicatie met deze 'byte level software handshake' doet (check eens mijn oude WBus protocol!) dan is er geen enkele reden om dit in de interrupt te doen. Er uit halen dus, gewoon in de main afhandelen.
ik zal dit eens onderzoeken, al vind ik het werken op interrupt basis wel proper 
anders goed nieuws, het probleem gevonden het lag dus zeker niet bij de afwerking van de interrupts 
als je een ringbuffer zijn plaats toewijst is het normaal dat je problemen krijg door deze te zetten ergens in bank 0 tussen T2CON en ADCON0 ( waar ook de registers van de USART liggen) (SCHAAM-mode)
ja een typfout is vlug gemaakt....
bedankt voor de hulp en info mensen