Hallo, ich habe das Problem dass sich der Controller ab einer Frequenz von ca.40kHz am Eingangspin aufhängt. Kann mir einer den Grund dafür erklären? Vielen Dank
ohne dass du uns sagtst wie schnell der controller ist nicht... und die Interruptroutine und deren Abarbeitungszeit wären auch nicht uninteressant...
Joshi schrieb: > Kann mir einer den Grund dafür > erklären? Ja. Da ist ein Fehler in Deinem Programm. Peter
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 | } |
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 | }
|
nicht "gast" schrieb: > PORTC = (PORTC & ~(1<<PC3 | 1<<PC4)) | PCINT_STATE++; PORTC = (PORTC & ~(1<<PC3 | 1<<PC4)) | PCINT_STATE++ << PC3;
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.