Hallo, ich beschäftige mich seit einige Teit mit den ATMega8 und habe im aktuellen Projekt das Problem, das der Interrupt (INT0) eine extrem lange Ausführungszeit hat. Konkret versuche ich ein Taktsignal (Messschieber) von 83KHz zu tasten. Bei jeder fallenden Flanke wird der Interrupt ausgelöst, der zu Testzwecken keinerlei Anweisungen beeinhaltet. Durch Togglen eines Ports in der Hauptschleiche (die auch nur das macht und nichts anderes), sehe ich das der Interrupt zu einer Verzögerung von rund 73uS führt. Dies sind bei 8 MHz interner Taktung etwas über 600 Takte ! Dies erscheint mir extrem viel. Ich nutze BASCOM. Ist das normal ? Gibt es hier gewisse Einstellungen, die man treffen muss ? Gruß Sebastian
Da ich Dein Programm nicht kenne kann ich dazu nichts sagen. Aber Deine Rechnung verstehe ich nicht. Ein Signal von 80kHz hat alle 12.5µs (bzw. alle 100 Takte des 8MHz-Controllers) eine fallende Flanke. Wie kannst Du da eine Verzgerung von 73µs bzw. 600 Takte feststellen? Woher weißt Du auf welche Flanke des Signals Du Dich bei der Berechnung beziehen musst?
Hallo, das komplette Programm kann ich heute Abend zur Verfügung stellen, hier mal die wichtgsten Sachen:
1 | on INT0 InterruptHandler |
2 | |
3 | do |
4 | toggle portb.2 |
5 | loop |
6 | end |
7 | |
8 | InterruptHandler: |
9 | return |
Das Taktignal liegt an INT0-Pin an und das Osszi am Port B2. Daher sehe ich ja wie lange die Hauptschleife aussetzt. Heute Abend mach ich davon mal ein Bild. Gruß Sebastian
> Ich nutze BASCOM. Ist das normal ?
Denke schon
Nimm doch mal C oder ASM
Sebastian T. schrieb: > Ich nutze BASCOM. Ist das normal ? Ja, Bascom sichert bei Aufruf der ISR unsinnigerweise (fast) alle Register, auch wenn sie von der ISR nicht verwendet werden. Das dauert... ...
Uwe schrieb: > Nimm doch mal C oder ASM Was meinst Du, warum er Bascom nimmt? Unabhängig davon kann man mit Bascom auch brauchbare Projekte realisieren, ein bissel Hintergrundwissen (zu dem auch die Architektur, also ASM gehört) schadet dabei aber nicht. ...
Sebastian T. schrieb: > sind bei 8 MHz interner Taktung etwas über 600 Takte ! Vergessen... Bist Du sicher, dass der Mega8 mit 8 MHz rennt? Ich vermute, dass er mit 1 MHz klappert, dann wären es etwa 75 Takte, was realistisch ist. Hast Du den Takt per Fusebits eingestellt oder hast Du nur im Quelltext die Taktangabe verändert? ...
Hallo, ich bin mir recht sicher, da ich es auf 8Mhz über die Fuses eingestellt habe (direkt im Studio). Wenn ich bspw folgenden Code verwende:
1 | do |
2 | toggle portb.2 |
3 | loop |
4 | end |
...dann komme ich auf ca. 1.2 MHz Rechtecksignal am Ozzi. Da der toggle Befehl vermutlich auch einige Takte benötigt erscheint es mir gerade noch logisch. Wenn ich auf 4MHz Fuse, dann komme ich auch auf noch länge Zeiten für den Interrupt. Mich irritiert es extrem, da man überall was von 100 Takten zu lesen bekommt. Gruß Sebastian
Sebastian T. schrieb: > Mich irritiert es extrem, da man überall was von 100 Takten zu lesen > bekommt. Ja. Die Abstände der fallenden Flanken Deines 83kHz-Signals sind aber kürzer als 100 Takte. Dein µC kommt vor lauter Interrupts kaum noch zur Ausführung der Main-Funktion.
Hallo, ja das ist sehr deprimierend, das der Interrupt so gigantisch lange braucht. Ich poste heute Abend mal Fotos davon. Es ist so das der Interrupt grobe 4-5 mal aufgerufen wird, wobei der Takt in der selben Zeit ca. 50 mal eine fallende Flanke aufweißt. Ohne Interrupt, mit pollen des Portzustandes komme ich immerhin auf ca. 40 von den 50 Flanken. Überall liest man, das die Interruptausführung 100 Takte dauert, bei mir sind es 600. Das kann irgendwie nicht hinkommen, aber das Ozzi lügt nicht. Gruß Sebastian
Sebastian T. schrieb: > Überall liest man, das die Interruptausführung 100 Takte dauert, bei mir > sind es 600. Wie kommst Du auf die 600? Du misst mit Deinem Oszi doch nur die Tätigkeit der Main-Funktion. Bevor diese es schafft, den Pin einmal zu toggeln, wird sie wohl 4-5 mal von Interrupts unterbrochen (die dann meinetwegen jeweils 100 Takte dauern). Mehr kannst Du doch mit Deinem Messaufbau gar nicht nachprüfen.
Kann BASCOM kein ASM-Listing rausgeben? Das sollte doch erklären wie's läuft.
Ccccc schrieb: > Kann BASCOM kein ASM-Listing rausgeben? > Das sollte doch erklären wie's läuft. Genau. Das und ein Oszibild. Dann hat die Spekuliererei ein Ende.
> Ich vermute, dass er mit 1 MHz klappert, dann wären es etwa 75 Takte, > was realistisch ist. 1 MHz geteilt durch 83 KHz ergibt rund 12.
Bloofart schrieb: > 1 MHz geteilt durch 83 KHz ergibt rund 12. Meine Aussage bezog sich aber nicht auf 83 kHz, sondern auf 600 Takte. Und die Zeitdauer der 600 Takte bei vermuteten 8 MHz entspricht etwa der bei realen 1 MHz. Aber das ist es ja nicht, wie uns bereits bewiesen wurde. Da bleibt nur noch, wie bereits erwähnt, dass die ISR aufgrund der kompletten Registersicherung zu langsam für die Anwendung ist. Abhilfe könnte der ISR-Aufruf mit dem Parameter "nosave" schaffen, dann muss man die benutzten Register aber selbst sichern und wiederherstellen. Dazu ist dann aber wieder etwas Wissen darüber erforderlich, wie Bascom intern (auf ASM-Ebene) arbeitet... ...
Hast du überhaupt ein externes Quarz angeschlossen? Das würde alles erklären. Gruß J
Jonas Biensack schrieb: > Hast du überhaupt ein externes Quarz angeschlossen? Das würde alles > erklären. > > Gruß > J Erstens das, und dann reicht es auch nicht, wenn der Quarz (egal ob intern oder extern) auf 8 MHz läuft. Man muß auch noch CKDIV8 zurücksetzen, damit nicht die 8 MHz durch 8 geteilt werden. Das würde bedeuten, man hat doch nur 1 MHz. Schau dort mal nach...
Hi >Man muß auch noch CKDIV8 >zurücksetzen, damit nicht die 8 MHz durch 8 geteilt werden. Kleiner Schönheitsfehler: Der ATMega8 hat keine CKDIV8-Fuse. MfG Spess
Ok, mein Fehler. Ich bin vom Mega88 ausgegangen, der hat sie. Ich nehm' alles zurück :-) Gruß Bernd
Hallo, anbei die Screenshots. Das Gelbe ist das Signal des Messchiebers. Das Grüne der Ausgang PB2. Das Ganze in verschiedenen Zoomstufen. Hier der Code:
1 | $regfile = "m8def.dat" |
2 | $crystal = 8000000 |
3 | $baud = 9600 |
4 | |
5 | on INT0 OnInterrupt |
6 | |
7 | DDRB.2 = 1 'Oszi-Kontrollausgang |
8 | |
9 | DDRD.2 = 0 'INT 0 |
10 | MCUCR = &B00000010 'int 0 fallende flanke |
11 | GICR = &B01000000 'int 0 aktivieren |
12 | |
13 | SREG.7 = 1 'interrupts ein |
14 | |
15 | Do |
16 | toggle portb.2 |
17 | Loop |
18 | |
19 | OnInterrupt: |
20 | return |
21 | |
22 | End |
Das mit dem Nosave werde ich probieren. Mir ist da gerade was aufgefallen. In dem 2.Screenshot rechts bei der letzten fallenden Flanke ist der Hauptschleifenausetzer wesentlich geringer und damit die Interruptausführzeit. Mein Messmethode hat hier vermutlich einen Fehler. Der Interrupt wird bestimmt direkt hintereinander ausgelöst und es erscheint die lange Abarbeitungszeit in der Phase der "dichten" Clock. Gruß Sebastian
Sebastian T. schrieb: > n dem 2.Screenshot rechts bei der > letzten fallenden Flanke ist der Hauptschleifenausetzer wesentlich > geringer und damit die Interruptausführzeit. Zumindest kannst Du da sehr schön ablesen, wie lange es von der fallenden Flanke bis zum Toggeln des Pins dauert. Und diese Zeit ist etwas größer als der Abstand zweier fallender Flanken. Deine main-Funktion schafft es also nicht in der Zeit zwischen zwei Interrupts, alle für das toggeln des Pins erforderlichen Operationen durchzuführen (sie wird immer wieder unterbrochen). Erst nach fünf- oder sechsmaligem Ausführen der ISR, ist endlich der Pin getoggelt.
Hallo, nach Korrektur meiner Messmethode komme ich nun ohne NoSave auf rund 125 Takte und mit NoSave und Nutzung von Assembler im Interrupt auf 100 Takte. Kann das normal sein ? Die Interruptfunktion sieht nun so aus:
1 | OnInterrupt: |
2 | push R16 |
3 | push R17 |
4 | in R16,SREG |
5 | push R16 |
6 | in R16,portB 'PortB invertieren |
7 | ldi R17,4 'XOR Bit 2 (2^2) |
8 | eor R16,R17 |
9 | !Out PortB , R16 |
10 | pop R16 |
11 | !Out Sreg , R16 |
12 | pop R17 |
13 | pop R16 |
14 | return |
Was macht er in der restlichen Zeit ? Der Assemblercode sind ja nicht 100 Takte. Gruß Sebastian
Sebastian T. schrieb: > Was macht er in der restlichen Zeit ? Der Assemblercode sind ja nicht > 100 Takte. Schon mal den Simulator probiert?
Wieso schreibst du das Togglen des Ports nicht einfach direkt in die Interrupt-Routine? Oder geht es dir darum, zu wissen, wie lange der Interrupt braucht bis er das Programm wieder in der main-Funktion ackert?
Sebastian T. schrieb: > Dies > sind bei 8 MHz interner Taktung etwas über 600 Takte ! Die 600 Zyklen kannst Du in der Pfeife rauchen, die stimmen nicht. Sobald der Handler zu lange dauert, wird sofort wieder ein Interrupt ausgeführt. Dazwischen führt das Main nur einen Befehl aus. Die Pin-Toggle-Loop dauert n Befehle, also sind die 600 Zyklen die Dauer von n Interrupts und nicht nur eines einzigen. Ein Interrupt dauert also (600-1) / n. Wie groß n ist, kannst Du ermitteln, indem Du die Interrupts sperrst oder die 83kHz abschaltest.
Um die Dauer nur eines Interrupts zu ermitteln geht auch: Loop: sei setze Pin <- hier haut nun der Interrupt rein cli lösche Pin
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.