Hallo
ich möchte an einem Atmega328P mehere PWMs erzeugen. Komischerweise
funktioniert in meinem code nur die erste for Schleife. Die zweite hat
keine Funktion. Sobald ich aber die erste auskommentiere funktioniert
die zweite. Dachte es hängt vielleicht mit der Funktion _delay_ms
zusammen. dies ist aber nicht der Fall. Den PWM erzeuge ich im Mode 5 (8
Bit).
Kann mir jemand weiterhelfen.
Dennis schrieb:> for (ui_i = 0x0000; ui_i <= 0x7FFF; ui_i++);> ...> for (ui_i = 0x0000; ui_i <= 0x7FFF; ui_i++);
Bist du dir sicher, dass dein Compiler das nicht wegoptimiert?
fop schrieb:> Das gibt oft nur eine 8 Bit breite Variable. Also eine, die Werte von 0> bis 255 aufnehmen kann.> Damit ist die Bedingunguc_i <= 0xFF quasi immer erfüllt. Deine Schleife> läuft also länger als Du denkst. Um> genau zu sein : ewig.
0xFF passt aber auch in 8 Bit...
Wolfgang schrieb:> Dennis schrieb:>> for (ui_i = 0x0000; ui_i <= 0x7FFF; ui_i++);>> ...>> for (ui_i = 0x0000; ui_i <= 0x7FFF; ui_i++);>> Bist du dir sicher, dass dein Compiler das nicht wegoptimiert?
Bin mir Sicher. Es läuft ja. Aber eben immer nur eine der beiden for
Schleifen. Wenn is z.B "//OCR1BL = uc_i;" wieder einkommentiere sehe ich
wie beide Ausgänge von 0x00 - 0xFF durchlaufen. Habe sicherheitshalber
aber auch die optimierung auf "none" gesetzt.
Matthias S. schrieb:> Das läuft alles so schnell durch, das du davon ohne Oszilloskop gar> nichts mitkriegst. Bau also die _delay_ms() wieder ein.
Ich habe ein Oszi dran. Ich kann sehr schön sehen wie die PWM von 0x00 -
0xFF durchlaufen wird.
fop schrieb:> unsigned char uc_i;> Das gibt oft nur eine 8 Bit breite Variable. Also eine, die Werte von 0> bis 255 aufnehmen kann.> Damit ist die Bedingunguc_i <= 0xFF quasi immer erfüllt. Deine Schleife> läuft also länger als Du denkst. Um> genau zu sein : ewig.
Wie gesagt, es geht ja.
Maxim B. schrieb:>> Ja, ich verstehe diese Tänze nicht...> Könntest du doch nicht einfach schreiben:TCCR1A |= (1<<WGM10);> TCCR1B |= ((1<<WGM12) | (1<<CS11) | (1<<CS10)); ?
Für mein Problem nicht relevant...
Dennis schrieb:> Für mein Problem nicht relevant...
Aber deine Schreibweise ist relevant.
Kuck mal weiter: überall gleiche Styl!
Ich würde dir empfehlen, ein bißchen über C-Sprache zu lesen.
Du schreibst auf C so, als ob du Assembler hättest.
Compiler ist kein Narr, er sieht, daß etwas nicht stimmt, und wirkt
verrückt.
Um Problem besser zu verstehen, kannst du compilierte asm ankucken. Ich
glaube nach deinem Styl, gerade mit asm hast du kein Problem.
Maxim B. schrieb:> Dennis schrieb:>> Für mein Problem nicht relevant...>> Aber deine Schreibweise ist relevant.> Kuck mal weiter: überall gleiche Styl!>> Ich würde dir empfehlen, ein bißchen über C-Sprache zu lesen.>> Du schreibst auf C so, als ob du Assembler hättest.>> Compiler ist kein Narr, er sieht, daß etwas nicht stimmt, und wirkt> verrückt.>> Um Problem besser zu verstehen, kannst du compilierte asm ankucken. Ich> glaube nach deinem Styl, gerade mit asm hast du kein Problem.
Also, jetzt habe ich besagte zuweisung direkt gemacht. Siehe da, kein
Unterschied... Und wo ist "überal gleiche Styl". Deine Vorschläge helfen
mir nicht weiter.
Dennis schrieb:> Deine Vorschläge helfen> mir nicht weiter.
Auch Vorschlag, ein C-Buch zu lesen?
Bitte begreife: je verständlicher und durchsichtiger dein Code, um so
weniger wahrscheinlich, daß du Fehler schreibst.
Hast du schon Ergebnis in asm gekuckt?
1
voidmfc_test(void)
2
{
3
unsignedintui_i;
4
unsignedcharuc_i;
5
6
7
for(uc_i=0x00;uc_i<=0xFF;uc_i++)
8
{
9
//OCR1AH = ((unsigned char) (ui_i >> 8));
10
//OCR1AL = ((unsigned char) (ui_i & 0x00FF));
11
OCR1AL=uc_i;
12
//OCR1BL = uc_i;
13
//_delay_ms(25);
14
for(ui_i=0x0000;ui_i<=0x7FFF;ui_i++);
15
16
}
17
18
19
for(uc_i=0x00;uc_i<=0xFF;uc_i++)
20
{
21
OCR1BL=uc_i;
22
for(ui_i=0x0000;ui_i<=0x7FFF;ui_i++);
23
//_delay_ms(25);
24
}
25
26
}
Kannst du bitte sagen:
1. warum willst du OSR-Register mal gesamt und mal byteweise schreiben?
Welche Gründe hast du dafür?
2. kannst du mit einfachen Worten beschreiben, was deine Funktion machen
sollte?
Die Lösung kam bereits viel weiter oben, nochmal zum Nachdenken an
Dennis.
1. Welche Werte kann ui_c annehmen?
2. Wann bricht die Schleife ab?
3. Wie oft wird mach_irgend_was() ausgeführt?
S. Landolt schrieb:> Liegt es vielleicht daran, dass OC1A/B nicht als Ausgänge> definiert> wurden? Mir ist unklar, warum derzeit überhaupt irgendetwas zu sehen> ist.
Entschuldige, da habe ich defines benutzt.
fop schrieb:> unsigned char uc_i;> Das gibt oft nur eine 8 Bit breite Variable. Also eine, die Werte von 0> bis 255 aufnehmen kann.> Damit ist die Bedingunguc_i <= 0xFF quasi immer erfüllt. Deine Schleife> läuft also länger als Du denkst. Um> genau zu sein : ewig.Martin H. schrieb:> Die Lösung kam bereits viel weiter oben, nochmal zum Nachdenken an> Dennis.>> 1. Welche Werte kann ui_c annehmen?> 2. Wann bricht die Schleife ab?> 3. Wie oft wird mach_irgend_was() ausgeführt?>> for (unsigned char uc_i = 0x00; uc_i <= 0xFF; uc_i++) {> mach_irgend_was();> }
Ich honk, vielen Dank euch beiden!
Dennis schrieb:> Ich honk, vielen Dank euch beiden!
Was gemerkt? Deine Einstellung/Arroganz beeinflusst wesentlich die
Problemlösung. Du hast es in deiner unendlichen Weisheit drei Mal
vorgezogen die Hinweise auf das Problem zu ignorieren.
Sogar jetzt ist deine Antwort noch Arrogant. Statt allen zu danken,
welche dir ehrlich versucht haben zu helfen, kommt diese selektive
Danksagung.
> #define PWM_MFC1_PIN DDRD |= (1<<DDD3);PORTD |= (1<<PORTD3)
So schreibt man kein Makros. Diese gehen bei bestimmten Konstellationen
voll in die Hose.
Die obige Formulierung funktioniert schon bei:
1
if(i_want_pwm)
2
PWM_MFC1_PIN;
nicht mehr.
Dann wird nämlich vom Makro lediglich das erste Statement links vom
Semikolen bedingt ausgeführt und das zweite unbedingt.
Also wird daraus aus Sicht des Compilers:
1
if(i_want_pwm)
2
DDRD|=(1<<DDD3);// bedingt
3
PORTD|=(1<<PORTD3)// unbedingt.
... was bestimmt nicht beabsichtigt ist. Beim nächsten Projekt werden
diese Makros einfach kopiert und man wundert sich dann, dass das
Programm nicht das tut, was es tun soll.
Eine kleinere Verbesserung wäre, das Semikolon im Makro durch ein Komma
zu ersetzen. Dann werden beide Kommandos bedingt ausgeführt, da sie als
ein Statement gezählt werden.
Optimale Lösung wären:
a) geschweifte Klammern im Makro
b) Erweiterung auf do { ... } while.
Aber die Komma-Variante wäre hier schon hilfreich.
Frank M. schrieb:> Eine kleinere Verbesserung wäre, das Semikolon im Makro durch ein Komma> zu ersetzen. Dann werden beide Kommandos bedingt ausgeführt, da sie als> ein Statement gezählt werden.
Bei einigen Programmierer wird noch do{...}while(0); in Gebrauch. Dabei
wird nach jedem Befehl "\" benutzt, etwa so:
Mir selber scheint aber die Lösung mit inline besser:
1
staticinlinevoidknopf_init(void){
2
KN_PLUS_DDR&=~(1<<KN_PLUS);
3
KN_MINUS_DDR&=~(1<<KN_MINUS);
4
KN_M_DDR&=~(1<<KN_M);
5
KN_F_DDR&=~(1<<KN_F);
6
DRKN_DDR&=~(1<<DRKN);
7
KN_PLUS_PORT|=(1<<KN_PLUS);
8
KN_MINUS_PORT|=(1<<KN_MINUS);
9
KN_M_PORT|=(1<<KN_M);
10
KN_F_PORT|=(1<<KN_F);
11
DRKN_PORT|=(1<<DRKN);
12
}
Besser aus zwei Gründen:
1. es wird dem Compiler überlassen, ob er "static inline" wahrnimmt oder
aus guten Gründen als normale Funktion übersetzt.
2. in Simulator wird Funktion Befehl nach Befehl sichtbar, während Macro
als einen einzigen Befehl durchgeführt. So ist es leicher Fehler zu
finden.
Maxim B. schrieb:> Bei einigen Programmierer wird noch do{...}while(0); in Gebrauch.
Schrieb ich doch oben als "Optimale Lösung".
> Dabei> wird nach jedem Befehl "\" benutzt, etwa so:
Frank M. schrieb:> Am Ende des Makros muss das Semikolon weg. Denn man wendet das Makro> dann so an: KNOPF_INIT(); // Hier das Semikolon, nicht> ins Makro!
Geschmackssache. Wird Semikolon in Macro, so wird Macro ohne Semikolon
in Programm verwendet. So sieht man sofort: das ist Macro und keine
Funktion.
Ich habe ein bißchen experimentiert mit solchen Macro. Am Ende aber
alles auf static inline - Funktionen geändert.
Ich glaube, Macro sind für andere Gebrauch besser: um Ausgänge nach
Bedarf anders definieren. Werden Macro als Funktionen verwendet, wird
ganze Text weniger verständlich. Aber Ziel der Sprache von Anfang an
gerade war, Texte verständlicher und dadurch möglichst fehlerfrei zu
schreiben.
Aber alles Geschmackssache. Wie sagte ein Pianist: Sie dürfen auch mit
Ihrer Nase Klavier spielen. Hauptsache Ergebnis stimmt...
Maxim B. schrieb:> Geschmackssache.
Nein. Fehlerträchtig. Man sollte immer sicherstellen, dass Makros sich
wie Funktionen verhalten - zumindest von der Syntax her.
Ein simples Beispiel:
Die stdio-Funktion getchar() ist in vielen UNIX-Varianten ein simples
Makro und keine Funktion. Der Komfort ist hier aber, dass Du das als
Programmierer überhaupt nicht wissen musst.
Ja, ich muß noch vieles lernen... Vielen Dank für Ihre Anweisung!
Also, nach while(0) von nun an schreibe ich nie mehr Semikolon!
Dann hat es auch wenig Sinn, an Regeln zu halten, solche Macros immer
mit Großbuchstaben zu schreiben - das sollte ja wie eine Funktion
aussehen.