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!
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
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.
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?
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
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.
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.
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.
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!
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.
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.