Pin Change Interrupt - Controller hängt sich auf ab 40kHz - ATMega168

Gast
Der Controller läuft mit 8MHz und die Interruptroutine sieht 
folgendermaßen aus:
1
ISR(PCINT2_vect)
2
{
3
  PCINT_count++;
4
}

Alle 20ms wird dann der Counter abgefragt und wieder auf Null gesetzt.

Die Routine sieht folgendermaßen aus:
1
void read_PCINT(void)
2
{
3
  switch(PCINT_state)
4
  {
5
    case 0: 
6
    //disable PIN Change Interrupt
7
    PCICR &= ~(1 << PCIE2);
8
    
9
    //read the countet Interrupts
10
    PCINT_buffer[0] = PCINT_count;
11
            
12
    //set colour direction to red
13
    PORTC &= ~(1 << PC3);
14
    PORTC &= ~(1 << PC4);
15

16
    //restore counter value
17
    PCINT_count  = 0;
18

19
    //increase state
20
    PCINT_state++;
21

22
    //enable PIN Change Interrupt
23
    PCICR |= (1 << PCIE2);
24
    break;
25

26
    case 1:  
27
    //disable PIN Change Interrupt
28
    PCICR &= ~(1 << PCIE2);
29
    
30
    //read the countet Interrupts
31
    PCINT_buffer[1] = PCINT_count;
32
            
33
    //set colour direction to green
34
    PORTC |= (1 << PC3);
35
    PORTC &= ~(1 << PC4);
36

37
    //restore counter value
38
    PCINT_count  = 0;
39

40
    //increase state
41
    PCINT_state++;
42

43
    //enable PIN Change Interrupt
44
    PCICR |= (1 << PCIE2);
45
    break;
46

47
    case 2:      
48
    //disable PIN Change Interrupt
49
    PCICR &= ~(1 << PCIE2);
50
    
51
    //read the countet Interrupts
52
    PCINT_buffer[2] = PCINT_count;
53
            
54
    //set colour direction to blue
55
    PORTC &= ~(1 << PC3);
56
    PORTC |= (1 << PC4);
57

58
    //restore counter value
59
    PCINT_count  = 0;
60

61
    //increase state
62
    PCINT_state = 0;
63

64
    //enable PIN Change Interrupt
65
    PCICR |= (1 << PCIE2);
66
    break;
67
  }
68
}
Gast
lässt sich deutlich kürzer schreiben
1
void read_PCINT(void)
2
{
3
    //disable PIN Change Interrupt
4
    PCICR &= ~(1 << PCIE2);
5
    
6
    //read the countet Interrupts
7
    PCINT_buffer[PCINT_STATE] = PCINT_count;
8

9
    PORTC = (PORTC & ~(1<<PC3 | 1<<PC4)) | PCINT_STATE++; 
10

11
    //restore counter value
12
    PCINT_count  = 0;
13

14
    //enable PIN Change Interrupt
15
    PCICR |= (1 << PCIE2);
16
}
(Firma: guloshop.de)
Hallo!

Joshi schrieb:
> Der Controller läuft mit 8MHz und die Interruptroutine sieht
> folgendermaßen aus:

Sicher, dass nicht das Fuse-Bit CKDIV8 auf 0 programmiert ist? In dem 
Fall würde dein Mikrocontroller nämlich mit 1 MHz laufen und den Fehler 
erklären.

1
> ISR(PCINT2_vect)
2
> {
3
>   PCINT_count++;
4
> }

Falls PCINT_count eine 16-Bit-Variable ist, braucht die Interruptroutine 
mehr als 50 Taktzyklen, wenn sie in C geschrieben ist.

Genaueres siehst du, wenn du dir den generierten Code disassemblieren 
lässt.

Mögliche Lösung: nimm Assembler, dann sind es 15 bis 17 Zyklen...

Zum PCI: Denk dran, dass der bei jedem Flankenwechsel ausgelöst wird, 
also beim Wechsel von 1 auf und und beim Wechsel von 0 auf 1. Falls dir 
eine Flanke reicht, nimm den INT0.
Joshi schrieb:
> Alle 20ms wird dann der Counter abgefragt und wieder auf Null gesetzt.
Warum nimmst du keinen Timer und taktest den extern über dein Signal? Da 
kannst du dann ohne Interruptlast zählen.

Ich tippe mal darauf, dass der µC ab einer bestimmten Signalfrequenz 
ständig in der ISR hängt, weil bevor die abgearbeitet ist, das 
Interruptflag schon wieder gesetzt wird und gleich nach dem reti ein 
neuer Aufruf der ISR stattfindet.

Gruß Oliver

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.