alle 32 Takte ein Interrupt ?
Nicht schlecht, soll der Controller sonst noch was machen ?
Poste mal bitte die *.lss Datei, damit man sehen kann, wie lange verweilt er in dem Interrupt.
Gruß Sebastian
Hi,
ich verwende den Timer0 eines Mega32 im CTC-Modus. Ich habe einen 16MHz Quarz angeschlossen, Fuses sind gesetzt. Ich möchte Interrupt alle 2µs auslösen.
Welchen Wert muss ich nun einsetzen? Prescaler habe ich ausgeschaltet (Clocksource ist also der Systemtakt (16MHz)).
Meine Berechnung:
Ein Takt dauert 1 / 16MHz = 62.5ns
Ich muss also alle (2µs / 62.5ns = 32) Takte einen Interrupt auslösen.
Folglich stelle ich OCR auf 32.
Es ergibt sich aber (mit Oszi-Messung), dass der Zeitabstand zwischen den IRQs (gemessen wird PORTA:0) etwas größer ist als 2µs (genauer gesagt: er ist 2,3µs groß).
Woran liegt das?
Dachte, es liegt vllt daran, dass durch den IRQ-Aufruf Zeit verbraucht wird, aber das sollte sich ja ausgleichen.
Gruß, CowZ
PS: Hier der Code:
Code:#include <stdint.h> #include <avr/io.h> #include <avr/interrupt.h> uint8_t sync; int main(void) { DDRA = 0xFF; // Timer initialisation // CTC TCCR0 |= (1<<WGM01); TCCR0 &= ~(1<<WGM00); // OC0 disabled TCCR0 &= ~( (1<<COM01) | (1<<COM01) ); // Clock TCCR0 |= (1<<CS00); TCCR0 &= ~( (1<<CS02) | (1<<CS01) ); // OCR Settings OCR0 = 32; // IRQ-Settings TIMSK |= (1<<OCIE0); // Compare Match IRQ sync = 0; sei(); while(1) {}; } ISR(TIMER0_COMP_vect) { if (sync) { PORTA = 1; sync = 0; } else { PORTA = 0; sync = 1; } }
alle 32 Takte ein Interrupt ?
Nicht schlecht, soll der Controller sonst noch was machen ?
Poste mal bitte die *.lss Datei, damit man sehen kann, wie lange verweilt er in dem Interrupt.
Gruß Sebastian
Linus TorvaldSoftware is like s e x: its better when its free.
Hi,
du meinst du .lst Datei?
Kein Problem, ist im Anhang
Gruß, CowZ
Ich meinte schon *lss, aber egal, die ist auch gut
Ich habe die ISR rauskopiert und die Takte eben gezählt(Hoffe, daß ich mich nicht grob verechnet habe)
Bevor der µC in die ISR springt vergehen noch 3(?) Takte insgesammt dann 40(?), tja dumm gelaufen...Code:ISR(TIMER0_COMP_vect) { ca: 1f 92 push r1 2 cc: 0f 92 push r0 4 ce: 0f b6 in r0, 0x3f 5 d0: 0f 92 push r0 7 d2: 11 24 eor r1, r1 8 d4: 2f 93 push r18 10 d6: 8f 93 push r24 12 if (sync) d8: 80 91 60 00 lds r24, 0x0060 14 dc: 88 23 and r24, r24 15 de: 29 f0 breq .+10 16 { PORTA = 1; e0: 81 e0 ldi r24, 0x01 17 e2: 8b bb out 0x1b, r24 18 sync = 0; e4: 10 92 60 00 sts 0x0060, r1 20 e8: 04 c0 rjmp .+8 22 } else { PORTA = 0; ea: 8b bb out 0x1b, r24 19 sync = 1; ec: 21 e0 ldi r18, 0x01 20 ee: 20 93 60 00 sts 0x0060, r18 22 f2: 8f 91 pop r24 24/24 f4: 2f 91 pop r18 26/26 f6: 0f 90 pop r0 28/28 f8: 0f be out 0x3f, r0 29/29 fa: 0f 90 pop r0 31/31 fc: 1f 90 pop r1 33/33 fe: 18 95 reti 37/37
Kannst Du das nicht anders lösen ?
Den zugehörigen Pin in Hardware toogeln lassen ?
Gruß Sebastian
P.S. Doch verrechnet Es war ein Takt zu viel....
Linus TorvaldSoftware is like s e x: its better when its free.
So sieht's aus!
Aber hast Du schon die unterschiedlichen Optimierungen versucht? Ich würde mit der Optimierung s (Space) anfangen. Es besteht Optimierungspotential bei den verwendeten Registern. Eigentlich käme der Compiler nämlich auch mit weniger als 5 Registern aus. Dann würdest Du einige Pushs usw. sparen und kämst so vielleicht in die Region von 25-31 Takte. Wenn Du dann noch als erstes in der ISR den Timer ausschaltest, und den OCR1 Wert auf 32-(optimierte Taktzahl) einstellst), also irgendwas zwischen 1-10, dann könnte es gehen.
Ansnonsten sehe ich gerade nur die Möglichkeit, das Programm in Assembler zu schreiben. Dann kannst Du Dir die ganzen Pushs und Pops sparen. Das müsste gehen, wenngleich dann auch nicht mehr viel weiteres geht.
Möglicherweise kannst Du auch (zb mit Inline Assembler) in C die ISR umgehen, indem Du statt des Funktionsaufrufs den Sprung selbst nutzt. Keine Ahnung ob und wie sowas geht. Vielleicht weiß das wer anders...
Gruß
Hallo,
als größte Optimierung würde ich die Globale Variable sync rausschmeissen und den Pin einfach nur in der ISR toogeln,
Das dürfte schon ein paar Takte einsparenCode:PORTA ^=(1<<PA1);
Aber wie gesagt, am besten alles in Hardware machen,
non PWM ,den zugehörigen PIN bei Compare Match toogeln und OCR0 auf 16 stellen.
Nachteil, es ist nicht unbedingt PA1
Vorteil der Controller kriegt langeweile und kann in der Zeit was anderes machen
Gruß Sebastian
Linus TorvaldSoftware is like s e x: its better when its free.
Ja stimmt, synch muss raus, aber
PORTA xor (1<<PA1) ?
warum nicht
PORTA = ~PORTA
Mit Optimierung meinte ich die Option im C-Compiler.
Ist ein µC keine Hardware???
Gruß
Hallo Gock,
Ich weiß nicht, was CowZ vor hatJa stimmt, synch muss raus, aber
PORTA xor (1<<PA1) ?
warum nicht
PORTA = ~PORTA
Mit PORTA = ~PORTA;
wackelst Du an allen PortA Pins
mit
PORTA^=(1<<PA0); <- PA0 und nicht PA1
nur am PA0 was der Aufgabenstellung eher entspricht
Na egal, wir wissen ja nicht, was wirklich verlangt wird...
Ich weiß, wie Du das meinst, die Variable rauszuschmeissen bringt aber das meisteMit Optimierung meinte ich die Option im C-Compiler.
klar, ich meine das Toggeln komplett in Hardware machen, ohne Interrupts!Ist ein µC keine Hardware???
Bei M32 wäre das der Pin PB3, der mit der ComparMatch Unit von Timer 0 zusammenhängt...
Gruß Sebastian
Linus TorvaldSoftware is like s e x: its better when its free.
Hi,
was ich schlussendlich vorhatte/vorhabe: einen BAS-Sync erzeugen. Mal schauen, vllt mach ich das auch mit nem CPLD, mal schauen.
Vielen Dank erstmal für eure Hilfe. Bin ab morgen eine Woche in Barcelona, danach mal gucken, wie ich das mache
Gruß, CowZ
@ izaseba
Ach die Hardware meinst Du... Sag das doch gleich!
Ja, auch ne gute Idee, aber wie Du schon sagtest, man weiß zu wenig, den optimalen Tip zu geben.
Die Schreibweise mit dem XOR kannte ich noch nicht.
Gruß
Lesezeichen