Problem med interrupt på PORTB.

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
bengt-re
EF Sponsor
Inlägg: 4829
Blev medlem: 4 april 2005, 16:18:59
Skype: bengt-re
Ort: Söder om söder
Kontakt:

Inlägg av bengt-re »

Sant, men erfarenhet är att med tidskritiska saker så går det ofta fortare med asm eftersom det fungerar från början och man slipper bråka och undra hur timingen skall bli - sen så går det ofta att kombinera - inline asm är rätt praktiskt ;)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Jag får in en periodisk dataström av ettor och nollor på RB5.

Bara "periodisk dataström" säger inte ett smack...
Hur ser den ut ? Periodtider ? Min-tid för en låg respektive hög puls ?

Sen angående att lägga BCF av RBIF flaggan *före* du läser PORTB, så
kan de få det hela att *se ut* som att det fungerar bättre. Men *INTE*
p.g.a något timing-fenomen som det har skivits om här.

RBIF är flaggan för "PORTB change interrupt", och den flaggan går bara att
clear *EFTER* att man har läst PORTB. Gör du det före så sätts den bara
direkt igen.

SE ***DATABLADET*** SIDAN 36 : "5.2 PORTB and TRISB Registers" ! :

> The user, in the interrupt service routine, can clear the interrupt in the following manner:
>
> a) Any read or write of PORTB. This will end the mismatch condition.
> b) Clear flag bit RBIF.
>
> A mismatch condition will continue to set flag bit RBIF. Reading PORTB will
> end the mismatch condition and allow flag bit RBIF to be cleared.

Det som händer med Icecap's ändring är att RBIF *aldrig* clearas, din
ISR loopar hela tiden och portpinnarna kopieras kontinuerligt, oavsett
om det har varit något ändring eller inte. Även om det till det yttre
i princip ger den funktion du ville, så är det sannolikt inte så du ville
att det skulle fungera. Då hade det varit enklare att skippa interrupt
och lägga en loop i main() som bara kopierade pinnarna hela tiden.

Så din originalkod är i princip korrekt.
Men det finns två saker som är nyckeln til problemet och som skulle ha
varit med i första inlägget, hur inpulserna ser ut och dina CONFIG inställningar.

Innan vi vet timingen på in-pulserna (och vilka krav du har på "följsamhet")
så går det naturligtsivs inte heller att säga något om val av programeringsspråk.
Eller om processorn behöver köras snabbare.

Beroende på vilken följsamhet du behöver mellan RB5 och RB3, så
kanske det även finns andra sätt att lösa det på. Om kraven är "låga",
så skulle kopieringen av pinnarna kunna ske i ett timer-interrupt vilket
är lite lättare att få stabilt.

Dangraf har dessutom helt rätt angående de övriga RB pinnarna. Om det
är "open inputs" så kommer de att ge falska interrupt. Utan tvekan. Du
kollar ju inte heller att det är just *RB5* som har ändrats !

Summerat så är tråden ett bra exempel på hur det det hela spårar ur i olika
felaktiga riktningar p.g.a att mycket nyckelinformation utelämnats i förstainlägget.
Och även att inte rätt följdfrågor ställdes direkt...

Slutligen några möjliga felorsaker :
- WDT
- Falska interrupt från andra RB-pinnar (kommer att ibland att dölja ändringar på RB5).
- Snabba spikar/störningar på insignalen.
jonte_s
Inlägg: 88
Blev medlem: 11 februari 2006, 17:13:48
Ort: Stockholm

Inlägg av jonte_s »

Har testat lite mer nu.

TRISB = 0b00100000 funkar alldeles utmärkt. Så det var som dangraf och Sodjan bla sa, att det kan ju komma interrupt på dem andra pinnarna…

(WDT är avstängd…)

>”Dangraf har dessutom helt rätt angående de övriga RB pinnarna. Om det
>är "open inputs" så kommer de att ge falska interrupt. Utan tvekan.”

Jo jag märkte det :) . Men hur skall man hindra at dem ger falska interrupt?
Skall man aktivera ” internal pull-up”?
När skall man använda pull-ups rent generellt?

Det här är koden som jag kör med nu och som verkar fungera:

Kod: Markera allt

char old_valueOf_F5;

void main(){
  TRISB = 0b111100000;        //1 = input, 0 = output
  
  INTCON.RBIE = 1;            //enable RB interrupt.
  INTCON.PEIE=1;              // pheripheral enable interrupt.
  INTCON.GIE=1;               // global enable interrupt
  while (1){
    delay_ms(500);
    PORTB.F0 = ~PORTB.F0;     // To check that we dont get stuck in interrupt().
  }
}

void interrupt(void){
  if(INTCON.RBIF == 1){
    INTCON.RBIF = 0;
    if(PORTB.F5 != old_valueOf_F5){
      PORTB.F3 = PORTB.F5;
      old_valueOf_F5 = PORTB.F5;
    }
  }
}
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Men hur skall man hindra at dem ger falska interrupt?

Inga öppna CMOS ingångar, det gäller *alltid*.

> När skall man använda pull-ups rent generellt?

Det beror ju helt på...

I det här fallet behövde du dom ju inte som ingångar.
Och om du hade gjort det, så hade de ju varit kopplade till något...
Skriv svar