Sida 1 av 2
Flera interrupts PIC
Postat: 12 maj 2014, 11:25:09
av Lullen
Har snart börja komma in i PIC programmeringen men som alla vet så skiljer det sig ganska mycket från vanlig programmering så det är en liten omställning.
Jag försöker skriva en enkel laptimer som till att börja med är så enkel som möjligt. Har inte alla moduler hemma så någon testning kan jag inte göra än.
Flödet i programmet är följande:
1. Initiera allt
2. Vänta på GPS modulen tills den skickar data via USART. Notifieras via en interrupt på RX.
3. Tolka datan
4. Kolla om mållinjen är passerad. Om den är det, räkna ut varvtiden och jämför den med den snabbaste tiden. Om varvtiden är den snabbaste visa grön LED, annars röd LED.
5. En timer körs i 1Hz och kollar om någon LED lyser. Om någon lyser öka antalet sekunder LEDen har lyst och om den är över 10sekunder släck LEDen.
Med andra ord så har jag två möjliga interrupts. Ena från timern och andra från USART. Dessa interrupts kan ju ske samtidigt vilket leder mig till frågan hur detta hanteras? Det finns low och high priority som jag troligtvis vill använda. High för USART, low för timer. Hittar dock ingen riktigt info om vad dessa gör exakt. Kan dock tänka mig att om low redan körs och en high kommer så kör den klart high innan low fortsätter?
Antar att någon kod inte behövs för att lösa min fråga men behövs den så kan jag slänga upp den.
Re: Flera interrupts PIC
Postat: 12 maj 2014, 11:32:36
av Icecap
En hög prioritet är viktigare än en låg prioritet, därför kommer en hög prioritet att avbryta en låg prioritet.
Men sättet man skiljer ut dom på är att kolla om interrupt-flaggan är satt. Om vi t.ex. bara har en prioritet:
* Spara undan register som måste sparas (gäller ej C som gör det automatisk).
* Kolla UART-Rx interrupt flagga, om den inte är aktiv hoppa över nästa steg.
* Göra vad som ska göras vid UART-Rx interrupt och nollställ sedan interrupt-flaggan.
* Kolla Timerns interrupt-flagga, är den inte aktiv hoppas det över nästa steg.
* Göra vad som ska göras vid timer-interrupt och nollställ sedan interrupt-flaggan.
* Återställ register som sparades (gäller ej C som gör det automatisk).
Re: Flera interrupts PIC
Postat: 12 maj 2014, 11:33:40
av TomasL
Kan ju vara bra att veta vilken processor du avser att använda.
Re: Flera interrupts PIC
Postat: 12 maj 2014, 11:52:14
av sodjan
> Dessa interrupts kan ju ske samtidigt vilket leder mig till frågan hur detta hanteras?
Om vi för att förrenkla det hela antar att du *inte* har en processor med dubbla
interrupt-nivåer. Alla interrupt hanteras i serie efter varandra. Det gäller även
om två olika interrupt kommer "samtidigt". Det som då är helt avgörande är
vilket responstid din applikation kräver av vardera interruptet.
Om det är så att båda interrupten kan acceptera att vänta lika länge
som det andra interruptet tar att bearbeta, så är ju allt OK! Bara att
köra dom efter varandra.
T.ex så är ju tiden för att att göra det som beskrivs i punkt 5 i princip
försumbart i rellation till intervallet på 1 sek. Sannolikt också i jämförelse
med den svarstid som krävs för seriekommunikationen från GPS'en.
> Notifieras via en interrupt på RX.
Det där kan tolkas som ett IOC på RX pinnen, men du menar nog ett
vanligt USART interrupt när ett helt tecken är mottaget. Vilken hastighet
kör GPS modulen med? Om det är 9600 b/s, så har du massor av tid
att "göra annat" mellan varje tecken.
Dina krav är väldigt låga och vilken PIC som helst fixar det enkelt.
Nackdelen med lösning för high/low interrupt prioritet är att man bara
har automatisk lagring av kontext i det ena fallet. SAnnolikt fixar t.ex
en C miljö detta åt dig i alla fall. Att du nämner det talar för att du har
tittat på en PIC18, men som sagt, vilket som helst av PIC16 fixar detta
enkelt också och du får lite fler storlekar att välja på.
Tanken är alltså att springa (?) med en GPS mottagare och en PIC.
Tråkig fråga, men kan inte en "app" på en smartphone (med GPS, men
det har väl alla i dag) fixa samma sak? Jag vet inte om det är enklare...
Re: Flera interrupts PIC
Postat: 12 maj 2014, 11:55:31
av Lullen
Icecap skrev:En hög prioritet är viktigare än en låg prioritet, därför kommer en hög prioritet att avbryta en låg prioritet.
Men sättet man skiljer ut dom på är att kolla om interrupt-flaggan är satt. Om vi t.ex. bara har en prioritet:
* Spara undan register som måste sparas (gäller ej C som gör det automatisk).
* Kolla UART-Rx interrupt flagga, om den inte är aktiv hoppa över nästa steg.
* Göra vad som ska göras vid UART-Rx interrupt och nollställ sedan interrupt-flaggan.
* Kolla Timerns interrupt-flagga, är den inte aktiv hoppas det över nästa steg.
* Göra vad som ska göras vid timer-interrupt och nollställ sedan interrupt-flaggan.
* Återställ register som sparades (gäller ej C som gör det automatisk).
Glömde säga att det är C som avses. Men i så fall vill jag nog inte använda high och low då båda måste ske?
Jag tolkar ditt svar som att om en high interrupt körs så kommer inte något hända när en ny interrupt kommer? Förutom att flaggan sätts men den kommer inte anropa funktionen på nytt? Med andra ord så borde det jag skrivit fungera som det är tänkt?
Kod: Markera allt
int secondsOn = 0;
char rx;
void interrupt interrupts(){
if(INTCONbits.TMR0IF == 1)
{
handleTmr0();
}
if(PIR1bits.RCIF == 1)
{
handleUsartRx();
}
}
void handleTmr0(){
if(PORTA.1 == 1 || PORTA.2 == 1){
secondsOn++;
if(secondsOn >= 5){
PORTA.1 = 0;
PORTA.2 = 0;
secondsOn = 0;
}
}
INTCONbits.TMR0IF = 0;
WriteTimer0(0xE17B); //Please use HEX. Decimal don't work
}
void handleUsartRx(){
rx = ReadUSART(); //read the byte from rx register
//do stuff with rx
PIR1bits.RCIF = 0; // clear rx flag
}
Alternativt att jag borde ändra min interrupt funktion till:
Kod: Markera allt
void interrupt interrupts(){
while(INTCONbits.TMR0IF == 1 || PIR1bits.RCIF == 1)
{
if(INTCONbits.TMR0IF == 1)
{
handleTmr0();
}
if(PIR1bits.RCIF == 1)
{
handleUsartRx();
}
}
}
TomasL skrev:Kan ju vara bra att veta vilken processor du avser att använda.
Min tanke var att använda PIC18F2550.
Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:01:40
av Lullen
sodjan skrev:> Dessa interrupts kan ju ske samtidigt vilket leder mig till frågan hur detta hanteras?
Om vi för att förrenkla det hela antar att du *inte* har en processor med dubbla
interrupt-nivåer. Alla interrupt hanteras i serie efter varandra. Det gäller även
om två olika interrupt kommer "samtidigt". Det som då är helt avgörande är
vilket responstid din applikation kräver av vardera interruptet.
Om det är så att båda interrupten kan acceptera att vänta lika länge
som det andra interruptet tar att bearbeta, så är ju allt OK! Bara att
köra dom efter varandra.
T.ex så är ju tiden för att att göra det som beskrivs i punkt 5 i princip
försumbart i rellation till intervallet på 1 sek. Sannolikt också i jämförelse
med den svarstid som krävs för seriekommunikationen från GPS'en.
> Notifieras via en interrupt på RX.
Det där kan tolkas som ett IOC på RX pinnen, men du menar nog ett
vanligt USART interrupt när ett helt tecken är mottaget. Vilken hastighet
kör GPS modulen med? Om det är 9600 b/s, så har du massor av tid
att "göra annat" mellan varje tecken.
Dina krav är väldigt låga och vilken PIC som helst fixar det enkelt.
Nackdelen med lösning för high/low interrupt prioritet är att man bara
har automatisk lagring av kontext i det ena fallet. SAnnolikt fixar t.ex
en C miljö detta åt dig i alla fall. Att du nämner det talar för att du har
tittat på en PIC18, men som sagt, vilket som helst av PIC16 fixar detta
enkelt också och du får lite fler storlekar att välja på.
Tanken är alltså att springa (?) med en GPS mottagare och en PIC.
Tråkig fråga, men kan inte en "app" på en smartphone (med GPS, men
det har väl alla i dag) fixa samma sak? Jag vet inte om det är enklare...
> Det där kan tolkas som ett IOC på RX pinnen, men du menar nog ett
vanligt USART interrupt när ett helt tecken är mottaget. Vilken hastighet
kör GPS modulen med? Om det är 9600 b/s, så har du massor av tid
att "göra annat" mellan varje tecken.
Se koden i förra inlägget. 9600 b/s verkar vara standard så jag tror jag kör med det även om modulen jag kollar på klarar andra hastigheter.
Tanken är att ha den på motorcykeln och då det inte är någon ovanlighet att man ligger i 200-250km/h vid mållinjen så är 1Hz för långsam. Min telefon (WP8) klarar inte av externa gps enheter, så isf måste jag köpa en android + en bluetooth gps. Så tänker man rent praktiskt så är det möjligt om även lite omständigt. Kraschar jag så lär jag förstöra material för 3000kr istället för 500kr. Jag har även haft min pickit 3 liggandes ett bra tag nu utan något roligt att göra och nu har jag äntligen fått inspirationen att lära mig PIC så det är också en av anledningarna.
Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:03:40
av sodjan
Ja, du kan ha en interrupt rutin (ISR) och helt enkelt kolla varifrån
interruptet kom (IF-flaggorna). Så fort du avslutar ISR'en kommer
den att köras om igen om deet finns fler aktiva IF-flaggor.
Ordningen som du kollar IF-flaggorna kommer att bli ett slags
prioritering, men enbart om de inträffar väldigt "samtidigt", inom
någon mikrosekund.
> Förutom att flaggan sätts men den kommer inte anropa funktionen på nytt?
Exakt. Så länge som koden ligger i din ISR, så är nya interrupt blockerade.
> Alternativt att jag borde ändra min interrupt funktion till:
Ja, något sådant. While satsen är väl onödig, rutinen kommer i alla fall
att anropas igen om det finns en aktiv IF-flagga. Du sparar bara
marginellt på det, låt processorn sköte det istället.
> Jag har även haft min pickit 3 liggandes ett bra tag nu utan något roligt att göra och nu har
> jag äntligen fått inspirationen att lära mig PIC så det är också en av anledningarna.
Ja, det är ju en alldeles utmärk anledning!

Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:05:14
av sodjan
> ...så är 1Hz för långsam.
Jaha? Det var ju du som nämnde det. D.v.s för att släcka lysdioden.
Men det har ju inget med den övriga hanteringen att göra, den kan
ju ha helt andra krav, specellt om det inte var jogging det gäller...

Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:11:41
av Lullen
Okej då känner jag att jag är med! Tackar för hjälpen
Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:18:21
av Icecap
För tydlighetens skull vill jag rekommendera:
Kod: Markera allt
void interrupt interrupts()
{
if(INTCONbits.TMR0IF == 1)
{
INTCONbits.TMR0IF = 0;
handleTmr0();
}
if(PIR1bits.RCIF == 1)
{
PIR1bits.RCIF = 0;
handleUsartRx();
}
}
Då blir det lättare att se i koden att flaggorna nollas osv. Ingen teknisk skillnad men det blir lättare att läsa om 6 månader.
Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:22:26
av sodjan
En annan sak...
Beroende på själva applikationen, så kan det ibland finnas anledning
till att tillfälligt stänga av interrupt från en viss källa. Det kan man
göra genom att hantera IE-flaggorna dynamisk från koden. Sedan
får man testa även dom i ISR'en, ungefär så här:
Kod: Markera allt
void interrupt interrupts(){
if ((INTCONbits.TMR0IF == 1) & (INTCONbits.TMR0IE == 1))
{
handleTmr0();
}
if ((PIR1bits.RCIF == 1) & (PIE1bits.RCIF == 1))
{
handleUsartRx();
}
}
Om man bara vill fördröja interruptet så sätter man bara xxxIE igen så sker det
direkt ifall xxxIF är satt. Om man helt vill stänga av ett interrupt under en viss
tid, så får man nolla xxxIF direkt *innan* man sätter xxxIE igen, då sker inget
förrens *nästa* interrupt från den aktuella källan.
> Min tanke var att använda PIC18F2550
OK, det är inte världens mest moderna PIC idag.

Men du kanske redan har dessa tillgängliga...
Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:27:35
av Wedge
Tändning och släckning verkar du ju ha designat att vara helt oberoende i och med att timern tickar på fritt med 1 Hz istället för att gå en viss tid från att dioden tänts. På det viset får du en noggrannhet på på-tiden på +/- 1 sekund. Känns inte som helt klockrent.
Behövs det ens en timer med interrupt för att hantera en lysdiodssläckning? Jag kan inte PIC-arkitektur, men på nåt vis borde det väl gå att "mäta" korta tider i storleksordningen några sekunder i idle-loopen, och med betydligt bättre noggrannhet än +/-1 sek?
Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:34:25
av sodjan
Men just *den* tiden var väl bara för att LED'en skulle släckas (alls)
efter en viss tid. Om det tar 8, 10 eller 12 sekunder spelar sannolikt ingen
större roll. Jag utgår från att det finns en annan tidtagning med
bättre upplösning för själva varvtiderna...
> Behövs det ens en timer med interrupt för att hantera en lysdiodssläckning?
Kanske inte, men svårt att hitta på något enklare. Och det har ingenting med
något specifik arkitektur att göra, det är nog ganska allmängiltigt.
Dessutom borde det alltså finnas en timer i alla fall för varvtiderna, och då
kan man lika gärna hantera släckningen av LED'en där också.
Sen så borde det inte vara en timer med just 1 sek intervall, sannolikt något
i still med 1/100 sek eller så. Det är ju bara att räkna på för att släka LED'en.
D.v.s att det enbart behövs en klocka "i botten" som hanterar både varvtiderna
och LED släckningen...
Eller kanske att även tiden läses från GPS modulen??
Re: Flera interrupts PIC
Postat: 12 maj 2014, 12:39:31
av Icecap
Det är väl generellt svårt att få timers att gå så långsamt som 1 sek. Detta med att återladda en timer är också mycket tveksamt, speciellt om det finns fler interrupt än just timern. Om det bara är för att släcka lite LED kan det inte plåga någon men är det för att räkna tid blir det strax mer besvärligt - och inexakt.
Det är väl knappast ett problem att t.ex. köra Timer0 och låta den köra med en prescaler osv. som ger kanske 10-30Hz. Då kan man kolla om lamporna är tända x sek * timer-interrupt-frekvensen. Bra noggrannhet, stabilt och enkelt.
Re: Flera interrupts PIC
Postat: 12 maj 2014, 13:23:00
av TomasL
Du bör stänga av interrupten det första du gör i din interruptfunktion, och starta dem när du är klar, dessutom är det lämpligt att rensa flaggorna det sista du gör, innan du startar interrupten igen.
Om du rensar flaggorna innan du hanterat orsaken till interruptet, kan du få falska triggningar istället.