Hallo
Habe in einem Programm diese Angabe für die Frequenz gefunden:
#define F_CPU 8E6
Habe versucht es umzurechnen in Binär Detimal oder Hexa. Leider komme
ich so auf Ergebnisse wie 142 ??
Bin zu blöd das zu verstehen.
Nehme immer sonst Angaben wie 8 000 000 oder 16 000 000. Damit kann ich
Rechnen.
LG Klaus
Hallo,
8E6 ist weder hex noch binär. Das ist eine Abkürzung um nicht hunderte
Nullen schreiben zu müssen. E steht für Exponent mit Basis 10.
Sprich eine 8 mit 6 Nullen dran.
Sprich 8MHz.
Hallo
Das sind halt einige der so typischen "Fallen" welche automatisch
entstehen wenn, wie bei Programmsprachen, "Nerds" und "Bücher schlaue"
irgendwelche Anwendungen erstellen.
Hinzu kommt das im Kern viele Programmiersprachen einfach nur alt sind
und die Darstellung von z.B. "Hoch 6" halt nur vereinfacht mit den
einfachen ASCII Zeichensatz von Anno 196X (Typenraddrucker,
Fernschreiber, Schreimaschine...)darstellbar ist.
Und selbst wenn es moderner ist:
Solche "Traditionen" sind halt sehr schwer auszurotten und vererben sich
leider weiter.
(Ganz anderer Bereich: "Das Licht löschen" ist in vielen Gegenden noch
üblich obwohl auch dort die elektrische Beleuchtung seit 100 Jahren und
mehr üblich ist)
Wer noch Taschenrechner vor 30Jahre und mehr nutzen musste ist die
Darstellung von "hoch" mittels "E" (auch mit 7 Segment Display
darstellbar) geläufig.
Und das E für "Exponent" also "Hoch diese Zahl nach den E" steht weis
auch jeder für den die Schulmathematik nicht eine Sache war die nach den
Abschluss möglichst schnell (oft weil es wie es gelehrt wurde und oft
noch wird) "vergessen" wurde.
Daher:
Nicht du Klaus bist "dumm" sondern die typischen Lehrmedien bzw. deren
Autoren die, wenn sie sich nicht ausdrücklich an Kinder wenden, Sachen
wie 4E6 als Selbstverständlichkeit hinnehmen die jeder automatisch aus
den Zusammenhang erkennt.
Da gibt es besonders im Bereich der Programmiersprachen (aber bei weiten
nicht nur dort) noch viel mehr an schlechten Beispielen wo sich
(angeblich...) hochwertiger Lehrstoff nicht traut mal diese eben doch
nicht selbstverständlichen Details zu erklären um ja nicht bei seinen
(im schlechten Sinne) "Nerdkollegen" als dumm dazustehen.
Betriebsblindheit, Angst davor "Selbstverständlichkeiten" auch bei
Literatur (und ähnlichen) die sich nicht an Einsteiger wendet wenigsten
noch mal kurz zu erwähnen bis klar erkennbare Arroganz der Lehrkraft
und des Autors ist leider kein Alleinstellungsmerkmal von einigen
"Spezialisten" in Foren sondern kommt leider auch öfter im Profiumfeld
vor.
Praktiker
Praktiker schrieb:> Hinzu kommt das im Kern viele Programmiersprachen einfach nur alt sind> und die Darstellung von z.B. "Hoch 6" halt nur vereinfacht mit den> einfachen ASCII Zeichensatz von Anno 196X (Typenraddrucker,> Fernschreiber, Schreimaschine...)darstellbar ist.
Wie würdest du es denn heute in einer "moderneren" Programmiersprache
darstellen? Als 8⋅10⁶? Wie gibst du das auf einer normalen Tastatur ein?
Hallo,
@Praktiker (Gast): Danke für den doch recht nutzlosen Roman...
Diese Art der Exponential-Darstellung nutzen auch Excel, OpenOffice usw.
auch heute noch genauso. Eine Suche z.B. bei Google nach 8E6 verweist
zumindest sofort auf "Zahlendarstellung".
Gruß aus Berlin
Michael
Praktiker schrieb:> Daher:> Nicht du Klaus bist "dumm" sondern die typischen Lehrmedien bzw. deren> Autoren die, wenn sie sich nicht ausdrücklich an Kinder wenden, Sachen> wie 4E6 als Selbstverständlichkeit hinnehmen die jeder automatisch aus> den Zusammenhang erkennt.
Was ist denn das für ein Blödsinn?
Demzufolge müsste man jedem, der einen Normalenvektor errechnen will,
alle Voraussetzungen beginnend beim auf's Töpfchen gehen erklären.
Tatsächlich ist (gekonntes) Programmieren eine anspruchvolle
Angelegenheit, die in vergangenen Zeiten (tm) von Menschen mit
entsprechender Vorbildung ausgeführt wurde, bei denen die Kenntnis des
Exponents zur Grundbildung gehörte. Bei Ardruino-verseuchten
Maker-Wurschtlern gibt's diese Vorbildung eben nicht.
Da drang eine Personengruppe in ein unbekanntes Terrain vor und weis nun
nicht, dass sich ein steinernes Ding aus Blöcken Treppe nennt.
Ob Klaus dumm ist? Vielleicht. Immerhin kann er nicht mal einen
Threadtitel richtig schreiben.
Das Threadthema hört sich irgendwie trollig an.
Vielleicht ist der Klaus gar nicht dumm, vielleicht bist Du dumm, der
auf die Trollerei mit gutmenschenversteherischen Erklärungsversuchen
hereinfällt.
Michael U. schrieb:> Eine Suche z.B. bei Google nach 8E6 verweist> zumindest sofort auf "Zahlendarstellung".
Mein Google tut das nicht, da ist die erste Seite geflutet mit:
> Anti-MPO - Single IC (Hu) aus Maus (8E6) - FITC ... - Dianova
und seinen Freunden und Verwandten.
Von Zahlendarstellungen ist da erstmal nix zu sehen.
Könnte auch daran liegen, dass Google weiß, was ich weiß, und auch was
ich noch nicht weiß, obwohl es in meinen Themenkomplex passt(passen
könnte).
MWS schrieb:> Bei Ardruino-verseuchten Maker-Wurschtlern gibt's diese Vorbildung eben> nicht.> Ob Klaus dumm ist? Vielleicht. Immerhin kann er nicht mal einen> Threadtitel richtig schreiben.
Ohne Worte. Arduino wäre richtig geschrieben. ;-)
Klaus schrieb:> Hallo> Habe in einem Programm diese Angabe für die Frequenz gefunden:>> #define F_CPU 8E6>> Habe versucht es umzurechnen in Binär Detimal oder Hexa. Leider komme> ich so auf Ergebnisse wie 142 ??> Bin zu blöd das zu verstehen.> Nehme immer sonst Angaben wie 8 000 000 oder 16 000 000. Damit kann ich> Rechnen.> LG Klaus
Das erzeugt aber ein double-Literal.
Fällt einem das im Code nicht fürchterlich auf die Füße?
Klaus schrieb:> #define F_CPU 8E6>> Habe versucht es umzurechnen in Binär Detimal oder Hexa. Leider komme> ich so auf Ergebnisse wie 142 ??
Netter Versuch. Aber falscher Tag. Freitag ist Trolltag.
Eins N00B schrieb:> Fällt einem das im Code nicht fürchterlich auf die Füße?
Eigentlich gehört an die Frequenz ein UL dran....
würde ich mal sagen......
Denn ein Vorzeichen braucht es doch nicht, und das default int ist
manchmal zu klein.
In C gibts vermutlich wenig Alternativen....
Aber in C++/Arduino kann man durchaus mal ein
> Frequenz frq {8_MHz};
einstreuen, wenn man das geschickt vorbereitet..
Veit D. schrieb:> Ohne Worte. Arduino wäre richtig geschrieben. ;-)
Ich war schon gespannt, wer zuerst auf meine eingebaute Vorlage
triggert, LOL.
Hätte aber eher was aus der Richtung der Ardruino-Fangemeinde erwartet.
"Ardruino" ist die meiner Einschätzung nach meistverwendete
Wortvergewaltigung der Arduino-Jünger, die nicht mal ihren eigenen
Propheten beim Namen kennen.
Hat manchmal was von Monty Python.
MWS schrieb:> Hätte aber eher was aus der Richtung der Ardruino-Fangemeinde erwartet.
Willst du Stress mit mich?
Vergiss es...
Was du da betreibst ist so ziemlich die dümmste Sorte von Arduino
Bashing, welche überhaupt möglich ist.
Das ignoriere ich noch nicht einmal!
Es sagt mehr über dich aus, als über die Ardruirno Jünger.
MWS schrieb:> Veit D. schrieb:>> Ohne Worte. Arduino wäre richtig geschrieben. ;-)>> Ich war schon gespannt, wer zuerst auf meine eingebaute Vorlage> triggert, LOL.>> Hätte aber eher was aus der Richtung der Ardruino-Fangemeinde erwartet.> "Ardruino" ist die meiner Einschätzung nach meistverwendete> Wortvergewaltigung der Arduino-Jünger, die nicht mal ihren eigenen> Propheten beim Namen kennen.> Hat manchmal was von Monty Python.
😂👍
Arduino Fanboy D. schrieb:> Eigentlich gehört an die Frequenz ein UL dran.
Warum? Nur, weil das alle so machen?
<util/delay.h> ist vorsätzlich so konzipiert worden, dass man F_CPU in
einer möglichst natürlichen Schreibweise schreiben kann. Für mich
gehört es dabei dazu, dass ich bei einem Quarz, der mit "3.6864 MHz"
beschriftet ist, halt auch "3.6864E6" schreiben kann, statt Nullen
zählen zu müssen. (Davon abgesehen, dass avr-libc natürlich C-tauglich
sein muss, behaupte ich mal, dass diese Varianten mit nachgesetzten
Einheiten in C++ zu der Zeit noch nicht möglich waren. Die erfüllen
ansonsten mein Lesbarkeits-Kriterium auch.)
Schade nur, dass die Schöpfer von <util/setbaud.h> das nicht
weitergeführt haben. Dort geht wirklich nur ein integer-Wert.
Das "UL" ist übrigens auch bei Ganzzahlen mittelmäßig überflüssig, denn
8000000 ist ohnehin schon mal "long" (auf einem AVR), und dass es nicht
negativ ist, ist offensichtlich. Wer auch immer damit etwas rechnet,
sollte von sich aus drauf achten, dass er es in der passenden integer
domain weiter benutzt.
Arduino Fanboy D. schrieb:> Willst du Stress mit mich?>> Vergiss es...> Was du da betreibst ist so ziemlich die dümmste Sorte von Arduino> Bashing, welche überhaupt möglich ist.> Das ignoriere ich noch nicht einmal!
Da isser schon, der Verteidiger aller Ardruinos. ;D
Es ist bezeichnend, dass ein Gutteil der Arduino-Nutzer den Namen nicht
richtig schreiben, das ist kein Gebashe, sondern Tatsache.
Und klar sagt das etwas über die Nutzer aus, das sind alles Einsteins.
Wenn Du nicht wüsstest, dass ich richtig liege, hättest Du Dir Deine
Antwort gespart.
Jörg W. schrieb:> Das langweilt hier. :(
Das ist aber auch ein langweiliger Thread, der ein wenig Stimmung
brauchte. :-)
Ich kann immer noch nicht glauben, dass der ernsthaft und nicht trollig
ist.
MWS schrieb:> Ich kann immer noch nicht glauben, dass der ernsthaft und nicht trollig> ist.
Naja, es gibt offenbar Leute, die nicht einmal die Grundlagen ihrer
Programmiersprache (hier: Schreibweisen von numerischen Konstanten)
beherrschen, aber trotzdem damit anfangen.
Zwar haben wir ein paar Forentrolle ähnlichen Formats, die nicht bis
Freitag warten können, aber der TE scheint nicht dazu zu gehören.
Jörg W. schrieb:> Zwar haben wir ein paar Forentrolle ähnlichen Formats, die nicht bis> Freitag warten können, aber der TE scheint nicht dazu zu gehören.
Eine Suche nach 8E6 macht mir auf duckduckgo als erstes einen
Taschenrechner auf, in dem dann 8000000 und als Erklärung 8*(10^6)
steht, bei google muss man mit weiteren Suchbegriffen eingrenzen, aber
trotzdem ist's einfach, denn man kennt was gesucht wird: eine Zahl.
Es muss ja nicht jeder autodidaktisch eingestellt sein, aber so einen
einfach rauszufindenden Kleckerkram nicht innerhalb 5 Minuten zu lösen
und statt dessen einen Thread mit Inhalt "Bin zu blöd" aufzumachen, ist
schon 'ne Leistung.
Klaus schrieb:> #define F_CPU 8E6>> Habe versucht es umzurechnen in Binär Detimal oder Hexa. Leider komme> ich so auf Ergebnisse wie 142 ??
Unglaubwürdig auch hier, wieso sollte man in Binär umrechnen? Außerdem
8E6 als Hex gelesen ist sicher nicht 142.
Ich glaub' also nicht, dass das echt ist.
Jörg W. schrieb:> Warum? Nur, weil das alle so machen?
Vielleicht haben deine "alle" ja auch manchmal einen guten Grund!
Einer der Gründe ist dass ein Takt nie negativ sein kann.
Aus dem Grund ist alleine schon das U angesagt.
Es kostet nichts, und macht dennoch klar, dass man was kapiert hat.
Zudem erlaubt es Warnungen, z.B. bei Vergleichen mit signed Values. Ein
Tor weniger für Schlampigkeiten.
Es ist ja nicht nur ein F_CPU only Problem.
Das findet sich schon noch häufiger in ganz anderen Ecken.
Bei
> uint32_t takt = 1234567;
brauche ich das nicht.
Das klappt immer, da hast du schon recht.
Bei einem
> #define takt 1234567UL
halte ich das fast für eine Pflicht.
Denn es gibt keine andere Möglichkeit dem define/Literal irgendwas an
Typeinformation mitzugeben.
Wie gesagt: Es kostet nichts....
(außer, etwas Sorgfalt und Disziplin)
Dem C Menschen wird das nicht so wichtig sein. Aber der C++ Bastler
kennt immerhin Templates, welche sehr viel mit Typen arbeiten, und auch
die TypeTraits.
Da kann sich jede Typisierungsschlampigkeit bitter rächen.
Arduino Fanboy D. schrieb:> Es ist ja nicht nur ein F_CPU only Problem.
Es geht hier aber um F_CPU, und darum, dass F_CPU eine Gleitkommazahl
sein kann und darf (zumindest für <util/delay.h>). Da ist die Bemerkung,
dass da ein "UL" dran gehöre, völlig unsinnig.
Arduino Fanboy D. schrieb:> Eins N00B schrieb:>> Fällt einem das im Code nicht fürchterlich auf die Füße?>> Eigentlich gehört an die Frequenz ein UL dran....> würde ich mal sagen......> Denn ein Vorzeichen braucht es doch nicht, und das default int ist> manchmal zu klein.
Man braucht zwar kein Vorzeichen, aber es stört auch nicht. Und ob int
zu klein ist oder nicht, ist egal. Wenn der Wert größer ist als int,
wird automatisch ein Typ gewählt, der groß genug ist, sofern vorhanden.
Abgesehen davon kann man an 8E6 kein UL anhängen, weil das eine den Wert
zu einem double macht, das andere zu einem unsigned long. 8E6UL ist kein
gültiges Literal.
> In C gibts vermutlich wenig Alternativen....> Aber in C++/Arduino kann man durchaus mal ein>> Frequenz frq {8_MHz};> einstreuen, wenn man das geschickt vorbereitet..
In C könnte man mit einem Makro
1
#define Mhz * 1000000
auch schreiben:
1
#define F_CPU 8 Mhz
Arduino Fanboy D. schrieb:> Einer der Gründe ist dass ein Takt nie negativ sein kann.> Aus dem Grund ist alleine schon das U angesagt.
Nö. Ich finde es eine Unsitte, Werte nur deswegen unsigned zu machen,
weil sie halt nicht negativ sind. Für mich gibt's nur zwei Gründe, einen
Typ unsigned zu machen:
- Ich brauche den Wertebereich
- Ich will damit Bitgefummel machen, wo das Vorzeichen stört
> Es kostet nichts, und macht dennoch klar, dass man was kapiert hat.
Dass ich kapiert habe, dass Taktraten nicht negativ sein können, muss
ich niemandem zeigen.
> Zudem erlaubt es Warnungen, z.B. bei Vergleichen mit signed Values. Ein> Tor weniger für Schlampigkeiten.
Und was habe ich davon?
Sorry, bin kein Troll auch wenn das einige glauben. Fange gerade mit
lesen eines Codes an und da sind viele Sachen unverständlich.
Sorry noch mal für die blöde Frage, kommt nicht wieder vor.
Klaus schrieb:> Fange gerade mit lesen eines Codes an und da sind viele Sachen> unverständlich.
Naja, die verschiedenen Varianten von numerischen Konstanten gehören nun
einmal zu den Grundlagen einer Programmiersprache, die solltest du dir
auf jeden Fall ansehen.
Klaus schrieb:> Sorry noch mal für die blöde Frage, kommt nicht wieder vor.
Das war keine blöde Frage, sie wirkte auf mich aber eher wie ein
Vorwurf. Nach dem Motto "Wie kann man nur so einen Müll schreiben, das
ist doch keine richtige Zahl!"
Daher kamen wohl die Reaktionen.
Jörg W. schrieb:> Klaus schrieb:>> Fange gerade mit lesen eines Codes an und da sind viele Sachen>> unverständlich.>> Naja, die verschiedenen Varianten von numerischen Konstanten gehören nun> einmal zu den Grundlagen einer Programmiersprache, die solltest du dir> auf jeden Fall ansehen.
Das stimmt, aber kann man das von Anfänger:innen erwarten?
Vielleicht ist ihm ja die ul-Geschichte bewusst, Hex scheint er zu
kennen, nur die Exponentialschreibweise noch nicht über den Weg
gelaufen.
Ich programmiere (leider) schon zu lange, um mich noch gut in die Lage
hineinversetzen zu können, ich kann mir aber vorstellen, dass es eine
Weile dauert, um überhaupt den Kopf so frei zu haben, sich detailliert
mit der Sprache auseinanderzusetzen und nicht mehr über einzelne
Konstrukten brüten zu müssen.
Vielleicht ähnelt das dem, wie es mir gegangen ist, als eich vor einiger
Zeit mal einen VHDL-Anlauf unternommen habe. Bevor ich das Buch
aufgemacht habe (übrigens über Empfehlungen hier im Forum ausgewählt ;)
), wirkte VHDL auch nur wie Salat.
Das ist ein Plädoyer für etwas mehr Verständnis gegenüber den
Anfänger:innen wie Klaus, deren Fragen für erfahrene Programmierer
vielleicht unverständlich trivial scheinen.
P.S.: Wer lautstark auf bestimmten Lösungen herumhackt, die vielleicht
einen selbst auch nicht unbedingt als Zielgruppe haben (Arduino, …),
lässt mich arg an der fachlichen Kompetenz der Autor:in zweifeln. Auch
wenn ich ihr/ihm damit vermutlich Unrecht tue.
Manchmal bin ich echt hin- und hergerissen, was ich von diesem Forum
halten soll …
Hallo,
Eins N00B schrieb:> Jörg W. schrieb:>> Klaus schrieb:>>> Fange gerade mit lesen eines Codes an und da sind viele Sachen>>> unverständlich.>>>> Naja, die verschiedenen Varianten von numerischen Konstanten gehören nun>> einmal zu den Grundlagen einer Programmiersprache, die solltest du dir>> auf jeden Fall ansehen.>> Das stimmt, aber kann man das von Anfänger:innen erwarten?> Vielleicht ist ihm ja die ul-Geschichte bewusst, Hex scheint er zu> kennen, nur die Exponentialschreibweise noch nicht über den Weg> gelaufen.
das eben hat mich etwas verwirrt, die ist (für mich?) nicht so
ungewöhnlich.
Ich hätte da mehr verwirrt geschaut, ob der Präprozzsor das in der
gewählten Programmierumgebung wirklich kennt.
Das passiert mir aber auch, wenn im Forum Fragen gestellt werden, wo ich
denke "Ohmsches Gesetz" oder "Stromkreis" müßte derjenige aber doch
schonmal gehört haben?
Gruß aus Berlin
Michael
Praktiker schrieb:> einfachen ASCII Zeichensatz von Anno 196X (Typenraddrucker,> Fernschreiber, Schreimaschine...)
Nicht zu vergessen: Computertastaturen. Die haben sich auch schon ne
Weile nicht mehr groß verändert ^^
Rolf M. schrieb:> Wie würdest du es denn heute in einer "moderneren" Programmiersprache> darstellen? Als 8⋅10⁶? Wie gibst du das auf einer normalen Tastatur ein?
<8> <⋅ (Layer 4+5)> <1> <0> <Compose> <^ (Layer 3+x)> <6> = 8•10⁶ ; ez
Aber ich bin da wohl Exot …
Michael U. schrieb:> Ich hätte da mehr verwirrt geschaut, ob der Präprozzsor das in der> gewählten Programmierumgebung wirklich kennt.
Du vergisst, dass der Präprozessor nur Texte ersetzt.
Auch sowas wie
1
#define F_CPU völliger Blödsinn
kann man erstmal schreiben – nur wird vermutlich niemand, der F_CPU
hinterher verwendet, damit was anfängen können. ;-)
Eins N00B schrieb:> nur die Exponentialschreibweise noch nicht über den Weg gelaufen
Hmm, macht eigentlich jeder Taschenrechner so.
Michael U. schrieb:> das eben hat mich etwas verwirrt, die ist (für mich?) nicht so> ungewöhnlich.> Ich hätte da mehr verwirrt geschaut, ob der Präprozzsor das in der> gewählten Programmierumgebung wirklich kennt.>> Das passiert mir aber auch, wenn im Forum Fragen gestellt werden, wo ich> denke "Ohmsches Gesetz" oder "Stromkreis" müßte derjenige aber doch> schonmal gehört haben?>> Gruß aus Berlin> Michael
Uff, das hätte ich aus dem Stehgreif auch nicht gewusst. GCC warnt einen
anscheinend sogar, wenn man Floats im CPP verwendet:
1
#if 4.0 > 2
2
#endif
3
#if 4e0 > 2
4
#endif
1
main.c:4:5: error: floating constant in preprocessor expression
Was ihn natürlich ja aber nicht daran hindert, Suchen und Ersetzen zu
betreiben (#define halt; ja etwas ungenau).
Ich habe schon einige Programme ohne ein einziges Gleitkommaliteral
geschrieben, das ist mir so zT auch mal ne Weile nicht begegnet.
Möchtest du darauf hinaus, dass die OPs es in dem Fall nicht haben und
du dich darüber wunderst?
Jörg W. schrieb:> Michael U. schrieb:>> Ich hätte da mehr verwirrt geschaut, ob der Präprozzsor das in der>> gewählten Programmierumgebung wirklich kennt.>> Du vergisst, dass der Präprozessor nur Texte ersetzt.>> Auch sowas wie> #define F_CPU völliger Blödsinn>> kann man erstmal schreiben – nur wird vermutlich niemand, der F_CPU> hinterher verwendet, damit was anfängen können. ;-)>> Eins N00B schrieb:>> nur die Exponentialschreibweise noch nicht über den Weg gelaufen>> Hmm, macht eigentlich jeder Taschenrechner so.
Auf meinem Casio muss ich dafür schon irgendwas umkonfigurieren, wenn
das überhaupt geht, sonst zeigt der ein kleines ×10 an. (der hat aber
auch ein Pixeldisplay). Und der ist auch schon über 10 Jahre alt.
Das erste ist Kontextabhängig ^^
Eins N00B schrieb:> GCC warnt einen anscheinend sogar, wenn man Floats im CPP verwendet:
Du musst zwischen dem Teil des Präprozessors unterscheiden, der einfach
nur Texte ersetzt und dem, der Bedingungen auswertet. Letzterer kann nur
mit Ganzzahlen umgehen, um die Entscheidung für die Bedingung zu
ermitteln. Das war schon immer so und hat nichts mit GCC zu tun.
Klaus schrieb:> Stehe die Rechnung nicht
Welchen Teil der Rechnung verstehst du denn nicht? Wenn man die
Typecasts mal weglässt, ist das ja erstmal eine ganz normale Berechnung,
wie man sie auch auf Papier machen könnte.
Muss für einen eher ältlichen Controller sein, bei moderneren würde man
lieber CTC (clear timer on compare match) benutzen statt Preload beim
Überlauf.
Klaus schrieb:> Stehe die Rechnung nicht.> // Prescaler 1024
Die 8 MHz werden also erstmal auf 8 kHz herunter geteilt, damit wird der
Timer getaktet.
> TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms
Zerlegen wir das mal:
> (F_CPU / 1024)
Ergibt die genannten 8 kHz
> 10e-3
Das sind die gewünschten 10ms wo er hin will. Die Formel soll berechnen,
wie viele Takte in 10ms stattfinden.
> + 0.5
Dient dazu, den Rundungsfehler zu minimieren. Da das Register nur
Integer Werte kennt, würde der C Compiler die berechnete Zahl immer nur
abrunden (ist halt so in C). Durch diese Addition kommt man auf eine
Rundung nach Schulregeln (alles ab 0.5 wird aufgerundet, alles darunter
wird abgerundet)
Angenommen, die Formel ergibt 123,6. Dann würde der C-Compiler das auf
123 abrunden. Durch die Addition von 0,5 haben wir aber nun 124,1. Der
Compiler rundet es auf 124 ab.
123,6 wird zu 124.
Angenommen, die Formel ergibt 123,4. Dann würde der C-Compiler das auf
123 abrunden. Durch die Addition von 0,5 haben wir aber nun 123,9. Der
Compiler rundet es auf 123 ab.
123,4 wird zu 123.
Dann bleibt noch das "minus" übrig:
> TCNT0 = -(irgendwas)
Er will dass der Timer nach n Takten überläuft. Deswegen muss man ihn
mit einem bestimmten Wert vor-laden, damit er nach n Takten die 255
überschreitet.
Hier wird ausgerechnet, wie weit n vom Überlauf des Timer entfernt ist,
also 256 - n. Oder einfach -n, was er hier gemacht hat. Dabei kommt das
gleiche bei heraus. Denn -1 ist mit 255 identisch, und -2 ist mit 254
identisch, usw. Ergibt sich aus der Darstellung negativer zahlen in den
Bits.
> (uint8_t)(int16_t)
Das kann ich nicht erklären, ich hätte hier nur "(uint8_t)" geschrieben,
damit die Fließkommazahl der Formel in 8 Bit Integer umgewandelt wird.
Eins N00B schrieb:> Jörg W. schrieb:>> Klaus schrieb:>>> Fange gerade mit lesen eines Codes an und da sind viele Sachen>>> unverständlich.>>>> Naja, die verschiedenen Varianten von numerischen Konstanten gehören nun>> einmal zu den Grundlagen einer Programmiersprache, die solltest du dir>> auf jeden Fall ansehen.>> Das stimmt, aber kann man das von Anfänger:innen erwarten?
Ich finde, man kann erwarten, dass sie sich dieses Wissen eigenständig
aneignen. Das ist heute dank Internet leichter denn je, und doch
scheinen immer mehr Menschen damit zu kämpfen.
Eins N00B schrieb:> Uff, das hätte ich aus dem Stehgreif auch nicht gewusst.
Der heißt Stegreif, da es sich nicht etwa um ein flugunfähiges
geflügeltes Fabelwesen handelt, sondern um einen Reif mit einem Steg.
;-)
Jörg W. schrieb:> Klaus schrieb:>> Stehe die Rechnung nicht>> Welchen Teil der Rechnung verstehst du denn nicht?
Das Problem liegt vielleicht in dem - und den Casts. Das ist so nicht
gerade sehr intuitiv.
Stefan ⛄ F. schrieb:> Zerlegen wir das mal:>> (F_CPU / 1024)>> Ergibt die genannten 8 kHz
Ist übrigens nicht sonderlich geschickt, denn das bringt mehr oder
minder große und an dieser Stelle vermeidbare Rundungsfehler ein.
Da die restliche Rechnung ohnehin im Gleitkommabereich erfolgen soll,
wäre es sinnvoller, das als
Boomer1337 schrieb:>> (F_CPU / 1024)>> Ergibt die genannten 8 kHz> Ich dachte F_CPU wäre 8E6 und nicht 8000*1024.
8e6 sind 8 Mhz. Das durch 1024 geteilt sind 8 kHz.
Wir müssen jetzt aber nicht den Lehrstoff der 6. klasse wiederholen,
oder?
https://www.lernhelfer.de/schuelerlexikon/physik/artikel/vorsaetze-von-einheiten
Oder zielt dein Einwand auf die Differenz zwischen 1000 und 1024 ab? Die
hat er so hin geschrieben, weil der Vorteiler die 8 MHz durch 1024
teilt. Es sind genau genommen 7,8125 kHz, falls es dich beruhigt.
> Das ist ein Freitagsthread
Nach der Erschöpfung schaltet das Hirn irgendwann ab, dagegen kann sich
niemand wehren. Deswegen wohl immer Freitag.
Stefan ⛄ F. schrieb:> Es sind genau genommen 7,8125 kHz, falls es dich beruhigt.
Ja, sind es, und genau darum sollte man auch durch 1024.0 teilen und
nicht einfach nur durch 1024. Bei letzterem kommt nämlich nur 7 raus,
die dann anschließend mit 10000 multipliziert wird. Der Unterschied ist
dann zwischen 70000 und 78125, immerhin 10 % zu klein.
Den Rundungsfehler-Ausgleich mit der Addition von 0,5 kann man sich dann
getrost schenken. ;-)
Aber: es ist natürlich in der Rechnung keinerlei Schutz vor völlig
daneben liegenden Ergebnissen drin. Ob nun 70000 oder 78125 – beide
Werte passen nicht einmal in einen uint16_t, ganz zu schweigen vom
Zieltyp uint8_t.
Richtig wäre meiner Meinung nach (ja, es ist Freitag, muss auch erstmal
drüber nachdenken ;-):
1
voidtimer_init(void)
2
{
3
TCCR0B=(1<<CS02)|(1<<CS00);// Prescaler 1024
4
TCNT0=(uint8_t)(int16_t)-(F_CPU/1024.0/100.0+0.5);// preload for 10ms = 100 Hz
Hallo Rolf M.,
du verblüffst mich mit deinen Aussagen.
> Abgesehen davon kann man an 8E6 kein UL anhängen, weil das eine den Wert> zu einem double macht, das andere zu einem unsigned long. 8E6UL ist kein> gültiges Literal.
Von 8E6UL war gar keine Rede. Klar das das nicht geht.
> Ich finde es eine Unsitte, Werte nur deswegen unsigned zu machen,> weil sie halt nicht negativ sind. Für mich gibt's nur zwei Gründe, einen> Typ unsigned zu machen:> - Ich brauche den Wertebereich> - Ich will damit Bitgefummel machen, wo das Vorzeichen stört
Warum soll das eine Unsitte sein? Wenn eine Variable nur für den
positiven Wertebereich vorgesehen ist, dann mach ich die unsigned. Ohne
jedes zögern. Außerdem funktioniert mit unsigned der Überlauf. Ich wüßte
nicht warum unsigned falsch wäre. Im Gegenteil. Wenn eine Rechnung
temporär einen größeren Wertebereich benötigt um Überläufe während der
Rechnung zu vermeiden, wird beginnend mit 1UL (oder 1L) multipliziert.
Dann ist der Wertebereich sichergestellt. Genauso wenn es temporär
Fließkomma sein muss wird beginnend mit 1.0 multipiziert.
>> Zudem erlaubt es Warnungen, z.B. bei Vergleichen mit signed Values. Ein>> Tor weniger für Schlampigkeiten.> Und was habe ich davon?
Na also wenn du das nicht weißt, dann weiß ich auch nicht. Du bist doch
C++ Programmierer oder nicht? Da sollte man doch jede Möglichkeit einer
Warnung nutzen um Fehler vermeiden zu können. Bei C++ dreht es sich doch
im Großen und Ganzen um Datentypsicherheit. Deswegen kann ich deine
Aussagen leider nicht nachvollziehen.
Jörg W. schrieb:> Stefan ⛄ F. schrieb:>> Es sind genau genommen 7,8125 kHz, falls es dich beruhigt.>> Ja, sind es, und genau darum sollte man auch durch 1024.0 teilen und> nicht einfach nur durch 1024. Bei letzterem kommt nämlich nur 7 raus,
Nicht wenn F_CPU als 8E6 definiert ist. ;-)
TCNT1 wird also mit -78 vorgeladen, bei 7,8125 kHz Takt läuft der Timer
nach 9,984 ms über, was die gewünschten 100 Hz (einigermaßen) ergibt.
Eine ebenso falsche (oder vielleicht richtige?) Rechnung dürfte sich
nochmal in der Interruptroutine wieder finden.
Aber nochmal: auf einem modernen Controller nimmt man dafür den
CTC-Modus des Timers, statt dieser Pfriemelei mit dem Vorladen. Sowas
hat man vor 20 Jahren bei den ersten AVRs machen müssen.
Rolf M. schrieb:>> Bei letzterem kommt nämlich nur 7 raus,>> Nicht wenn F_CPU als 8E6 definiert ist. ;-)
Wo du Recht hast, hast du natürlich Recht. :-)
Jörg W. schrieb:> Ja, sind es, und genau darum sollte man auch durch 1024.0 teilen und> nicht einfach nur durch 1024.
Verstehe ich nicht. Ob ich eine Fließkommazahl (die 8E6) durch 1024 oder
durch 1024.0 teile ändert doch nichts daran, dass der Algorithmus für
Fließkommazahlen verwendet wird. Oder etwa doch?
Hätte er wie jeder "normale" Mensch
> #define F_CPU 8000000UL
geschrieben, dann wäre es auch für mich klar, dass die 1024 als
Fließkommazahl geschrieben werden müssen.
Stefan ⛄ F. schrieb:> Hätte er wie jeder "normale" Mensch>> #define F_CPU 8000000UL>> geschrieben, dann wäre es auch für mich klar wichtig, die 1024 als> Fließkommazahl auszudrücken.
Genau darauf bezog ich mich (als Idee), Rolf hatte es ja schon
korrigiert.
Solche Rechnungen im Inneren des Codes sollte man in jedem Falle so
aufschreiben, dass es eben egal ist, ob der Nutzer 8E6 oder 8000000 da
hin geschrieben hat.
Hallo,
@ Stefan:
8000000 / 1024 ist eine Ganzzahlrechnung mit Rundungsfehler
8000000.0 / 1024
oder
8000000 / 1024.0 ist eine Fließkommarechnung
Ich selbst würde es ja so schreiben
Stefan ⛄ F. schrieb:> Ist denn hier jemand der den Sinn des doppelten castens erklären kann?>>> (uint8_t)(int16_t) -Fließkommazahl
Vielleicht wollte der Urheber einen Zwischenwert generieren, in dessen
Wertebereich das Ergebnis auf jeden Fall rein passt. Ich wüsste aber
nicht, wozu das nötig sein könnte.
Stefan ⛄ F. schrieb:> Ist denn hier jemand der den Sinn des doppelten castens erklären kann?>>> (uint8_t)(int16_t) -Fließkommazahl
Nö :)
1
(gdb) p (unsigned char)-(8E6 / 1024.0 / 100.0 + 0.5)
2
$1 = 178 '\262'
3
(gdb) p (unsigned char)(int)-(8E6 / 1024.0 / 100.0 + 0.5)
4
$2 = 178 '\262'
Der AVR-GDB ist auch der Meinung, dass beide Ausdrücke das Gleiche
ergeben. ;-)
(uint8_t oder int16_t sind keine native data types, die kennt der
Debugger nicht ohne geladenes ELF-File, daher hier die native types
benutzt.)
So wie es bei euch klingt, vergessen wir mal ganz schnell diese komische
Rechnung. Wenn ihr als Profis für manche Ausdrücke keine Erklärung hat,
was soll ich da als Anfänger sagen.
Nach der Rechnung soll es ein Timer mit 8 Bit füe 10 mS wwerden. Der CTC
ist gut da für geeignet. Da werde ich mal sehen ob ich einen für die
10ms und 1ms zusammen bekomme.
Klaus schrieb:> Nach der Rechnung soll es ein Timer mit 8 Bit füe 10 mS wwerden.
Nicht nach der Rechnung, aber nach dem Kommentar neben der Rechnung. ;-)
> Der CTC> ist gut da für geeignet.
Ja.
> Da werde ich mal sehen ob ich einen für die> 10ms und 1ms zusammen bekomme.
Einer reicht, alle 1 ms. Bei jedem 10. Aufruf werden halt die Aktionen
für 10 ms dann auch noch mit abgearbeitet.
Die allerersten AVRs hatten diesen CTC-Modus noch nicht. Um dort einen
regelmäßigen Timer-Interrupt zu erreichen, der sich nicht durch die
volle Zählweite abbilden lässt (in diesem Falle von 1:256, da es ein
8-Bit-Timer ist), musste man mit dieser Preload-Krücke arbeiten: das
Zählerregister wurde auf einen bestimmten Wert vorgeladen, um den
Zeitabstand bis zum Überlauf-Interrupt zu verkürzen. Im
Überlauf-Interrupt selbst wurde dann als erstes der Preload-Wert neu
geladen, danach die restlichen Aktionen ausgeführt. Damit hat man aber
natürlich zusätzlich noch die Zeit für die Interruptannahme, und wenn
gerade ein anderer Interrupt aktiv ist, bekommt man Jitter, weil der
Preload erst später erfolgt. Daher ist das eher eine Krücke, und alle
waren froh, dass es in den späteren Controllern dann CTC gab.
Der Preload-Wert ist "256 - <Wert, der für Timeout nötig ist>", aber die
256 kürzt sich bei der Rechnung raus (ganzzahliger Überlauf), daher
steht da oben dann einfach nur ein negatives Vorzeichen vor dem
berechneten Ausdruck.
Vielleicht könnte man gerade auch als Anfänger mal einen Blick in
"einfache" Assembler-Listings werfen. Da findet man z.B. so etwas:
; cpu clock in hertz
.equ F_CPU = 16000000
...und mit etwas weiterer Suche könnte man auch Initialisierungsroutinen
für die serielle Schnittstelle finden, wo sowohl der Teiler für eine
gewünschte Baudrate berechnet wird, als auch der tatsächliche zum
zulässigen Fehler. Macht natürlich der Assembler, den man dann auch mit
einer entsprechenden Fehlermeldung abbrechen lassen kann!
Gruß Rainer
Rainer V. schrieb:> mal einen Blick in "einfache" Assembler-Listings werfen
Warum willst du jetzt jemanden, der gerade mit C anfängt, auch noch mit
Assembler verwirren?
Klaus schrieb:> OCR0A=249;
Das ist halt genau das, was der andere Code versucht, automatisch zu
berechnen.
1
OCR0A=(uint16_t)(F_CPU/64.0/* prescaler 64 *//1000/* Hz = 1 ms */);
Das kommt übrigens auf 125 für 8 MHz. Ich denke, du hast einen
off-by-one Fehler drin bei dir.
Jörg W. schrieb:> Warum willst du jetzt jemanden, der gerade mit C anfängt, auch noch mit> Assembler verwirren?
Na weil er ja offensichtlich kein "theoretischer" C-ler werden will. Er
hat halt eine konkrete Maschine und da halte ich es ganz sicher für
nötig, mal in die untere Programmierebene abzusteigen. Schon allein die
Port-Pin's, die es ja letztlich machen müssen, schaut man sich doch
nicht in "C" an...aber ich glaube, mit etwas Willen geht es natürlich
ganz ohne Assembler...genau so wie mich im Berufsleben der erste Dokter
der E-Technik damit überraschte, dass er nicht in der Lage war, eine
vernünftige Lötstelle zu produzieren. Und das nicht als gepflegte
Attitüde...nein, man hatte sofort eine Höllenangst, dass der Mensch sich
mit dem Griff zum Lötgerät, eigenhändig aus der Welt schaffen würde :-)
Gruß Rainer
Rainer V. schrieb:>> Warum willst du jetzt jemanden, der gerade mit C anfängt, auch noch mit>> Assembler verwirren?>> Na weil er ja offensichtlich kein "theoretischer" C-ler werden will.
Du hast eine reichlich verschobene Vorstellung von der Welt.
> Er> hat halt eine konkrete Maschine und da halte ich es ganz sicher für> nötig, mal in die untere Programmierebene abzusteigen.
Das geht auch mit C ganz prima. Habe ich mehr als 15 Jahre beruflich
gemacht. Irgendwelches Assembler-Gefummel zu pflegen, hätte mir wohl
kein Kunde bezahlen wollen.
Dass man, wenn man auf der Ebene arbeitet, den Assemblercode lesen
können muss, halte ich übrigens für unbestritten. Dafür muss man sich
aber nicht mit dem Assembler selbst herum schlagen. Auf Compilerebene
hat man halt Gleitkommazahlen, bei denen man sich nicht in jedem
Rechenschritt überlegen muss, ob der Ausdruck jetzt über- oder
unterlaufen kann und welchen Verlust an Genauigkeit man gerade mit dem
aktuellen Schritt eingeht, den man dann durch irgendwelche Skalierungen
(die wieder überlaufen könnten) wieder ausgleicht. Nichtsdestotrotz: im
Compilat steht, siehe oben, am Ende eine 8-Bit-Konstante. (Als Kontrolle
kann man die sich natürlich vorher mit dem Taschenrechner ermitteln,
aber auch der rechnet mit Gleitkommazahlen.)
> aber ich glaube, mit etwas Willen geht es natürlich> ganz ohne Assembler...
Ja. Kaum zu glauben, ARM Cortex-M wurde ausdrücklich so entworfen, dass
man selbst die Initialisierung und Vektortabelle komplett in C
ausdrücken kann. Die spinnen sicher alle bei ARM, oder?
Der Fehler bei Klaus steckt in der falschen Bitzuweisung. Das WGM01 Bit
steht in TCCR0A und nicht in TCCR0B. Dann klappt das auch. Vorausgesetzt
die Interrupts sind generell freigegeben. Wenn man das alles inkl.
Formel korrigiert kommt man auf
1
constuint16_tfreq=1000;// [Hz]
2
voidset_Timer0();
3
4
intmain(void)
5
{
6
configTimer0();
7
sei();
8
9
while(1)
10
{}
11
}
12
13
voidconfigTimer0()
14
{
15
TCCR0A=_BV(WGM01);// CTC
16
TCNT0=0;
17
OCR0A=(F_CPU/64/freq)-1;// Compare Value
18
TIMSK0=_BV(OCIE0A);// enable Compare Match A
19
TCCR0B=_BV(CS01)|_BV(CS00);// Prescaler 64 und Timer starten
Jörg W. schrieb:> Dass man, wenn man auf der Ebene arbeitet, den Assemblercode lesen> können muss, halte ich übrigens für unbestritten. Dafür muss man sich> aber nicht mit dem Assembler selbst herum schlagen.
Ich denke, da beißt die Maus keinen Faden ab, aber irgendwann biste dann
doch schon beim Portx.y ... egal ob in Ass. oder Hochsprache...man kann
offensichtlich nie zu wenig voraussetzen. Im Gegenteil, man wundert sich
eher immer wieder, wie viel weniger man nun doch vorraussetzen muß!
Gruß Rainer
Hallo,
ihr übertreibt ja total. Man muss dafür weder Assembler schreiben noch
lesen können. Man kann sich alle Werte notfalls auch auf der seriellen
ausgeben lassen.
Eine kleine Verbesserung sei noch erlaubt
1
voidconfigTimer0(constuint16_tf)
2
{
3
TCCR0A=_BV(WGM01);// CTC
4
TCNT0=0;
5
OCR0A=(F_CPU/64/f)-1;// Compare Value
6
TIMSK0=_BV(OCIE0A);// enable Compare Match A
7
TCCR0B=_BV(CS01)|_BV(CS00);// Prescaler 64 und Timer starten
Veit D. schrieb:> Man muss dafür weder Assembler schreiben noch lesen können.Müssen nicht, aber siehe oben: es ist gewiss sinnvoll, sich mal
anzusehen, was nach der Rechnung mit dem Compiler heraus gekommen ist.
Deine Verbesserung kann nach hinten los gehen: der Gleitkommausdruck
wird jetzt u. U. zur Laufzeit berechnet statt vom Compiler. Mit der
globalen Konstante (genauer: unveränderlichen Variable) für die
Zielfrequenz kann der Compiler das sehr sicher zur Compilezeit
berechnen. Wenn man sie als Parameter an die Funktion übergibt, hängt es
davon ab, ob er während des Compilierens auch feststellen kann, dass der
Aufruf mit einer tatsächlichen Konstante erfolgte¹. Das "const" im
Parameter erzwingt dies keineswegs, das verhindert nur, dass man den
Wert innerhalb der Funktion modifizieren kann.
Ich würde bei deiner vorhergehenden Version bleiben.
¹ Durch Ansehen des erzeugten Assemblercodes kann man natürlich genau
das verifizieren. ;-)
Jörg W. schrieb:> Ich denke, du hast einen off-by-one Fehler drin bei dir.
Diese Bemerkung ziehe ich zurück. Am Ende noch 1 zu subtrahieren ist
korrekt – habe jetzt nochmal ins Datenblatt geschaut (Veit hat das ja
bei sich auch so stehen).
Hallo,
sollte eine Komfortvariante werden. ;-) Aber stimmt schon, so einen
Intervall-Timer ändert man nie wieder. Ich hoffe Klaus kann damit was
anfangen und darauf aufbauen.
Danke fürs verifizieren. :-)
Klaus schrieb:> void timer_init() // Timer 8 Bit, 8MHz, 1ms> { // Timer 0 konfigurieren> TCCR0A = 0; // CTC Modus> TCCR0B = (1<<WGM01)|(1<<CS01)|(1<<CS00); // Prescaler 64> TCNT0=1;> OCR0A=124;> TIMSK0|=(1<<OCIE0A); // Interrupt erlauben> }
Sorry, habe euren Text nicht ganz verstanden, einer sagt 125 der andere
124. Was stimmt den? Laut Berechnung müsste es 124 sein.
Klaus schrieb:> einer sagt 125 der andere 124. Was stimmt den?
Lies doch bitte nicht nur punktuell, sondern den kompletten Thread.
Ich hatte mich korrigiert. Eins weniger ist richtig, steht ja auch im
Datenblatt der AVRs.
Müsst ihr euch immer streiten. Es gibt genügend andere Probleme.
Also ein anderes Problem um rechnisch auf 1ms zu kommen.
Gegeben:
Frequenz 8 000 000 HZ (8 MHz)
Prescaler 64
Rechnung:
Timer 8 Bit x Vorteiler 256 x 64 16384
t= ----------------------- = -------- = ------- = 0,002048 s = 2,048 ms
Systemtakt 8000000 8000000
Wie komme ich jetzt mit der Rechnung per Fuss auf die 124 als
Einstellung für die Einstellung?
Die Berechnung vorher hat das Programm im Netz gemacht.
Hallo,
ich habe mir mal den Spass gemacht eine automatische Berechnung zu
erstellen.
Man ist eben nur in der [ms] Einheit und in 8Bit innerhalb 1...16ms
eingeschränkt. Funktioniert, aber so ganz glücklich bin ich mit der
doppelt vorhandenen Formel nicht. Einmal muss ich den passenden
Prescaler suchen und dann muss ich damit den Compare Wert berechnen. Mit
constexpr kann ich aber nur einen Rückgabewert haben. Wer da eine Idee
hat, nur zu.
1
/*
2
Arduino Mega2560
3
Timer0: CTC, Mode 2
4
17.07.2021
5
Berechnet und konfiguriert an Hand der ISR Aufrufperiode alle notwendigen Timer0 Parameter automatisch.
Hallo Klaus,
du hast doch im Manual für jeden Timer Modus eine Formel stehen. Diese
stellst du auf die gesuchte Größe um.
Tipp. Wenn du erstmal mit Frequenzen rechnest und nicht mit
Periodendauer gehts leichter. Dann geht das Formel umstellen erstmal
einfacher.
Klaus schrieb:> Als Ergenbis bekomme ich 15,8 ? Das stimmt wohl nicht. Habe ich die> Bezeichnungen falsch zugeordnet?
Das kann man im Kopf rechnen, wenn auf dem Strich 8000000 steht und 1000
rauskommen soll, dann muss unterm Strich 8000 stehen. Das kann man durch
zweimal 64 teilen und schon kommt 62,5 raus. Also unbrauchbar, weil's
nicht auf geht.
Da schaust Du Dir evtl. die falsche Formel, bzw. den falschen Modus an,
wobei CTC prinzipiell richtig ist. Der Mode ist richtig, bei dem im
Teiler nur einmal N benutzt wird, dann geht's mit Top = 124 (125 - 1)
auch auf.
Klaus schrieb:> Umstellung der Formel stimmt jetzt, aber wieso nicht 124?
Dein "2 x" im Nenner bezieht sich auf die Frequenz, die sich am
OCxy-Ausgang ergibt, wenn du bei jedem Erreichen der Zählschwelle den
OCxy-Ausgang umschalten lässt ("Waveform generation" wird das da auch
genannt). Wenn du aber auf die Interrupt-Frequenz guckst, brauchst du
diesen Teiler 2 nicht, denn es wird ja bei jedem Erreichen der
Zählschwelle ein Interrupt ausgelöst.
Hallo,
der Modus ist schon richtig und die Formel auch. Der Knackpunkt ist die
Bedeutung von Zielfrequenz und dessen Periodendauer. Wenn der Pin OCR0A
mit 1kHz takten soll, dann stimmt 62,5. Dafür gilt die Formel.
Du möchtest aber keinen 1kHz Takt am Timerpin erzeugen sondern eine ISR
Aufruffrequenz von 1ms. Die 1ms ist deine Periodendauer. Deswegen
Ergebnis mal 2 nehmen oder praktischerweise das durch 2 weglassen.
Das wird dir klarer wenn du ein Taktsignal aufmalst und die
Periodendauer einzeichnest. Dann markierst du die Stellen an denen dafür
notwendigerweise die ISR auslösen muss, wenn angenommen die ISR/OCR0A
ein Takt erzeugen soll. Ist blöd zu erklären, deswegen aufmalen, dann
sollte es Klick machen.
Hi
Der OC-Interrupt wird aber bei jedem Flankenwechsel ausgelöst, also muss
die Frequenz 500 Hz und nicht 1000 Hz sein. Damit kommst du bei deiner
Rechnung auf 125. Und die ergeben 125-1=124.
MfG Spess