ATMega328 553 Takte warten mit Inline Assembler

Gast #4095079
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
Gast #4095131
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
Gast #4095401
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
Gast #4095450
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

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.