Hallo liebe Community Ich stehe vor folgendem problem: Ich muss in meiner Anwendung einen Rechteck Takt erzeugen. DutyCycle vorzugsweise 1/1 Die Geschwindigkeit sollte 500kHz + sein... (Je mehr desto besser) Ich habe mir dazu mal folgenden Chip genauer angeschaut: DS1085 http://www.maxim-ic.com/datasheet/index.mvp/id/3491 Dieser erzeugt selbstständig Signale im bereich von 8.1kHz - 133MHz bei einer genauigkeit von 0.75% Soweit so gut.... Das problem ist, ich sollte den Takt in meinem uC programm definiert Starten können. Also genau wissen das der Takt jetzt mit der Steigenden Flanke beginnt etc. deshalb dachte ich daran, Das Taktsignal mit dem AVR zu erzeugen. Dieser muss während der Signal Erzeugung nichts weiteres tun ausser die erzeugung und nach einer definierten zeit (zähler stand) wieder stoppen. Ist es sinnvoll solch ein Signal mit dem AVR mit ein bisschen Assembler zu erzeugen? Mit welchen Maximalen Taktraten kann ich in etwa rechnen bei einem 12Mhz bzw. einem 20MHz AVR Takt? Danke schonmal
Claudio Hediger schrieb: > Ist es sinnvoll solch ein Signal mit dem AVR mit ein bisschen Assembler > zu erzeugen? Und was erhoffst du dir dabei von Assembler? Deinen Takt kann der Timer des AVR ganz alleine erzeugen. Ein paar Konfigurationsbits richtig setzen und du hast deinen Takt an einem Pin. (Das ist eine PWM mit einstellbarem TOP Wert und einem Comparewert genau in der Mitte). > Mit welchen Maximalen Taktraten kann ich in etwa rechnen bei einem 12Mhz > bzw. einem 20MHz AVR Takt? theoretisch müsste man auf die Halfte der Taktfrequenz kommen. Die eigentliche Frage ist aber eine andere: Wie genau kannst du von der Maximalfrequnz ausgehend abstufen und ist es erlaubt bei hohen Frequenzen von 1:1 abzuweichen.
Karl heinz Buchegger schrieb: > theoretisch müsste man auf die Halfte der Taktfrequenz kommen. > Die eigentliche Frage ist aber eine andere: Wie genau kannst du von der > Maximalfrequnz ausgehend abstufen und ist es erlaubt bei hohen > Frequenzen von 1:1 abzuweichen. Die Maximalfrequenz ist eigentlich irrelevant. Es spielt also keine rolle ob es 1MHz 2 oder 5MHz sind. Wobei 5MHz ein idealer Wert sein dürfte. Ich nehme an, das ich durch Setzen eines Flags den Timer direkt Starten kann oder?
Karl heinz Buchegger schrieb: > und ist es erlaubt bei hohen > Frequenzen von 1:1 abzuweichen. Ja es ist minim erlaubt
Claudio Hediger schrieb: > Ich nehme an, das ich durch Setzen eines Flags den Timer direkt Starten > kann oder? So ist es. Vorteiler setzen -> der Timer läuft Vorteiler wegnehmen -> der Timer steht
Karl heinz Buchegger schrieb: > So ist es. > Vorteiler setzen -> der Timer läuft > Vorteiler wegnehmen -> der Timer steht Ok sehr schön :) Und damit ich weiss wie viele Takte bereits ausgegeben wurden, wäre es meiner meinung nach die beste lösung eine Variable in der Interrupt Funktion des Timers zu erhöhen. Was meinst du?
Claudio Hediger schrieb: > Karl heinz Buchegger schrieb: >> So ist es. >> Vorteiler setzen -> der Timer läuft >> Vorteiler wegnehmen -> der Timer steht > > Ok sehr schön :) > > Und damit ich weiss wie viele Takte bereits ausgegeben wurden, wäre es > meiner meinung nach die beste lösung eine Variable in der Interrupt > Funktion des Timers zu erhöhen. Was meinst du? Dass du dann bei hohen Taktfrequenzen Schwierigkeiten kriegen wirst, weil auch der ISR Aufruf und dessen Abarbeitung Zeit braucht.
Gast
#1894748
Karl heinz Buchegger schrieb: > Dass du dann bei hohen Taktfrequenzen Schwierigkeiten kriegen wirst, > weil auch der ISR Aufruf und dessen Abarbeitung Zeit braucht. Ja, doch anderst ist es ja kaum zu lösen oder?
Gast
#1894871
Karl heinz Buchegger schrieb: > Dass du dann bei hohen Taktfrequenzen Schwierigkeiten kriegen wirst, > weil auch der ISR Aufruf und dessen Abarbeitung Zeit braucht. Wäre es denn im ISR Aufruf sinnvoll direkt mit Assembler befehlen den eigenen Zähler zu erhöhen und zu prüfen, ob der gewünschte wert bereits erreicht ist?
Claudio Hediger schrieb: > Wäre es denn im ISR Aufruf sinnvoll direkt mit Assembler befehlen den > eigenen Zähler zu erhöhen und zu prüfen, ob der gewünschte wert bereits > erreicht ist? In dem Fall bin ich tatsächlich geneigt 'ja' zu sagen. Nicht weil der Compiler erhöhen und Abfrage nicht genausogut hinkriegst wie du selber. Sondern, weil du höchst wahrscheinlich einen besseren Funktion Prolog/Epilog hinkriegst als der Compiler.
Gast
#1894894
Karl heinz Buchegger schrieb: > In dem Fall bin ich tatsächlich geneigt 'ja' zu sagen. > Nicht weil der Compiler erhöhen und Abfrage nicht genausogut hinkriegst > wie du selber. > Sondern, weil du höchst wahrscheinlich einen besseren Funktion > Prolog/Epilog hinkriegst als der Compiler. Ok sehr schön.... Vielen Dank für deine Hilfe... Ich werde es mal versuchen :) nur noch eine kleine frage, was ist mit prolog und epilog genau gemeint?
Claudio Hediger schrieb: > Karl heinz Buchegger schrieb: >> Dass du dann bei hohen Taktfrequenzen Schwierigkeiten kriegen wirst, >> weil auch der ISR Aufruf und dessen Abarbeitung Zeit braucht. > > Wäre es denn im ISR Aufruf sinnvoll direkt mit Assembler befehlen den > eigenen Zähler zu erhöhen und zu prüfen, ob der gewünschte wert bereits > erreicht ist? Das kann ebenfalls die Harware erledigen. Einfach das Signal extern auf einen Eingang zurückgeben und einen zweiten Timer damit hochzählen lassen.
Claudio Hediger schrieb: > nur noch eine kleine frage, was ist mit prolog und epilog genau gemeint? http://en.wikipedia.org/wiki/Function_prologue
Gast
#1894933
Johann L. schrieb: > Das kann ebenfalls die Harware erledigen. Einfach das Signal extern auf > einen Eingang zurückgeben und einen zweiten Timer damit hochzählen > lassen. Ahh das ist ja perfekt :) Vielen Dank... Ich verwende einen Atmega8 soweit ich weiss hat dieser einen 16bit counter.. Ich muss nämlich auf 32768 Zählen... somit sollte das ja bei diesem Controller kein problem sein oder?
Claudio Hediger schrieb: > nur noch eine kleine frage, was ist mit prolog und epilog genau gemeint? Solange du das fragen musst .... lass Assembler Assembler sein und programmiere alles in C.
Gast
#1895000
Karl heinz Buchegger schrieb: > Solange du das fragen musst .... lass Assembler Assembler sein und > programmiere alles in C. Das hatte ich nach dem tipp, die hardware zählen zu lassen auch vor :) Trozdem Danke
Gast
#1895420
Andere unkomplizierte Möglichkeit: Den Burst einfach durch Pintoggeln in einer Schleife generieren.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
Vor dem Aufruf muss das Z-Registerpaar auf die gewünschte Anzahl der Pulse gesetzt werden, z. B. erzeugt...
1 | |
2 | |
3 | |
...einen genau 32768 Pulse langen Burst mit der Taktfrequenz FOSC/4 auf Pin 0 von Port B.
Gast
#1895442
Hi >Den Burst einfach durch Pintoggeln in einer Schleife generieren. Pintoggeln geht bei neueren AVRs durch das Schreiben einer 1 in das entsprechende Bit des PIN-Registers. 'Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.' MfG Spess
Gast
#1895454
Vuvuzelatus schrieb: > Andere unkomplizierte Möglichkeit: Den Burst einfach durch Pintoggeln in > einer Schleife generieren. > GenerateBurst: > ldi r16, 0 > ldi r17, 1 > out DDRB, r17 > > rjmp LoopH > > LoopL: > out PORTB, r16 > > subi ZL, 1 > sbci ZH, 0 > breq Fertig > > LoopH: > out PORTB, r17 > > nop > rjmp LoopL > > Fertig: > ret > > Vor dem Aufruf muss das Z-Registerpaar auf die gewünschte Anzahl der > Pulse gesetzt werden, z. B. erzeugt... > ldi ZL, Low (32768) > ldi ZH, High(32768) > rcall GenerateBurst > > ...einen genau 32768 Pulse langen Burst mit der Taktfrequenz FOSC/4 auf > Pin 0 von Port B. Wow vielen Dank! Das ist ja fantastisch :) Ich nehme an, das ich bevor ich diesen Code ausführe, die register auf dem Stack sichern mus mittels push oder? Ich weiss ja nicht wo der Compiler welches register verwendet Zum ende muss ich sie wieder mit pop herstellen oder? Besten Dank
Gast
#1895642
Ich pushe mal kurz :)
Das kriegt dir der C-Compiler genauso hin. Aber ganz so einfach ist es dann auch wieder nicht. Du willst ja die Frequenz auch einstellen können.
Gast
#1895715
Karl heinz Buchegger schrieb: > Das kriegt dir der C-Compiler genauso hin. > Aber ganz so einfach ist es dann auch wieder nicht. > Du willst ja die Frequenz auch einstellen können. Oh das tut mir leid... anscheinend habe ich da was falsches geschrieben... Die frequenz muss nicht unbedingt einstellbar sein. Trozdem Danke für den Hinweis :)
Gast
#1895718
Sorry für doppelpost ich kann eben nicht editieren war nicht angemeldet... Ich hab den Assembeler code um folgendes erweitert
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
Mein jetziger Code
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
Wie könnte ich die anzahl takte mittels Parameter in der Funktion übergeben? Danke :)
Claudio Hediger schrieb: > Oh das tut mir leid... anscheinend habe ich da was falsches > geschrieben... > Die frequenz muss nicht unbedingt einstellbar sein. Okay. Kann auch sein, dass ich im Eröffnungsposting etwas rausgelesen habe, was nicht dort steht. Das ändert die Situation allerdings. D.h. du willst nur eine bestimmte Anzahl an Pulsen möglichst schnell rausblasen.
Claudio Hediger schrieb: > Wie könnte ich die anzahl takte mittels Parameter in der Funktion > übergeben? Indem du den Compiler arbeiten lässt :-)
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
wird übersetzt zu (wenn man den Compiler am inlining hindert)
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
und das ist doch nicht schlecht. Den 2ten sbiw könnte man noch einsparen. Aber sonst sehe ich nicht mehr viel Potential.
Gast
#1895769
Karl heinz Buchegger schrieb: > wird übersetzt zu (wenn man den Compiler am inlining hindert) Was genau meinst du mit ihn am inlining hindern? Karl heinz Buchegger schrieb: > D.h. du willst nur eine bestimmte Anzahl an Pulsen möglichst schnell > rausblasen. Ja und ich muss genau wissen wie lange das die clocks sind also welche Taktrate sie haben. Karl heinz Buchegger schrieb: > und das ist doch nicht schlecht. Den 2ten sbiw könnte man noch > einsparen. Aber sonst sehe ich nicht mehr viel Potential. Wie lange dauert denn in diesem fall der assembler code? und ist es ein duty cycle cvon 1/1?
Claudio Hediger schrieb: > Was genau meinst du mit ihn am inlining hindern? Bei dir passt irgendwie gar nichts zusammen. Auf der einen Seite willst du alles unbedingt in Assembler machen, auf der anderen Seite schimmert immer wieder durch, dass du davon (sagen wirs mal freundlich) keine Ahnung hast. Die Frage gehört auch dazu > Wie lange dauert denn in diesem fall der assembler code? genauso wie die hier > und ist es ein duty cycle cvon 1/1? die letzte lässt sogar darauf schliessen, dass du von Programmieren nicht allzuviel Ahnung hast. Natürlich ist der Duty Cycle 1:1. In jedem Durchlauf wird der Pin getoggelt (in den anderen Zustand gebracht). 1 Durchlauf dauert immer gleich lang (bis auf ev. den ersten bzw. den letzten), daher kann der Duty Cycle nur 1:1 sein.
Gast
#1895812
Karl heinz Buchegger schrieb: > Bei dir passt irgendwie gar nichts zusammen. > Auf der einen Seite willst du alles unbedingt in Assembler machen, auf > der anderen Seite schimmert immer wieder durch, dass du davon (sagen > wirs mal freundlich) keine Ahnung hast. Hmmm also Ich habe früher mal mit Assembler die AVRs programmiert... das ist jedoch schon ein weillchen her. Alles möchte ich bestimmt nicht in assembler machen. Mir geht es hier wirklich nur um diese kleine zeitkritische stelle. Zudem ist es meiner meinung nach nicht schlimm etwas nicht zu wissen. Wenn ich ja der Profi in assembler wäre, würde ich ja wohl kaum ein Topic in diesem Forum verfassen, oder etwa nicht? Leider weiss ich immer noch nicht was du damit gemeint hast :) Karl heinz Buchegger schrieb: >> und ist es ein duty cycle cvon 1/1? > > die letzte lässt sogar darauf schliessen, dass du von Programmieren > nicht allzuviel Ahnung hast. > > Natürlich ist der Duty Cycle 1:1. In jedem Durchlauf wird der Pin > getoggelt (in den anderen Zustand gebracht). 1 Durchlauf dauert immer > gleich lang (bis auf ev. den ersten bzw. den letzten), daher kann der > Duty Cycle nur 1:1 sein. Ich weiss das beim Pin Toggeling ein Tastverhältnis von 1:1 entsteht, jedoch war ich irritiert, da beim ASM Code lediglich eine 0 mit sbi geschrieben wird
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
Falls sbi 0x16, 0 den Pin automatisch bei jedem durchgang toggelt, ist es für mich auch absolut verständlich das es ein Duty Cycle von 1:1 ergibt
Claudio Hediger schrieb: > Hmmm also Ich habe früher mal mit Assembler die AVRs programmiert... > das ist jedoch schon ein weillchen her. Das muss schon sehr lange her sein. Du scheinst so gut wie alles vergessen zu haben. Daher wäre es besser, wenn du von der Prämisse ausgehst: Ich steig wieder bei 0 ein. > jedoch war ich irritiert, da beim ASM Code lediglich eine 0 mit sbi > geschrieben wird Schau dir bitte im Instruction Set an, was der Befehl sbi wirklich macht! Und was bei neueren AVR ein Bitsetzen am PIN Register bewirkt.
Claudio Hediger schrieb: > Zudem ist es meiner meinung nach nicht schlimm etwas nicht zu wissen. Da hast du recht. Das ist nicht schlimm. Warum es geht: Wenn du in C schreibst, dann schreib auch in C Die meisten, die das das erste mal versuchen, wissen gar nicht worauf sie sich einlassen, wenn sie Assembler mit C mischen wollen. Die meisten denken auch, dass sie den Compiler ja leicht übertrumpfen. So nach dem Motto: Ich krieg gerade mal eine for-Schleife im 3ten Anlauf fehlerfrei hin, aber hey: so schwer kann das doch nicht sein, den Compiler auszustechen. Wenn du Laufzeit Probleme hast, dann sieh erst mal zu, dass du sie mit dem Compiler lösen kannst. Viele Codestellen, die als ineffizienter Assemblercode vom Compiler erzeugt werden, haben ihre Ursache darin, dass der Programmierer C nicht beherrscht und daher dem Compiler entweder zuviele Freiheitsgrade lässt oder dem Compiler Nebenbedingungen aufs Auge drückt die ihn am Optimieren hindern. Auf Assembler weicht man als C-Programmierer nur dann aus, wenn man tatsächlich über jeden Takt die Kontrolle braucht und das auch nur dann, wenn man sich angesehen hat, was der Compiler erzeugt und man einen Weg hat, wie man das besser machen kann. Gut: Dein Problem ist von der Sorte - jeder Taktzyklus zählt. Aber auch dann, schreibt man sich immer erst eine entsprechende C-Routine, sieht sich an, wie der Compiler das umsetzt und tauscht dann Funtkionsinhalte durch Assembler Code aus. Und dann stellt sich die Frage nach: Wie kriege ich da Argumente rein, wie mache ich Dinge variabel so gar nicht mehr. Der Compiler hat das Framework erzeugt und nur noch die innersten Konstrukte tausch ich aus. Als C-Programmiere fängt man so gut wie nie damit an, gleich erstmal einen Assemblerteil zu postulieren nur weil man das Gefühl hat, das man den brauchen wird. Wenn dein Auto (deiner Meinung nach) zuviel Sprit braucht, dann kann dein erster Gedanke nicht sein, wie du die Verbrennung in den Brennkammern optimieren kannst. Sondern du schaust dir zb erst einmal den Reifendruck an, nimmst die Dachträger vom Dach etc.
Gast
#1895867
Vielen Dank für dein langes Posting :) Ich stimme dem in allen punkten zu.... Ich werde mich nun also mal an die sache ranmachen und erstmal mit C weiterfahren.... Danke nochmals :)
Gast
#1896305
Karl heinz Buchegger schrieb: > #include <avr/io.h> > > void Burst( uint16_t Count ) > { > while( Count-- ) > PINB |= ( 1 << PB0 ); > } > > int main() > { > Burst( 32 ); > } Ich hab nun den Code getestet.... Leider kommt damit kein Clock raus :(
Claudio hediger schrieb: > Leider kommt damit kein Clock raus :( Das war auch kein komplettes vollständiges Beispiel, sondern es ging nur um die Fragestellung: Was macht der Compiler aus der Schleife in der Funktion Burst. Um das im Assembler Listing zu sehen, muss ich zb keinen Port auf Ausgang schalten. Ich kann auch davon ausgehen, dass der µC tatsächlich einer von der Sorte ist, der mittels Bitsetzen im Pin Register den Ausgabeport toggelt (das hängt aber vom tatsächlichen Typ des AVR-µC ab. Ältere können das nicht)
Gast
#1896333
Die älteren Atmel beherrschen das Toggeln bei Schreiben auf den Eingangspin nicht, der ATM8 könnte dazugehören. Außerdem muss das DDRx Register auf Ausgang gesetzt werden, sonst geht auch nix.
Gast
#1896337
Karl heinz Buchegger schrieb: > (das hängt aber vom tatsächlichen Typ des AVR-µC ab. > Ältere können das nicht) Ich verwende einen Atmega8 wie bereits weit(er) oben geschrieben. Diese kann es leider nicht :( Somit würde mir nur noch die Assembler variante bleibe oder sehe ich da was nicht?
Claudio hediger schrieb: > Somit würde mir nur noch die Assembler variante bleibe oder sehe ich da > was nicht? Und wie würdest du das dann in Assembler schreiben? (Die C Variante sieht genau gleich aus wie die Assembler Variante. Wenn du es in C nicht kannst, kriegst du es auch in Assembler nicht hin. Ich kann ehrlich dieses ewige sofortige 'dann muss ichs in Assembler machen' schon nicht mehr hören. Für dich scheint Assembler die Lösung aller Probleme zu bedeuten) Schreibs komplett in Assembler, dann stellt sich die Frage schon nicht mehr.
Gast
#1896369
Karl heinz Buchegger schrieb: > Die C Variante sieht genau gleich aus wie die Assembler Variante Ok jetzt hab ichs endlich kapiert :P sorry für die soooo lange leitung ich habs nun also so programmiert:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Einfach mal als kleiner test Ich komme jedoch auf 1Mhz getaktet ist der AVR mit 12Mhz Müsste das nicht flotter sein?
Claudio hediger schrieb: > ich habs nun also so programmiert: >
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
> > Einfach mal als kleiner test > Ich komme jedoch auf 1Mhz getaktet ist der AVR mit 12Mhz > Müsste das nicht flotter sein? Du möchtest hier keine Variablen benutzen. Denn dann bleibt dem Compiler nichts anderes übrig, als tatsächlich die Operationen so auszuführen, wie du sie hingeschrieben hast Wert vom Port holen Variablenwert holen miteinander verunden Wert an den Port schreiben
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
1 << CLOCK_PIN ist eine Konstante (0x02). Und erst jetzt ermöglichst du dem Compiler zu optimieren was nur geht (sofern der Optimizer eingeschaltet ist). Der Umweg über die #define hat nur den Zweck, die komplette Hardwarekonfiguration an einer Stelle beisammen zu haben. Ändert sich der Pin, brauchst du das nur beim CLOCK_PIN an einer Stelle ändern und neu kompilieren.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
würde genau dasselbe machen, aber die Hardwareinfo ist über mehrere Stellen verstreut. AVR-GCC-Tutorial
Gast
#1896386
Karl heinz Buchegger schrieb: > void fast_clock(void) > { > while(1) > { > PORTC &= ~( 1 << PC1 ); > PORTC |= ( 1 << PC1 ); > } > } Ok vielen dank... Also ich hab das mal soweit getestet.... Ich komme damit auf etwa 1.2Mhz Merkwürdigerweise ist das signal alles andere als stabil! Es schwankt zwischen 1Mhz und 1.5Mhz hin und her!
Claudio hediger schrieb: > Karl heinz Buchegger schrieb: >> void fast_clock(void) >> { >> while(1) >> { >> PORTC &= ~( 1 << PC1 ); >> PORTC |= ( 1 << PC1 ); >> } >> } > > Ok vielen dank... > > Also ich hab das mal soweit getestet.... > Ich komme damit auf etwa 1.2Mhz Assembler Code ansehen. Das müsste in eine Schleife cbi ... sbi ... rjmp ... übersetzt werden. Das sind in Summe 6 Takte, d.h du bist bei 12/6 = 2Mhz Durch Loop Unrolling ginge da noch was, aber wesentlich schneller wirds nicht mehr. Und du willst ja auch noch Pulse zählen.
Gast
#1896397
fast clock section in assembler
1 | |
2 | |
3 | |
4 | |
Gast
#1896401
so siehts aus wenn ich count runterzähle
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Claudio hediger schrieb: > Merkwürdigerweise ist das signal alles andere als stabil! > Es schwankt zwischen 1Mhz und 1.5Mhz hin und her! Da zweifle ich mal die Verwendung des 12Mhz Quarzes an. Interne 8Mhz würden bedeuten: 8 / 6 = 1.33Mhz und das passt ziemlich gut zu deinen 1.2Mhz. Und auch die Schwankungen würden sich dadurch erklären. -> Fuse-Bits ansehen, ob der Mega tatsächlich auf Quarz gefused ist.
Gast
#1896412
Hmmm also wenn ich den Quarz entferne läuft nix mehr und die Fuses sind meiner Meinung nach auch korrekt... Siehe angehängtes bild
Claudio hediger schrieb: > Hmmm also wenn ich den Quarz entferne läuft nix mehr OK. Das genügt mir um den Quarz zu akzeptieren. Das ist ein deutliches Indiz. Aber ein Quarz schwingt nicht so unregelmässig (ausser er ist defekt) Irgendwelche Interrups aktiv?
Gast
#1896415
Was soll denn eigentlich das hier sein ?
1 | |
Völlig unsinnige Anweisung. Kostet 2 Zyklen.
Gast
#1896419
Karl heinz Buchegger schrieb: > Claudio hediger schrieb: >> Hmmm also wenn ich den Quarz entferne läuft nix mehr > > OK. Das genügt mir um den Quarz zu akzeptieren. Das ist ein deutliches > Indiz. > Aber ein Quarz schwingt nicht so unregelmässig (ausser er ist defekt) > > Irgendwelche Interrups aktiv? Es sind keine Interrupts aktiv nach dem main geht direkt in die Endlosschleofe mit der Takterzeugung. Ich habe den quarz kurzerhand ausgetauscht... Leider das selbe ergebnis
Claudio hediger schrieb: > Ich habe den quarz kurzerhand ausgetauscht... Leider das selbe ergebnis Hmm. Gibts doch gar nicht. Das Messverfahren ist über jeden Zweifel erhaben?
Gast
#1896443
Karl heinz Buchegger schrieb: > Hmm. > Gibts doch gar nicht. > > Das Messverfahren ist über jeden Zweifel erhaben? hmmm merkwürdig es geht nun plötzlich :S nun ja... vielleicht hab ich es nicht richtig kompiliert das duty cycle ist 8:2 (2 ist low) Kann man das noch etwas optimieren?
Claudio hediger schrieb: > das duty cycle ist 8:2 (2 ist low) > > Kann man das noch etwas optimieren? Jetzt ist der Zeitpunk, an dem man auf Assembler muss Aus
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
muss
1 | |
2 | |
3 | |
4 | |
5 | |
werden. Dann sollte sich ein 1:1 Verhältnis einstellen. Das kriegen wir nicht mehr in C gebacken, weil wir ihm nicht vorschreiben können, dass er Teile des Schleifenkonstrukts mitten zwischen die Setz und Lösch Anweisungen reinziehen soll. Ich bin in inline_Assembler aber zu schwach. Mit diesen Clobber Listen hab ich so meine liebe Mühe :-) Aber ich probiers mal, wenn ich zu Hause bin.
Gast
#1896475
Karl heinz Buchegger schrieb: > Aber ich probiers mal, wenn ich zu Hause bin. Vielen Dank :) Ich bin sehr froh um deine Hilfe!
Gast
#1896547
Karl Heinz, will Dir jetzt den Spaß nicht verderben ;-)
> Jetzt ist der Zeitpunk, an dem man auf Assembler muss
Nein, muss man nicht.
Man muss nur geschickt umstellen.
Das hier braucht 8 Zyklen, entsprechend 1,5MHz bei genau 1:1
Tastverhältnis:1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Und der Compiler baut auch den Murks nicht rein, daß er ein SBIW 0 verwendet, zumindest hier bei mir nicht. :-)
MWS schrieb: > Karl Heinz, will Dir jetzt den Spaß nicht verderben ;-) Ganz im Gegenteil. Wenn Assembler vermeidbar ist, dann umso besser >
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Kopfklatsch. Manchmal ist alles so naheliegend und man siehts trotzdem nicht. Ich war so sehr auf while( Ctr-- ) fixiert, dass ich in die Richtung gar nicht nachgedacht habe. Danke.
Gast
#1897503
Man kann sogar einfach meine Assemblerroutine von oben so in C abbilden, dass der Compiler wieder den gleichen Maschinencode daraus macht. Der "Trick": Man lässt das 'breq' und das 'rjmp' zu 'goto's werden - der Compiler übersetzt sie dann brav wieder in 'breq' und 'rjmp' zurück. Im Ergebnis bekommt man damit wieder die mit dieser Methode maximal erreichbare Pulsfrequenz FOSC/4.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
Gast
#1897510
Vuvuzelatus schrieb: > Im > Ergebnis bekommt man damit wieder die mit dieser Methode maximal > erreichbare Pulsfrequenz FOSC/4. Fantastisch :) Vielen Dank! Aber klappt das auch wenn man nur einen Pin ändern möchte und nicht den gesamten Port? also mit
1 | |
Gast
#1897526
Hi >Im Ergebnis bekommt man damit wieder die mit dieser Methode maximal >erreichbare Pulsfrequenz FOSC/4. Eher FOSC/8. MfG Spess
Gast
#1897577
>Aber klappt das auch wenn man nur einen Pin ändern möchte und nicht den >gesamten Port? > >also mit > >PORTC &= ~( 1 << PC1 ); Klar, nur die Pulsfrequenz ist dann etwas geringer, nämlich FOSC/10 statt FOSC/8, weil dieses Konstrukt in sbi/cbi übersetzt wird, die je zwei Takte benötigen. PORTB = 0 und PORTB = 1 wird über out erledigt, das nur einen Takt verbraucht. >Eher FOSC/8. Jooo... danke, Spess :-) Meine "FOSC/4" ist falsch, ich korrigiere: Von jeder Flanke bis zur nächsten sind es 4 Takte, aber da ein Puls aus zwei Flanken besteht (L-->H und H-->L), ist die resultierende Frequenz FOSC/8.
Gast
#1897653
Noch eine verbesserte Version. Wieder FOSC/8, aber ohne Nebenwirkung auf den Pins PB1 bis PB7. Alle Pins außer PB0 bleiben auf den Zuständen, die sie beim Aufruf der Routine haben. Falls anderer Ausgabepin als PB0 gewünscht, einfach im Code ändern.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
Gast
#1897677
Hi Mal ehrlich. Mit Assembler wäre man schon zehn mal fertig. Statt dessen wird hier tagelang mit C Problemen herum gedoktert, die man ohne C nicht hätte. MfG Spess
spess53 schrieb: > Hi > > Mal ehrlich. Mit Assembler wäre man schon zehn mal fertig. Statt dessen > wird hier tagelang mit C Problemen herum gedoktert, die man ohne C nicht > hätte. > Übertreib nicht. Ein C-Kundiger hat die Schleife genauso schnell, wie du das alles in Assembler (ok. bei der Schleife hab ich etwas geschlafen um sie auf 1:1 zu bringen) Und vom ganzen Rest rundherum reden wir mal nicht :-) Wenn sich Vuvuzelatus spielen will, soll er das tun. Für den Rest ist
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
perfekt und spielt alle Stückchen die man braucht.
Gast
#1898055
Vielen Dank Läuft nun alles einwandfrei :)
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
