Forum: Mikrocontroller und Digitale Elektronik Geschwindigkeit?


von Mr.Burns (Gast)


Lesenswert?

Hallo,

ich habe einen Atmega32 mit 1 MHz auf einem STK-600 laufen.
Der Takt kommt vom STK-600, am XTAL1 kann ich per Ossi ca. 1 MHz messen.
Habe nun folgenden simplen Code übersetzt (mit AVR Studio 5 Optimierung 
-O1) dann zum Atmega32 übertragen:

int main(void)
{
    DDRD |= 0x04; // Bit 2 auf Ausgang setzen;
    while(1)
    {
    PORTD ^= ( 1 << PD2 ); // PD2 toggeln
    }
}

Wenn ich nun an Pin 2 von PortD messe, bekomme ich 'nur noch' 66 kHz 
angezeigt.
Wenn ich mit -O3 kompiliere ändert sich nichts.
Warum kommt von dem 1Mhz bei so simplen Code keine höhere Frequenz am 
PD2 an? Ist der Compiler nicht effizient oder mache ich einen 
Denkfehler?

Danke für Infos!

von Bob (Gast)


Lesenswert?

Schau Dir mal den Assembler-Code an, im Simulator,

dann wießt Du was das Ding in Wirklichkeit tut.

(Sofern das Studio 5 noch anbietet)

von Peter D. (peda)


Lesenswert?

67kHz sind 7 Zyklen pro Schleifendurchlauf. Das ist für eine RISC-CPU 
ganz o.k.

Mit -Os solltest Du etwas besser werden.
Andere Optimierungen sollte man nur dann nehmen, wenn man auch weiß 
warum.


Peter

von Ralph (Gast)


Lesenswert?

Mr.Burns schrieb:
> PORTD ^= ( 1 << PD2 ); // PD2 toggeln

Diese Zeile enthält eine ganze Menge mehr als es auf den ersten Blick 
aussieht.

Aufgespalten auf einzelne Befehle sieht das in etwa so aus:
( ist jetzt nicht speziell auf AVR's geschrieben, dafür kenne ich die 
Teile zu wenig)

1. Lade "PORTD" in ein Register ( Sollte 1 Assembler Intruction sein )
2. Lade "1" in ein Register  ( Sollte 1 Assembler Intruction sein )
3. Lade "PD2" in ein Register  ( Sollte 1 Assembler Intruction sein )
4. Schiebe "1" um eine Stelle nach Links und erhöhe den Zähler  ( Sollte 
1 oder 2 Assembler Intruction(s) sein )
5. Vergleiche Zähler mit Register "PD2" ( Sollte 1 Assembler Intruction 
sein )
6. Sprung nach 4. oder nach 7. ( Sollte 1 Assembler Intruction sein )
7. ^ Operation auf Register "PORTD" mit Register "1" ( Sollte 1 
Assembler Intruction sein )
8. Schreibe Register "PORTD" nach der Adresse für "PORTD"

Also ich komme da im günstigsten Fall auf 8 Instructions. ==> 1 MHz / 8 
= 125 KHz am Ausgang.

Dazu kommt noch die While(1) Loop mit idealerweise einer Instruction.
==> also noch 1 MHz / 9 = 111 KHz

Je nachdem wie groß der Wert PD2 ist, kommen die entsprechenden 
Wiederholungen für die Punkte 4 - 6 hinzu.

Wenn du dir jetzt das Assemblerlisting in deiner IDE ansiehst, wirst du 
etwas ähnliches wie meine Punkte finden.

von Oliver (Gast)


Lesenswert?

Ralph,

(1 << PD2) ist für den Compiler eine Konstante, dafür wird kein Code 
erzeugt, der etwas nach links schiebt.

Poste mal den Assemblercode.

Ist evtl. die Fuse CKDIV8 gesetzt?

von Mr.Burns (Gast)


Lesenswert?

Hallo,

Danke erstmal für die Antworten, wie prüfe ich ob CKDIV8 gesetzt ist in 
AVR Studio 5?

Danke!

von Walter S. (avatar)


Lesenswert?

Fuses auslesen

von Sebastian M. (compressed)


Lesenswert?

das sollten bei "-O3" 5 ticks sein (*2)

also 100kHz


1
PORTD ^= ( 1 << PD2 ); // PD2 toggeln
2
  c0:  94 e0         ldi  r25, 0x04  ; 4
3
  c2:  82 b3         in  r24, 0x12  ; 18
4
  c4:  89 27         eor  r24, r25
5
  c6:  82 bb         out  0x12, r24  ; 18
6
  c8:  fc cf         rjmp  .-8        ; 0xc2 <main+0x4>

von Peter D. (peda)


Lesenswert?

Mr.Burns schrieb:
> Danke erstmal für die Antworten, wie prüfe ich ob CKDIV8 gesetzt ist in
> AVR Studio 5?

Deine Mainloop dauert nur 7 Zyklen, also kann sie nicht gesetzt sein.


Peter

von H.Joachim S. (crazyhorse)


Lesenswert?

@Sebastian: rjmp braucht 2 Zyklen, also insgesamt 6. Dafür aber 2 
Register.
Mit sbic/sbis und sbi/cbi komme ich auch auf 7, ohne Registernutzung.

von Ralph (Gast)


Lesenswert?

Oliver schrieb:
> (1 << PD2) ist für den Compiler eine Konstante, dafür wird kein Code
> erzeugt, der etwas nach links schiebt.


Erstmal ist das eine Anweisung die zur Laufzeit ausgeführt wird und 
KEINE Konstante.

Wenn der Compiler erkennen kann, das PD2 eine Konstante ist, kann unter 
Umständen diese Anweisung zur Compilezeit berechnet und als Konstante in 
den Code eingefügt werden.

Das muss aber nicht so sein.

Aus dem Ursprungspost geht nicht hervor ob "PD2" eine Konstante oder 
eine Variable ist.

von Vlad T. (vlad_tepesch)


Lesenswert?

Ralph schrieb:
> Wenn der Compiler erkennen kann, das PD2 eine Konstante ist
natürlich kann er das.
Es ist ein Symbol, dass er auflösen muss und wo 2 rauskommt
Kann er das nicht, gibts einen Fehler zur Compile-Zeit
> , kann unter
> Umständen diese Anweisung zur Compilezeit berechnet und als Konstante in
> den Code eingefügt werden.

sobald irgend eine optimierung angeschaltet ist wird das ersetzt.

von gaast (Gast)


Lesenswert?

Ralph schrieb:
> Erstmal ist das eine Anweisung die zur Laufzeit ausgeführt wird und
> KEINE Konstante.
> [...]
> Aus dem Ursprungspost geht nicht hervor ob "PD2" eine Konstante oder
> eine Variable ist.

Erst so sicher, und dann doch wieder nicht?
Ja, PD2 ist eine Konstante, nein, natürlich kannst du es nicht wissen, 
wenn du dich nicht mit dem AVR-GCC auseinander setzt, und nein, das wäre 
an sich auch kein Problem, aber dann bitte auch die Füße stillhalten 
falls dich jemand korrigiert.

von MrBurns (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

danke erstmal an alle hier!

PD2 ist wie folgt definiert:

#define PD2 2

(aus C:\Programme\Atmel\AVR Studio 5.0\AVR 
ToolChain\avr\include\avr\iom32.h
  (542):    #define PD2     2
)

Ich weiß aber immernoch nicht, wie ich auslesen kann, ob ich einen 
Vorteiler verwende.
Habe mal einen Screenshot von den Fuses im AVR Studio 5 gemacht.
Wo sehe ich nun dort den Vorteiler?

Danke!

von Ulrich (Gast)


Lesenswert?

Der Mega32 hat noch gar keinen Vorteiler für den µC Takt. Den gibt es 
dann beim neueren, sonst ähnlichen Mega324.

Prüfen ob CLKDIV8 gestetzt ist kann man durch auslesen der Fuses mit dem 
dem Programmer. Wie das angezeigt wird hängt von der Software ab mit der 
man den Programmer steuert.

von Karl H. (kbuchegg)


Lesenswert?

MrBurns schrieb:

> Wo sehe ich nun dort den Vorteiler?

Der Mega32 hat keine CKDIV8 Fuse (siehe Datenblatt, in dem stehen alle 
Fuses und auch speziell diejenigen, die die Taktfrequenz des µC 
betreffen). Also kann die auch nicht eingeschaltet sein. (*)


DU hast also keinen 'Vorteiler'. Wenn dein µC mit einem 1Mhz Quarz 
getaktet wird, dann läuft der auch mit 1Mhz. Hängst du einen 16MHz QUarz 
und (und sind die Fuses so, dass der auch benutzt wird), dann läuft der 
auch mit 16Mhz.

* Zur Not kann man auch darauf vertrauen, dass das Brennprogramm alle 
Fuses einbes speziellen Prozessors kennt.

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.