Forum: Mikrocontroller und Digitale Elektronik MCU-Clock zur Laufzeit ermitteln


von Micha R. (michaavr)


Lesenswert?

Hallo,

habe mal irgenwo gesehen, dass im Bascom die Taktfrequenz des AVR's 
mittels einer internen Variable (Bascom AVR) ausgelesen werden kann.

Das Statement $Crystal=xxx speichert den Wert in einer internen 
Variablen von Bascom ab.

Wie heißt diese Variable?

Irgendwie war das _frequency oder _crystal oder was ähnliches.

Kann mir jemand Auskunft geben oder einen Link nennen?

von Rudolph R. (rudolph)


Lesenswert?

Man kann den Prozessor-Takt nicht ohne Referenz zur Laufzeit ermitteln.

Es gibt nur das #DEFINE mit dem man dem Compiler übergibt, was man für 
die zur Laufzeit auftretende Taktfrequenz hält.

von Micha R. (michaavr)


Lesenswert?

Doch das geht!

Ich habe es selbst schon mal ausprobiert.

In Bascom-AVR gibt es definitiv eine Variable, in der der Wert 
gespeichert wird.

Zuweisung erfolgt mit dem Statement: $CRYSTAL

(#Define gibts in Bascom-AVR nicht. Das sieht wohl eher nach C aus)

von Stefan Salewski (Gast)


Lesenswert?

>Man kann den Prozessor-Takt nicht ohne Referenz zur Laufzeit ermitteln.

Ich denke schon -- Atmels USB-Bootloader im AT90USB macht es wohl auch.

Geht evtl. mit Watchdog als Referenz oder so...

von Rudolph R. (rudolph)


Lesenswert?

Stimmt, das #DEFINE kommt von C.
Aber ob BASIC oder C ändert nichts daran, dass man die Taktfrequenz 
nicht einfach zur Laufzeit auslesen kann.

Nochmal, man erhält bestenfalls den Wert, den man vorher eingestellt 
hat.
Das ist gerade bei Benutzung des RC-Oscillators bestenfalls dicht dran 
aber eben nicht der aktuelle Takt.

von Micha R. (michaavr)


Lesenswert?

Ich hatte im netz mal ne seite gefunden, da waren diese Variablen 
beschrieben. Kann die Seite leider nicht finden.

Da gabs auch eine Systemvariable, mit der man die Compilerversion 
ermitteln, mit der das Programm compiliert wurde.

von Rudolph R. (rudolph)


Lesenswert?

> Geht evtl. mit Watchdog als Referenz oder so...

Der Watchdog ist als Referenz auch nicht geeignet, da das auch nur ein 
RC-Oscillator und somit von der Spannung und der Temperatur abhängig 
ist.

Also ich bleibe dabei, die Taktfrequenz lässt sich ohne Referenz nicht 
zur Laufzeit ermitteln.
Bestenfalls lässt sich auslesen, was man für die auftretende 
Taktfrequenz gehalten hat, als man den Code kompiliert hat.

von Micha R. (michaavr)


Lesenswert?

Hier für alle unwissenden:

habs gefunden:

_XTAL enthält die mit Statement $CRYSTAL angegebebe Taktfrequenz
_RAMSIZE enthält die Größe des RAM-Speichers
_ERAMSIZE enthält die Größe des EEProm-Speichers
_BUILD enthält die Version des Compilers
_COMPILER gibt eine Kennung des Kompilers zurück

Bitte mal ausprobieren!

Es funktioniert.

von Stefan Salewski (Gast)


Lesenswert?

>Der Watchdog ist als Referenz auch nicht geeignet, da das auch nur ein
>RC-Oscillator und somit von der Spannung und der Temperatur abhängig
>ist.

Das ist klar. Aber Atmels Bootloader im AT90USB1287 scheint mit allem 
für USB erlaubten Taktraten zu funktionieren, zumindest mit 8 bzw 16 
MHz. Ich denke die machen da irgendeinen groben Vergleich mit irgendwas 
internem -- ich meinte mich zu erinnern mit dem Watchdog, aber ich kann 
das jetzt nicht finden. (Gut, man könnte behaupten die probieren einfach 
alle Taktraten durch, also 16, 8, 4, 2, 1 MHz. Kann ich auch nicht 
ausschließen.)

von Micha R. (michaavr)


Lesenswert?

Hier, das hat ein kleines testprogramm ausgespuckt:

Ausgabe der System-Variablen:
_XTAL = 3686400
_CHIP = 17
_RAMSIZE = 1024
_ERAMSIZE = 512
_BUILD = 11190
_COMPILER = 90

und das kleine Programm hierzu:

$regfile = "m8def.dat"
$crystal = 3686400
$baud = 9600


   print "Ausgabe der System-Variablen:"
   print "_XTAL = " ; _xtal
   print "_CHIP = " ; _Chip
   print "_RAMSIZE = " ; _ramsize
   print "_ERAMSIZE = " ; _eramsize
   print "_BUILD = " ; _Build
   print "_COMPILER = " ; _compiler
   wait 1
end

es gibt noch viel mehr Variablen, z.B. wie groß der UART-Empfangsbuffer 
ist, und wieviel Bytes darin enthalten sind usw.

von Peter D. (peda)


Lesenswert?

Stefan Salewski wrote:

> Aber Atmels Bootloader im AT90USB1287 scheint mit allem
> für USB erlaubten Taktraten zu funktionieren, zumindest mit 8 bzw 16
> MHz. Ich denke die machen da irgendeinen groben Vergleich mit irgendwas
> internem

Nö, die machen nen Vergleich mit was externem, nämlich dem USB-Takt vom 
Master (PC).

Sowas geht auch mit der UART, nennt sich Autobaud.


Peter

von Marc S. (eurofighter) Benutzerseite


Lesenswert?

Micha R. wrote:
> Hier für alle unwissenden:
>
> habs gefunden:
>
> _XTAL enthält die mit Statement $CRYSTAL angegebebe Taktfrequenz
> _RAMSIZE enthält die Größe des RAM-Speichers
> _ERAMSIZE enthält die Größe des EEProm-Speichers
> _BUILD enthält die Version des Compilers
> _COMPILER gibt eine Kennung des Kompilers zurück
>
> Bitte mal ausprobieren!
>
> Es funktioniert.

und wieder hast du nur den wert, den du selber eingestellt hast. wenn du 
16 mhz vorgibst (quarz), aber die fuses auf den 1MHZ internen sthen 
(also auslieferungezustand) wird in diser variablen 16 MHZ stehen, da 
ganze aber nur auf 1 MHZ laufen ;)

Gruß, Marc

von Peter D. (peda)


Lesenswert?

Micha R. wrote:
> es gibt noch viel mehr Variablen

Nö, das sind keine Variablen, sondern Konstanten, die zur Compilezeit 
einfach nur festgelegt werden.

Sie müssen nicht den realen Werten entsprechen.

D.h. _XTAL ändert sich nicht, wenn Du den Quarz änderst, _RAMSIZE ändert 
sich nicht, wenn Du das Hex in nen größeren AVR brennst usw.


Peter

von Micha R. (michaavr)


Lesenswert?

Natürlich ändert sich der Wert für _XTAL nicht, wenn man den Quarz 
ändert.

Darum gehts ja auch garnicht.

Vielmehr, wenn man einen genauen Takt vom Timer braucht, z.B. 1Hz, dann 
müssen bei unterschiedlichen Takten die Compare1n-Werte verändert 
werden.

Mit der KONSTANTEN _XTAL läßt sich das im Programm erledigen.

Vorausgesetzt $Crystal ist korrekt angegeben!

Natürlich spuckt auch _CHIP nur den Wert richtig aus, wenn die richtige 
Definitionsdatei mit $REGFILE="m8def.dat" angegeben ist.

von Marc S. (eurofighter) Benutzerseite


Lesenswert?

dein Threadtitel sagt aber eindeutig, das du die Taktrate des µC ZUR 
LAUFZEIT ermitteln willst ?!

von Stefan Salewski (Gast)


Lesenswert?

Peter Dannegger (peda) schrieb am 01.03.2008 um Uhr 15:12:

>Nö, die machen nen Vergleich mit was externem, nämlich dem USB-Takt vom
>Master (PC).

Wäre möglich. Das Signal liegt aber nur an den D+ bzw. D- Pins an, und 
soweit ich weiss hat man auf diese Pins keinen direkten (dokumentierten) 
Zugriff. Naja, ist nicht so wichtig, der Threadstarter wollte wohl eh 
keine dynamische Taktbestimmung machen, sondern nur das auslesen, was er 
selbst anderswo definiert hatte.

Gruß

Stefan Salewski

von Micha R. (michaavr)


Lesenswert?

Ja das stimmt. Das mache ich ja auch.
Natürlich war nicht gemeint den angehängten Quarz zu ermitteln, sondern 
die Taktfrequenz, mit der die MCU versorgt wird.

Grund der Anfrage war eine Sub zu schreiben, in der ein Compare-Wert für 
nen Timer berechnet werden soll, um ein Takt an PortB.1 von 38000Hz zu 
erzeugen (IR-Träger).

Da die Sub in verschiedenen Projekten mit unterschiedlichen Takten zum 
Einsatz kommen soll, muß im Programm der Compare-wert berechnet werden, 
um unabhängig vom Clock immer die 38000Hz zu erreichen.

von Michael U. (amiga)


Lesenswert?

Hallo,

Micha R. wrote:
> Ja das stimmt. Das mache ich ja auch.
> Natürlich war nicht gemeint den angehängten Quarz zu ermitteln, sondern
> die Taktfrequenz, mit der die MCU versorgt wird.

Die MCU wird mit dem Takt versorgt, den der Quarz erzeugt, der 
dranhängt.
Was also willst Du mit Deiner obigen Feststellung nun ausdrücken?

Du bekommst nur den Wert zur Laufzeit, den der Programmierer zur 
Compile-Zeit in $Crystal hinterlassen hat und damit auch alle 
Abhängigketen.

Was also willst Du da zur Laufzeit berechnen? Es ist doch bereits beim 
compilieren bekannt.

Gruß aus Berlin
Michael

von Micha R. (michaavr)


Lesenswert?

Ok,

Du kennst bestimmt den befehl RC5Send zum senden von IR-Signalen nach 
Philips.

Warum glaubst du, daß der Befehl immer funktioniert, egal welcher Quarz 
du dran machst?

Ganz einfach:
Im Programm legst du mit $Crystal die Frequenz fest.

Jetzt schreibst du eine eigene IR-Sende-Routine (anderes Protokoll), die 
auch mit unterschiedlichen Quarzen funktionieren soll. Dann must du 
einen Timer verwenden, um die IR-Trägerfrequenz zu erzeugen. Dieser 
läuft im RTC-Modus (Realtime). Also brauchst du einen Compare-Wert, bei 
dem der Zähler zurückgesetzt werden soll.

So nun versuch mal zu rechnen :

Compare1A=$Crystal/38000

geht nicht!

Alsu brauchst du _XTAL

Compare1A=_XTAL/38000  das funktiopniert!

jetzt verstanden?

von Michael U. (amiga)


Lesenswert?

Hallo,

wir reden aneinander vorbei...

Wie Bascom Variablen/Konstanten/ Definitionen verwaltet, ist mir egal, 
ich programmiere nicht in Bascom.

Es geht um das Prinzip der Sache und das ist unabhängig von der 
Programmiersprache.

Der Wert von $Crystal und damit auch der Wert von _XTAL wird beim 
Schreiben des Programms durch den Programmierer festgelegt.

Ich gehe auch stark davon aus, daß auch Bascom beim Compilieren in der 
Zeile
Compare1A=_XTAL/38000
bereits das Ergebnis der Rechnung einträgt.

Wenn also _XTAL durch $Crystal mit 8000000 Hz festgelegt wird, ist das 
Ergebnis immer 8000000/38000 = 210,5xxx. Da das Ergebnis ein Iteger sein 
muß, also 210.

Im diesem compilierten Programm wird also Compare1A IMMER mit 210 
geladen werden.

Da muß zur Laufzeit nichts gerechnet werden, das kann sich nicht mehr 
ändern, wenn das .hex erstmal fertig im Flash ist.
Es wäre also nur ein schlechter Compiler, wenn er das nicht fest 
erzeugt.
Das traue ich nichtmal Bascom zu.

Falls Bascom die Möglichkeit bietet, schau Dir den erzeugten 
Assemblercode an, wenn Du dort eine Division an der Stelle findest, 
schmeiß Bascom weg...

Gruß aus Berlin
Michael

von Matthias L. (Gast)


Lesenswert?

>wenn Du dort eine Division an der Stelle findest,
>schmeiß Bascom weg...

Das braucht man aber nicht an der Division festmachen ;-)

**duck und weg**

von Peter D. (peda)


Lesenswert?

Micha R. wrote:
> Warum glaubst du, daß der Befehl immer funktioniert, egal welcher Quarz
> du dran machst?

Nein!

Es funktioniert nur dann, wenn Du genau den Quarz anschließt, den Du zur 
Compilezeit angegeben hast.


> Im Programm legst du mit $Crystal die Frequenz fest.

Also zur Compilezeit!

Was Dir hier alle die ganze Zeit zu erklären versuchen.

Es wird absolut nichts zur Laufzeit ermittelt, sondern bereits zur 
Compilezeit berechnet. Deine Überschrift ist also falsch.


Peter

von Micha R. (michaavr)


Lesenswert?

Also ich merke, hier muß man ganz exakt sein.

Also klar lege ich den Quarz beim Kompilieren fest ($Crystal).
Und es ist auch richtig, daß Compare1A=_XTAL/38000 den berechneten Wert 
fest anlegt. Natürlich nicht zur Laufzeit (wäre aber möglich!).

Der Punkt ist der, daß ich nicht immer irgendwo im Programm den 
Comparewert festlegen muß, wenn ich einen anderen Quarz verwende.

In meinen programmen gebe ich sowieso immer $Crystal an. Den Wert ändere 
ich auch entsprechend bei Verwendung eines anderen Quarzes.

Damit ich aber nicht 2 Werte ($Crystal und Compare1A) ändern muss, 
wollte ich eben den Compare1A berechnen. Dazu brauche ich eine 
Möglichkeit, den eingestellten Takt ($Crystal) zu ermitteln.

Mit $Crystal kann aber nicht gerechnet werden. Deshalb _XTAL.

Das wars was ich noch sagen wollte.

Jedenfalls meine Frage, wie ich den eingestellten Takt ($Crystal) 
auslesen kann (mit _XTAL) ist damit beantwortet.

Danke euch allen für die Unterstützung.

Mitch.

von Michael U. (amiga)


Lesenswert?

Hallo,

ich hab gerade mal aus Interesse in das basavr-PDF geschaut, wer hat 
denn sowas verbrochen???
Wenn ich nicht vorher weiß, daß ich _XTAL suche, sehe ich keine Chance, 
in dem Chaos solche Informationen zu finden...

Gruß aus Berlin
Michael

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.