Forum: Mikrocontroller und Digitale Elektronik mega 8 läuft zu langsam?


von max (Gast)


Lesenswert?

moin,
ich habe nen mega 8 aufm stk500 und will ihn mit quarz auf 8mhz laufen 
lassen.
ich habe alles angeschlossen auch die fuses gesetzt doch wenn ich mitm 
ossi messe habe ich gerade mal rund 2mhz.
ich habe folgendes zum messen in der hauptschleife:

 while(1)
 {
 PORTB=~PINB;
 }

warum ist das so langsam?
es wird ja wohl kaum so stark durch c ausgebremst werden, oder?

mfg max

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Schau im Assemblerlisting (der vom C Compiler ggf. erzeugten *.LST oder 
der *.LSS Datei oder im AVR Studio Disassembler) nach, wieviele 
Assemblerbefehle der C-Compiler aus diesem Mini-C-Code gemacht hat.

Der AVR lann pro Trakt im günstigsten Fall einen Befehl abarbeiten, bei 
manchen Befehlen sind sogar mehr Takte notwendig... Die Takte pro Befehl 
stehen iM Assembler Instruction Set Manual.

2 MHz am IO-Pin bei 8 MHz CPU-Takt sind bei dem Hintergrund nicht übel.

von jens (Gast)


Lesenswert?

Hallo,

Du wolltest sicher schreiben:
while(1)
 {
 PORTB=~PORTB;
 }
Was hast du gegen 2Mhz. Da ist ein Vergleich und eine Zuweisung bei. 
Kenne mich nicht mit Assembler aus, sonst könnte man sicher die Takte 
ermitteln. Besser du stellst den Takt über einen Timer fest. Der läuft 
über die Hardware und ist von Programmlaufzeiten unabhängig.

Gruß

Jens

von holger (Gast)


Lesenswert?

>ich habe nen mega 8 aufm stk500 und will ihn mit quarz auf 8mhz laufen
>lassen.

Die Quarzfrequenz misst du am Quarzoscillator (XTAL1/XTAL2)

von max (Gast)


Lesenswert?

ich werde leider nicht schlau aus dieser datei...

wie kann ich denn am besten messen wie schnell er wirklich läuft?
ich habe jetzt mal nen 20mhz quarz draufgesteckt und messe jetzt 5mhz an 
portb
kommt ja eigendlich hin:
(20mhz_gequarzt/8mhz_gequarzt)*2mhz_gemessen=5mhz_gemessen
ich glaube ich probier mich mal in assembler...

vielen dank

wenn trotzdem jemand noch ne idee hat wäre das toll.
ich will eigendlich nur ausloten wie schnell ich mit dem timer1 
interupts
machen kann und wieviel zeict ich dazwischen habe.

von max (Gast)


Lesenswert?

der quarz schwingt wunderbar.
ich habe mich nur gewundert das ich mit dem timerinterupt so komische 
zeiten hatte.
wenn ich jetzt über die kommentare nachdenke scheint es vielleicht 
normal zu sein.

von AVRFan (Gast)


Lesenswert?

>wie kann ich denn am besten messen wie schnell er wirklich läuft?

Du kannst Dir z. B. ein Mini-Assemblerprogramm schreiben, dass Dir einen 
Pin alle exakt 10 Taktzyklen toggelt:
1
   [PORTB als Ausgang konfigurieren]
2
3
Loop:
4
   com r16
5
   out PORTB, r16
6
   nop
7
   nop
8
   nop
9
   nop
10
   nop
11
   nop
12
   rjmp Loop

ich habe jetzt mal nen 20mhz quarz draufgesteckt und messe jetzt 5mhz an
portb
kommt ja eigendlich hin:
(20mhz_gequarzt/8mhz_gequarzt)*2mhz_gemessen=5mhz_gemessen

Du wirst mit Deinem C-Programm am Pin immer ein Viertel der 
Quarzfrequenz messen. Ist ja auch klar: Dein Controller führt 
wahrscheinlich
1
Loop:
2
   com r16
3
   out PORTB, r16
4
   rjmp Loop

aus, und das sind 4 Taktzyklen von out bis zum nächsten out (com und out 
benötigen je 1 Zyklus, rjmp 2 - siehe Datenblatt).

>wenn trotzdem jemand noch ne idee hat wäre das toll.

Ne Idee für was??

>ich will eigendlich nur ausloten wie schnell ich mit dem timer1
>interupts machen kann und wieviel zeict ich dazwischen habe.

Wie schnell brauchst Du es denn?

von max (Gast)


Lesenswert?

ich weiss auch nicht was ich gemacht habe aber jetzt ists besser
habe jetzt:

SIGNAL(SIG_OVERFLOW1)
{
PORTB=~PORTB;
TCNT1=65000;
}

und ich messe ca 70µs, das ist top (mit 8mhz quarz)

vielen dank ihr füchse :)

mfg max

von Walter (Gast)


Lesenswert?

wie jetzt, vorhin warst du mit 2MHz unzufrieden und jetzt reichen dir 
14kHz?

von AVRFan (Gast)


Lesenswert?

>TCNT1=65000;

Kleiner Hinweis: Das mit dem Reload von TCNT1 im Overflowinterrupt 
funktioniert zwar, allerdings kannst Du nicht wissen, wann genau der 
Interrupthandler aufgerufen wird, weil die Instruktionen nicht alle 
gleich viel Taktzyklen beanspruchen (clr: 1, rjmp: 2, rcall: 3, ret: 4), 
oder auch, weil es noch andere Interrupts oder critical sections geben 
kann.

Tip: Wenns genau sein soll, lass den Timer besser im CTC-Mode laufen 
(siehe Datenblatt).  Dann wird bei Überschreiten eines wählbaren Wertes 
ein OutputCompareMatch-Interrupt ausgelöst und der Timer automatisch 
sofort wieder auf Null gesetzt.

von max (Gast)


Lesenswert?

vielen dank für den tip ich hab mich schon gefragt wie das mit der 
gleichmäßigkeit dann ist. was ist denn wenn der interupt kommtn wärend 
ich noch im handler bin?

von mehrfacher STK500-Besitzer (Gast)


Lesenswert?

>was ist denn wenn der interupt kommtn wärend ich noch im handler bin?

Die werden erst nach Verlassen der ISR angesprungen, sonfern man die 
anderen Interruptquellen nicht explizit in der ISR wieder frei gibt.
Der AVR besitzt keine Interrupt-Prioritäten, wie der 8051.

von AVRFan (Gast)


Lesenswert?

>was ist denn wenn der interupt kommtn wärend ich noch im handler bin?

Der gleiche Interrupt A sollte selbstverständlich niemals auftreten, 
während das Programm noch im Interrupthandler von A verweilt.  Das würde 
das Konzept der Interrupts zunichte machen (Erklärungen dazu weiter 
unten).  Es gilt ja die Regel, dass alle Interrupthandler so kurz wie 
möglich zu halten sind, damit der µC immer genug Luft hat, alle 
auftretenden Interrupts abzuarbeiten.

Was man natürlich nicht verhindern kann, ist das Auftreten einer 
Interruptbedingung B, während sich das Programm gerade im 
A-Interrupthandler aufhält. Viele Interrupts werden schließlich von 
externen Ereignissen ausgelöst, und wenn Du z. B. ein Zeichen von Deinem 
PC über die serielle Schnittstelle abschickst, weißt Du nicht, womit 
Dein Programm in dem Moment beschäftigt ist, in dem die 
UARTDataRxComplete-Interruptbedingung zutrifft.

Dann passiert folgendes. Grundsätzlich wird beim Auftreten einer 
Interruptbedingung immer augenblicklich das zugehörige Interrupt-Flag 
von der Interruptlogik gesetzt.  Diese Flags stecken in den 
I/O-Registern Deines Controllers (z. B. ICF1, TOV1, RXC, TXC, ACI). 
Damit ist der Interrupt "vorgemerkt" (engl. pending interrupt).  Wann 
jedoch der Sprung auf den Interruptvektor (und von dort aus in den 
Interrupthandler) erfolgt, hängt vom I-Flag im SREG (globales 
Interrupt-Freigabeflag) ab.  Solange es gelöscht (alle Interrupts 
gesperrt) ist, erfolgt kein Sprung - der Interrupt bleibt vorgemerkt.

Ist es gesetzt, wird in jedem Fall noch die gerade ausgeführte 
Instruktion zuende verarbeitet, und dann erfolgt der Sprung auf den 
Interruptvektor.  Mit diesem Sprung wird automatisch gleichzeitig das 
spezifische Interruptflag gelöscht (*) und ebenso das I-Flag. 
Interrupthandlers können also nicht durch andere Interrupts 
geinterrupted werden (außer Du setzt das I-Flag am Anfang des Handlers 
durch ein "sei" - das solltest Du aber wegen des Risikos eines 
Stacküberlaufs niemals tun). Das Wieder-Setzen des I-Flags geschieht i. 
a. mit dem "reti" am Ende eines Interruptshandlers, wobei dies dem 
Programmierer obliegt.

(*) Meistens, aber es gibt spezielle Fälle, wo es anders geregelt ist.

Das I-Flag kann man auch selbst löschen und wieder setzten (mit "cli" 
und "sei"), wenn man möchte, dass bestimmte kritische Programmabschnitte 
aus irgendeinem Grund nicht von einem Interrupt unterbrochen werden. Das 
nennt man eine Critical Section.  Auch solche Abschnitte sollten 
möglichst kurz gehalten werden.

Und klar, es kann sogar sein, dass im Moment des Wieder-Setzens des 
I-Flags zufällig mehrere Interrupts anstehen. Dann wird derjenige 
davon ausgeführt, der am weitesten "oben" in der Interruptvektor-Tabelle 
steht, während die anderen natürlich pending bleiben.  Das ist dann so 
eine Art Interrupt-Priorität (aber keine "echte" wie bei anderen 
Controllerfamilien).

Bei lange dauernden Interrupts würde man Gefahr laufen, Interrupts zu 
"verlieren".  Das wäre dann der Fall, wenn ein Interruptflag gesetzt 
würde, welches schon gesetzt ist.  Hält man dagegen alle 
Interrupthandler und alle critical sections wie gesagt kurz, kann das 
nicht passieren, weil alle Pending-Flags schnell wieder gelöscht werden.

Man kann diesen Mechanismus übrigens auch im Simulator vom AVRStudio in 
allen Einzelheiten nachverfolgen.  Gegebenenfalls viel Spaß ;-)

von max (Gast)


Lesenswert?

joa danke!!!

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
Noch kein Account? Hier anmelden.