Hi, ich würde gerne eine genaues Delay haben. Man könnte dazu einen Timer nutzen aber ich würde gerne mal sehen wie man das mit Inline Assembler schafft. 553 x NOP würde gehen :) aber da gibt es sicherlich bessere Möglichkeiten die auch weniger Speicher verbrauchen. Ich brauche also eine Warteschleife in ASM die ich C-Code nutzen kann (Inline Assembler). Ich hoffe das hier schon mal jemand gemacht. Danke UnendlichHoherPotentialtopf
schau dir mal die Datei delay_basic.h in util an (bei WinAVR bzw AVR libc dabei) --> Taktgenaue warteschleifen
So ganz klappt es noch nicht. Der Compiler schmeißt noch einen Fehler. C:\Temp\ccTCJIsi.s:59: Error: garbage at end of line
1 | asm volatile ("ldi R24, HIGH(552)" "\n\t" |
2 | "ldi R24, LOW(552)" "\n\t" |
3 | "WGLOOP0: dec R24" "\n\t" |
4 | "brne WGLOOP0" "\n\t" |
5 | "nop"); |
UnendlichHoherPotentialtopf
Drei Fehler habe ich noch gefunden :) Den High Wert muss ich in Register 25 schreiben. HIGH und LOW mag der Compiler nicht. sbiw anstatt dec. Jetzt sieht das so aus
1 | asm volatile ("ldi R24, 0x28" "\n\t"
|
2 | "ldi R25, 0x02" "\n\t" |
3 | "WGLOOP1:" "\n\t" |
4 | "sbiw R24" "\n\t" |
5 | "brne WGLOOP1" "\n\t" |
6 | "nop"); |
So geht das zwar durch den Compiler aber die LED ist fast aus. Bei einem delay von 553 Takten (_delay_loop_2(553)) sieht man ein schönes Pulsen. hier der ganze code
1 | #include <avr/io.h> |
2 | #include <util/delay.h> |
3 | #include <util/delay_basic.h> |
4 | |
5 | void pwm_init() |
6 | {
|
7 | // Init TCCR0
|
8 | TCCR0A |= (1<<WGM00)|(1<<COM0A1)|(1<<WGM01); |
9 | TCCR0B |= (1<<CS00); |
10 | // PD6 als Ausgang
|
11 | DDRD |= (1<<PD6); |
12 | }
|
13 | |
14 | void main() |
15 | {
|
16 | uint8_t brightness; |
17 | |
18 | pwm_init(); |
19 | |
20 | while(1) |
21 | {
|
22 | // increasing brightness
|
23 | for (brightness = 0; brightness < 255; ++brightness) |
24 | {
|
25 | OCR0A = brightness; |
26 | |
27 | //_delay_loop_2(553);
|
28 | |
29 | asm volatile ("ldi R24, 0x28" "\n\t" |
30 | "ldi R25, 0x02" "\n\t" |
31 | "WGLOOP0:" "\n\t" |
32 | "sbiw R24,1" "\n\t" |
33 | "brne WGLOOP0" "\n\t"); |
34 | }
|
35 | |
36 | // decreasing brightness
|
37 | for (brightness = 255; brightness > 0; --brightness) |
38 | {
|
39 | OCR0A = brightness; |
40 | |
41 | //_delay_loop_2(553);
|
42 | |
43 | asm volatile("ldi R24, 0x28" "\n\t" |
44 | "ldi R25, 0x02" "\n\t" |
45 | "WGLOOP1:" "\n\t" |
46 | "sbiw R24,1" "\n\t" |
47 | "brne WGLOOP1" "\n\t"); |
48 | |
49 | }
|
50 | }
|
51 | }
|
Jetzt kommt es aber total unerwartet für mich. Wenn ich in der For Schleife (egal ob in decreasing oder increasing) das _delay_loop_2(553) nutze und den ASM Code auskommentiere funktioniert es auch. UnendlichHoherPotentialtopf
S. Landolt schrieb: > sbiw und brne benötigen jeweils 2 Takte. OK, das habe ich geändert aber das ändert nichts an dem Problem, dass wenn ich beide ASM Teile aktiv habe, die LED nicht pulst sondern einfach nur ganz schwach glimmt. UnendlichHoherPotentialtopf
So jetzt funktioniert es aber ein Erklärung habe ich nicht. Also ich hatte bei Optimazation immer -Os. Jetzt habe ich -O 0 genommen und jetzt funktioniert es. Sieht für mich aus als würde der Compiler das wegoptimieren. Warum aber nur wenn ich es zweimal nutze? UnendlichHoherPotentialtopf
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.