[ASSEMBLY] Como calcular raiz quadrada PIC

Nesse post coloco algumas formas de calcular raiz quadrada com o PIC na linguagem assembler, encontradas na internet, muito útil ao se calcular , por exemplo, a tensão RMS de uma leitura.

Os autores foram mencionados, acima de suas rotinas.

;****************************************************************
;* RAIZ QUADRADA *
;****************************************************************
;*******************************************************************
;* CONFIGURATION BITS && INCLUDES *
;*******************************************************************

IFDEF __18F4320 ;

#INCLUDE

__CONFIG _CONFIG1H, _IESO_OFF_1H & _FSCM_OFF_1H & _HSPLL_OSC_1H

__CONFIG _CONFIG2L, _BOR_OFF_2L & _PWRT_OFF_2L

__CONFIG _CONFIG2H, _WDT_OFF_2H

__CONFIG _CONFIG3H, _CCP2MX_ON_3H & _MCLRE_ON_3H & _PBAD_DIG_3H

__CONFIG _CONFIG4L, _STVR_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L

__CONFIG _CONFIG5L, _CP0_ON_5L & _CP1_ON_5L & _CP2_ON_5L & _CP3_ON_5L

__CONFIG _CONFIG5H, _CPB_ON_5H & _CPD_OFF_5H

__CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_ON_6L & _WRT3_ON_6L

__CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H

__CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L &_EBTR2_OFF_7L & _EBTR3_OFF_7L

__CONFIG _CONFIG7H, _EBTRB_OFF_7H

ENDIF

;********************************************************
;* Variaveis *
;********************************************************

CBLOCK 0x100

; Do próprio arquivo
ValorL,ValorH
RaizQuadrada

AARGB0,AARGB1
BARGB0,BARGB1
REMB0,REMB1
POINTY
XISPORDH,XISPORDL
XISH,XISL
LOOP_COUNT
LOOPCOUNT

W_TEMP
STATUS_TEMP ;INTERRUPÇÕES
PCLATH_TEMP
FSR_TEMP

AARGC0,AARGC1
BARGC0,BARGC1
REMC0,REMC1,REMC2,REMC3
LOOP_CT

dicMax
dicMin
dicValL,dicValH
dicRes
ENDC

;********************************************************
;* Variáveis *
;********************************************************
VALOR_INICIAL EQU .65300

;*******************************************************************
;* VETOR DE RESET *
;*******************************************************************

ORG 0x00 ;ENDEREÇO INICIAL DE PROCESSAMENTO

MOVLB .1 ; SETA bloco padrão de RAM
GOTO INICIO

;****************************************************************
;* Tabelas da Raiz Quadrada *
;****************************************************************

RAIZ1a EQU .0 ; De 0x0000 ate 0x3FFF
RAIZ2a EQU .128 ; De 0x4000 ate 0x7FFF
RAIZ3a EQU .181 ; De 0x8000 ate 0xBFFF
RAIZ4a EQU .221 ; De 0xC000 ate 0xFFFF

tabAproxRaiz:

ADDWF PCL,F

RETLW RAIZ1a
RETLW RAIZ2a
RETLW RAIZ3a
RETLW RAIZ4a

tabRaizL:

ADDWF PCL,F

RETLW low( RAIZ1a * RAIZ1a )
RETLW low( RAIZ2a * RAIZ2a )
RETLW low( RAIZ3a * RAIZ3a )
RETLW low( RAIZ4a * RAIZ4a )

tabRaizH:

ADDWF PCL,F

RETLW high( RAIZ1a * RAIZ1a )
RETLW high( RAIZ2a * RAIZ2a )
RETLW high( RAIZ3a * RAIZ3a )
RETLW high( RAIZ4a * RAIZ4a )

INICIO:

;Teste do Método Padrão

MOVLW low(VALOR_INICIAL)
MOVWF AARGC1
MOVLW high(VALOR_INICIAL)
MOVWF AARGC0
CALL RAIZ_PADRAO

; Resultado em BARGC1

;Teste do Método Hiper-Newton
MOVLW low(VALOR_INICIAL)
MOVWF XISH
MOVLW high(VALOR_INICIAL)
MOVWF XISL
CALL HIPER
CALL NEWTON

;OBS: Pode ser dividido em 2 chamadas
;Resultado em XISPORDL
;Teste do Metodo Aproximação por produtos notáveis

MOVLW low(VALOR_INICIAL)
MOVWF AARGB1
MOVLW high(VALOR_INICIAL)
MOVWF AARGB0
CALL RaizQuadradaAPN

;Resultado em WREG

;Teste do Metodo de Dicotomia

MOVLW low(VALOR_INICIAL)
MOVWF dicValL
MOVLW high(VALOR_INICIAL)
MOVWF dicValH
CALL Dicotomia

;Resultado em WREG

GOTO INICIO

;********************************************************************
;* Raiz Quadrada Método Padrão *
;* Autor: Aluno da ETE Jorge Street *
;********************************************************************
;* Extrai a Raiz utilizando o algoritmo aprendido Ginásio *
;********************************************************************

;********************************************************************
;* RAIZ: EXTRAI A RAIZ QUADRADA DE UM NUMERO DE 16 BITS *
;* ENTRA: AARGC0;AARGC1 *
;* SAI: BARGC1 *
;* TAMANHO: BYTES *
;********************************************************************

; AARGC0,AARGC1
; BARGC0,BARGC1
; REMC0,REMC1,REMC2,REMC3
; LOOP_CT

RAIZ_PADRAO:
CLRF BARGC0
CLRF BARGC1
CLRF REMC0
CLRF REMC1

MOVLW .8
MOVWF LOOP_CT

RAIZ2:
BCF STATUS,C
RLCF BARGC1,F
RLCF BARGC0,F

RLCF REMC1,F
RLCF REMC0,F
RLCF REMC1,F
RLCF REMC0,F

SWAPF AARGC0,W
MOVWF REMC3
RRCF REMC3,F
RRCF REMC3,W
ANDLW 0X03

ADDWF REMC1,F
BTFSC STATUS,C
INCF REMC0,F
RLCF AARGC1,F
RLCF AARGC0,F
RLCF AARGC1,F
RLCF AARGC0,F

INCF BARGC1,F

MOVF BARGC1,W
SUBWF REMC1,W
MOVWF REMC3
MOVF BARGC0,W
SUBWFB REMC0,W
MOVWF REMC2

BC RAIZ3
DECF BARGC1,F
BRA RAIZ1

RAIZ3:
MOVFF REMC3,REMC1
MOVFF REMC2,REMC0
INCF BARGC1,F

RAIZ1:
DECFSZ LOOP_CT,F
BRA RAIZ2

BCF STATUS,C
RRCF BARGC0,F
RRCF BARGC1,F

RETURN

;********************************************************************
;* Raiz Quadrada Método Hiper-Newton *
;* Autor: Renato Loureiro *
;********************************************************************
;* Faz uma aproximação do Resultado da Raiz Quadrada *
;* utilizando uma aproximação hiperbólica e uma iteração do *
;* processo de Newton-Rhapson *
;********************************************************************

;*******************************************************************
;* RAIZ: EXTRAI A RAIZ QUADRADA DE UM NUMERO DE 16 BITS *
;* ENTRADA: XISH:XISL *
;* SAÍDA: XISPORDH:XISPORDL *
;* CHAMA: IDIV1616 *
;*******************************************************************

;*******************************************************************
; AJUSTE HIPERBÓLICO
;*******************************************************************

HIPER:
MOVLW .31
MOVWF POINTY
MOVFF XISL,XISPORDH
MOVFF XISH,XISPORDL ;E VAI DIVIDIR X/D
HIPER_1:
MOVLW .4
SUBWF POINTY,F ;PONTEIRO DA TABELA
BNC HIPER_4 ;CHEGOU NO ULTIMO BIT DOS 3 BYTES?
BTFSC XISPORDL,7
BRA HIPER_4
BTFSC XISPORDL,6
BRA HIPER_4
;E QUE O VALOR JÁ E MENOR QUE 256
RLCF XISPORDH,F ;SE NÃO VAI ROTACIONANDO
RLCF XISPORDL,F ;ATE ENCONTRAR UM "1"
BRA HIPER_1
HIPER_4:
CLRF XISPORDH
MOVLW .215 ;SOMA C = 215
ADDWF XISPORDL,F
BTFSC STATUS,C,A
INCF XISPORDH,F

MOVLW high(TAB_HIPER)
MOVWF TBLPTRH,A
MOVLW low(TAB_HIPER)
MOVWF TBLPTRL,A
INCF POINTY,W
ADDWF TBLPTRL,F,A
CLRF WREG,A
ADDWFC TBLPTRH,F,A

TBLRD*+
MOVFF TABLAT,AARGB1
TBLRD*+
MOVFF TABLAT,AARGB0

MOVFF XISPORDL,BARGB1
MOVFF XISPORDH,BARGB0 ;NO DIVISOR ESTA "C + X/D"

CALL IDIV1616 ;FAZ B/(C + X/D)

BTFSS REMB0,7 ;ARREDONDA SE NECESSÁRIO
BRA HIPER_6
INCFSZ AARGB1,F
BRA HIPER_6
INCF AARGB0,F
HIPER_6:
TBLRD*+
MOVFF TABLAT,XISPORDL
TBLRD*
MOVFF TABLAT,XISPORDH ;PEGA O VALOR DA TABELA DE "A"

MOVF AARGB1,W
SUBWF XISPORDL,F
MOVF AARGB0,W
SUBWFB XISPORDH,F ;FAZ H = A - B/(C + X/D)

RETURN

;*******************************************************************
; ITERAÇÃO DE NEWTON
;*******************************************************************

NEWTON: ;X**1/2 = 1/2 * ( H + X/H)
MOVFF XISPORDL,BARGB1
MOVFF XISPORDH,BARGB0
MOVFF XISL,AARGB1
MOVFF XISH,AARGB0

CALL IDIV1616 ;AQUI FAZ H/X

BTFSS REMB0,7 ;ARREDONDA SE NECESSÁRIO
BRA NEWTON_1
INCFSZ AARGB1,F
BRA NEWTON_1
INCF AARGB0,F

NEWTON_1:
MOVF AARGB1,W
ADDWF XISPORDL,F ;AQUI FAZ H + H/X
MOVF AARGB0,W
ADDWFC XISPORDH,F

BCF STATUS,C,A
RRCF XISPORDH,F ;AQUI FAZ 1/2 * (H + X/H)
RRCF XISPORDL,F

RETURN

;*******************************************************************
;* DIVISAO 16x16 -> 16 *
;* AARGC0 , AARGC1 / BARGC0 , BARGC1 *
;* RESULTADO : AARGC0 , AARGC1 *
;* RESTO: REMC0 , REMC1 *
;*******************************************************************

IDIV1616:

CLRF REMC0
CLRF REMC1

MOVLW D'16'
MOVWF LOOP_CT
PU1616:
RLCF AARGC0,W
RLCF REMC1, F
RLCF REMC0, F
MOVF BARGC1,W
SUBWF REMC1, F
MOVF BARGC0,W
SUBWFB REMC0, F

BC K66LL
MOVF BARGC1,W
ADDWF REMC1, F
MOVF BARGC0,W
ADDWFC REMC0, F

BCF STATUS,C,A
K66LL:
RLCF AARGC1, F
RLCF AARGC0, F

DECFSZ LOOP_CT, F
BRA PU1616

RETURN

;*******************************************************************
; TABELA PARA AJUSTE HIPERBÓLICO
;
; FORMULA: H = A - B/(C + X/D)
;
; D = 2**n tal que X/D seja o maior numero possível < 256 ; ; C = 0,84 * 256 ; B = 1,29 * 4096 * D**1/2 ; A = 1,68 * 16 * D**1/2
;*******************************************************************
TAB_HIPER:
;X
; DW BL
; DW BH
; DW AL
; DW AH
;0 - 256 D = 1
DW 0X152E
;B = 5422
DW 0x001C
;A = 28
;256 - 512 D = 2
DW 0X1DF3
;B = 7667
DW 0x0027
;A = 39
;512 - 1024 D = 4
DW 0X2A5C
;B = 10844
DW 0x0037
;A = 55
;1024 - 2048 D = 8
DW 0X3BE7
;B = 15335
DW 0x004E
;A = 78
;2048 - 4096 D = 16
DW 0X54B6
;B = 21686
DW 0x006F
;A = 111
;4096 - 8192 D = 32
DW 0X77CE
;B = 30670
 DW 0x009C
;A = 156
;8192 - 16384 D = 64
DW 0XA96D
;B = 43373
DW 0x00DD
;A = 221
;16384 - 32768 D = 128
DW 0XEF9C
;B = 61340
DW 0x0138
;A = 312
;********************************************************************
;* Raiz Quadrada Método de aproximação por produtos notáveis *
;* Autor: Renato Gobet Uzun *
;********************************************************************
;* Procura constantemente o valor da raiz utilizando o principio * ;* n^2 = (n-1)^2 + 2(n-1) + 1 * ;******************************************************************** ;************************************************************************
;* *
;* Raiz Quadrada *
;* *
;************************************************************************
;* *
;* Valor de Entrada = AARGB0, AARGB1 *
;* MSB LSB *
;* *
;* Valor de Saida = WREG *
;* *
;* *
;* W = (AARGB0:1)^ 1/2 *
;* *
;************************************************************************
;* *
;* Obs: Já considerado o tempo de chamada da Rotina *
;* *
;************************************************************************
#DEFINE nQuadradoH BARGB0
#DEFINE nQuadradoL BARGB1
#DEFINE nComparaH AARGB0
#DEFINE nComparaL AARGB1
#DEFINE Result LOOPCOUNT RaizQuadradaAPN:
; Tratando a unica Exceção
MOVF nComparaH,W
;Testa se > que 0xFExx
ADDLW 0x02
BTFSC STATUS,C
RETLW 0xFF

MOVF nComparaH,W
MULLW (1>>2)
MOVFF PRODH,Result

; Resut >-- 2 bits + Sig de

; Chama Tabelas de Inicialização

MOVF Result,W
CALL tabRaizL
MOVWF nQuadradoL

MOVF Result,W
CALL tabRaizH
MOVWF nQuadradoH

MOVF Result,W
CALL tabAproxRaiz
MOVWF Result

LoopRaizQuadrada:

MOVF nComparaL,W
SUBWF nQuadradoL,W ; W = nQuadradoL - nComparaL
MOVF nComparaH,W
SUBWFB nQuadradoH,W ; W = nQuadradoH - nComparaH
BC FimRaizQuadrada

RLCF Result,W
BTFSC STATUS,C
INCF nQuadradoH,F
ADDWF nQuadradoL,F
BTFSC STATUS,C
INCF nQuadradoH,F ; nQuadrado += 2 * Result

INFSNZ nQuadradoL,F
INCF nQuadradoH,F ; nQuadrado += 1

INCF Result,F ; Result++

GOTO LoopRaizQuadrada

FimRaizQuadrada:

BTFSS STATUS,Z ; Se for diferente de Zero
DECF Result,F ; Decrementa

MOVF Result,W
RETURN

;********************************************************************
;* Raiz Quadrada Método da Dicotomia *
;* Autor: Renato Gobet Uzun *
;********************************************************************
;* Utiliza o método numérico da Dicotomia *
;********************************************************************

Dicotomia:

MOVLW .7
MOVWF LOOP_COUNT

SETF dicMax
CLRF dicMin

DicLoop:

MOVF dicMax,W
ADDWF dicMin,W
RRCF WREG,F
BTFSC STATUS,C
ADDLW .1

MOVWF dicRes ; Res = (Max+Min)/2

MULWF dicRes ; PROD = Res * Res
MOVF PRODL,W
SUBWF dicValL,W
MOVF PRODH,W
SUBWFB dicValH,W

BTFSS STATUS,C
MOVFF dicRes,dicMax

BTFSC STATUS,C
MOVFF dicRes,dicMin

DECFSZ LOOP_COUNT
BRA DicLoop

MOVF dicMax,W
ADDWF dicMin,W
RRCF WREG,F
BTFSC STATUS,C
ADDLW .1

RETURN

END

Obrigado e até o próximo post.

DATEK Tecnologia Eletrônica
[ASSEMBLY] Como calcular raiz quadrada PIC
Tags:                     

Deixe uma resposta

%d blogueiros gostam disto: