Interrupt i mikroC / Extern interrupt?
Interrupt i mikroC / Extern interrupt?
Jag har en quadrature encoder med 3600 pulser/varv som jag vill läsa av med en PIC 16f877A @ 20Mhz. Jag vill räkna pulserna och visa dom på en display, detta har jag fått att fungera genom att sätta A och B pinnen från encodern till två vanliga digitala ingångar. Problemet är att under den tid det tar att skriva ut antalet pulser på displayen så missar räknaren pulser.
Så till frågan, hur ska man lösa detta på effektivast sätt?
Edit: Glömde skriva att jag använder mikroC.
Så till frågan, hur ska man lösa detta på effektivast sätt?
Edit: Glömde skriva att jag använder mikroC.
Man löser det vid att ha 1 interrupt!
Den sitter på ena pulståget och vid interrupt kollar den fasen på andra pulsen, då vet den om det är + eller -.
En variabel (X) räknas då upp eller ner enl. detta.
Sedan gör ISR inget mer!
I mainloopen har du en annan variabel (Y):
På det sätt är ISR'n snabb och utläsningen tar den tid den tar.
Den sitter på ena pulståget och vid interrupt kollar den fasen på andra pulsen, då vet den om det är + eller -.
En variabel (X) räknas då upp eller ner enl. detta.
Sedan gör ISR inget mer!
I mainloopen har du en annan variabel (Y):
Kod: Markera allt
if(X != Y)
{
Y = X;
printf(Display,Y); // Nåja, du fattar nog...
}
Tack, för snabbt svar, nu fungerar det! Men en konstig sak är att det bara verkar vara 1800 pulser / varv. Har provat att vrida motor axeln precis ett varv och den visar då ca 1800. Vad kan det bero på? Om det är av intresse så ser min kod ut så här:
Kod: Markera allt
char *siffra[7];
int i=0;
void interrupt(){
INTCON.INTE = 0;
if(PORTD.F3==0){
i++;
}
else{
i--;
}
INTCON.INTE = 1;
INTCON.INTF = 0;
}
void main(){
INTCON.INTE = 1;
INTCON.PEIE = 1;
INTCON.GIE = 1;
OPTION_REG.INTEDG = 1;
PORTB = 0;
TRISB = 1;
PORTD = 0;
TRISD = 8;
Lcd_Config(&PORTB,2,3,0,7,6,5,4);
Lcd_Init(&PORTB);
Lcd_Cmd(LCD_CURSOR_OFF);
while(1){
IntToStr(i,siffra);
Lcd_Out(2,4,siffra);
}
}
Kod: Markera allt
void interrupt(VOID)
{
INTCON.INTE = 0; // VARFÖR?
if(!PORTD.F3)
{
i++;
}
else
{
i--;
}
INTCON.INTE = 1; // VARFÖR?
INTCON.INTF = 0; // VARFÖR? Edit: Därför!!!
}
Du har 3600 pulser om du räknar alla fram (eller bak) flankor på båda pulstågen. Du kan åstadkomma det vid att ha 2 interrupt som räknar på ovanstående sätt.
Senast redigerad av Icecap 9 februari 2008, 21:30:45, redigerad totalt 1 gång.
INTCON.INTE = 0; och INTCON.INTE = 1;
Har jag med för att det inte ska kunna bli en interrupt till innan den aktuella interrupten har räknats. Vet inte om det är nödvändigt.
INTCON.INTF = 0; Har jag med efter att ha läst detta i databladet:
Har jag med för att det inte ska kunna bli en interrupt till innan den aktuella interrupten har räknats. Vet inte om det är nödvändigt.
INTCON.INTF = 0; Har jag med efter att ha läst detta i databladet:
INTF: RB0/INT External Interrupt Flag bit
1 = The RB0/INT external interrupt occurred (must be cleared in software)
0 = The RB0/INT external interrupt did not occur
> Jag har sett att det står i databladet att det finns 15 interrupts på 16f877A
> men vet inte vilka som dom menar förutom RB0/INT?
Figure 14-10. (*SÅ* svart var det väl inte att se...
)
> Finns det fler interrupt-pinnar än RB0/INT jag kan använda?
Se kapitel 14.11.3. Vet dock inte om det passar in på ditt fall. Kanske...
> men vet inte vilka som dom menar förutom RB0/INT?
Figure 14-10. (*SÅ* svart var det väl inte att se...

> Finns det fler interrupt-pinnar än RB0/INT jag kan använda?
Se kapitel 14.11.3. Vet dock inte om det passar in på ditt fall. Kanske...