Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter fuer schwierige und grosse Gaerten im Test

Für den allgemein Interessierten und für Power-User, die ihr Bascom-Programm mit etwas Assembler-Code aufpeppen möchten, stelle ich recht zwanglos einige Assembler-Codeschnipsel zusammen mit den zugehörigen Bascom-Statements zur Verfügung.

Die meisten Beispiele könnte man mit Inline-Assemler direkt ersetzen, wenn man mal probieren wollte, man muß natürlich auf Daten- und Labeladressen aufpassen

Die meisten Bascom-Funktionen ergeben im Code dann folgende Teile:

  • Der Aufruf
    • die Vorbereitung, also das Laden von Registern mit den konkreten Argumenten,
    • einen Call auf den eigentliche Funktions-code
    • das Abliefern des Ergebnisses
  • Die Funktion selbst

ADC

Config ADC

CONFIG Adc = Single , Prescaler = Auto
	LDI	r24,0x06
	OUT	ADCSR,r24

Start ADC

START ADC
	SBI	ADCSR,ADEN


Getadc()

  • Aufruf
DIM X AS WORD                  laut "prog.RPT"  an der Adresse 0x0063
X = GETADC(0)

ergibt folgenden Code:

	LDI	r24,0x00       ADC-Kanal-Nummer nach Register 24
	OUT	ADMUX,r24      in den ADC-Multiplexer

	CALL	L_0x00F6       Aufruf der getadc-funktion

	LDI	XL,0x63        laden der Ergebnisadresse  (DIM X AS WORD)
	LDI	XH,0x00
	ST	X+,r24         Speichern ergebnis   (R24:r25) in "X"
	ST	X,r25
  • Funktion
L_0x00F6:
	SBI	ADCSR,ADSC   Starten der 1. Konversion
L_0x00F8:
	SBIC	ADCSR,ADSC   Fertig ? 
	RJMP	L_0x00F8     nein, Loop1
	SBI	ADCSR,ADSC   Starten der 2. Konversion
L_0x00FE:
	SBIC	ADCSR,ADSC   Fertig ? 
	RJMP	L_0x00FE     nein, Loop2
	IN	r24,ADCL     Ergebnis auslesen r24:r25
	IN	r25,ADCH
	RET                  fertig

BITWAIT

Bitvariable

  • Aufruf
Dim A As Bit
BITWAIT A , Set                                             'wait until bit a is set
  • Code
L_0x007A:
	LDS	r24,0x0060
	SBRS	r24,7
	RJMP	L_0x007A

IO-Register

  • Aufruf
BITWAIT Portb.7 , Reset                                     'wait until bit 7 of Port B is 0.
  • Code
L_0x008C:
	SBIC	PORTB,PB7
	RJMP	L_0x008C



PULSEIN

DIM Result AS WORD
PULSEIN Result , Pind , 2 , 1
  • Aufruf
	LDI	ZL,0x30         // Adresse von SFR PIND
	LDI	r24,0x02	// PinNr 2
	LDI	r16,0xFF        // State 1

	CALL	PULSEIN

	LDI	XL,0x60        laden der Ergebnisadresse  
	LDI	XH,0x00
	ST	X+,r24		// store result
	ST	X,r25

Hier kommen mehrere Funktionen zum Einsatz, die auch ggf. für andere Zwecke aufgerufen werden.

  • Idle Loop
L_0x009C:
	SBIW	ZL,0x0001
	BRNE	L_0x009C
	RET
  • Set_ErrBit
	SET
	BLD	r6,2
	RET
  • Clear_ErrBit
	CLT
	BLD	r6,2
	RET
  • MakeMask
	LDI	r25,0x01
	AND	r24,r24
	BREQ	L_0x00BC
	CLC
L_0x00B6:
	ROL	r25
	DEC	r24
	BRNE	L_0x00B6
L_0x00BC:
	MOV	r24,r25
	COM	r25
	RET
  • Pulsein, die eigentliche Funktion
PULSEIN:
	CALL	Clear_ErrBit
	CLR	ZH
	CLR	XL		// clear Timout Lo
	CLR	XH		// clear Timout Hi
	CALL	MakeMask      // R24 Mask, R25 neg Mask
	AND	r16,r24
	LDD	r0,Z + 1	// DDRD
	AND	r0,r25		// Make Input
	STD	Z + 1,r0	// DDRD
L_0x00D8:	// -------------	Loop
	LDD	r0,Z + 0	// PIND
	AND	r0,r24		// PIND & Mask 
	EOR	r0,r16		// (PIND & Mask) ^ State 
	BRNE	L_0x00E6	// Ok  PIN != State
	ADIW	XL,0x0001	// Timeout counter++
	BREQ	L_0x0118	// elapsed->ERR-Exit
	RJMP	L_0x00D8	// cont'd Loop
L_0x00E6:
	CLR	XL		// clear Timout Lo
	CLR	XH		// clear Timout Hi
L_0x00EA:	// -------------	Loop
	LDD	r0,Z + 0	// PIND
	AND	r0,r24		// PIND & Mask 
	EOR	r0,r16		// (PIND & Mask) ^ State 
	BREQ	L_0x00F8	// Ok  PIN == State
	ADIW	XL,0x0001	// Timeout counter++
	BREQ	L_0x0118	// elapsed->ERR-Exit
	RJMP	L_0x00EA	// cont'd Loop
L_0x00F8:
	CLR	XL		// clear Timout Lo
	CLR	XH		// clear Timout Hi

L_0x00FC:
	PUSH	ZL		// Save
	PUSH	ZH
	LDI	ZL,0x20		// calc from $XTAL 		
	LDI	ZH,0x00
	CALL	L_0x009C	// 10 µS Idle
	POP	ZH		// Restore
	POP	ZL
	LDD	r0,Z + 0	// PIND
	AND	r0,r24		// PIND & Mask 
	EOR	r0,r16		// (PIND & Mask) ^ State 
	BRNE	L_0x011C	// OK, Pulsein done *********
	ADIW	XL,0x0001	// PulseCounter++
	BRNE	L_0x00FC	// cont'd Loop	
L_0x0118:
	CALL	Set_ErrBit
L_0x011C:
	MOV	r24,XL		// result --> R24:r25
	MOV	r25,XH
	RET			// that's it

ENCODER

  • Aufruf
 DIM Result AS BYTE
 Result = ENCODER(pind.1 , Pind.3 , Leftlabel , Rightlabel , 0)
  ...
  ...
Leftlabel:
   Return
Rightlabel:
   Return
  • Code
	LDI	XL,0x60			; result
	LDI	XH,0x00
	CLT				; clear t-bit  (no wait)
L_0x008C:
	LD	r20,X			; Lesen Result (vorheriger Pin-Wert)
	IN	r16,PIND
	CLR	r24			; clear
	SBRC	r16,1			; pind.1
	ORI	r24,0x01		; A = 1
	SBRC	r16,3			; pind.3
	ORI	r24,0x02		; B = 2
	CP	r24,r20			; <> previous
	BRNE	L_0x00A2		; difference
	BRTS	L_0x008C		; t-bit ?	( wait)
	RJMP	L_0x00C2		; no diff, no wait -> xit
L_0x00A2:
	ST	X,r24			; store new as old
	SWAP	r20			; OLD 
	ADD	r24,r20			; OLD + NEW
	CPI	r24,0x02
	BREQ	Leftlabel		; left
	CPI	r24,0x10
	BREQ	Leftlabel		; left
	CPI	r24,0x23
	BREQ	Leftlabel		; left
	CPI	r24,0x31
	BREQ	L_0x00BE		; left
	CALL	Rightlabel		; call Right
	RJMP	L_0x00C2		; xit
L_0x00BE:
	CALL	Leftlabel		; call Left
L_0x00C2:

Anmerkung: hier ist kein Return, da der Code direkt eingefügt wird

Leftlabel:
	RET
Rightlabel:
	RET

Die Links-Rechts Routinen sind hier sparsam gehalten. Normalerweise wird man hier wohl Schritte zählen.

Dividieren 32Bit (LONG)

Das folgende Beispiel ist eigentlich eine Bascom-Source mit inline Assembler. Es zeigt, wie Bascom zwei signed LONG dividiert, und durch den Assembler kann man sich das auch im Simulator bitweise anschauen, wie das läuft.

Anmerkung: Nach der Division befindet sich der Divisionsrest in r16:r19. Wenn den jemand braucht, könnte er ihn nach einer long-Division dort abholen.

  • Aufruf
$regfile = "m32def.dat"                                     ' specify the used micro
$crystal = 8000000

Dim Vala As Long
Dim Valb As Long
Dim Valc As Long

   Vala = 14
   Valb = 1
' das Bascom Äquivalent wäre:
'      Valc = Vala / Valb
$asm
   Loadadr Vala , X                    ' Laden r16:r19 mit Vala
   LD r16,X+
   LD r17,X+
   LD r18,X+
   LD r19,X+
   Loadadr Valb , X                    ' Laden r20:r23 mit Valb
   LD r20,X+
   LD r21,X+
   LD r22,X+
   LD r23,X+
$end Asm

   Gosub L_0x0112                      ' Dividieren  r16:r19 / r20:r23 --> r20:r23

$asm
   Loadadr Valc , X                    ' speichern Ergebnis in Valc
   ST X+,r20
   ST X+,r21
   ST X+,r22
   ST X+,r23
$end Asm

End
  • Funktions-Code
'-----------------------------------------
'
'-----------------------------------------
L_0x0112:
$asm
   RCALL L_0x0174        'Operanden Vorzeichen prüfung und ggf. umdrehen auf positiv
                         'register r0.0 zeigt, ob das Ergebnis negativ ist
   RCALL L_0x0120        'Prüfen Divisor auf NULL. Wenn nicht, dann dividieren
   BLD r0,1              't-bit -> r0.1 (Error)
   RJMP L_0x010C         'finish

L_0x010C:
   SBRC r0,0             'Ergebnis negativ ?
   RCALL L_0x011A	 'ja, Ergebnis negativ machen
   RET                   'so oder so, Funktionsende

L_0x011A:
   RCALL L_0x018A        'Ergebnis auf negativ (r20:r23)
   RCALL L_0x019C        'Rest auf negativ (r16:r19) 
   RET


'-----------------------------------------
' Prüfen divisor auf NULL 
'-----------------------------------------
L_0x0120:
   MOV r24,r20                 'Kopieren r20:r23 -> r24:r27
   MOV r25,r21
   MOV r26,r22
   MOV r27,r23
   CLT			       ' clear T-bit
   !OR r20,r21                 ' prüfen auf NULL 
   !OR r20,r22
   !OR r20,r23
   BRNE L_0x0136               ' <> NULL --> dividieren
   !SET                        ' ==NULL set t-Bit
   RET
'-----------------------------------------
' dividieren r16:r19 / r20:r23  --> r20:r23
'-----------------------------------------
L_0x0136:
   MOV r20,r16                 'r16:r19->r20:r23
   MOV r21,r17
   MOV r22,r18
   MOV r23,r19
   CLR r16                     'clear r16:r19
   CLR r17
   CLR r18
   CLR r19

   LDI ZH,32                   'Zähler  (32 Bit)
'-----------------------------------------
' divisions-Schleife
'-----------------------------------------
L_0x0148:
   LSL r20                     'shift left r20:r23
   ROL r21                   
   ROL r22
   ROL r23                     '(das oberste Bit wandert nach r16:r19)

   ROL r16                     'shift left r16:r19
   ROL r17
   ROL r18
   ROL r19

   !SUB r16,r24                'subtrahieren 
   SBC r17,r25
   SBC r18,r26
   SBC r19,r27

   ORI r20,1                   'Ergebnis auf 1
   BRCC L_0x016E               'kein Überlauf, bleibt so

   ADD r16,r24                 'Überlauf, wieder addieren
   ADC r17,r25
   ADC r18,r26
   ADC r19,r27
   ANDI r20,254               'und den Ergebnis 1-er wieder löschen
L_0x016E:
   DEC ZH                     'Zähler--
   BRNE L_0x0148              '23-Bit Schleife
   RET                        'fertig

'-----------------------------------------
' Prüfen der Operanden 
'-----------------------------------------
L_0x0174:
   CLR r0                     'Kontroll-Register säubern
   CLT                        't-bit löschen
   SBRS r23,7                 ' r20:r23 Negativ ?
   RJMP L_0x0180              'nö, ist positiv
   RCALL L_0x018A             'ja, auf positiv umdrehen 
   !SET                       'und t-bit setzen
L_0x0180:
   BLD r0,0                   't-bit ins Kontroll-register r0.0
   RCALL L_0x0196	      'Prüfen r16:r19
   BLD r1,0		      't-bit -> r1.0
   EOR r0,r1		      'Exklusiv Or der beiden +- Prüfungen
                              'Vorzeichen verschieden ---> Ergebnis muss negativ sein
   RET                        'e bien
'-----------------------------------------
' r20:r23 auf positiv
'-----------------------------------------
L_0x018A:
   RCALL L_0x01B0             'invertieren
   SUBI r20,0xFF              ' +1
   SBCI r21,0xFF
   SBCI r22,0xFF
   SBCI r23,0xFF
   RET
'-----------------------------------------
' Prüfen  r16:r19
'-----------------------------------------
L_0x0196:
   CLT                        'clear t-bit
   SBRS r19,7                 'sign bit set ?
   RET                        'no
'-----------------------------------------
' r16:r19 auf positiv
'-----------------------------------------
L_0x019C:
   COM r16                   'invertieren
   COM r17
   COM r18
   COM r19
   SUBI r16,0xFF             '+1
   SBCI r17,0xFF
   SBCI r18,0xFF
   SBCI r19,0xFF
   !SET                     't-bit setzen
   RET
'-----------------------------------------
'  invertieren r20:r23
'-----------------------------------------
L_0x01B0:
   COM r20
   COM r21
   COM r22
   COM r23
   RET

$end Asm

Return

Multiplizieren 32Bit (LONG)

Hier ist ein Unterschied, ob der µC über den MUL-Befehl verfügt.

Mit "MUL" (Atmega32)

	MOVW	r24,r16         'r16:r19 -> r24:r27
	MOVW	r26,r18

	MUL	r20,r24         'r20 * r24
	MOVW	r16,r0          '-> r16:r17

	MUL	r20,r26		'r20 * r26
	MOVW	r18,r0          '-> r18:r19

	MUL	r20,r27		'r20 * r27
	MOV	r2,r0		'--> r2

	MUL	r20,r25		'r20 * r25
	ADD	r17,r0		'r17:r18:r19 + r0:r1:r2
	ADC	r18,r1
	ADC	r19,r2

	MUL	r21,r26		'r21 * r26
	MOV	r2,r0
	MUL	r21,r24		'r21 * r26
	ADD	r17,r0		'r17:r18:r19 + r0:r1:r2
	ADC	r18,r1
	ADC	r19,r2

	MUL	r21,r25		'r21 * r26
	ADD	r18,r0		'r18:r19 + r0:r1
	ADC	r19,r1

	MUL	r22,r24		'r22 * r26
	ADD	r18,r0		'r18:r19 + r0:r1
	ADC	r19,r1

	MUL	r22,r25		'r22 * r26
	ADD	r19,r0		'r19 + r0

	MUL	r23,r24		'r23 * r26
	ADD	r19,r0		'r19 + r0

	RET

Ohne "MUL" (AT90S2313)

Hier wird "zu Fuß" multipliziert. Das Vorbereiten der Operanden ist wie beim Dividieren (Prüfung auf NULL entfällt natürlich), auch die Korrektur der Ergebnisses ist genauso (Ergebnis ist diesmal aber in R16:r19).

Ich beschränke mich daher auf das Listing der eigentlichen Multiplikation der beiden 32-Bit Zahlen R16:r19 * r20:r23 ---> r16:r19

'------------------------------------------
'
'------------------------------------------
	MOV	r24,r20      'r20:r23 ---> r24:r27
	MOV	r25,r21
	MOV	r26,r22
	MOV	r27,r23
	CLR	r20          'Löschen r20:r23
	CLR	r21
	CLR	r22
	CLR	r23
	LDI	ZH,0x21      'Zähler 31 (Überlauf nach 32 Bit wird nicht berücksichtigt)
	CLC
	RJMP	L_0x00B6     'Einstieg in die Schleife
'------------------------------------------
'  Schleife
'------------------------------------------
L_0x00A4:
	BRCC	L_0x00AE     
	ADD	r20,r24      ' Nur bei Carry wird addiert
	ADC	r21,r25
	ADC	r22,r26
	ADC	r23,r27
L_0x00AE:
	LSR	r23          'shift right r20:r23
	ROR	r22
	ROR	r21
	ROR	r20          ' Carry -> r16:r19

L_0x00B6:                    'Einsprungs-Stelle
	ROR	r19          'shift right r16:r19
	ROR	r18
	ROR	r17
	ROR	r16
	DEC	ZH           'Zähler
	BRNE	L_0x00A4     'Schleife <> 0
	RET                  'fertig

SERIN

SERIN (und SEROUT) stellen die allgemeinste Form der Software UART dar. Es kann zur Run-Time von einem Aufruf zum nächsten so ziemlich alles verändert werden: PIN, Polarität, Baudrate, Stopp-Bits, Databits (7 od.8 ) und Parity. Anders als bei der normalen SW-UART kann der gleiche Pin zum Senden und Empfangen werden, was für einige half-duplex Kommunikationsformen sehr praktisch ist. Es kann aber nur entweder empfangen oder gesendet werden, eine Bus-Arbitrierung ist also nicht möglich.

Diese Variationsmöglichkeiten haben ihren Preis. Insbesonders die Berechnung der Delay-Counter für die Baudrate, die bei jedem Aufruf neu geschieht, tut weh.

Aber wir wollen hier auch keine Urteile abgeben, sondern nur "sine ira et studio" die Dinge zeigen, wie sie sind. Zum daraus lernen (und ev. dann besser machen) reicht es immer.

  • Aufruf
$crystal = 8000000
Dim Mystring As String * 10
Dim Mybaud As Long

  Mybaud = 9600

  Serin Mystring , 0 , D , 0 , Mybaud , 0 , 8 , 1

Zur Bedeutung der Parameter bitte Bascom-Help verwenden. Nur soviel: es wird unterschieden, ob die Empfangs-variable ein String ist oder nicht. Wenn ja, läuft die Routine, bis ein <CR> empfangen wird, ansonsten muß eine Länge angegeben werden.


Zur Berechnung der Schleifenzähler werden die internen 32-Bit Funktionen verwendet, die hatten wir schon, also laß ich sie hier weg.

  • Code

Vorbereiten der Parameter

	LDI	XL,0x6B       'Adresse von "MyBaud"
	LDI	XH,0x00
	LD	r16,X+        ' Baudrate --> r16:r19
	LD	r17,X+
	LD	r18,X+
	LD	r19,X

	LDI	XL,0x6F       ' next free SRAM ("___SER_BAUD") (LONG)
	LDI	XH,0x00
	ST	X+,r16        ' speichern der Baudrate
	ST	X+,r17
	ST	X+,r18
	ST	X,r19

	CALL	L_0x0374	'calc counter nach "___SER_BAUD"
'---------------------------------------------------------------------------
'Bascom berechnet:  Counter =  (( $CRYSTAL / Baudrate ) + 42 ) / 8 
'Das ist ein Schleifenzähler für die Dauer eines halben Bits
'---------------------------------------------------------------------------
	LDI	r24,0x01	'1 stopp-bit
	ST	-Y,r24
	LDI	r24,0x00	'no parity
	ST	-Y,r24
	LDI	r24,0x08	'8 Bit
	ST	-Y,r24
	LDI	XL,0x60		'daten-empfangs adresse ("MyString")
	LDI	XH,0x00
	CLR	r24             '= 0
	ST	-Y,r24		
	LDI	ZL,0x31		' Adresse von  DDRD für PinD 
	LDI	r24,0x00        '
	CLT			' Polarität 
	CALL	L_0x02BE	' CALL der eigentlichen "SERIN" Funktion

Einige Hilfs-Funktionen

'-----------------------------------------
; Makemask  r24 Bit# -->  Mask ->r24  !Mask ->r25
'-----------------------------------------
L_0x01CC:
	LDI	r25,0x01
	AND	r24,r24
	BREQ	L_0x01DA
	CLC
L_0x01D4:
	ROL	r25
	DEC	r24
	BRNE	L_0x01D4
L_0x01DA:
	MOV	r24,r25
	COM	r25
	RET
'-----------------------------------------
' Odd-Even PARITY
'-----------------------------------------
L_0x01E0:
	PUSH	r16
	PUSH	r24
	LDI	r16,0x08
	CLR	r25
L_0x01E8:
	ROL	r24
	BRCC	L_0x01EE
	INC	r25
L_0x01EE:
	DEC	r16
	BRNE	L_0x01E8
	POP	r24
	POP	r16
	RET
'-----------------------------------------
' stringleng  ASCIZ   R24 =  strlen( @X )
'-----------------------------------------
L_0x0202:
	LDI	r24,0xFF
L_0x0204:
	INC	r24
	LD	r25,X+
	AND	r25,r25
	BRNE	L_0x0204
	RET

Die Funktion

'-----------------------------------------
'SERIN
'-----------------------------------------
L_0x02BE:
	RCALL	L_0x01CC	makemask
	CLR	ZH

	LDD	r0,Z + 0	DDRD
	AND	r0,r25		Make Input
	STD	Z + 0,r0	

	INC	ZL		PORTD

	LDD	r0,Z + 0
	AND	r0,r25
	STD	Z + 0,r0        Clear PORTD.x

	SBIW	ZL,0x0002       ->PIND

	MOV	r16,r24		Mask
	MOV	r22,r25		!Mask
	LD	r20,Y+          Byte count  
	MOV	r19,r20
L_0x02DA:
	LDD	r17,Y + 0	Bit (8)
	CPI	r17,0x07	7 Bit ?
	BRNE	L_0x02F2	
'---- 7 Bits
	LDD	r17,Y + 1	parity
	CPI	r17,0x00
	BRNE	L_0x02EC
	LDD	r18,Y + 2       stopp
	SUBI	r18,0xF9	no Parity
	RJMP	L_0x0302
L_0x02EC:
	LDD	r18,Y + 2	stopp
	SUBI	r18,0xF8	+ Parity
	RJMP	L_0x0302
'---- 8 Bits
L_0x02F2:
	LDD	r17,Y + 1	parity
	CPI	r17,0x00
	BRNE	L_0x02FE	-->yes
	LDD	r18,Y + 2	stopp
	SUBI	r18,0xF8	no parity
	RJMP	L_0x0302
L_0x02FE:
	LDD	r18,Y + 2	stopp
	SUBI	r18,0xF7	+ parity

L_0x0302:
	MOV	r21,r18
'----------------------------------------
' Byte Loop   R18 /R21 bits  X data pntr  Z PIN(d)  T-Bit revert  Y Parameter  r20 Len r19 String
'----------------------------------------
L_0x0304:
	LDD	r0,Z + 0	Rx Pin
	AND	r0,r16		mask
	BRTS	L_0x030E	T-Bit ?
	BREQ	L_0x0312	Low--> start
	RJMP	L_0x0304	continue wait loop
L_0x030E:   'reverted 
	BRNE	L_0x0312	high--> start
	RJMP	L_0x0304	continue wait loop
L_0x0312:
	RCALL	L_0x035E	1/2 Bit
L_0x0314:
	RCALL	L_0x035E	1/2 Bit			2 + 
	RCALL	L_0x035E	1/2 Bit			2 +
	CLC			clear carry		1
	LDD	r0,Z + 0	Rx Pin			2
	AND	r0,r16		Mask			1
	BREQ	L_0x0322	=0			1/2	
	SEC			set carry		1
L_0x0322:
	DEC	r18		count bits		1
	BREQ	L_0x032C				1/2
	ROR	r24		shift in carry r24:r25	1
	ROR	r25					1
	RJMP	L_0x0314	cont'd loop		2

L_0x032C:
	CPI	r21,0x0A	bit-size <> 10 	?
	BRLO	L_0x033A	<
	SUBI	r21,0x09	-9
L_0x0332:
	ROL	r25		adjust data ->right
	ROL	r24
	DEC	r21
	BRNE	L_0x0332	
L_0x033A:
	BRTC	L_0x033E
	COM	r24		revert data Byte
L_0x033E:
	LDD	r17,Y + 0
	CPI	r17,0x07
	BRNE	L_0x0346
	ANDI	r24,0x7F	clear 2^^7
L_0x0346:
	ST	X+,r24		store data
	CPI	r19,0x00	string ?
	BRNE	L_0x0358	no
	CPI	r24,0x0D	yes = <CR>
	BRNE	L_0x02DA	no, continue
	CLR	r24		yes, make ASCIZ & exit
	ST	X,r24		0x00
L_0x0354:
	ADIW	YL,0x0003	restore Y
	RET			exit
L_0x0358:
	DEC	r20		count 
	BREQ	L_0x0354	all done
	RJMP	L_0x02DA	continue

'-------------------------------------------
' 1/2 Bit Delay
'-------------------------------------------
L_0x035E:
	PUSH	r24		2
	PUSH	r25		2
	LDS	r24,0x006F	2
	LDS	r25,0x0070	2
L_0x036A:
	SBIW	r24,0x0001	1
	BRNE	L_0x036A	1/2
	POP	r25		2
	POP	r24		2
	RET			4

Autor

Benutzer:PicNick

Siehe auch


LiFePO4 Speicher Test