<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=129.27.233.10</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=129.27.233.10"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/129.27.233.10"/>
	<updated>2026-04-10T14:41:54Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Assembler_Makros&amp;diff=94454</id>
		<title>AVR Assembler Makros</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Assembler_Makros&amp;diff=94454"/>
		<updated>2016-11-29T16:13:30Z</updated>

		<summary type="html">&lt;p&gt;129.27.233.10: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:AVR]]&lt;br /&gt;
&lt;br /&gt;
Hier entsteht eine Sammlung von verschiedenen nützlichen [[Makro|Makros]] für den [[AVR]] [[Assembler]].&lt;br /&gt;
&lt;br /&gt;
=== 16 Bit Konstante in Z-Pointer laden ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.MACRO SetZPtr ;(Adresse)&lt;br /&gt;
        ldi     ZL, LOW(@0)&lt;br /&gt;
        ldi     ZH, HIGH(@0)&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich auch möglich mit X- und Y-Pointer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Speicher==&lt;br /&gt;
=== 2 Register ohne Zwischenspeicher vertauschen ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.MACRO SWAP ;(a, b)&lt;br /&gt;
        eor     @0, @1&lt;br /&gt;
        eor     @1, @0&lt;br /&gt;
        eor     @0, @1&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Arithmetik==&lt;br /&gt;
&lt;br /&gt;
=== Konstante addieren ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.MACRO ADDI ;(a, k)&lt;br /&gt;
        subi    @0, -(@1)&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konstante addieren (16 Bit) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.MACRO ADDIW ;(RdL:RdH, k)&lt;br /&gt;
        subi    @0L, LOW(-@1)  &lt;br /&gt;
        sbci    @0H, HIGH(-@1)&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
oder (sinnlos)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.MACRO ADDIW ;(Rd, k)&lt;br /&gt;
        sbiw    @0, (-@1)&lt;br /&gt;
.ENDMACRO&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
DAS geht auch ohne Makro&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
        adiw a, b&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
SBIW und ADIW sind aber beide auf die Register(paare) R24, R26, R28, R30 beschränkt UND nehmen nur Zahlen &amp;lt;64 an.&lt;br /&gt;
&lt;br /&gt;
==I/O==&lt;br /&gt;
&lt;br /&gt;
Bei grösseren und neueren AVRs sind etliche I/O-Register nicht mit IN/OUT-Befehlen ansprechbar. LDS/STS erreicht zwar alle, ist aber bei kleineren oder älteren ineffizient.&lt;br /&gt;
&lt;br /&gt;
=== Port lesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.macro input&lt;br /&gt;
  .if @1 &amp;lt; 0x40&lt;br /&gt;
	in	@0, @1&lt;br /&gt;
  .else&lt;br /&gt;
  	lds	@0, @1&lt;br /&gt;
  .endif&lt;br /&gt;
.endm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Port schreiben ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.macro output&lt;br /&gt;
  .if @0 &amp;lt; 0x40&lt;br /&gt;
	out	@0, @1&lt;br /&gt;
  .else&lt;br /&gt;
  	sts	@0, @1&lt;br /&gt;
  .endif&lt;br /&gt;
.endm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Portbit abfragen ===&lt;br /&gt;
&lt;br /&gt;
Abfrage eines Bits eines I/O-Ports und Sprung wenn 1/0.&lt;br /&gt;
Überschreibt u.U. ZL.&lt;br /&gt;
&lt;br /&gt;
Branch if Bit in I/O-Register is Set&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.macro bbis ;port,bit,target&lt;br /&gt;
  .if @0 &amp;lt; 0x20&lt;br /&gt;
 	sbic	@0, @1&lt;br /&gt;
	rjmp	@2&lt;br /&gt;
  .elif @0 &amp;lt; 0x40&lt;br /&gt;
	in	zl, @0&lt;br /&gt;
	sbrc	zl, @1&lt;br /&gt;
	rjmp	@2&lt;br /&gt;
  .else&lt;br /&gt;
	lds	zl, @0&lt;br /&gt;
	sbrc	zl, @1&lt;br /&gt;
	rjmp	@2&lt;br /&gt;
  .endif&lt;br /&gt;
.endm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Branch if Bit in I/O-Register is Cleared&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.macro bbic ;port,bit,target&lt;br /&gt;
  .if @0 &amp;lt; 0x20&lt;br /&gt;
 	sbis	@0, @1&lt;br /&gt;
	rjmp	@2&lt;br /&gt;
  .elif @0 &amp;lt; 0x40&lt;br /&gt;
	in	zl, @0&lt;br /&gt;
	sbrs	zl, @1&lt;br /&gt;
	rjmp	@2&lt;br /&gt;
  .else&lt;br /&gt;
	lds	zl, @0&lt;br /&gt;
	sbrs	zl, @1&lt;br /&gt;
	rjmp	@2&lt;br /&gt;
  .endif&lt;br /&gt;
.endm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Location Pointer ==&lt;br /&gt;
=== Align ===&lt;br /&gt;
Manchmal ist es notwendig, Tabellen oder Puffer auf eine bestimmte Byte- oder Wortgrenze zu bringen, z.B. um beim Zugriff einen Überlauf des Index in das obere Adressbyte zu verhindern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.macro      align   ;align to 1&amp;lt;&amp;lt;@0&lt;br /&gt;
alignfromhere:&lt;br /&gt;
      .if (alignfromhere &amp;amp; ((1&amp;lt;&amp;lt;@0)-1))   ;if not already aligned&lt;br /&gt;
         .org  (alignfromhere &amp;amp; (0xffff&amp;lt;&amp;lt;@0)) + (1&amp;lt;&amp;lt;@0)&lt;br /&gt;
      .endif&lt;br /&gt;
.endmacro&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@0 bezeichnet die Anzahl rechtsbündiger binärer Nullen.&lt;br /&gt;
Beispiel: align 8 setzt die nächste Adresse auf $xx00.&lt;br /&gt;
Funktioniert in allen Segmenten.&lt;br /&gt;
&lt;br /&gt;
== Delay ==&lt;br /&gt;
=== Verzögerung um X Nanosekunden ===&lt;br /&gt;
von Klaus2m5&lt;br /&gt;
&lt;br /&gt;
Taktgenaue Verzögerung der Instruktionsausführung durch Angabe der Verzögerungszeit&lt;br /&gt;
in Nanosekunden. Dabei werden maximal 4 Instruktionen erzeugt.&lt;br /&gt;
Taktgenau bedeutet, dass auf die nächste volle Anzahl von Takten&lt;br /&gt;
aufgerundet wird. Beispiel: 75ns bei 20MHZ (50ns Taktzeit) bedeutet eine tatsächliche&lt;br /&gt;
Verzögerung von 2 Zyklen und entspricht 100ns.&lt;br /&gt;
&lt;br /&gt;
Die Variable Osc_Hz muss der verwendeten Taktquelle angepasst werden und definiert&lt;br /&gt;
die CPU-Taktfrequenz in Hertz.&lt;br /&gt;
&lt;br /&gt;
wait_ns wird mit folgenden Parametern aufgerufen:&lt;br /&gt;
  1. Verzögerungszeit in Nanosekunden&lt;br /&gt;
  2. bereits verbrauchte Takte&lt;br /&gt;
  3. ein Immediate-Register (R16-R31) als Zähler&lt;br /&gt;
Bereits verbrauchte Takte werden aus den Instruktionen errechnet, die zwischen&lt;br /&gt;
den zu verzögernden Ereignissen liegen. Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
            sbi     porta,0&lt;br /&gt;
            wait_ns 1000,2,R16&lt;br /&gt;
            cbi     porta,0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In diesem Fall besteht die Anzahl der verbrauchten Takte lediglich aus den Instruktionen,&lt;br /&gt;
die zum Ereignis führen. Am Ende von SBI wird die steigende Flanke, am Ende von CBI&lt;br /&gt;
die fallende Flanke des Signals erzeugt. Wenn wir also möglichst exakt eine&lt;br /&gt;
Pulsbreite von einer Mikrosekunde erzeugen wollen, müssen wir die Ausführungszeit&lt;br /&gt;
von CBI von unserer Wartezeit abziehen. Die Ausführung von CBI liegt vor dem Ereignis!&lt;br /&gt;
&lt;br /&gt;
Wenn die Verzögerungszeit kleiner als die Anzahl bereits verbrauchter Taktzyklen ist,&lt;br /&gt;
wird keine weitere Verzögerung erzeugt. Die maximale Verzögerung ist 767 Takte&lt;br /&gt;
entsprechend 38350ns bei 20MHZ. Bei niedrigeren Frequenzen wird eine längere Verzögerung&lt;br /&gt;
erreicht, allerdings nimmt dann auch die Genauigkeit der Verzögerung ab (exakt bis +1 Takt).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
;&lt;br /&gt;
; wait_ns  waittime in ns , cyles already used , waitcount register &lt;br /&gt;
;&lt;br /&gt;
;     cycles already used will be subtracted from the delay&lt;br /&gt;
;     the waittime resolution is 1 cycle (delay from exact to +1 cycle)&lt;br /&gt;
;     the maximum delay at 20MHz (50ns/clock) is 38350ns&lt;br /&gt;
;     waitcount register must specify an immediate register&lt;br /&gt;
;&lt;br /&gt;
.set     Osc_Hz         = 7372800                    ;7,3728 MHz (Baudrate xtal)&lt;br /&gt;
.set     cycle_time_ns  = (1000000000 / Osc_Hz)      ;clock duration&lt;br /&gt;
.macro   wait_ns&lt;br /&gt;
      .set cycles = ((@0 + cycle_time_ns - 1) / cycle_time_ns - @1)&lt;br /&gt;
      .if (cycles &amp;gt; (255 * 3 + 2))&lt;br /&gt;
        .error &amp;quot;MACRO wait_ns - too many cycles to burn&amp;quot;&lt;br /&gt;
      .else&lt;br /&gt;
        .if (cycles &amp;gt; 6)&lt;br /&gt;
          .set  loop_cycles = (cycles / 3)      &lt;br /&gt;
          ldi   @2,loop_cycles&lt;br /&gt;
          dec   @2&lt;br /&gt;
          brne  pc-1&lt;br /&gt;
          .set  cycles = (cycles - (loop_cycles * 3))&lt;br /&gt;
        .endif&lt;br /&gt;
        .if (cycles &amp;gt; 0)&lt;br /&gt;
          .if   (cycles &amp;amp; 4)&lt;br /&gt;
            rjmp  pc+1&lt;br /&gt;
            rjmp  pc+1&lt;br /&gt;
          .endif&lt;br /&gt;
          .if   (cycles &amp;amp; 2)&lt;br /&gt;
            rjmp  pc+1&lt;br /&gt;
          .endif&lt;br /&gt;
          .if   (cycles &amp;amp; 1)&lt;br /&gt;
            nop&lt;br /&gt;
          .endif&lt;br /&gt;
        .endif&lt;br /&gt;
      .endif&lt;br /&gt;
.endmacro&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Strukturierte Programmierung ==&lt;br /&gt;
&lt;br /&gt;
===SAM (Structured Assembly Macros)===&lt;br /&gt;
von Klaus2m5&lt;br /&gt;
&lt;br /&gt;
SAM unterstützt strukturiertes Programmieren durch If-Then-Else und Do-Loop Makros. Beliebige Verschachtelung und Mehrfachbedingungen sind möglich. Läuft unter aktuellen Versionen von AVRASM2.&lt;br /&gt;
&lt;br /&gt;
Einige Beispiele:&lt;br /&gt;
 &lt;br /&gt;
Verschachteltes If-Then-Else&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
            cpi   r16,&#039;a&#039;&lt;br /&gt;
            ifeq  a_chr&lt;br /&gt;
              cpi   r17,&#039;b&#039;&lt;br /&gt;
              ifeq   a_and_b&lt;br /&gt;
                ;...a&amp;amp;b&lt;br /&gt;
              else   a_and_b&lt;br /&gt;
                ;...a&amp;amp;-b&lt;br /&gt;
              end    a_and_b&lt;br /&gt;
            else  a_chr&lt;br /&gt;
              cpi r17,&#039;c&#039;&lt;br /&gt;
              ifeq  c_but_no_a&lt;br /&gt;
                ;...-a&amp;amp;+c&lt;br /&gt;
              else  c_but_no_a&lt;br /&gt;
                ;...-a&amp;amp;c&lt;br /&gt;
              end   c_but_no_a&lt;br /&gt;
            end   a_chr&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Mehrere und/oder verknüpfte Bedingungen&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
            cpi   zh,high(end_buffer)&lt;br /&gt;
            ifeq_and    end_buffer_reached&lt;br /&gt;
            cpi   zl,low(end_buffer)&lt;br /&gt;
            ifeq        end_buffer_reached&lt;br /&gt;
              ldi   zh,high(buffer)       ;wrap buffer&lt;br /&gt;
              ldi   zl,low(buffer)&lt;br /&gt;
            end         end_buffer_reached&lt;br /&gt;
            ld    r0,z+                   ;read buffer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Das Gleiche als Do-Loop&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
; reading a buffer until end&lt;br /&gt;
; similar to: for z = buffer to end_buffer&lt;br /&gt;
            ldi   zh,high(buffer)   ;init buffer pointer&lt;br /&gt;
            ldi   zl,low(buffer)&lt;br /&gt;
            do    read_buf&lt;br /&gt;
              ld    r0,z+&lt;br /&gt;
              cpi   zh,high(end_buffer)&lt;br /&gt;
            loopne read_buf&lt;br /&gt;
              cpi   zl,low(end_buffer)&lt;br /&gt;
            loopne read_buf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mehr Beispiele und das SAM-include als [[Media:sam.zip|Download.]]&lt;/div&gt;</summary>
		<author><name>129.27.233.10</name></author>
	</entry>
</feed>