Forum: Mikrocontroller und Digitale Elektronik ATMega328 553 Takte warten mit Inline Assembler


von UnendlichHoherPotentialtopf (Gast)


Lesenswert?

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

von nga (Gast)


Lesenswert?

schau dir mal die Datei delay_basic.h in util an (bei WinAVR bzw AVR 
libc dabei)
--> Taktgenaue warteschleifen

von spess53 (Gast)


Lesenswert?


von UnendlichHoherPotentialtopf (Gast)


Lesenswert?

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

von UnendlichHoherPotentialtopf (Gast)


Lesenswert?

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

von S. Landolt (Gast)


Lesenswert?

sbiw und brne benötigen jeweils 2 Takte.

von UnendlichHoherPotentialtopf (Gast)


Lesenswert?

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

von UnendlichHoherPotentialtopf (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.