```
.equ c1 = 50000 ; Number of exections of the loops
ldi R25,HIGH(c1) ; Load MSB register with the upper byte
ldi R24,LOW(c1) ; Load LSB register with the lower byte
Loop: ; Loop starts here
sbiw R24,1 ; Decrease double register value by one
brne Loop ; if not zero start loop again, if zero continue
```

```
```

The constant c1 again defines the number of loop executions. As the 16 bit
register can have 65,536 different numbers, it can count 256 times longer
than with an 8 bit register only.
The instruction "SBIW R24,1" decreases the register pair word-wise. That means that whenever the LSB underflows, the MSB is also automatically reduced by 1. Note that only the register pairs R25:R24, R27:R26, R29:R28 and R31:R30 can do that. As R27:R26 (called X), R29:R28 (called Y) and R31:R30 (called Z) can do additional things, R25:R24 is the number 1 candidate for that use as 16 bit counter.

```
.equ c1 = 50000 ; No instruction, 0 cycles, only for the assembler
ldi R25,HIGH(c1) ; 1 cycle
ldi R24,LOW(c1) ; 1 cycle
Loop: ; Loop starts here, no instruction, only for the assembler
sbiw R24,1 ; 2 cycles
brne Loop ; 2 cycles if not zero, 1 cycle if zero
```

```
```

The number of clock cycles is the sum of
- Load: 2 instructions 1 cycle each, once executed,
- Loop: 2 cycles for SBIW, two cycles for BRNE and not zero, executed (c1 - 1) times,
- Loop end: 2 cycles for SBIW, one cycle for BRNE, executed once.

or:

or even simpler:

Variable delays of different durations are sometimes necessary. That is the case e. g. if the software should work at different clock frequencies. Then we have to calculate the counter value from the clock frequency. Such a piece of software is shown below. Two different delays are used as calculation examples (1 ms and 100 ms).

```
;
; Delay 16-Bit with variable duration
;
.include "tn13def.inc"
;
; Hardware-dependant constant
;
.equ fc = 1200000 ; Controller clock (default)
;
; My constant
;
.equ fck = fc / 1000 ; Controller frequency in kHz
;
; Delay routine
;
Delay1ms: ; 1 ms routine
.equ c1ms = (1000*fck)/4000 - 1 ; Constant for 1 ms
ldi R25,HIGH(c1ms) ; Load counter
ldi R24,LOW(c1ms)
rjmp delay
;
Delay100ms: ; 100 ms routine
.equ c100ms = (100*fck)/4 - 1 ; Constant for 100 ms
ldi R25,HIGH(c100ms) ; Load counter
ldi R24,LOW(c100ms)
rjmp delay
;
; Delay loop, expects constant in R25:R24
;
Delay:
sbiw R24,1 ; Count down
brne Delay ; Until zero
nop ; additional delay
```

Hint: The constants c1ms and c100ms are calculated in two different ways to reduce
rounding inaccuracies in integer division and to avoid overflows of 32-bit integers.
```
.equ c1 = 0 ; 0 clock cyles (only the assembler works)
ldi R25,HIGH(c1) ; 1 clock cycle
ldi R24,LOW(c1) ; 1 clock cycle
Loop: ; Loop start
nop ; do nothing, 1 clock cycle
nop ; do nothing, 1 clock cycle
nop ; do nothing, 1 clock cycle
nop ; do nothing, 1 clock cycle
nop ; do nothing, 1 clock cycle
nop ; do nothing, 1 clock cycle
sbiw R24 ; 2 clock cycles
brne Loop ; 2 clock cycles if not zero, 1 clock cycle when zero reached
```

```
```

Each loop cycle (except for the last one) now consumes 10 clock cycles, the last
one only nine. The following formulas apply:
nc = 2 + 10*(c1 - 1) + 9

or

nc = 10 * c1 + 1

At max (c1 = 0) now 655,361 clock cycles delay are possible.

If you need a certain number of clock cycles nc, calculate the constant c1 by

c1 = (nc - 1) / 10

or in integer math with rounding:

c1 = (nc - 1 + 5) /10

```
.include "tn13def.inc" ; for an ATtiny13
.equ cDelay = 500 ; Delay in milli-seconds per half-wave
.equ clock = 1200 ; Clock frequency in kHz (default)
.equ c1 = ((cDelay*clock)-1+5)/10 ; Delay counter, determines the blink frequency
; Hint: +5 added for rounding, result is 60,000)
sbi DDRB,0 ; Portbit is output
Loop:
sbi PORTB,0 ; Portbit to high
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop1:
nop
nop
nop
nop
nop
nop
sbiw R24,1
brne Loop1
cbi PORTB,0 ; Portbit to low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop2:
nop
nop
nop
nop
nop
nop
sbiw R24,1
brne Loop2
rjmp Loop
```

```
```

Blink well!
To the top of that page

©2009-2019 by http://www.avr-asm-tutorial.net