Hallo,
ich habe ein Problem mit meinem ATmega8. Dieser sollte eigentlich mit
einem externen Quarz auf 8Mhz laufen (die Fuses sind auf Bild2 zu
sehen).
Wenn ich allerdings die Frequenz messe ist dieser um den Faktor 10 zu
langsam d.h. er läuft nur mit 800 khz (siehe Bild 1).
Dieses Ergebnis habe ich bekommen indem ich einfach einen IO Pin toggeln
lasse:
while(1)
{
PORTC ^= (1<<0);
}
Hat da jemand eine Idee an was das liegen könnte ?
MfG.
Das togglen erfolgt nicht in einem taktzyklus (und selbst dann hättest
du nur 4 mhz), schreib lieber ein proggi das einen timer als ausgabe
verwendet (und einen festen Teiler hat)...
Peter II schrieb:> Max D. schrieb:>> Das togglen erfolgt nicht in einem taktzyklus>> doch macht es.
nachtrag:
Wenn man es wirklich toggelt, aber ich sehe gerade das er es ja von hand
macht. Dann ist es wirklicht nicht der Fall.
Peter II schrieb:> Max D. schrieb:>> Das togglen erfolgt nicht in einem taktzyklus>> doch macht es.
naja, der loop verzögert dann, dann hast du nichtmehr einen zyklus (ich
wollts einfach halten)
>doch macht es.>PORTC ^= (1<<0);
Nein. XOR ist immer:
IN Rxx, PORTC
EOR Rxx, 0x01
OUT PORTC, Rxx
JMP zurück
Aber das sollte man im ASM-Listing erkennen. Da kann man zählen. Diese
vier Befehle sollten acht Takte brauchen..
Okey das habe ich mir fast gedacht.
Allerdings war mir nicht klar das das so gravierend ist da ja immerhin
nur 1/10 der original Taktfrequenz übrig bleiben.
µC Neuling schrieb:> Okey das habe ich mir fast gedacht.> Allerdings war mir nicht klar das das so gravierend ist da ja immerhin> nur 1/10 der original Taktfrequenz übrig bleiben.
So
1
while(1)
2
{
3
PORTC|=(1<<0);
4
PORTC&=~(1<<0);
5
}
sollte es schneller gehen. Das müsste dich fast bis auf 2.6Mhz bringen.
Allerdings ist die 'Schwingung' dann leicht asymetrisch.
Bis auf 4Mhz kommt man dann nur noch mit dem Einsatz eines Timers, den
den Pin in Hardware toggelt.
µC Neuling schrieb:> ich habe ein Problem mit meinem ATmega8.
Nein, hast du nicht. Du hast vielmehr ein Problem mit dem Verständnis
deiner Programmiersprache. Was allerdings insofern entschuldbar ist, als
daß es sich um eine Scheißsprache handelt. Allerdings hast du sie selber
ausgewählt und zwar ganz offensichtlich falsch für den beabsichtigten
Zweck, der ja wohl die Messung einer Taktfrequenz ist.
Dafür sind Hochsprachen grundsätzlich ungeeignet, auch
Pseudohochsprachen bzw. aufgedonnerte Makroassembler wie C. Weil man
einfach nicht vorhersagen kann, was der gewählte Compiler in der
gewählten Version mit den gewählten Optimierungsoptionen letztlich für
einen Code produziert.
In einer richtigen Sprache (natürlich Assembler) siehst du hingegen
jederzeit, was genau du tust.
Dieser syntaktisch wunderschön aufgedonnerte Bullshit:
> while(1)> {> PORTC ^= (1<<0);> }
wird vom Compiler (ohne Optimierung) nämlich (bestenfalls) etwa so
ausgedrückt:
loop:
in reg1,PORTC ;1
ldi reg2,1<<0 ;1
eor reg1,reg2 ;1
out PORTC,reg1 ;1
rjmp loop ;2
d.h.: Du müßtest also zwar keine 8 MHz messen, aber immerhin 8/6, also
ca. 1,33 Mhz. Keine Ahnung, wie es dein C-Compiler schafft, die Sache
noch suboptimaler umzusetzen, aber von 1,33MHz bis 800kHz ist es nicht
mehr allzu weit, ich würde es also auf jeden Fall erstmal dem Compiler
anlasten.
Übrigens: In Assembler schafft man ohne Änderung des Grundkonzeptes
wenigstens 8/5=1,6MHz, einfach indem man die Initialisierung von reg2
aus der Schleife holt. Die meisten Compiler schaffen das inzwischen
allerdings auch in irgendeiner Optimierung.
Mit einem etwas besseren Ansatz, den einem weder Assembler noch Compiler
abnehmen können, (zwei Hilfregister, beide vor dem Eintritt in die
Schleife initialisiert) schon 8/4=2MHz und bei Ausnutzung eines Features
der neueren AVRs (Hardwaretogglen) 8/3=2,67MHz. Und natürlich: Wenn man
einen Timer zu Hilfe nimmt, kommt man auf 8/2=4MHz. Und das Ende der
Geschichte ist die Benutzung von CLKO, was die Sache dann endgültig auf
8/1=8MHz bringt. Mehr geht absolut nicht. ;o)
> Dieser sollte eigentlich mit> einem externen Quarz auf 8Mhz laufen
Das tut er aller Wahrscheinlichkeit nach auch.
@kbuchegg: Wie kommst Du denn auf die 2,6MHz?
Deine Schleife compiliert hier zu SBI, CBI, RJMP, mit 1, 1 und 2 Takten,
es müßten also 2MHz mit einem Puls-Pausen-Verhältnis von 1:3
herauskommen.
@c-hater: Du übersiehst, daß bei der XOR-Variante eine Periode des
Ausgangssignals zwei Schleifendurchläufe braucht.
c-hater schrieb:> Du müßtest also zwar keine 8 MHz messen, aber immerhin 8/6, also> ca. 1,33 Mhz
Das ist nicht die Frequenz, sondern die halbe Periode. Für eine ganze
Periode muss die Schleife 2x durchlaufen werden, das wäre dann 665kHz.
Bei 800kHz wurde also noch etwas optimiert.
Gruß Dietrich
R. Max schrieb:> @kbuchegg: Wie kommst Du denn auf die 2,6MHz?>> Deine Schleife compiliert hier zu SBI, CBI, RJMP, mit 1, 1 und 2 Takten,> es müßten also 2MHz mit einem Puls-Pausen-Verhältnis von 1:3> herauskommen.
Ah, richtig. rjmp braucht länger. Ich hatte alles mit 1 Takt angesetzt.
Danke für die Korrektur.
> Die meisten Compiler schaffen das inzwischen> allerdings auch in irgendeiner Optimierung.
Deine Polemik ist nicht zum aushalten.
Wenn du von C wenig Ahnung hast und es nicht magst, dann ist das ok.
Aber hör bitte auf, den Unsinn auch noch zu verbreiten.
µC Neuling schrieb:> while(1)> {> PORTC ^= (1<<0);> }
Bist du auf den alten ATmega8 angewiesen? Wenn du den Nachfolger seines
Nachfolgers nimmst, also den ATmega88A und damit einen einigermaßen
aktuellen Mikrocontroller, dann kannst du das Togglen so erreichen:
1
while(1)
2
{
3
PINC=(1<<0);
4
}
Das läuft ungefähr dreimal so schnell, weil es vom Compiler in ganze
zwei Assembler-Befehle übersetzt wird, die insgesamt 3 Takte brauchen:
Karl Heinz Buchegger schrieb:> Wenn du von C wenig Ahnung hast und es nicht magst, dann ist das ok.> Aber hör bitte auf, den Unsinn auch noch zu verbreiten.
Naja, da er ja offensichtlich von Assembler genauso wenig Ahnung hat
(seine Berechnung der resultierenden Frequenz legen dies zumindest
nahe), relativieren sich seine Aussagen entsprechend ;-)
Karl Heinz Buchegger schrieb:> Wenn du von C wenig Ahnung hast und es nicht magst, dann ist das ok.
Ich habe durchaus Ahnung von C, aber gerade deshalb mag ich die Sprache
nicht. Nur Leute, die es gerade so schaffen in C zu programmieren und
auch nix anderes können, die mögen C.
> Aber hör bitte auf, den Unsinn auch noch zu verbreiten.
Das ist kein Unsinn.
Dietrich L. schrieb:> Das ist nicht die Frequenz, sondern die halbe Periode. Für eine ganze> Periode muss die Schleife 2x durchlaufen werden, das wäre dann 665kHz.
Ähem, ja natürlich. Peinlich, peinlich...
c-hater schrieb:> Nur Leute, die es gerade so schaffen in C zu programmieren und> auch nix anderes können, die mögen C.
ich habe schon in Assembler programmiert als deine Eltern sich
wahrscheinlich noch nicht gekannt haben. Anfangs noch von Hand
assembliert Hex-Zahlen eingetippt, später mit Assembler und dann endlich
C (zwischendurch noch Algol, Fortran, Pascal, Lisp, PL1, ...) und ich
kann Dir sagen alles ist besser als Assembler (den ich nur verwende wenn
ich irgendwelche Zyklen zählen muss)
Ich möchte dich Mal sehen wenn Du einen Compiler oder ein auch nur
leicht komplexes Programm in Assembler schreibst.
c-hater schrieb:>> Das ist nicht die Frequenz, sondern die halbe Periode. Für eine ganze>> Periode muss die Schleife 2x durchlaufen werden, das wäre dann 665kHz.>> Ähem, ja natürlich. Peinlich, peinlich...
nicht so schlimm, in Assembler kann das schon Mal passieren ;-)
Markus Weber schrieb:> Bist du auf den alten ATmega8 angewiesen? Wenn du den Nachfolger seines> Nachfolgers nimmst, also den ATmega88A und damit einen einigermaßen> aktuellen Mikrocontroller, dann kannst du das Togglen so erreichen
Angewiesen bin ich nicht wirklich auf den ATmega8, ich bin im Moment nur
ein bisschen am Ausprobieren und hatte mit dazu ein günstiges
Starterkit gekauft wo eben dieser ATmega8 dabei war.
Mir geht es auch gar nicht darum einen IO Pin mit 8Mhz toggeln zu lassen
sondern mich hatte nur gewundert wie die Differenz zwischen
Prozessortakt und der Frequenz des IO Pins zustande kommt.
Aber das hat sich ja geklärt ;-)
MfG.