Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Laderegler Test Tueftler Seite

K (PIC16(F/LF)XXX)
K (Hex Dec Wandlung)
Zeile 679: Zeile 679:
 
== Hex Dec Wandlung ==
 
== Hex Dec Wandlung ==
  
Weil das UP mit PAD erstellt wurde, ist es fast nicht kommentiert. Genaue Funktionsweise ist im http://www.rn-wissen.de/index.php/PIC_Assembler#Hex_Dec_Wandlung erklärt.
+
Weil das UP mit PAD erstellt wurde, ist es fast nicht kommentiert. Genaue Funktionsweise und Register sind im http://www.rn-wissen.de/index.php/PIC_Assembler#Hex_Dec_Wandlung erklärt.
  
 
  Hex_Dec call CClr ; Hex>A, D>Dec
 
  Hex_Dec call CClr ; Hex>A, D>Dec

Version vom 28. Juli 2010, 19:57 Uhr

PIC16(F/LF)XXX

Einige ASM Beispiele für PC12... und PIC16... befinden sich in http://www.rn-wissen.de/index.php/PIC_Assembler#Codeschnipsel .

UART Routine

Senden:

RS232send
	banksel  	TXREG			; Zur Bank von TXREG umschalten
	movwf	        TXREG			; Move w to TXREG 
	banksel	        PIR1			; Zur Bank von PIR1 umschalten
Waittx	
	btfss		PIR1, TXIF		; Wenn bit in PIR1,TXIF HIGH übergehe den nästen Befehl
	goto		Waittx			; Gehe zu WaitTX
	bcf		PIR1, TXIF 		; Interrupt Flag Löschen (Optionam muss nicht umbedinkt gemacht werden)
	return

Fehlerbehandlung:

uart_ferr				; Auf Frameerror testen
	btfsc	RCSTA, FERR
	goto	uart_err
	return
uart_oerr				; Auf Overrunerror testen
	btfsc	RCSTA, OERR
	goto	uart_err
	return
uart_err				; Fehlerbehandlung
	; Fehlerbehanlungsroutine hier einfügen!!!!!!!!!!!!!!!!!
        ; z.b. Interupt beenden und RCREG nicht sichern
	bcf	RCSTA, CREN		; Fehler Bits Löschen
	bsf	RCSTA, CREN
	return				; Interupt beenden und zurück zur Main schleife

Entfangen per Interupt:

int	; Interupt STATUS und W sichern
	movwf	wtemp			; W Sichern
	swapf	STATUS, w		; Status Sichern
	movwf	stemp			; Status Speichern
	btfss	PIR1, RCIF		; Interupt vom USART wenn nicht
	goto	intend			; Interupt beenden
	; Interupt Code uart
	call	uart_ferr		; Auf Frame Errors Testen <b>(siehe Fehlerbehandlung) </b>
	call	uart_oerr		; Auf Overrunerrors Testen
	movf	RCREG,w			; uart RX Reg sichern
	movwf	rx
intend  ; Interupt beenden und STATUS + W zurückspielen
	bcf	PIR1, RCIF		; Interuptflag Löschen
	swapf	stemp, w		; Status restore
	movwf	STATUS
	swapf	wtemp, f		; W restore
	swapf	wtemp, w
	retfie				; Interupt Beenden

DG-16080 Text-Mode

Senden:

	movlw	0x00
	movwf	adrl			; LOW ADR
	movlw	0x00
	movwf	adrh			; High ADR
	call	disp_send_char		; Adressregister setzen und vorbereiten zum Daten schreiben
	movlw	B'01001000'		; H
	call	disp_send_d
	movlw	B'01100001'		; a
	call	disp_send_d
	movlw	B'01110101'		; u
	call	disp_send_d

Display Anschlüsse:

	#define RS	PORTC, 0	; Display Command(H)/DATA(L)
	#define RW	PORTC, 2	; Display Read(H)/Write(L)
	#define E	PORTC, 3	; Display Enable
	#define	CS	PORTC, 4	; Display Chip Enable(L)
	#define	WDATA	PORTB		; Display Datenport (PORTB)
	#define YM	PORTA, 3	; Touch y- ADC
	#define YP	PORTA, 2	; Touch y+ PWR
	#define XP	PORTA, 4	; Touch x+ PWR
	#define XM	PORTA, 1	; Touch x- ADC

dg-16080.inc

disp_init				; Display Inialisieren
	bcf	RW			; Startbedinungen herstellen
	nop
	bcf 	CS
	movlw	0x00			; Mode Control REG
	call	disp_send_c		; Send Command
	movlw	b'00111000'		; DB5=ON/OFF, DB4=Master/Slave, DB3=Blink, DB2=Coursor, DB1/DB0=TEXT(00)/GRAFIG(10)
	call	disp_send_d		; Send Data
	movlw	0x01			; Character Pitch REG
	call	disp_send_c		; Send Command
	movlw	0x75			; 7x8px
	call	disp_send_d		; Send Data
	movlw	0x02			; Nummer oh Char REG
	call	disp_send_c		; Send Command
	movlw	D'26'			; Anzahl horit. Zeichen -1
	call	disp_send_d		; Send Data
	movlw	0x03			; Display Duty REG
	call	disp_send_c		; Send Command
	movlw	0x4F			; Display Duty
	call	disp_send_d		; Send Data
	movlw	0x04			; Cursor Position REG
	call	disp_send_c		; Send Command
	movlw	D'7'			; Curserstrich y-Pos -1
	call	disp_send_d		; Send Data
	return
disp_send_c				; Send Command
	bsf	RS
	movwf	WDATA
	bsf	E
	nop
	bcf	E
	call	delay_10_µs
	return
disp_send_d				; Send DATA
	bcf	RS
	movwf	WDATA
	bsf	E
	nop
	bcf	E
	call	delay_10_µs
	return
disp_cls				; Display Löschen Textmode
	movlw	0x0A			; Low Reg
	call	disp_send_c
	movlw	0x00			; Low Adr
	call	disp_send_d
	movlw	0x0B 			; High Reg
	call	disp_send_c
	movlw	0x00			; High Adr
	call	disp_send_d 
	movlw	0x0C			; DATA REG
	call	disp_send_c
	movlw	D'65'
	movwf	count
disp_cls_loop
	movlw	B'00100000'		; 65x5
	call	disp_send_d
	call	disp_send_d
	call	disp_send_d
	call	disp_send_d
	call	disp_send_d
	decfsz	count,1
	goto	disp_cls_loop
	return
disp_send_char				; Zeichen senden (ADRL,ADRH,Char)
	movlw	0x0A			; Low Reg
	call	disp_send_c
	movf	adrl,w			; Low Adr
	call	disp_send_d
	movlw	0x0B 			; High Reg
	call	disp_send_c
	movf	adrh,w			; High Adr
	call	disp_send_d 
	movlw	0x0C			; DATA REG
	call	disp_send_c
	return

Touchscreen: Config für die ADCs VREF=VDD

	banksel	TRISA			; Zu Bank von TRISA umschalten
	movlw	B'00001011'		; PortA I/O setzen (1=In, 0=Out) (Reinfolge RB7,RB6...)
	movwf	TRISA			; PortA I/O setzen
	banksel	ADCON1			; Zur Bank von ADCON1 umschalten
	movlw	B'10010100'		; Alle Analog VDD=VREF, Right jutyfy, fosc/8, AN0,1,3=AN, AN2,4-7=Dig.
	movwf	ADCON1			; Move w to ADCON1
	banksel	ADCON0			; zu Bank von TRISA umschalten
	movlw	B'01000001'		; Enable ADC
	movwf	ADCON0			; Move w to ADCON0
touch_read
	; Y
	bcf	YP
	bsf	XP
	bcf	ADCON0,5			; ADC Auswehlen
	bcf	ADCON0,4
	bsf	ADCON0,3
	call	adc_read			; Read ADC AD1 Daten
	banksel	ADRESL
	movf	ADRESL,w
	movwf	ylow
	banksel	ADRESH
	movf	ADRESH,w
	movwf	yhigh
	bcf	YP
	bcf	XP
	; X
	bcf	XP
	bsf	YP
	bcf	ADCON0,5			; ADC Auswehlen
	bsf	ADCON0,4
	bsf	ADCON0,3
	call	adc_read			; Read ADC AD3 Daten
	banksel	ADRESL
	movf	ADRESL,w
	movwf	xlow
	banksel	ADRESH
	movf	ADRESH,w
	movwf	xhigh
	bcf	YP
	bcf	XP
	return
adc_read
	movlw	D'30'			; Wait Acquisition Time 20MHz
	movwf	count
adc_read_loop
	decfsz	count,F
	goto	adc_read_loop
	bsf	ADCON0,GO		; Setze ADCON0,GO, Int A/D Conversation
adc_read_loop_1				; Wen ADC bereit 
	btfsc	ADCON0,GO		; Ist ADCON0,GO = 0 dann ubergehe den nesten Befehl
	goto	adc_read_loop_1		; Warte bis ADC fertig
	return

--Theborg 12:00, 23. Jan 2010 (CET)

Schieberegister (z.b. CD4094)

	; Datenleitungen Schiberegister alles Ausgänge
	#define		CLK		PORTB, 0
	#define		D	 	PORTB, 1
	#define		STR		PORTB, 2
	#define		OE		PORTB, 3
 cd4094_send
	banksel	PORTB
        bcf             OE
	bcf		STR
	btfsc	cdsend, 0
	bsf		D
	btfss		cdsend, 0
	bcf		D
	bsf		CLK
	bcf		CLK
	btfsc	cdsend, 1
	bsf		D
	btfss		cdsend, 1
	bcf		D
	bsf		CLK
	bcf		CLK
	btfsc	cdsend, 2
	bsf		D
	btfss		cdsend, 2
	bcf		D
	bsf		CLK
	bcf		CLK
	btfsc	cdsend, 3
	bsf		D
	btfss		cdsend, 3
	bcf		D
	bsf		CLK
	bcf		CLK
	btfsc	cdsend, 4
	bsf		D
	btfss		cdsend, 4
	bcf		D
	bsf		CLK
	bcf		CLK
	btfsc	cdsend, 5
	bsf		D
	btfss		cdsend, 5
	bcf		D
	bsf		CLK
	bcf		CLK
	btfsc	cdsend, 6
	bsf		D
	btfss		cdsend, 6
	bcf		D
	bsf		CLK
	bcf		CLK
	btfsc	cdsend, 7
	bsf		D
	btfss		cdsend, 7
	bcf		D
	bsf		CLK
	bcf		CLK
	bsf		STR
        bsf             OE
	return

--Theborg 23:13, 15. Sep 2009 (CEST)

MAX7456 (S/W OSD)

Variabeln und I/0:

	cblock	0x70		; Variabeln ab 0x70 setzen alle Register max 16stk.
	SPI_DATA_WRITE		; Zu Sendene SPI Daten
	SPI_DATA_READ		; Gelesend SPI Daten
	m_char			; Maxim7456 und sda5708 Zeichen
	m_pos			; Maxim7456 Position
	endc 			; Variabeln setzen beenden

	#define	SPI_CS	PORTC, 7; SPI Slave Select max7456

Config:

	; PORTC
	banksel	TRISC			; auf Bank 1 umschalten
	movlw	B'10010000'		; PortC I/O setzen (1=In, 0=Out) (Reinfolge RC7,RC6...)
	movwf	TRISC			; PortC I/O setzen
	banksel	PORTC
	clrf	PORTC			; PortC auf 0 setzen
	; SPI
	banksel	SSPSTAT
	movlw	B'11000000'		; Mitlere Geschwindigkeit Output Time 
	movwf	SSPSTAT
	banksel	SSPCON
	movlw	B'00100001'		; MODE 1,1, SPI MASTER, 1/16 Tosc SSP ON
	movwf	SSPCON
	banksel	PORTC
	bsf	SPI_CS			; SPI Slave Select aus (high)
	return

SPI Sende/Enfangs Rotinen:

SPI_Send
	banksel	PORTC
	bcf		SPI_CS			; Chip Select an (Low)
	nop
	nop
	nop
	banksel	SSPBUF
	movf	SPI_DATA_WRITE, W
	movwf	SSPBUF
	banksel	SSPSTAT
SPI_Wait
	btfss	SSPSTAT, BF		; Ist das Senden Komplet ?
	goto	SPI_Wait			; Wen nicht gehe zu SPIWait
	nop
	nop
	nop
	banksel	PORTC
	bsf 		SPI_CS			; Chip Select aus (High)
	return 
SPI_Read
	banksel	PORTC
	bcf		SPI_CS
	nop
	nop
	nop
	banksel	SSPBUF
	movf	SSPBUF, W
	movwf	SPI_DATA_READ
	banksel	PORTC
	nop
	nop
	nop
	banksel	PORTC
	bsf		SPI_CS
	return

Defines ASCII to MAX7456 Charset und Config und Schreibrotienen (Achtung es kann sein das die #define nicht mit mpasm Funktioniert mit gpasm wird groß und kleinschreibung unterschiden):

max7456_define				; Defines für den max7456 Zeichensatz
	#define	m_sp	0x00		; Space
	#define	m_1		0x01
	#define	m_2		0x02
	#define	m_3		0x03
	#define	m_4		0x04
	#define	m_5		0x05
	#define	m_6		0x06
	#define	m_7		0x07
	#define	m_8		0x08
	#define	m_9		0x09
	#define	m_0		0x0A
	#define	m_A		0x0B
	#define	m_B		0x0C
	#define	m_C		0x0D
	#define	m_D		0x0E
	#define	m_E		0x0F
	#define	m_F		0x10
	#define	m_G		0x11
	#define	m_H		0x12
	#define	m_I		0x13
	#define	m_J		0x14
	#define	m_K		0x15
	#define	m_L		0x16
	#define	m_M	0x17
	#define	m_N		0x18
	#define	m_O		0x19
	#define	m_P		0x1A
	#define	m_Q		0x1B
	#define	m_R		0x1C
	#define	m_S		0x1D
	#define	m_T		0x1E
	#define	m_U		0x1F
	#define	m_V		0x20
	#define	m_W	0x21
	#define	m_X		0x22
	#define	m_Y		0x23
	#define	m_Z		0x24
	#define	m_a		0x25
	#define	m_b		0x26
	#define	m_c		0x27
	#define	m_d		0x28
	#define	m_e		0x29
	#define	m_f		0x2A
	#define	m_g		0x2B
	#define	m_h		0x2C
	#define	m_i		0x2D
	#define	m_j		0x2E
	#define	m_k		0x2F
	#define	m_l		0x30
	#define	m_m		0x31
	#define	m_n		0x32
	#define	m_o		0x33
	#define	m_p		0x34
	#define	m_q		0x35
	#define	m_r		0x36
	#define	m_s		0x37
	#define	m_t		0x38
	#define	m_u		0x39
	#define	m_v		0x3A
	#define	m_w		0x3B
	#define	m_x		0x3C
	#define	m_y		0x3D
	#define	m_z		0x3E
	#define	m_KLa	0x3F	; (
	#define	m_KLz	0x40		; )
	#define	m_.		0x41
	#define	m_?		0x42
	#define	m_sem	0x43		; ;
	#define	m_:		0x44
	#define	m_ko	0x45		; ,
	#define	m_ag	0x46		; Agostroff
	#define	m_bs	0x47		; Backslasch
	#define	m_as	0x48		; Anfürungsstriche
	#define	m_minus  0x49		; Minus
	#define	m_ka	0x4A		; <
	#define	m_ga	0x4B	; >
	#define	m_at	0x4C	; @ oder at
	#define	m_wait	0xfb		; Wartezeichen
	#define	m_ls		0xf9		; Lautsprecher
	#define	m_lso	0xfa		; Tonsignal
	#define	m_ff		0xff		; Ausgefültes feld
	return

max7456_conf					; Max7456 Config
	movlw	0x00				; VM0 Video Mode Register 0 (Write)
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movlw	B'01001000'		; 0 , 1=PAL, 00=Auto Sync, 1=Enable OSD, 0=Enable OSD immer, 0=SW RST, 0=Enable Video Buffer
	movwf	SPI_DATA_WRITE	
	call		SPI_Send	
	movlw	0x01				; VM1 Video Mode Register 1
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movlw	B'00000100'		; 0 = NA, 000=Background MODE Brightness 100%, 11=Blinking Time 160ms, 00=Blinking Duty Cycle BT:BT
	movwf	SPI_DATA_WRITE
	call		SPI_Send	
	movlw	0x02				; HOS Horizontal Offset Register
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movlw	B'00101111'		; 00 = NA, 100000 = Horitzontal Offset
	movwf	SPI_DATA_WRITE
	call		SPI_Send	
	movlw	0x03				; VOS Vertical Offset Register
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movlw	B'00010111'		; 000 = NA, 10000 = Vertical Offset
	movwf	SPI_DATA_WRITE
	call		SPI_Send	
	return

max7456_cls					; max7456 ausgabe Löschen
	movlw	0x00				; VM0 Video Mode Register 0 (Write)
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movlw	B'01001010'		; 0 , 1=PAL, 00=Auto Sync, 1=Enable OSD, 0=Enable OSD immer, 1=SW RST, 0=Enable Video Buffer
	movwf	SPI_DATA_WRITE	
	call		SPI_Send	
	call		max7456_conf
	return

max7456_add_high				; High adressbereich
	movlw	0x05				; Ersten 256 zeichen Low = 0x00, Letzten 256 Zeichen High=0xff 
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movlw	0xFF
	movwf	SPI_DATA_WRITE	
	call		SPI_Send	
	return

max7456_add_low				; Low Adressbereich
	movlw	0x05				; Ersten 256 zeichen Low = 000, Letzten 256 Zeichen High=225 
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movlw	0x00
	movwf	SPI_DATA_WRITE	
	call		SPI_Send	
	return

max7456_send_char
	movlw	0x06				; Zeichen Position links nach rechts erste reihe 0-29, 30-......
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movf	m_pos, W
	movwf	SPI_DATA_WRITE	
	call		SPI_Send	
	movlw	0x07				; Zeichen Sonderzeichen sihe Define in max7456.inc
	movwf	SPI_DATA_WRITE	
	call		SPI_Send
	movf	m_char, W
	movwf	SPI_DATA_WRITE	
	call		SPI_Send	
	return

Zeichen Senden:

	movlw	D'12'			; Position
	movwf	m_pos
	movlw	m_e			; Zeichen (hier das kleine e) oder direkt den wert des Zeichens im MAX7456 REG.
	movwf	m_char
	call	max7456_send_char; Schreiben

High/low Adressbereich (low = ersten 256 Zeichen, High die letzten 128 Zeichen);

	call		max7456_add_low	; Low Adressbereich
	;call		max7456_add_high; Low Adressbereich

--Theborg 23:13, 15. Sep 2009 (CEST)

PIC18(F/LF)xxxx

Programmspeicher (Flash) beschreiben und lesen

Weil das Programteil wurde mit PAD erstellt ist fast nicht kommentiert. Zuerst wird der benötigter Bereich gelöscht und danach werden dort Daten aus RAM gespeichert. Dazu wurden zwei Register "Tmp" und "Tmp1" benutzt, die im Program definiert werden müssen.

Store		movff	F2,FS2
		movff	F1,FS1
		movff	F0,FS0
		clrf	TBLPTRU			; erase flash memory (7BC0-7FFF)
		movlw	0x7B
		movwf	TBLPTRH
		movlw	0xC0
		movwf	TBLPTRL
		movlw	0x11
		movwf	Tmp
FlashEraseL	bsf	EECON1,EEPGD
		bcf	EECON1,CFGS
		bsf	EECON1,WREN
		bsf	EECON1,FREE
		bcf	INTCON,GIE
		movlw	0x55
		movwf	EECON2
		movlw	0xAA
		movwf	EECON2
		bsf	EECON1,WR
		bsf	INTCON,GIE
		btfsc	EECON1,WR
		bra	$-2
		movlw	0x40
		addwf	TBLPTRL
		btfsc	_C
		incf	TBLPTRH,1
		decfsz	Tmp,1
		bra	FlashEraseL
		lfsr	FSR0,0x0020		; write parameter 32 bytes (7BC0-7BDF)
		clrf	TBLPTRU
		movlw	0x7B
		movwf	TBLPTRH
		movlw	0xC0
		movwf	TBLPTRL
		tblrd*-
		movlw	4
		movwf	Tmp1
FlashProgPL	movlw	8
		movwf	Tmp
WriteFPL	movff	POSTINC0,TABLAT
		tblwt+*
		decfsz	Tmp,1
		bra	WriteFPL
		bsf	EECON1,EEPGD
		bcf	EECON1,CFGS
		bsf	EECON1,WREN
		bcf	INTCON,GIE
		movlw	0x55
		movwf	EECON2
		movlw	0xAA
		movwf	EECON2
		bsf	EECON1,WR
		bcf	PIR2,EEIF
		bsf	INTCON,GIE
		decfsz	Tmp1,1
		bra	FlashProgPL
		bcf	EECON1,WREN
WriteSMP	lfsr	FSR0,0x100		; write samples 1024 bytes (7C00-7FFF)
		clrf	TBLPTRU
		movlw	0x7C
		movwf	TBLPTRH
		clrf	TBLPTRL
		tblrd*-
		movlw	0x80
		movwf	Tmp1
FlashProgL	movlw	8
		movwf	Tmp
WriteFL		movff	POSTINC0,TABLAT
 		tblwt+*
		decfsz	Tmp,1
		bra	WriteFL
		bsf	EECON1,EEPGD
		bcf	EECON1,CFGS
		bsf	EECON1,WREN
		bcf	INTCON,GIE
		movlw	0x55
		movwf	EECON2
		movlw	0xAA
		movwf	EECON2
		bsf	EECON1,WR
		bcf	PIR2,EEIF
		bsf	INTCON,GIE
		decfsz	Tmp1,1
		bra	FlashProgL
		bcf	EECON1,WREN
		return

Um die Daten aus Flash zurück auf ursprüngliche Adressen im RAM zu übertragen, würde folgendes Programmfragment verwendet in dem Register "STmp" benutzt wurde, der auch im Programm definiert werden muss.

Restore		lfsr	FSR0,0x0020		; restore parameter 32 bytes (7BC0-7BDF)
		clrf	TBLPTRU
		movlw	0x7B
		movwf	TBLPTRH
		movlw	0xC0
		movwf	TBLPTRL
		bsf	EECON1,EEPGD
		bcf	EECON1,CFGS
FlashRAMP	movlw	0x20
		movwf	STmp
FlashRAMPL	tblrd*+
		movff	TABLAT,POSTINC0
		decfsz	STmp,1
		bra	FlashRAMPL
		lfsr	FSR0,0x100		; restore samples 1024 bytes (7C00-7FFF)	
		clrf	TBLPTRU
		movlw	0x7C
		movwf	TBLPTRH
		clrf	TBLPTRL
		bsf	EECON1,EEPGD
		bcf	EECON1,CFGS
		call	FlashRAM
		call	FlashRAM
		call	FlashRAM
FlashRAM	clrf	STmp
FlashRAML	tblrd*+
		movff	TABLAT,POSTINC0
		decfsz	STmp,1
		bra	FlashRAML
		return

Hex Dec Wandlung

Weil das UP mit PAD erstellt wurde, ist es fast nicht kommentiert. Genaue Funktionsweise und Register sind im http://www.rn-wissen.de/index.php/PIC_Assembler#Hex_Dec_Wandlung erklärt.

Hex_Dec		call	CClr			; Hex>A, D>Dec
		call	DClr
		movlw	1
		movwf	C0
		movlw	0x18			; 24 bit Hex (6digits) > 32 bit Dec (8 digits)
		movwf	HTmp
Hex_DecL	btfsc	A0,0
		call	AddDC
		call	CopyCB
		call	AddCB
		call	ARotRb
		decfsz	HTmp,1
		bra	Hex_DecL
		return
AClr		lfsr	FSR0,A4	
		movlw	5
		bra	RegClr
BClr		lfsr	FSR0,B4
		movlw	5
		bra	RegClr
CClr		lfsr	FSR0,C4
		movlw	5
		bra	RegClr
DClr		lfsr	FSR0,D4
		movlw	5
RegClr		movwf	ATmp
RegClrL		clrf	POSTINC0
		decfsz	ATmp,1
		bra	RegClrL
		return
CopyCB		lfsr	FSR0,C0
		lfsr	FSR1,B0
		bra	CopyReg
CopyCD		lfsr	FSR0,C0
		lfsr	FSR1,D0
		bra	CopyReg
CopyDC		lfsr	FSR0,D0
		lfsr	FSR1,C0
CopyReg		movlw	5
		movwf	ATmp
CopyRegL	movff	POSTDEC0,POSTDEC1
		decfsz	ATmp,1
		bra	CopyRegL		
		return
AddCA		lfsr	FSR0,A0			; C+A>C
		lfsr	FSR1,C0
		bra	AddReg
AddCB		lfsr	FSR0,B0			; C+B>C
		lfsr	FSR1,C0
		bra	AddReg
AddDC		lfsr	FSR0,C0			; D+C>D
		lfsr	FSR1,D0
AddReg		bcf	_Ferr
		bcf	_Fcrp
		movlw	5
		movwf	ATmp
AddRegL		bcf	_Fcra
		movf	INDF0,0
		addwf	INDF1,0
		btfsc	_C
		bsf	_Fcra
		daw
		movwf	INDF1
		btfsc	_C
		bsf	_Fcra
		btfss	_Fcrp
		bra	AddRegN
		movlw	1
		addwf	INDF1,0
		daw
		movwf	INDF1
		btfsc	_C
		bsf	_Fcra
AddRegN		bcf	_Fcrp
		btfsc	_Fcra
		bsf	_Fcrp
		movf	POSTDEC0,1
		movf	POSTDEC1,1
		decfsz	ATmp,1
		bra	AddRegL
		btfsc	_Fcra
		bsf	_Ferr
		return
ARotRb		lfsr	FSR0,A2	
RRotRb		movlw	3			; rotates A register 1 bit right
		movwf	RTmp
		bcf	_Fcrp
		btfsc	A0,0
		bsf	_Fcrp
RRotRbL		bcf	_Fcra
		btfsc	INDF0,0
		bsf	_Fcra
		bcf	_C
		btfsc	_Fcrp
		bsf	_C
		rrcf	INDF0,1
		bcf	_Fcrp
		btfsc	_Fcra
		bsf	_Fcrp
		movf	POSTINC0,1
		decfsz	RTmp,1
		bra	RRotRbL
		return

LiFePO4 Speicher Test