Hallo,
mir raucht schon der Schädel von dem Datenbuch was mir auch nicht
weiterhilft mit den Timern. Ich will einfach nur
Timer 2: 40khz Frequenz (25us Periode) auf Pin und das war es. Ein
Ausschalten auch noch dazu.
Hat da jemand vielleicht einfach ein paar Zeilen Code, die ich anpassen
kann?
Ich blick da nicht mehr durch zwischen Waveform Mode, PWM Mode,
Capture, welchen nehme ich denn nun?
Gruss,
Christian
Toll... ja, aber das nützt nix, ich muss an die Registerebenr dran! Der
Arduino Murks bietet da nichts an.
Kann ja nicht so schwer sein, auf dem Cortex alles kein Thema, da bin
ich schneller fertig als beim Arduino....
40 khz, d.h. 8E6 Hz : 1 : (199+1) = 40.000
Prescaler = 1
Timer Top bei 199
soweit bin ich schon. Da muss er dann zurücksetzen auf 0 und den Pin
toggeln.
Ich kann mit solchen Bruchstück-Sätzen leider nicht viel anfangen. Da
gibt es noch einiges mehr, was gesetzt werden will. bei jedem anderen uC
ist das einfacher als bei Atmel.
Wenn eine Periode 25us sind, dann muss er bei 25us schalten und bei 50us
einen Auto-Reload machen. Dann habe ich 50% Duty Cycle.
Nein. Bei jedem Compare alle 25us den Pin OC2 togglen. Also von 0 auf 1
und von 1 auf 0. Genau das hat S. Landolt gesagt. Geht im TCCR2A mit
COM2A1 und COM2A0
Christian J. schrieb:> und was mache ich mit diesen Waveform Bits? Wie müssen die gesetztt> werden?
ProTipp (Von Cyberlord zu Mikrosklaven):
Das Datenblatt hat ja nicht nur diese Tabellen zu bieten, sondern sogar
auch Prosa welche die verschiedenen Modi erklärt. Und ich fühle dass da
bei dir etwas Bedarf besteht.
> bei jedem anderen uC ist das einfacher als bei Atmel.
Natürlich. Wenn man nicht schwimmen kann ist die Badehose schuld. AVR
ist da echt ganz ganz doll kompliziert.
S. Landolt schrieb:> Mann, das kostet mich ein Drittel der Kaffeepause.
Ja, das kommt davon, wenn man auf dem Handy tippt statt am PC :-)
Ist aber schon gut, ich hämmer das heute abend in einen Arduino rein,
Oszi dazu und üblicherweise ist nach rund 20 Minuten etwas fertig, was
genaudas macht, ohne dass ich mir die Romane aus dem Datenbuch
durchlesen muss.
Christian J. schrieb:> die Romane aus dem Datenbuch> durchlesen muss.
Haha, das ist Lustig - trial and error! Programmierung.
Also ich arbeite streng nach dem Datenblatt und es funktioniert dann
immer.
Was sollte einem sonst "sagen" wie es geht?
Christian J. schrieb:> Ist aber schon gut, ich hämmer das heute abend in einen Arduino rein,> Oszi dazu und üblicherweise ist nach rund 20 Minuten etwas fertig, was> genaudas macht, ohne dass ich mir die Romane aus dem Datenbuch> durchlesen muss.
Warum machst du dann hier überhaupt so lange rum? Oben war Arduino noch
Murks. Bist du Wankelmütig?
> Kann ja nicht so schwer sein, auf dem Cortex alles kein Thema, da bin> ich schneller fertig als beim Arduino....
Wie kommt es das du das angeblich auf einem Cortex ohne in Datenblättern
zu lesen mal so locker machst und beim popeligen AVR scheiterst? Passt
doch nicht zusammen.
Ich persönlich habe dich in die Schublade "talentlosen Schwätzer"
gesteckt.
Cyblord -. schrieb:> Ich persönlich habe dich in die Schublade "talentlosen Schwätzer"> gesteckt.
Da sind wir schon zwei.... keine Ahnung wieso du meinst noch auf meine
Beiträge reagieren zu müssen? Na lassen wir das, hier fehlt eindeutig
der Ignore Filter.
Also ich opfere einen Teil meiner Pause, und ja, musste selbst erst ins
Datenblatt schauen, dann solche Reaktion - na, ich wünsche weiterhin
viel Erfolg.
S. Landolt schrieb:> Also ich opfere einen Teil meiner Pause, und ja, musste selbst erst ins> Datenblatt schauen, dann solche Reaktion - na, ich wünsche weiterhin> viel Erfolg.
Wundert mich auch. Aber talentlos und arrogant geht leider oft Hand in
Hand.
S. Landolt schrieb:> Also ich opfere einen Teil meiner Pause, und ja, musste selbst erst ins> Datenblatt schauen, dann solche Reaktion - na, ich wünsche weiterhin> viel Erfolg.
Nun komm runter.... danke Dir doch für Deine Mühen. Es funktioniert ja!
Ich hänge es hier nochmal drunter
Die unten stehende Kombination von Bits ist die einzige, die mir eine
Frequenz von 40khz erzeugt. Alle denkbar anderen haben eine fixe
Frequenz von 15.x khz (8 Mhz Takt). Das AVR Datenblatt ist teils schwer
verständlich, auch nach x Mal durchlesen blicke ich teilweise nicht
durch. Wie man in Foren sieht viele andere allerdings auch nicht.
Ich habe ein Rechteck an Pin B3 (Arduino = 11), also an OC2A. Hätte es
zwar lieber gern an OC2B aber das habe ich nicht hin gekriegt. Falls es
überhaupt möglich ist. zB mit OCRB. Aber bei CTC steht nur OCRA in der
Tabelle.
Die Frage ist: Was hat dieses WGM22 Bit für eine Bewandnis? Eigentlich
sollte es doch gelöscht sein für CTC Mode, oder? Könnte ja auch sein,
dass ich den Fast PWM Mode erwischt habe. Auch der hat bei OCRA = TOP
seinen Match.
In Tabelle 17-8 steht
Mode 2: WGM2 = 0, WGM1 = 1, WGM0 = 0 (CTC Mode), Top = OCRA.
Wenn man diese "Verallgemeinerung" anlegt steht da für Timer 2 doch
WGM22 = 0; WGM21 = 1, WGM20 = 0
Ob da ein x fehlt für die Timer Nummer?
Nur kommt da dann nichts aus dem Pin raus. Da ich eine IR Diode dran
habe muss sicher gestellt sein, dass beim Abschalten der Pin auf 0 geht.
Das scheint nicht immer der Fall zu sein, wenn man den Pin nicht in den
Normalmode zurück stellt.
1
/* Startet oder stoppt den Timer 2 */
2
voidTimer2Enable(boolstat)
3
{
4
/* OC2B Pin = INT 1 Pin (PD 3)
5
OC2A Pin = MOSI Pin (PB 3)
6
*/
7
8
cli();
9
if(stat){
10
OCR2A=50;// Compare Match A Register auf 40khz
11
TCCR2A=(1<<COM2A0)|(1<<WGM20);
12
TCCR2B=(1<<WGM22)|(1<<CS20);// Mode 2 CTC Prescaler 1 und Timer starten
Christian J. schrieb:> OCR2A = 50;> TCCR2A = (1 << COM2A0) | (1 << WGM20);> TCCR2B = (1 << WGM22) | (1 << CS20);
In der Reihenfolge steckt ein Problem und lauert nur darauf einen
Wahnsinnig zu machen.
Ich habe nicht alles geprüft.
Aber dieses ist mir aufgefallen!
Ob Timer2 davon betroffen ist, weiß ich auch nicht genau.
Aber viele AVR Timer sind es.
Prüfe also selber die folgenden Aussagen !
Folgende Situation:
Der Timer befindet nach dem Reset in Mode0
Der Arduino Startup Code bereitet ihn für PWM vor.
Im PWM Mode wird OCR2A gelatscht.
Im CTC Mode nicht.
Du schreibst also 50 in das Latch.
Stellst dann den Mode um.
Folge: Der Latchinhalt landet nie im Register.
Mit einigen Timern(allen?) führt das zur Totalblockade des AVR
Arduino Fanboy D. schrieb:> Folge: Der Latchinhalt landet nie im Register.
Dass er es doch tut lässt sich auf dem Oszi einwandfrei nachvollziehen.
Jede Veränderung des Wertes ändert die Frequenz um n * 1/8E6 Schritte.
39,95xx khz erziele ich. Das reicht auch. Nur die Frage: Bin ich
überhaupt im CTC Mode ??? Habe noch stur alle relevanten Bits
durchprobiert, nur mit dieser Kombination funzt es.
Arduino Fanboy D. schrieb:> Phasenrichtige PWM
Und womit würde man dann den Duty Cycle einstellen? Bei mir ist der fix
50% mit "Toggle OCRA". PWM heisst ja Puls Weiten Modulation. Für IR sind
ca 30% besser als 50% weil weniger Energie verbraucht wird.
Christian J. schrieb:> Die unten stehende Kombination von Bits ist die einzige, die mir eine> Frequenz von 40khz erzeugt.
Nein, mit OCR2A = 50 bestimmt nicht.
Dein 328 läuft mit 8MHz, d.h. eine Clockperiode dauert 125ns.
Du willst alle 25us Pin OC2A toggeln.
Marc V. schrieb:> Und das war es schon, funktioniert bestimmt, 1000 Mal erprobt.
Der einzige Unterschied bei dir ist doch das WGM22 Bit weg und dafür das
WGM21 rein und der Matchwert 199.
Danke, ich probiere es aus!. Aber doch... 40khz kommen bei mir raus,
ganz sicher nach gemessen :-) Nur warum das so ist war nicht klar.... 50
ist 200 / 4... also schon mal ein Vielfaches.
Christian J. schrieb:> Und womit würde man dann den Duty Cycle einstellen?
Willst du doch gar nicht....
Das ist alles gar nicht ganz so schwer...
Nur ausprobieren, dass ist hier die schlechteste aller Lösungswege.
Denn die Anzahl der möglichen Permutationen ist erstaunlich groß.
Es bleibt dabei:
Datenblatt lesen und das so oft und so lange, bis es verstanden ist.
Hier eine 16MHz Version.
Für 8MHz Arduinos könntest du OCR2A verdoppeln
Oder eine passendere Vorteiler/OCR2A Kombination ermitteln.
Christian J. schrieb:> Danke, ich probiere es aus!. Aber doch... 40khz kommen bei mir raus,> ganz sicher nach gemessen :-) Nur warum das so ist war nicht klar....Christian J. schrieb:> TCCR2B = (1 << WGM22) | (1 << CS20); // Mode 2 CTC Prescaler 1> und Timer starten
Nein, du hast MODE 5 eingeschaltet und das ist laut DaBla:
PWM, Phase Correct
Arduino Fanboy D. schrieb:> #define AtomicSection ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
Ok. Bringt das hier Vorteile gegenüber sei und cli? Soll ja wohl
heissen, dass da kein Int zwischenfunken darf denke ich mal.
Marc V. schrieb:> Nein, du hast MODE 5 eingeschaltet und das ist laut DaBla:> PWM, Phase Correct
Ich glaube es euch! Es kam ja das Gewünschte heraus. Nur warum war die
Frage.... kriegt man das Signal auch auf dem INT 1 Pin hin?
Christian J. schrieb:> Arduino Fanboy D. schrieb:>> #define AtomicSection ATOMIC_BLOCK(ATOMIC_RESTORESTATE)>> Ok. Bringt das hier Vorteile gegenüber sei und cli? Soll ja wohl> heissen, dass da kein Int zwischenfunken darf denke ich mal.
Ja, es löscht erst das Flag und erzwingt dann, am Ende des Blocks, dass
Interrupt Enable Flag wieder auf den alten Stand gesetzt wird.
Händisch ist oft/meist fehlerträchtiger, als ein erprobter Automatismus.
Harry L. schrieb:> Was ist daran fehlerträchtig?
Da bei einem Arduino eh dauernd ein INT läuft ist es auch wumpe den aus
und wieder ein zu schalten. Schaltet man ihn ab funktioniert einiges
nicht mehr, zb die Serielle nicht, delay usw. usw.
Christian J. schrieb:> Harry L. schrieb:>> Was ist daran fehlerträchtig?>> Da bei einem Arduino eh dauernd ein INT läuft ist es auch wumpe den aus> und wieder ein zu schalten. Schaltet man ihn ab funktioniert einiges> nicht mehr, zb die Serielle nicht, delay usw. usw.
Ja und?
Man schaltet den ja deshalb auch nicht dauerhaft aus, sondern nur für
kritische Abschnitte, die selten länger als wenige µs dauern.
"Wumpe" ist das ganz und gar nicht!
Arduino Fanboy D. schrieb:> Im PWM Mode wird OCR2A gelatscht.> Im CTC Mode nicht.>> Du schreibst also 50 in das Latch.> Stellst dann den Mode um.> Folge: Der Latchinhalt landet nie im Register.
Äh, warum nicht?
> Mit einigen Timern(allen?) führt das zur Totalblockade des AVR
Äh, warum?
Oliver
Oliver S. schrieb:> Äh, warum nicht?
Weil der Latchinhalt erst in das Register geschrieben wird, wenn der
Zähler TOP erreicht.
Oliver S. schrieb:> Äh, warum?
Tja.....
Das Problem ist das Latch, in Verbindung mit dem Moduswechsel von PWM
auf Compare Match
Hier kann ich dir ein Beispiel für eine solche Blockade liefern.
Nur Timer init und ISR
(es stammt nicht aus meiner Feder, Kritik am Stil wird verpuffen)
Geschrieben für Arduino Mega, also ATMEGA2560
Harry L. schrieb:> Arduino Fanboy D. schrieb:>> Händisch ist oft/meist fehlerträchtiger, als ein erprobter Automatismus.>> Was ist daran fehlerträchtig?void blabla(void)> {> uint8_t sreg;> sreg = SREG;> cli();> ...> ...> ...> SREG = sreg;> }>> genau so wird das in einer Microchip-App-Note beschrieben.
Kann ja sein!
Tausend Fliegen beweisen: Scheiße schmeckt gut!
Im Ernst:
cli();
...
...
...
SREG = sreg;
Man könnte das ein oder andere cli() oder SREG = sreg, versehentlich
löschen, falsch platzieren.
Bei Blockklammern fallen fehlende Klammern sofort auf.
Der Compiler jault erzürnt ....
Und durch die (hoffentlich vorhandene) Einrückung sieht man klar und
deutlich was zusammen gehört.
Also:
Es ist grundsätzlich egal, welche Methode man verwendet.
Mir, ist allerdings die Block Methode lieber!
Und ja, natürlich kann man auch über diese Geschmacksfrage,
Glaubenskriege anzetteln.
Arduino Fanboy D. schrieb:> Hier kann ich dir ein Beispiel für eine solche Blockade liefern.
Kannst du nicht. "Totale Blockade" gibt es beim ATMega schlicht gar
nicht. Das Programm macht nicht das, was der Programmierer sich
vorgestellt hat, aber laufen tut das immer.
Zudem setzt du in der angeblich fehlerhaften Version 2 Register OCRA vor
allen anderen. Das Latch-Problem kann da also gar nicht auftreten.
Natürlich kann das ein Problem sein, wenn man eins der gelatchten
Register erts nach der Anwahl des Timermodus schreibt. Der Wert wird
dann erst beim nächsten BOTTOM/TOP geupdated, oder wann auch immer in
dem Modus das Register geupdated wird. Je nachdem, was man da vorher in
die Register geschrieben hat, passiert das eventuell gar nicht, wobei
mir dazu beim OCR jetzt erst einmal kein Fall einfallen will.
Eine Blockade tritt da aber niemals auf.
Oliver
Oliver S. schrieb:> Das Latch-Problem kann da also gar nicht auftreten.
Irgendwas hast du da noch nicht ganz verstanden.
Oliver S. schrieb:> Eine Blockade tritt da aber niemals auf.
Getestet?
Warum nicht?
Die genannten Bedingungen eingehalten?
Arduino Fanboy D. schrieb:> Oliver S. schrieb:>> Das Latch-Problem kann da also gar nicht auftreten.> Irgendwas hast du da noch nicht ganz verstanden.
Äh, doch.
>> Oliver S. schrieb:>> Eine Blockade tritt da aber niemals auf.> Getestet?> Warum nicht?> Die genannten Bedingungen eingehalten?
Natürlich. Es passiert - nix. Der Prozessor läuft in seiner
Programmende-Endlosschleife fröhlich vor sich hin. Der Timer macht halt,
was man ihm sagt, und nicht, was sich der Programmierer wünscht. Von
totaler Blockade aber keine Spur.
Oliver
Oliver S. schrieb:> Äh, warum nicht?>>> Mit einigen Timern(allen?) führt das zur Totalblockade des AVR>> Äh, warum?>> Irgendwas hast du da noch nicht ganz verstanden.> Äh, doch.Äh stört Dich dieser Sprachfehler nicht?
Äh mir würde das maximal auf's Schwein gehen!
SCNR
Oliver S. schrieb:> Natürlich. Es passiert - nix.
Ok, das nix nehme ich zurück. avrlibc baut ein cli vor die
Endlosschliefe. Mit einem while(1) im main wird in beiden Verisonen die
ISR angesprungen.
Oliver
Christian J. schrieb:> Ja, es funzt,. mit 20.3 khz :-)
Mein Fehler, für 40KHz am OC2A muss der Pin alle 12,5us toggeln,
nicht alle 25us.
Demzufolge muss OCR2A 99 und nicht 199 sein.
Marc V. schrieb:> Mein Fehler, für 40KHz am OC2A muss der Pin alle 12,5us toggeln,> nicht alle 25us.
Hast du auch ne Lösung für schnelle Stop/Starts? Den Takt abklemmen mit
CS0. Für IR muss aber auf jeden Fall dann PB3 auf low gehen.
Landholts Lösung ist für mich besser, da ich damit den DC absenken kann
denke ich. 30% reichen.
TCCR2A = 0;
TCCR2B = 0;
Kannst noch rauswerfen, die nächsten Befehle sind ja Zuweisungen,.
Ich will dich nicht schocken aber dein Code, copy & paste grad
ausprobiert erzeugt leider nichts. Nacktes Pro Mini Board aus der Tüte.
Nur einen High Pegel auf dem PB3 Pin. Nehme ich WGM22 wieder rein kommt
40khz aber OCR2B hat keinerlei Auswirkungen.
Ok, Fehler suche ich jetzt aber nicht mehr, muss noch bügeln.....
Christian J. schrieb:> Hast du auch ne Lösung für schnelle Stop/Starts? Den Takt abklemmen mit> CS0. Für IR muss aber auf jeden Fall dann PB3 auf low gehen.
Was heißt schnell ?
Nachdem du einmal Init gemacht hast:
STOP:
1
TCCR2B = 0;
2
PORTB &= ~(1<<PB3);
Das braucht selbst beim GCC nur 2+2 Takte, da meistens r1 dazu
genommen wird und dessen Inhalt ist normallerweise immer 0.
Erneuter START:
Arduino Fanboy D. schrieb:> cli(); // Interrupts ausschalten> TCNT2 = 0; // Reset Register> OCR2A = 249; // Compare> TIMSK2 = (1<<OCIE2A); // Compare Match A> TCCR2A = (1<<WGM21); // set Mode> TCCR2B = (1<<CS22); // Prescaler 64> sei();
Schießt den uC tatsächlich völlig ab. Der ist nirgendwo mehr. Öfter mal
was Neues.... beim ARM käme wohl eine "Hard Fault Exception" aber beim
AVR328P eher nicht. Die nachfolgende Blink Routine wird gar nicht mehr
erreicht und ein Reboot Findet auch nicht statt. Nur der WDT holt ihn
wieder raus.
> Schießt den uC tatsächlich völlig ab.
Sagen wir lieber "den Arduino" statt "den uC"; und wenn die
Arduino-Umgebung nicht einen ganz ungewöhnlichen Kunstgriff in der ISR
für OCIE2A verwendet, so läuft das Hauptprogramm sehr wohl weiter, aber
extrem langsam, immer nur ein einziger Befehl pro ISR-Aufruf.
Hi
>Schießt den uC tatsächlich völlig ab. Der ist nirgendwo mehr.
Dann macht entweder die Arduino-Software total Mist oder du hast einen
anderen Fehler.
Wenn ich die Initialisierung mit diese Werten in Assembler mache,
springt der Controller wie gewünscht in den TIMER2_COMPA-Interrupt und
gibt eine Frequenz von 250Hz aus.
MfG Spess
Arduino Fanboy D. schrieb:> Das Problem ist das Latch, in Verbindung mit dem Moduswechsel von PWM> auf Compare Match
Kannst du mal für mein Verständnis ein vollständiges Programm zeigen?
Denn in deinem Beispiel sehe ich gar kein PWM-Mode, da wird der Timer
von was auch immer auf CTC Mode (nur WGM21=1) eingestellt.
"Was auch immer" war bei meinem Test Normal-Mode nach Reset.
Oliver
S. Landolt schrieb:> Sagen wir lieber "den Arduino" statt "den uC"; und wenn die> Arduino-Umgebung nicht einen ganz ungewöhnlichen Kunstgriff in der ISR> für OCIE2A verwendet,
Ich habe da keine wiss. Untersuchung gemacht. Ein Dauer INT Feuer, weil
ein Bit nicht zurück gesetzt wurde legt auch jede CPU lahm, auch den
ARM. Und die Arduino IDE setzt hauptsächlich den Frame über den Code
namens setup und loop. Zudem wird Timer 0 für Millis gebrauchtr. Alles
was aber in den Routinen steht, da ist nur der GCC für zuständig. Ich
kenne auch den Startup Code nicht, geschweige denn weiss ich nicht, ob
da Default INT Handler installiert sind.
Möge sich damit jemand befassen, der Spass daran hat. zb mit AVR Studio
und einem echten Debugger am JTAG Port. Das habe ich alles nicht.
S. Landolt schrieb:> Aber Sie verstehen nun, weshalb ich vorsichtshalber das Nullsetzen von> TCCR2A und B voranstellte.
Nein. Nur wenn da Mechanismen am Werk sind, die irgendein Schaltwerk
bedienen. Register sind ja keine RAM Variablen, sondern Hardware Latches
mit Leitungen dran von und zu irgendwelchen Peripherien. Auch beim ARM
gibt es solche, die in einer bestimmten Reihenfolge gesetzt werden
müssen, obwohl dieses im ersten Moment unsinnig erscheint. Um das zu
ergründen müsste man den VHDL Code des AVR haben und den im Simulator
laufen lassen. Und ich nehme an, dass der nicht Open Source ist.
Errata steht nix drin:
https://www.kitronik.co.uk/pdf/46101_atmega328_summary.pdf
Hi
>Lassen Sie dies hier mal laufen, und anschließend das erste 'sts>TCCR2A,tmp0' auskommentieren.
Mit dem sts kommen ca. 165kHz und ohne ca. 16kHz heraus. Und weiter?
MfG Spess
Christian J. schrieb:> Errata steht nix drin:> https://www.kitronik.co.uk/pdf/46101_atmega328_summary.pdf
So isses. Da das Datenblatt zu dem Thema Reihenfolge auch nichts weiter
sagt, kann das höchstens eine Fehler im Prozessor sein, aber kein
genrelles Latch-Problem.
Und nochmals meine Frage: Woran hast du gesehehn, daß der Prozessor
"nirgends mehr" ist?
Oliver
Ok....
Ich glaube ich muss einen kleinen Rückzug machen!
Denn das Problem ist gerade auch bei mir nicht reproduzierbar.
Schade eigentlich, den original Testcode habe/finde ich nicht mehr.
Den mit der Totalblockade.
Hinter der Totalblockade muss ich jetzt also ein deutliches Fragezeichen
platzieren.
Was allerdings weiterhin gültig bleibt:
Der OCR2A Wert wird nicht übernommen.
Das gilt auf jeden Fall für den Timer2 vom ATMEga328P und ATMega2560
1
OCR2A=50;
2
TCCR2A=(1<<WGM21);
3
TCCR2B=(1<<CS22);
>> In der Reihenfolge steckt ein Problem und lauert nur darauf einen> Wahnsinnig zu machen.>> .... Folgende Situation:>> Der Timer befindet sich nach dem Reset in Mode0> Der Arduino Startup Code bereitet ihn für PWM vor.>> Im PWM Mode wird OCR2A gelatscht.> Im CTC Mode nicht.>> Du schreibst also 50 in das Latch.> Stellst dann den Mode um.> Folge: Der Latchinhalt landet nie im Register.
Oliver S. schrieb:> Kannst du mal für mein Verständnis ein vollständiges Programm zeigen?> Denn in deinem Beispiel sehe ich gar kein PWM-Mode, da wird der Timer> von was auch immer auf CTC Mode (nur WGM21=1) eingestellt.>> "Was auch immer" war bei meinem Test Normal-Mode nach Reset.
Den komplett blockierenden Code finde ich gerade nicht.
Ist allerdings auch ein Arduino Programm gewesen, weiß nicht ob dir das
dann helfen würde.
Der Arduino Startupcode erzeugt folgenden Timer2 Zustand:
1
// Arduino Startup Code Fragment
2
TCCR2A=1;
3
TCCR2B=4;
4
TCNT2=51;// ca. zaehlerstand zum Zeitpunkt des Eintritts in die Main loop
5
TIMSK2=0;
6
OCR2A=0;
Gilt für Mega2560 und 328P,
TCNT2 unterscheidet sich geringfügig
S. Landolt schrieb:>> TCCR2B = (1<<CS22);>> Was passiert, wenn statt des Vorteilers 64 (CS22) der Vorteiler 1 (CS20)> genommen wird?
Ja, so sieht es stehend aus
Die Serielle Ausgabe kann sich gerade noch eine 0 abquetschen, dann
nichts mehr.
Auch wieder Mega2560 und 328P identisches Verhalten.
Nachtrag
So wie ich es jetzt sehe:
Die Interrupt Priorität von Timer 2 ist höher als die die von Timer0
(delay,millis) und auch höher als die von der UART.
Also kommen beide nicht mehr dran.
So entsteht der Eindruck des völligen Stillstands.
Richtig so?
Arduino Fanboy D. schrieb:> Richtig so?
Das ist zwar richtig, aber wie Tim schon anmerkte, müsste der PB7
trotzdem togglen. Die ISR sollte ja aufgerufen werden.
Oliver
Oliver S. schrieb:> wie Tim schon anmerkte, müsste der PB7> trotzdem togglen. Die ISR sollte ja aufgerufen werden.
Ja, das ist auch so...
Welches bei 16MHz Takt zu einem ca. 250kHz Rechteck am Pin führt.
Der LA zeigt es.
Der LED_BULITIN (an PB7) sieht man es nicht an.
Schätze mal, dass der Operationsverstärker da nicht mit kommt.
Ja, der Arduino Mega und UNO hat einen Operationsverstärker zwischen
LED und Prozessor Pin, damit die LED das Signal nicht belastet, wenn der
Pin als Eingang genutzt werden soll.
Was den Eindruck des Stillstands verstärkt.
Oliver S. schrieb:> Passiert das auch mit Timer 3?
Bisher nicht getestet...
Timer0 bis Timer2 sind betroffen.
Also vermutlich auch Timer 3
Einfach ins Datenblatt schauen. Dürfte reichen.
Wenn OCRXY gelatched ist, wird es ihn auch betreffen.
Wenn es nur Timer 2 gewesen wäre, könnte das auch noch mit dessen
Asynchron-Funktionalität zusammenhängen. Aber wenn 0 und 1 auch
betroffen snd, dann wirds bei allen Timer so sein.
Ist aber m.E. immer noch ein Fehler, der in die Errata gehört, und kein
generelles Latch-Problem.
Oliver
Wie auch immer...
Meinen Dank an euch!
Vorher war mir klar:
Initialisierungsreihenfolge beachten, sonst evtl. derbe Probleme.
Jetzt habe ich ein deutlicheres Bild davon, was wirklich passiert.
Und warum es diese Probleme gibt.
Danke!
> Fehler, der in die Errata gehört
Was sollte Atmel/Microchip dort schreiben?
Für mich ist es ein typischer Programmierfehler, der nur deshalb leicht
tückisch ist, weil hier zwei "Programmierer" arbeiten, einmal die
Arduino-Umgebung und dann der eigentliche Programmierer.
Das ist kein Programmierfehler, und es hat nichts mit Arduino zu tun.
Das Datenblatt gibt keine Reihenfolge der Initialisierung vor. Natürlich
sollte beim Umschalten von einem gelatchten auf einen ungelachten Modus
das entsprechend Register aus dem Latch geupdated werden, wenn da ein
noch nicht geschriebener Wert drinsteht.
Das ist ein klarer Implementierungsfehler (wenn es denn ohne Reihenfolge
funktionieren sollte), oder ein Fehler im Datenblatt, wenn es eine
bestimmte Reihenfolge benötigt.
Oliver
> beim Umschalten von ... Modus ... geupdated
Zugegeben, das wäre eine Möglichkeit. Trotzdem bin ich der Meinung, dass
das etwas viel verlangt ist von der Hardware, nur wegen eines solchen
Sonderfalles. Und aus dem Datenblatt lässt es sich herauslesen, mit ein
wenig Mühe.
S. Landolt schrieb:> Und aus dem Datenblatt lässt es sich herauslesen, mit ein> wenig Mühe.
Na ja, man kann da alles mögliche hineininterpretieren. Da steht:
"The OCR2x Register access may seem complex, but this is not case. When
the double buffering is enabled, the
CPU has access to the OCR2x Buffer Register, and if double buffering is
disabled the CPU will access the OCR2x
directly."
Da steht natürlich nicht, daß bei einem Mode-Wechsel (der ein Normal-
und kein Sonderfall ist) Buffer und Register synchronisiert werden, es
steht aber auch nicht da, daß dies nicht geschieht. Das wäre aber
durchaus erwähnenswert.
Statt dessen stehen breit und ausführlich die eigentlich nicht
erwähnenswerten Fälle drin, daß ein Compare-Match bei einen Wert größer
TOP niemals triggert, oder daß ein ein neuer Top-Wert kleiner als der
aktuelle Zählerstand erst im nächsten Timerzyklus triggert.
Oliver
S. Landolt schrieb:> Und aus dem Datenblatt lässt es sich herauslesen, mit ein> wenig Mühe.
Mit am erstaunlichsten finde ich daran, dass der OCR2A Wert (falsch?)
auslesbar ist!
OCR2A = 0;
PWM mode aktivieren
OCR2A = 200;
Compare Match aktivieren
Danach:
Beim OCR2A auslesen bekommt man die 200 gereicht.
Obwohl der Timer mit einem OCR2A == 0 arbeitet.
Das scheint mir dann doch schon sehr gemein zu sein.
Und hätte ein Sprüchlein im Datenblatt verdient.
> hätte ein Sprüchlein im Datenblatt verdient
Vielleicht dieses hier?
"When the double buffering is enabled, the CPU has access to the OCR2x
Buffer Register ..."
Betonung auf 'Buffer-'.
"Gemein" oder nicht, ich kann nichts dafür und kann's auch nicht ändern.
Arduino Fanboy D. schrieb:> Compare Match aktivieren
Offiziell heisst der CTC.
S. Landolt schrieb:> "Gemein" oder nicht, ich kann nichts dafür und kann's auch nicht ändern.
Sacht ja keiner. Aber im CTC-Modus hat die CPU direkten Zugriff aufs
Register, liest da 200, der Timer arbeitet aber mit 0. Das ist nicht
einfach nur im Datenblatt ungünstig beschrieben oder gemein, daß ist ein
Fehler.
Oliver
Okay, eben ausprobiert, und - Arduino Fanboy & Oliver S., ich sei,
gewährt mir die Bitte ...: Dass im CTC-Modus, also einem ungepufferten,
beim Auslesen nicht der aktuelle Stand von OCR2A zurückgegeben wird,
betrachte auch ich als (gemeinen) Fehler.
Weiss von euch Arduino Experten jemand wie man den Serial.print auf eine
andere Funktion umleitet? Der geht ja auf die Hardware Uart. Oder eine
vergleichbare Funktion aufsetzt? Ich verwende nur 2 Möglichkeiten
serial.print("Text...");
und
serial.print(buffer);
Ich habe aber eine IR Diode. Und das F Makro funktioniert nicht, wenn
man zb nimmt
SendIRString(char* text)
Gibt es da einen Trick?
Bisher sieht es so aus
/* Sende einen 0 terminierten String per IR */
void SendIRString(char* text)
{
while (*text)
SendIRByte(*text++);
SendIRByte(0);
}
IRLED ist mit einer Handykamera so eben zu sehen, die dimmt auch munter
drauf los.
ich könnte alles auf sprintf_P umschreiben aber das wäre eine irre
Arbeit. Mache ich nur bei komplexen Ausgaben.
Arduino Fanboy D. schrieb:> #include <Streaming.h> // findest du schon... ;-)> // ist nicht unbedingt nötig, erlaubt allerdings das Streaming
Funzt :-)
Nur ein Prototypen Problem. Arduino braucht ja keine und mich ärgert das
etwas dass das System .h und .c da nicht so läuft. Ins .h kommt das
Interface rein, ins .c der private Code.
Christian J. schrieb:> Nur ein Prototypen Problem. Arduino braucht ja keine und mich ärgert das> etwas dass das System .h und .c da nicht so läuft. Ins .h kommt das> Interface rein, ins .c der private Code.> Arduino braucht ja keine
Das stimmt so nicht wirklich!
Es macht sich selber welche, wenn du keine baust.
Das betrifft aber nur *.ino Dateien.
Keine *.c, *.cpp und *.h Dateien, die stehen in deiner Verantwortung.
Wieso überhaupt *.c?
Nimm *.cpp, dann musst du nicht die Extrawürste backen um mit dem C++
Rest klar zu kommen.
C++.... ne, alter Hase bleibt bei C.
struct IrZeugs: Print
{
virtual size_t write(uint8_t value)
{
SendIRByte(value);
return 1;
}
};
Aber dieses zweifach verschachtelte Konstrukt hier .... für mich nicht
so ganz verstehbar. Funktioniert aber. irgendwie verwurstelt das
Zeichenweise den Stream. Eine Funktion ist einem Struct, öfter mal was
Neues.
Wie würde das aussehen, wenn in einem Rutsch die IR Ausgabe erfolgen
soll und die normale Print Ausgabe dahinter? Ich baue mir einige
komplexe Ausgaben mit sprintf_P zusammen und schiebe die nach buf rein.
Wäre gut, wenn die Ausgabe meiner Bastelei auf Seriell und IR kommen
würde. Einen Nachteil sehe ich nur darin, dass serial.print die Ausgabe
per INT erledigt und dadurch IR beeinflusst würde, weil ich da zwingend
die INT abschalten muss, damit die Zeiten stimmen. Aber man kann ja auch
serial.flush() vorher aufrufen oder die IR Ausgabe vorziehen.
Die EEPROM Ausgabe liesse sich sicher auch verstreamen, nur müsste da
dann ein zeiger mitlaufen aus das aktuelle Element.
Wäre schwer?
Christian J. schrieb:> C++.... ne, alter Hase bleibt bei C.
Dann musst du wohl von Arduino weg, oder deine Einstellung ändern.
Denn:
> Aber dieses zweifach verschachtelte Konstrukt hier .... für mich nicht> so ganz verstehbar. Funktioniert aber.
Das ist naives, aber dennoch lupenreines C++.
Siehe: https://playground.arduino.cc/Code/Printclass/
So wie vieles, sehr vieles, SEHR *SEHR* vieles in der Arduino Welt.
Alles? Nee, aber sehr vieles!
Aber wenn du willst, dann mache dir deine Problem!
Soviele du möchtest.
Christian J. schrieb:> Wäre schwer?
Nein, quasi nur ein Fingerschnippen...
;-) aber nicht für C++ Verweigerer ;-)
Tipp:
Von der EEPROM Klasse erben und das Print Interface implementieren.
Und ja, einen Index wird man mitführen müssen, und auch ein bisschen um
die Grenzen kümmern, damit da keine ganz gruseligen Dinge passieren.
Oder besser sofort Stream implementieren... dann klappts auch mit dem
Lesen.
Arduino Fanboy D. schrieb:> Auch wieder Mega2560 und 328P identisches Verhalten.
Hm....
Ich habe jetzt dann doch mal meinen Arduino Mega und den Logikanalysator
aus dem Keller gekramt, um das mal nachzuvollziehen.
Alledings ohne Arduino-Framework, und ohne serielle Ausgabe.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
voidsetTimer2()// CTC, Mode 2
5
{
6
cli();
7
// Interrupts ausschalten
8
TCNT2=0;// Reset Register
9
OCR2A=249;// Compare
10
11
TIMSK2=(1<<OCIE2A);// Compare Match A
12
TCCR2A=(1<<WGM21);// set Mode
13
TCCR2B=(1<<CS20);// Prescaler 1
14
//TCCR2B = (1<<CS22); // Prescaler 64
15
sei();
16
// Interrupts einschalten
17
}
18
19
ISR(TIMER2_COMPA_vect)// Timer 2 Interrupt
20
{
21
PINB=(1<<PB7);// toggle
22
}
23
24
intmain(void)
25
{
26
DDRB=1<<PB7;
27
setTimer2();
28
while(1)
29
{}
30
}
Ergebis: PB7 toggelt nicht mit 250kHz, sondern brav mit 32khz, so wie es
auch sein sollte.
Oliver
Oliver S. schrieb:> sondern brav mit 32khz, so wie es> auch sein sollte.
Deinen Code habe ich jetzt nicht überprüft, kann ich mir aber lebhaft
vorstellen.
Denn der Timer kommt im Mode 0 aus dem Reset.
Dann klappt das auch alles.
Lass den Timer mal kurze Zeit in einem PWM Mode laufen...
Und dann schalte um.
Du wirst sehen.....
> Alledings ohne Arduino-Framework
Aber genau das war doch der springende Punkt! Dass nämlich der Timer ein
'Vorleben' hatte, von dem man erstmal nichts weiß.
Das trifft es nicht ganz - der Trick ist, OCRA2 beim vorlaufenden PWM-
größer zu machen als im späteren CTC-Modus, dann bleibt der zweite Wert
im Pufferregister stecken.
S. Landolt schrieb:> Das trifft es nicht ganz - der Trick ist, OCRA2 beim vorlaufenden> PWM-> größer zu machen als im späteren CTC-Modus, dann bleibt der zweite Wert> im Pufferregister stecken.
Scheint auch nicht ganz zuzutreffen, in meinem Beispiel oben ist er ja
im PWM-Modus kleiner als im CTC-Modus. Mit viel kleineren Werten, nicht
nur bei 0, wird er nicht übernommen. Vermutlich, wenn der Wert kleiner
als der aktuelle Zählerstand ist.
Der Arduino-Code initialisiert den Timer 2 auf PWM 8 Bit mit OCRA=0.
Warum die überhaupt da dran rumfummeln, keine Ahnung.
Ich muß mir das die Tage nochmals genauer anschauen. Dafür war mir der
Sonntag Nachmittag dann doch zu schade.
Oliver
Oliver S. schrieb:> Der Arduino-Code initialisiert den Timer 2 auf PWM 8 Bit mit OCRA=0.> Warum die überhaupt da dran rumfummeln, keine Ahnung.
Im Startcode vorbereiten für PWM, damit das nicht in analogWrite()
gemacht werden muss.
So wie auch andere Vorbereitungen für andere Arduino Features, wie
millis(), delay() usw durchgeführt werden.
Das muss man hinnehmen, wenn man in der Welt unterwegs ist.