Ich bin am Überarbeiten meiner Sourcen und stellte Fest: FAST-PWM auf
Timer0 habe ich nicht implementiert. Kein Problem (dachte ich), Timer0
sollte genauso sein wie Timer 2.
Pustekuchen !
Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht und ich habe
jetzt auch schon wirklich ne lange Zeit ins Datenblatt geschaut, aber
ich komme nicht drauf!
Warum produziert Timer2 eine korrekte, besser gesagt eine erwartete
Frequenz, von 1315 Hz, aber Timer0 eine Frequenz von 163 Hz ?
Beide sollten im Fast-PWM Modus laufen (WGM22=WGM21=WGM20= 1 und
WGM02=WGM01=WGM00= 1), haben denselben Prescaler und dieselben
Comparewerte.
Was übersehe ich ?
Hallo,
was haben wir (ich) versucht dir im letzten Thread zum Thema
beizubringen?
Bist du lernfähig? Es gibt auch keinen Prescaler 5. Auch wenn ich erahne
was das sein soll, macht man nicht.
Ralph S. schrieb:> Timer0 habe ich nicht implementiert. Kein Problem (dachte ich), Timer0> sollte genauso sein wie Timer 2.
Bei allen AVR Mega/Tiny ist Timer 0 anders als die anderen, und Timer 2
ist ganz anders.
Oliver
Veit D. schrieb:> was haben wir (ich) versucht dir im letzten Thread zum Thema> beizubringen?> Bist du lernfähig? Es gibt auch keinen Prescaler 5. Auch wenn ich erahne> was das sein soll, macht man nicht.
Ich bin ja sonst ein sehr umgänglicher Mensch, aber gehts dir noch gut
??? Noch überheblicher gehts ja nun wohl wirklich nicht ! Behandel mich
mal nicht wie einen dummen Schuljungen. Wenn du nur absolut ansatzweise
halb so gut wärst würdest du etwas sehen (und jeder hat seinen eigenen
Stil und macht die Dinge so, wie er sie eben macht).
Einen Prescaler lt. Datenblatt gibt es nicht, sonder wird über 3 Bits
eingestellt macht bei Timer 0 und 2 insgesamt 8 Möglichkeiten... du
kapierst und hast etwas Ahnung von binären Zahlen - ich kann das auch,
überheblich sein. Das sind dann sämtliche Kombinationen von 0-0-0 bis
1-1-1 ... die clockselctorbits liegen auf D3:D0 auf den jeweiligen
Registern, was da heißt: 5 entspricht 1-0-1 und setzt CS2:CS1:CS0 auf
... na ... überleg das mal .. natürlich auf Option 5 , in Worten FÜNF
... und das ist der Prescaler ... na... für was ... für einen Divisor
128.
Für dich vllt. hätte man das auch Prescaleroption nennen können oder wie
auch immer. Ändert aber nichts an der Tatsache dass du keinen Deut
geholfen hast ! (im übrigen ist das in MEINER Source dokumentiert)
Ich reg mich auf ... BEIZUBRINGEN ... VEIT ist noch sein Clone von
zensiert
Meine Gedanken über dich ... kennst du nicht, aber jetzt vllt. schon .
Ich bitte dich höfflichst, dich von meinen Threads fernzuhalten. Danke !
S. Landolt schrieb:> Stimmt!> Faktor 8 zwischen den Ergebnissen - aha: bei Timer2 entspricht die '5'> /128, bei Timer0 /1024.
Die Initialisierung wird an anderer Stelle vorgenommen und hat dann
etwas in dieser Art, weil ein automatischer Scan der Optionen
vorgenommen wird. Da st
S. Landolt schrieb:>> ... macht man nicht.>> Stimmt!> Faktor 8 zwischen den Ergebnissen - aha: bei Timer2 entspricht die '5'> /128, bei Timer0 /1024.
Sagt wer, dass "MAN" das nicht macht?
Im übrigen Programm steht da dann so etwas drin:
1
switch (csbits)
2
{
3
case 1 : divisor= 1; break;
4
case 2 : divisor= 8; break;
5
case 3 : divisor= 64; break;
6
case 4 : divisor= 256; break;
7
case 5 : divisor= 1024; break;
8
default : break;
9
}
Damit ein iterativer Scan über alle möglichen einstellbaren Frequenzen
machbar ist.
Naaaaaatürlich kann man auch so etwas machen:
TCCR2B = (1 << WGM22) | CS22 | CS21 | CS20;
Das ist dann besser lesbar? Ich kenne nicht jedes Bit und jeden Teiler
auswendig (vor allen Dingen nicht wie die Teilerverhältnisse sind) und
noch lustiger, dass der Teiler von Timer1 zu Timer0/2 abweicht. Also
erklärt mir nicht, was "MAN" tut und was nicht !
Vllt. sollt ich für die absoluten "Lehrmeister" (ich bin selbst
Ausbilder) dann noch hinzuschreiben:
// 1 : CS20= 0; CS21= 0; CS20= 0;
so als Kommentar?
Mir ist das binäre Zahlensysteme (und das hexadezimale) durchaus
geläufig !
Oliver S. schrieb:> Bei allen AVR Mega/Tiny ist Timer 0 anders als die anderen, und Timer 2> ist ganz anders.>> Oliver
Das bemerke ich gerade, nur werde ich nicht schlau draus was. Ich sehe
noch andere Optionen, aber lt. Datenblatt müßte das funktionieren. Müßte
! (und es hat wohl auch einen Grund, warum ich damals Timer0 nicht als
PWM-Generator verwendet habe).
Ziel des ganzen ist ein:
uint16_t pwmt0_setfreq(uint16_t freq, uint16_t duty);
uint16_t pwmt1_setfreq(uint16_t freq, uint16_t duty);
uint16_t pwmt2_setfreq(uint16_t freq, uint16_t duty);
Das funktioniert für Timer1 (16-Bit) und Timer2 (8-Bit) sehr gut. Die
wirklich eingestellte Frequenz wird zurückgegeben. Nur Timer0 will da
nicht (wobei das ganz merkwürdige ist, dass das für bestimmte
Einstellung doch funktioniert).
Und wenn ich schon dabei bin: Wenn eine PWM auf einem Pin bereits
gelaufen ist, sagen wir mittels Timer1 auf PB1.
Wie initialisiert man den PB1 nach gestoppter PWM wieder als GPIO ?
> Ich kenne nicht jedes Bit und jeden Teiler auswendig ...
Nun ja, und eingangs gezeigte Schreibweise verleitet eben dazu, nicht
ins Datenblatt zuschauen. Nach meiner unmaßgeblichen Meinung zumindest.
> (ich bin selbst Ausbilder)
Pardon, dann allerdings erstaunt mich der Umgangston.
S. Landolt schrieb:> /128, bei Timer0 /1024.
Timer 0 hat dieselben Einstellungen des Prescalers wie Timer1 und nicht
wie Timer 2
Das war der Fehler.
--------------
Und an die Besserwisser:
Nein, das hätte man auch mit einer Bitverknüpfung nicht richtig gemacht:
TCCR2B = (1 << WGM22) | CS22 | CS20; // teilt durch 128
TCCR0B = (1 << WGM02) | CS02 | CS00; // teilt durch 1024
S. Landolt schrieb:> Ich hatte doch oben geschrieben, dass diese '5' bei Timer0 einen> Vorteiler von 1024 einschaltet.
;-) ja ... sorry... ich habe es in meinem Zorn überlesen gehabt. Danke
Ralph S. schrieb:> Wie initialisiert man den PB1 nach gestoppter PWM wieder als GPIO ?
Ganz einfach. Du musst im Register TCCR0A die COM0Ax/COM0Bx bits wieder
löschen, dann ist das wieder ein normaler GPIO.
> Nein, das hätte man auch mit einer Bitverknüpfung> nicht richtig gemacht:>> TCCR2B = (1 << WGM22) | CS22 | CS20; // teilt durch 128> TCCR0B = (1 << WGM02) | CS02 | CS00; // teilt durch 1024
Pardon, aber: so natürlich auf gar keinen Fall.
Ralph S. schrieb:> Behandel mich> mal nicht wie einen dummen Schuljungen.
Er behandelt dich als das, was du bist: offensichtlich vollständig
lernresistent.
> Einen Prescaler lt. Datenblatt gibt es nicht
Ach ja? Also in meinem DB gibt's sogar eine ganze Tabelle dazu, nämlich
folgende:
Table 15-9. Clock Select Bit Description
CS02 CS01 CS00 Description
0 0 0 No clock source (Timer/Counter stopped)
0 0 1 clk I/O /(No prescaling)
0 1 0 clk I/O /8 (From prescaler)
0 1 1 clk I/O /64 (From prescaler)
1 0 0 clk I/O /256 (From prescaler)
1 0 1 clk I/O /1024 (From prescaler)
1 1 0 External clock source on T0 pin. Clock on falling edge.
1 1 1 External clock source on T0 pin. Clock on rising edge.
> eingestellt macht bei Timer 0 und 2 insgesamt 8 Möglichkeiten...
Ja, nur halt verschiedene. Die entsprechende Tabelle von Timer2
(natürlich ebenfalls im DB enthalten) sieht nämlich so aus:
Table 18-9. Clock Select Bit Description
CS22 CS21 CS20 Description
0 0 0 No clock source (Timer/Counter stopped).
0 0 1 clk T2S /(No prescaling)
0 1 0 clk T2S /8 (From prescaler)
0 1 1 clk T2S /32 (From prescaler)
1 0 0 clk T2S /64 (From prescaler)
1 0 1 clk T2S /128 (From prescaler)
1 1 0 clk T 2 S /256 (From prescaler)
1 1 1 clk T 2 S /1024 (From prescaler)
> was da heißt: 5 entspricht 1-0-1 und setzt CS2:CS1:CS0 auf> ... na ... überleg das mal .. natürlich auf Option 5 , in Worten FÜNF> ... und das ist der Prescaler ... na... für was ... für einen Divisor> 128.
Bei Timer2 ja, aber nicht bei Timer0...
S. Landolt schrieb:>> Nein, das hätte man auch mit einer Bitverknüpfung>> nicht richtig gemacht:>>>> TCCR2B = (1 << WGM22) | CS22 | CS20; // teilt durch 128>> TCCR0B = (1 << WGM02) | CS02 | CS00; // teilt durch 1024>> Pardon, aber: so natürlich auf gar keinen Fall.
Ganz genau: so eben nicht!
Bentschie schrieb:> Ganz einfach. Du musst im Register TCCR0A die COM0Ax/COM0Bx bits wieder> löschen, dann ist das wieder ein normaler GPIO.
genau das tut es nicht !
Ralph S. schrieb:> S. Landolt schrieb:>>> Nein, das hätte man auch mit einer Bitverknüpfung>>> nicht richtig gemacht:>>>>>> TCCR2B = (1 << WGM22) | CS22 | CS20; // teilt durch 128>>> TCCR0B = (1 << WGM02) | CS02 | CS00; // teilt durch 1024>>>> Pardon, aber: so natürlich auf gar keinen Fall.>> Ganz genau: so eben nicht!
In anderen Programmen (außerhalb des automatischen Einstellens) habe ich
das so gemacht (und hätte ich in meinen weiteren Sourcen gelesen, wäre
es mir aufgefallen):
1
#define tim01_divisor1 1
2
#define tim01_divisor8 2
3
#define tim01_divisor64 3
4
#define tim01_divisor256 4
5
#define tim01_divisor1024 5
Für das Scanen war das aber nicht praktikabel (und wurde deshalb mit
switch-case gemacht... )
Ralph S. schrieb:> Und an die Besserwisser:>> Nein, das hätte man auch mit einer Bitverknüpfung nicht richtig gemacht:>> TCCR2B = (1 << WGM22) | CS22 | CS20; // teilt durch 128> TCCR0B = (1 << WGM02) | CS02 | CS00; // teilt durch 1024
Ergibt aber keinen Sinn. Außer du hast dir deine eigenen 'CSnn'
definiert.
S. Landolt schrieb:> Pardon, aber: so natürlich auf gar keinen Fall.
Das ist ganz normal...
Wenn die Zorn Emotion das Gehirn durchspült, setzt der Verstand und die
Logik aus.
Zorn schließt die Poren der Wahrnehmung.
Ralph S. schrieb:> genau das tut es nicht !
Doch genau so tut das!
Du kannst die Pins an den Timer binden, und auf umgekehrtem Wege wieder
lösen.
Ralf G. schrieb:> Ergibt aber keinen Sinn. Außer du hast dir deine eigenen 'CSnn'> definiert.
Wenn du das ausprobierst, wirst du feststellen, dass diese als
Bitpositionen in der AVR-Toolchain bpsw. in iom328p.h deklariert sind
und automatisch mit eingebunden werden.
Ralph S. schrieb:> Wenn du das ausprobierst, wirst du feststellen, dass diese als> Bitpositionen in der AVR-Toolchain bpsw. in iom328p.h deklariert sind> und automatisch mit eingebunden werden.
Ähh, ich glaube ja er meint das du die Schiebeoperation vergessen hast.
Also statt:
TCCR2B = (1 << WGM22) | CS22 | CS20; // teilt durch 128
das hier:
TCCR2B = (1 << WGM22) | (1 << CS22) | (1 << CS20); // teilt durch 128
Siehst du es jetzt?
Durchschnaufen, baumeln lassen... runterkommen (gilt für mich)
Wie hatte das der Fanboy gesagt:
Arduino Fanboy D. schrieb:> Wenn die Zorn Emotion das Gehirn durchspült, setzt der Verstand und die> Logik aus.> Zorn schließt die Poren der Wahrnehmung.
Stimmt
S. Landolt schrieb:>> ... im letzten Thread ...>> Hallo Veit Devil,>> ? - mit Herrmann verwechselt, oder gusseisernes Gedächtnis?
Hallo,
vielleicht habe ich ihn ja doch verwechselt, liegt im Bereich des
möglichen. Dann tuts mir leid. Timer Threads gabs in letzter Zeit zu
viele.
Nur wenn man mit jeder Antwort immer nur Bruchstücke liefert, muss
zwangsweise Verwirrung entstehen. Man sieht ja was dabei herauskommt. Im
Eingangsthread war nichts ersichtlich was er am Ende alles definiert
bzw. nicht definiert hat. Man musste aus seiner Sicht falsche Schlüsse
ziehen. Ich habe jedoch hier die Lust verloren meine Hilfe anzubieten.
Hallo,
ich habs doch richtig in Erinnerung gehabt.
Beitrag "AVR, progmenu array mit strings und unsigned char: will nicht so recht !"
Ich zitiere:
Veit D. schrieb:
> Ab dem neuen Jahr zeigste den kompletten Code!
Ralph S. schrieb:
> den zeige ich in der Regel immer. Hier ging es aber ums Array an sich> (und das was die Lösung war hatte ich schon mal gewußt und schlicht> wieder vergessen gehabt).
... und für den ganze Ärger (ich reg mich nicht mehr auf), der komplette
(und fertige) Code im Anhang (den sowieso keiner lesen will).
Irgendwie habt ihr es wirklich wirklich drauf, einem ...
Im Anhang halt (und kümmere ich mich um meine anderen Dinge).
> Irgendwie habt ihr es wirklich wirklich drauf, einem ...
Wie dem auch sei - Tatsache ist, dass bereits nach zehn Minuten der
korrekte Hinweis kam, in anständigem Umgangston.
Veit D. schrieb:> Hallo,>> ich habs doch richtig in Erinnerung gehabt.> Beitrag "AVR, progmenu array mit strings und unsigned char: will nicht> so recht !">> Ich zitiere:>> Veit D. schrieb:>> Ab dem neuen Jahr zeigste den kompletten Code!>> Ralph S. schrieb:>> den zeige ich in der Regel immer. Hier ging es aber ums Array an sich>> (und das was die Lösung war hatte ich schon mal gewußt und schlicht>> wieder vergessen gehabt).
Was machst du mich eigentlich immer permanent schräg von der Seite an?
Ich habe dir noch nicht ans Bein gepinkelt oder vors Schienbein
gestoßen. Du bist auch nicht mein Arbeitgeber oder mein Vormund oder
mein was weiß ich und schon überhaupt gar nicht hast du irgendein Recht
mich (oder sonst jemanden) zu bevormunden und Regeln aufzustellen. Wenn
du nur xyz daherlaberst ohne einen fachlichen Zusatz, so kannst es
lassen. Dann... gibts hier welche, die fahren auch jemanden über den
Mund und meinen zu schulregeln zu müssen, lassen dann aber dennoch einen
fachlichen Kommentar oder eine Idee ab.
Du gehörst schlicht nur zu denen, die sagen: so nicht ! Das ist einfach.
Aber schon gar nicht - und jetzt sage ich : so nicht - lädt man im
Reflex eine Beleidigung ab ohne noch mal richtig den Sachverhalt gelesen
zu haben. Hier muß ich sagen Burschi:
SO NICHT !
Das hier ist ein tolles Forum, würde es nicht solche wieder zensiert
geben wie es dich gibt. Sie können einem den Spaß an der Sache
verleiten. Außerdem macht der Ton bekanntlich die Musik. Einem Menschen,
der kurz vor der Rente ist zu behandeln wie jemandem im 1. Lehrjahr
(ohne genauer hinzugucken) ist schlichtweg extremst daneben deshalb auch
hier:
SO NICHT !
Respekt - und ich gehe davon aus dass du deutlich jünger bist als ich -
ist etwas, das du scheinbar noch lernen mußt. Nicht vor mir, es gibt
genügend, die Respekt vor mir haben. In der heutigen Zeit scheint es
immer weniger Anstand und Manieren zu geben und du gehörst zu
Führungsgruppe der Manier- und Anstandslosen. Ich sagte Führungsgruppe,
denn es gibt da noch einige andere mehr.
Es ist nicht Sinn und Zweck der Übung, mit brachialer Gewalt jedem
seinen eigenen Stil aufzwingen zu wollen (das fängt bspw. mit der Art
und Weise der Einrückung im Quelltext an) und hört mit
Namenskonventionen nicht auf.
So, und dann zu dem "vollständigen Code" : Es kann bisweilen etwas schon
sehr groß werden im Code und keiner wird das lesen. In der Regel kann
ich schon sehr gut realisieren wo der Teufel begraben ist (und in diesem
Falle hier war es die Initialisierung). Was interessiert der komplett
andere Rest?
Es ist unglaublich, wie schnell (und ich muß auch sagen bösartig) manche
hier sofort reagieren wenn etwas nicht so geschrieben ist wie IHR das
wollt. Unfassbar.
Ich hoffe das lesen genügend, aber helfen wird dieser Text hier auch
nichts... Leider
Außerdem hatte ich es ja gesagt Veit D. : es wäre mir Recht, wenn du
dich von Postings von mir fernhälst, von dir kommt nur die heiße Luft
die ich nicht brauche. In aller Regel würde ich von mir aus über dich
nicht schreiben und auch zu den Kommentaren die du ablädst (so er sich
nicht direkt auf mich bezieht) keine Äußerung tätigen. Schade ist, dass
es hier nicht so etwas wie \ ignore user gibt (wie das in uralten Chats
mal möglich war) um den Mist von manchen erst gar nicht zu lesen.
In diesem Sinne: Es ist Feiertag
Ralph S. schrieb:> ... und für den ganze Ärger (ich reg mich nicht mehr auf), der komplette> (und fertige) Code im Anhang (den sowieso keiner lesen will).
Ich hab' ihn gelesen und festgestellt, dass er immer noch sehr
unvollständig ist. Er bildet gerade mal einen Teil der "klassischen"
ATMegas ab.
> Irgendwie habt ihr es wirklich wirklich drauf, einem ...
Ja, die Wahrheit ist manchmal schwer zu akzeptieren. Aber sie bleibt
trotzdem wahr. Das ist dein Problem: du bist nicht bereit, diese
Wahrheit zu akzeptieren. Und die heisst: Es ist Schwachsinn, Baugruppen,
die in ihrer Hardware offensichtlich massiv differieren können, über ein
gemeinsames API benutzen zu wollen.
Das führt nach den Gesetzen der Logik nämlich unweigerlich dazu, dass
entweder Teile der Funktionalität verborgen werden müssen (=der
Arduino-Weg...) oder dass das API mindestens genauso komplex sein muss,
wie die Hardware selber (=der Weg vieler APIs für die Hardware neuerer
MCUs).
Beides ist letztlich Scheisse, denn es verhindert, dass man einfach im
DB nachschauen kann, um die Funktion festzulegen bzw. zu ermitteln.
Ein Irrweg, der letztlich nur in den Abgrund führen kann. So oder so,
man macht sich abhängig von den "Zulieferern".
S. Landolt schrieb:> Wie dem auch sei - Tatsache ist, dass bereits nach zehn Minuten der> korrekte Hinweis kam, in anständigem Umgangston.
... der kam von dir als erstem und ich habe mich auch bedankt. Von dir
hatte ich es auch gar nicht so.
Aber bei so etwas hier:
Veit D. schrieb:> was haben wir (ich) versucht dir im letzten Thread zum Thema> beizubringen?
... unglaublich. So rede ich nicht mal mit Lehrlingen wenn sie zum
wiederholten male gleiches falsch machen.
Veit D. schrieb:> Bist du lernfähig?
Bin ich, es wird zwar langsamer, aber immer noch satt...
Veit D. schrieb:> Es gibt auch keinen Prescaler 5
Den es eben sehr wohl gibt, selbst C-hater hat das absolut auch so
gesehen (und das will schon etwas heißen) und außerdem (aber zeitlich
nach dir)
c-hater schrieb:> Bei Timer2 ja, aber nicht bei Timer0...
meinen Fehler gesehen hat.
Wirklich wirklich wirklich übel an diesem Forum ist, dass man sich auf
jeden großen oder kleinen Fehler stürzt wie ein Geier um sich über
andere zu stellen. Das ist nicht Sinn und Zweck. Ich habe keine Ahnung
wie oft ich ein Problem- und ein Problemchen gehabt habe, das mich Zeit
gekostet hat und das hier jemand sofort gesehen hätte.
Es gibt Dinge, da geht es ums lernen, ums Verständnis. Da ist es
gerechtfertigt bestimmte Dinge durchzukauen, nachzuhaken, zu fragen ob
etwas verstanden wurde. Und dann gibt es Fehlersuche bei der im besten
Falle das Vorgehen bei der Fehlersuche eine Sache ist.
Ich muß aber nicht rudimentäres C neu lernen und mich dem Stil anderer
anpassen oder gar unterwerfen ("das macht man so nicht") und ich habe
auch kein Verständnisproblem, wie eine PWM, ein Timer oder ein Interrupt
funktioniert (dafür mache ich das schon - auch beruflich - zu lange).
Aber du hast Recht, der Ton blieb halbwegs anständig (außer von Veit...
und von C-hater von dem man das sowieso gewohnt ist.. aber hier auch:
von C-hater kommt wenigstens ein fachlicher Hinweis).
@ Ralph S.
Du bist leider dermaßen in deiner Wutphase gefangen, dass du nicht
verstehen möchtest was in deinem Eingangspost schief gelaufen ist. Wie
will man da helfen? Vielleicht war ich zu direkt, vielleicht auch nicht.
Beleidigend war es auf jeden Fall nicht. Von permanent kann auch keine
Rede sein. Du steigerst dich in etwas rein was gar nicht vorhanden ist.
Wie c-hater schon sagte, dein Code ist immer noch fehlerhaft.
Ich lasse mich gern belehren und korrigieren, aber wer laut wird muss
liefern können.
Ralph S. schrieb:> (ich bin selbst Ausbilder)
Dann bin ich froh, dass dich nicht während meiner Ausbildung vor dir
hatte.
Und du solltest auch darüber froh sein.
Bei dem ganzen Schaum vorm Mund, merkst du gar nicht, das du dich am
dollsten daneben benimmst....
Tipp:
Lese dir den Thread noch mal in einem Monat durch.
Zudem wäre es mir recht, wenn du mich nicht weiter per PMs belästigst.
an Ralph S.:
Da Sie seit neun Jahren dabei sind, kennen Sie ja auch die gravierenden
Missstände hier - die Umgangsformen sind regelmäßig unterirdisch. Und
von einem Ausbilder hätte ich bessere Nerven erwartet; aber ich sehe und
akzeptiere, dass es sich geradezu um eine allergische Reaktion handelt.
Und muss zugeben, dass auch ich über Veit D.s Ton etwas erstaunt war -
eigentlich kenne ich ihn anders.
an Veit D.:
> ... Eingangspost schief gelaufen ist. Wie will man da helfen?
Es lag doch offen zutage!? Das ursprüngliche Problem, meine ich; um
andere Fehler kümmere ich mich nicht, zumindest nicht ungefragt.
Ein schönen Abend allerseits, ich bin hier weg.
Ralph S. schrieb:> Vllt. sollt ich für die absoluten "Lehrmeister" (ich bin selbst> Ausbilder)Ralph S. schrieb:> Ich bitte dich höfflichst, dich von meinen Threads fernzuhalten. Danke !
Dann solltest du in der Lage sein, Konsistenz zwischen deiner Wortwahl
und dem Inhalt herzustellen.
c-hater schrieb:> Es ist Schwachsinn, Baugruppen,> die in ihrer Hardware offensichtlich massiv differieren können, über ein> gemeinsames API benutzen zu wollen.
Puuuh, darüber kann man trefflich streiten. Ich gebe dir in soweit
Recht, dass hierüber sich Fehler einschleichen (wie man gesehen hat) und
ich gebe dir erst recht Recht damit, dass über so ein API nicht mehr
gesehen wird was sich dahinter verbirgt (und dass das heute leider die
übliche Geschichte ist wo etwas zu "lernen" aufhört, weil man nur eine
API verwendet aber kein Gespür dafür hat wieso das funktioniert und wo
die Grenzen liegen).
Die API eines PKW's und eines LKW's sind gleich: Gaspedal, Bremspedal,
Kupplung, Lenkrad. Wenn du nicht weißt, warum das Ding fährt kannst du
dennoch damit fahren. Aber bisweilen ist es sinnvoll zu wissen, warum
das fährt, wie das zu reagieren hat und was man machen kann und was man
tunlichst nicht machen sollte. Die API ist aber gleich.
c-hater schrieb:> Das führt nach den Gesetzen der Logik nämlich unweigerlich dazu, dass> entweder Teile der Funktionalität verborgen werden müssen
Genau das war mein Sinn !
c-hater schrieb:> (=der> Arduino-Weg...)
Na ja ... hmmm.... ob man jetzt den "Arduino-Weg" mag oder nicht sei
dahingestellt.
Es sind fertige Baugruppen und die verwendet man eben, ohne sich
jedesmal neu Gedanken darüber zu machen warum das jetzt funktioniert.
Bspw. weiß ich, dass auf einem Cortex Controller schon alleine für die
GPIO's ein Takt einzuschalten ist und eine Unmenge an Konfiguration zu
machen ist, bevor ich auch nur eine 1 oder 0 setzen kann. Es macht
keinen Sinn, mir jedesmal Gedanken darüber zu machen wie das geht (und
schon gar nicht für unterschiedliche Prozessorfamilien). Es sollte doch
genügen, wenn man im Datenblatt sieht wie es geht, das einmal umsetzt
und die Grenzen der Umsetzung kennt.
Wenn es dann spezieller wird, oder die Resourcen (Geschwindigkeit ist
auch eine Resource) nicht reichen, kann man sich noch einmal etwas
vornehmen.
Ob das alles Scheiße ist, darf jeder für sich selbst beantworten.
c-hater schrieb:> Beides ist letztlich Scheisse, denn es verhindert, dass man einfach im> DB nachschauen kann, um die Funktion festzulegen bzw. zu ermitteln.
Na ja... ich hab heute lange ins DB geschaut und in aller Regel schaue
ich ins DB. Aber das DB hat die böse Angewohnheit wie ein
selbstgeschriebener Text: Du liest deinen Text (deinen eigenen) 1000 mal
und findest keine Schreibfehler. Weil du GLAUBST deinen eigenen Text zu
kennen. Jemand anderes sieht die Fehler jedoch sofort. Genauso verhält
es sich mit dem Datenblatt. Du liest die entsprechenden Stellen zig
mal.. im vorliegenden Falle gibt es 3 Tabellen mit den Prescaler-Bits. 2
sind identisch, einer differiert. Du siehst noch nicht einmal sofort,
wenn du auf die Tabelle schaust, zu welchem Timer die jetzt gerade
gehören die du auf dem Bildschirm hast. Dann kommt die "Unmöglichkeit"
hinzu, dass ein 8-Bit Timer dieselben Einstellungen (beim Prescaler) wie
der 16-Bit Timer hat wo man eigentlich schwer davon ausgeht, dass eher
die beiden 8-Bit Timer identisch wären. Dann vergleicht man zwar noch
(und zwar immer wieder) die Positionen der Selektorbits im Register...
aber wie in meinem Falle nicht mehr alle Teiler (was mir natürlich nicht
mehr passieren wird, zumindest nicht mit AVR).
Dass du kein Freund vom Arduino-Weg bist, ist bekannt. So wirklich ein
Freund davon bin ich auch nicht, aber Arduino hat den einen Vorteil
eben, dass die Hardware sehr abstrahiert wird. Wie stark man diese
Abstraktionen annehmen will sollte jedem selbst überlassen bleiben.
Im Laufe meines Berufslebens hatte ich mit MCS-51, PIC16F, MSP430, AVR,
STM32F und STM8F zu tun (lustigerweise dienstlich noch nie NXP). Hier
habe ich es mir sehr zur Angewohnheit gemacht, eine API (auch wenn die
Hardware sehr unterschiedlich ist) so ähnlich wie nur möglich zu machen.
Kommt es auf Geschwindigkeit nicht an, werden Pins immer nach demselben
Schema angesprochen. Muß es genauer werden, schaut man eben nochmal ins
Datenblatt. Scheiße ist... das Rad jedesmla neu zu erfinden
S. Landolt schrieb:> Und muss zugeben, dass auch ich über Veit D.s Ton etwas erstaunt war -> eigentlich kenne ich ihn anders.>> an Veit D.:>> ... Eingangspost schief gelaufen ist. Wie will man da helfen?> Es lag doch offen zutage!? Das ursprüngliche Problem, meine ich; um> andere Fehler kümmere ich mich nicht, zumindest nicht ungefragt.
Keine Sorge. Eigentlich helfe ich jedem der möchte im normalen Ton. Hier
lag noch eine Erinnerung im Gedächtnis, deswegen ist das etwas direkter
gewurden. Wer das als Beleidigung aufgefasst hat bitte ich um
Entschuldigung.
Ralph S. schrieb:> Die API eines PKW's und eines LKW's sind gleich: Gaspedal, Bremspedal,> Kupplung, Lenkrad. Wenn du nicht weißt, warum das Ding fährt kannst du> dennoch damit fahren.
Nicht wirklich. Das fängt schon auf viel kleinerer Ebene an: ein Mensch,
der nur auf einem Vehikel mit Automatikgetriebe gelernt hat, ist unfähig
ein Vehikel mit manueller Schaltung zu fahren. Und tatsächlich nimmt
sogar der Gesetzgeber (der mit technischer Kompetenz typischerweise
nicht gerade gesegnet ist) darauf die entsprechende Rücksicht...
So blöd ich Auto-Vergleiche normalerweise finde: das ist ein schönes
Beispiel, wo sie vom Prinzip her durchaus passen...
Arduino-User=Automatik-Fahrer...
Schlimm ist nur, dass zwar dem Automatik-Fahrer verboten ist, ein Auto
mit manuellem Schaltgetriebe im öffentlichen Straßenverkehr zu bewegen,
aber nicht dem Arduino-Sklaven, einen Controller, von dem er ganz
offensichtlich nichtmal das DB gelesen hat...
Hier würde ich dringend eine entsprechende Gesetzgebung fordern.
Insbesondere für den Fall, dass es in's Netzwerk geht...
Ralph S. schrieb:> Die API eines PKW's und eines LKW's sind gleich: Gaspedal, Bremspedal,> Kupplung, Lenkrad. Wenn du nicht weißt, warum das Ding fährt kannst du> dennoch damit fahren. Aber bisweilen ist es sinnvoll zu wissen, warum> das fährt, wie das zu reagieren hat und was man machen kann und was man> tunlichst nicht machen sollte. Die API ist aber gleich.
Dein Interface ist dabei jedoch absolut irreführend.
Dein Interface spricht "prescaler".
Jeder denkt gleich das es einen Prescaler 5 nicht gibt. Damit sind wir
wieder beim Eingangsposting. Ohne zu wissen was du mit prescale
definierst muss man erstmal zum Schluss kommen das es falsch ist. Ich
selbst würde auch niemals abweichend vom Manual irgendwas neues
erfinden. Weil es die Nutzung erschwert. Man benötigt in deinem Fall
wieder eine Übersetzungstabelle welche Nummer welchen tatsächlichen
Prescaler darstellt. Das will man doch nicht.
Einen Hinweis gebe ich dir noch, wie man es vernünftiger, lesbarer
schreiben kann. Dann ist zumindestens Prescaler gleich Prescaler und
nicht irgendwas aus der Luft gegriffenes.
So, jetzt hatte ich mir ja eigentlich vorgenommen gehabt, eine Weile nix
im Forum zu schreiben, aber jetzt mal ohne "roten Kopf" ohne Zorn, im
"normalen" halt:
Veit D. schrieb:> void runTimer1 (const unsigned int prescaler)> {> TCCR1B &= ~( _BV(CS12) | _BV(CS11) | _BV(CS10) );>> switch (prescaler) {> case 1 : TCCR1B |= _BV(CS10); break;> case 8 : TCCR1B |= _BV(CS11); break;> case 64 : TCCR1B |= _BV(CS11) | _BV(CS10); break;> case 256 : TCCR1B |= _BV(CS12); break;> case 1024 : TCCR1B |= _BV(CS12) | _BV(CS10); break;> default : break;> }> }
Man muß ja dieses _BV(bitposition) nicht unbedingt lieben (und ich mags
gar nicht, dann schon wirklich eher die für mich geläufigere
Schreibweise
case 1 : TCCR1B |= (1 << CS10); break;
Aber wie auch immer, ich stell das jetzt mal zwar auszugsweise aber
komplett zusammnenkopiert als Ganzes aus meinem eigenen
Sourcenverzeichnis hier ein:
// und hier damit das als Gesamtes funktioniert ist.
60
int main(void)
61
{
62
tim2_fastpwm_init(tim2_divisor128, 127, 63);
63
while(1);
64
}
Das ganze (und ich stoße so etwas normalerweise nicht an) zur
Diskussion, zu dem, was man tut und was nicht.
Das hier sind für mich 2 Dinge, um nicht immer ins Datenblatt schauen zu
müssen, sondern ich verwende sie einfach (und das seit Jahren). Da wird
man wohl betriebsblind, weil das eben meine Namensgebung ist. So, was
ist daran jetzt (keine provokative Frage) verkehrt. Standardmäßig
kopiere ich mir den Header in mein Projektordner und mache (wenn wie im
hier vorliegenden Falle) meine Einstellungen.
Ist es tatsächlich besser, anstelle von
#define tim2_divisor32 3
besser:
#define tim2_divisor32 (1 << CS01 ) | (1 << CS00)
oder:
#define tim2_divisor32 (_BV(CS11) | _BV(CS10))
zu schreiben?
Macht es denn keinen Sinn, sich für die Dinge die man permanent braucht
sich seine eigene API zu schaffen mit der man versucht halbwegs
konsistent mit anderen Familien zu sein. Jetzt würde ich wirklich
wirklich wirklich gerne wissen, wie ihr das handhabt (aber bitteschön
nicht mit dem Anspruch dass das Gott und die Welt übernehmen muß).
Grundsätzlich (und deswegen ärgere ich mich über meinen Zorn)
hinterfrage ich meine Dinge schon immer wieder mal, bei Elektronik /
Hardware, Software oder auch sonst im Leben ob meine Ansichten oder
Verhaltensweisen noch gültig sind. Wie handhabt ihr Eure euch eigenen
API's ?
Hallo,
ach Mensch Ralph, du machst dir dein Leben hier echt unnötig schwer.
Mir ist es doch vollkommen egal wie du die Bitschieberei schreibst.
1
(1<<CS10)
2
oder
3
_BV(CS10)
Es ging um den Prescaler. Wenn du deine "Nummerierung" so richtig
findest dann mach das. Nur sorge bitte beim nächsten Thread dafür das
man auch gleich sieht was das bedeutet, ansonsten führt das wieder zur
Verwirrung. Es hat auch niemand etwas gegen selbst geschriebene APIs
bzw. Interfaces. Hat niemand behauptet und wird niemand behaupten.
Falls du mich fragst. Ich würde bei den vorhandenen im Manual stehenden
Prescaler Werten bleiben. Das heißt ich würde in dem Fall
1
#define tim2_divisor32 32
schreiben. Und eigentlich würde ich gar kein define schreiben. Enums in
dem Fall eigentlich auch nicht. Ich würde
1
constuint8_ttim2_divisor32=32;
schreiben. Außer es gibt Gründe für define. Wie gesagt, diese defines
kann man sich dann auch gleich schenken. Denn normalerweise schaut man
ins Manual welche Prescaler ein Timer hat und freut sich wenn man diese
Angabe direkt ohne Umschweife im Interface verwenden kann. Das Interface
ist das was man als Erstes sieht, dass muss möglichst leicht
verständlich sein.
so, ich habe mir das jetzt ein paar mal mit verschiedenen Optionen
angeguckt, wie es für mich am besten ausschaut, nicht nur für die Timer
jetzt ... auch wenn es ein paar Byte mehr Flash kostet (wenn der eng
wird muß man das eben händisch machen) mach ich das jetzt so, dass der
Teilerfaktor als Zahlenwert der Funktion übergeben wird:
Ganz glücklich bin ich dennoch nicht mit der Lösung, weil es als
Funktionsargument für - clockdivider - eine 16-Bit Variable benötigt.
pwmt0_init(32, 127, 63);
Hallo,
wenn du alles const machst was konstant ist, dann wird auch das switch
quasi wegoptimiert. Zumindestens ist das bei C++ so. Sollte auch bei C
so sein, denke ich.
Schreib mal
Veit D. schrieb:> Dir fehlt in der Funktionssignatur noch eine Klammer.
die ist beim Kopieren "verlustig" gegangen ! Ohne die Klammer würde der
Compiler Fehler ausgeben.
Hmm... mit einem const davor kann ich dann aber zur Laufzeit den Timer
nicht mehr ändern !
Ralph S. schrieb:> Hmm... mit einem const davor kann ich dann aber zur Laufzeit den Timer> nicht mehr ändern !
Bei einem const vor einem Funktionsparameter kannst du den Parameter in
der Funktion nicht mehr ändern.
Das verhindert manche logische Fehler und hilft dem Optimierer etwas
aufs Pferd.
Aber nichts kann dich daran hindern die Funktion mit verschiedensten
Parametern aufzurufen.
Hallo,
habe es selbst ausprobiert mit der einen gezeigten Funktion. Es belegt
306 Byte Flash und 0 Byte RAM. Unabhängig ob die Funktionsparameter
konstant sind oder nicht. Unabhängig davon sollte man sie dennoch
konstant machen. Erklärt hat das schon Arduino Fanboy. Bewahrt einem vor
Syntax Unsinn o.ä..
Ich verstehe nicht warum Arduino Fanboy negativ bewertet wird. Ist doch
alles korrekt was er sagt.
Im Nachhinein erklärt, kann der Compiler das wohl nicht weiter
optimieren, weil der Übergabeparameter direkt als Literal ja schon
konstant ist. So schlau ist der Compiler also schon.
Der größere const Effekt lauert darin, dass hatte ich tiefer in Gedanken
gehabt, wenn man den Prescaler als Variable übergibt und diese konstant
macht. Wenn man den zur Laufzeit ändern möchte geht das natürlich nicht.
Mit enums macht das auch großen keinen Sinn.
Ändere ich den Prescaler Datentyp auf uint8_t werden "nur" 290 Byte
Flash und 0 Byte RAM belegt. Kommt es dir wirklich auf die 16 Byte Flash
an? Ich persönlich halte das für den falschen Weg.
Mit enums habe ich auch experimentiert, es ändert sich nicht viel, je
nachdem was man damit anstellt. Reicht von 290 bis 316 Byte Flash,
abhängig ob man das enum direkt übergibt oder mittels zusätzlicher enum
Variable
enums können Sinn machen, wenn du damit sprechende Variablen definierst
um den Timer-Mode als Parameter zu übergeben.
Jetzt liegst an dir womit du glücklich wirst. Für mich zählt in erster
Linie lesbarer Code. Wenn man sich deine gezeigte Funktion anschaut,
dann erübrigt sich die einkommentierte Doku, weil genau das 1:1 im
switch case steht. Das ist für mich lesbarer Code.
Ich habe mir jetzt genügend Gedanken für dich gemacht. Es gibt Tausende
Möglichkeiten. Wähle die Sinnvollste.
Veit D. schrieb:> Ändere ich den Prescaler Datentyp auf uint8_t werden "nur" 290 Byte> Flash und 0 Byte RAM belegt. Kommt es dir wirklich auf die 16 Byte Flash> an? Ich persönlich halte das für den falschen Weg.
Nein, kommt mir nicht darauf an. Im Moment geht es mir schlicht darum
(deswegen jetzt mal zur Diskussion gestellt gewesen) was denn am
praktikabelsten ist.
Veit D. schrieb:> Ich habe mir jetzt genügend Gedanken für dich gemacht.
Na ja, das hat ja keiner verlangt, aber dennoch danke !
Veit D. schrieb:> dann erübrigt sich die einkommentierte Doku
... das kommt immer dann so vor, wenn ich etwas neu mache. Dann kopiere
ich mir die entsprechenden Stellen aus dem Datenblatt und habe das dann
in der Übersicht. Schlimm wirds (wie mir hier ja passiert ist), wenn das
falsch "abgeschrieben" wurde, sich dann nach dem falsch abgeschriebenen
aber gerichtet wird.
Veit D. schrieb:> Wenn man den zur Laufzeit ändern möchte geht das natürlich nicht.
Das ist aber genau das, was ich momentan mache. Dieses zu ändern während
der Laufzeit, weil ich nicht nur die Duty-Cycle ändern will, sondern
auch die Frequenz.
--------------------------------
Es ist gut, wenn wir diesen Thread abschließen !