;*************************************************************************************************************************** ; ; LC_METER_TINY ; ; MEDIDOR DE INDUTANCIA E CAPACITANCIA COM VISUALIZAÇÃO EM LCD USANDO TECNICA 'LARIOS' DE MULTIPLEXAÇÃO POR REDE RC ; E USANDO APENAS 3 FIOS PARA LIGAÇÃO COM LCD . ; MICROCONTROLADOR USADO: PIC 12F629 DE APENAS 8 PINOS ; USA CRISTAL DE 4 MHZ PARA ESTABILIZAÇÃO DE FREQUENCIA . ; ; INICIO DO PROJETO: 16/10/2012 TERMINO:03/11/2012 ; ; SITE : LARIOS.TECNOLOGIA.WS ; AUTOR: CLÁUDIO LÁRIOS ; BASEADO EM VARIAS VERSÕES DO LC_METER ENCONTRADO NA INTERNET, COM TOTAL REFORMULAÇÃO DE ROTINAS VISANDO MINIMIZAR ; O TAMANHO DO PROGRAMA NA FLASH (SENDO ESTE O 'GRANDE DESAFIO',POIS TEMOS APENAS 1024 BYTES DISPONIVÉIS NO 12F629). ; OBS. FINS DIDÁTICOS: NÃO TENTE RODAR EM SIMULADOR COMO O 'PROTEUS' QUE, PROVAVELMENTE, NÃO IRÁ FUNCIONAR. ; DEVERÁ SER FEITA MONTAGEM COM COMPONENTES REAIS E EM ALGUNS CASOS, DEVIDO A TOLERANCIA DOS COMPONENTES ; TERÁ QUE SER FEITO AJUSTES. POR ISTO, O MONTADOR DEVERÁ TER CONHECIMENTOS DE ELETRONICA GERAL, ALÉM DE PROGRAMAÇÃO ; DE MICROCONTROLADORES (NÃO RECOMENDADO PARA INICIANTES). ; TAMANHO DO PROGRAMA APÓS COMPILADO: 1018 LINHAS ; ;**************************************************************************************************************************** #INCLUDE ; ARQUIVO PADRAO __CONFIG _BODEN_ON & _CP_OFF & _PWRTE_ON & _WDT_OFF & _MCLRE_ON & _XT_OSC ; PALAVRA DE CONFIGURAÇÃO (_INTRC_OSC_NOCLKOUT) ERRORLEVEL -302 ;SUPRIME A MENSAGEM DE ERRO DO BANCO 0 ;PAGINACAO DE MEMORIA; #DEFINE BANK0 BCF STATUS,RP0 ;SETA BANK0 DE MEMORIA #DEFINE BANK1 BSF STATUS,RP0 ;SETA BANK1 ;VARIAVEIS NA RAM CBLOCK 0X20 ;ENDERECO INICIAL DE MEMORIA FPE,AARGB4,AARGB3,AARGB2,AARGB1,AARGB0,AEXP,SIGN,FPFLAGS,BARGB3,BARGB2,BARGB1,BARGB0,BEXP,CARGB1,CARGB0,CEXP ;PARA PONTO FLUTUANTE TEMP0,TEMP1,TEMP2,TEMPB0,TEMPB1,FLAGS,RES3,RES2,RES1,RES0,LC,LC1,CCAL1,CCAL0 TREG,TREG1,AUX, F1EXP,F1,F1A,SINAL ENDC ;LINHAS DE CONTROLE PARA O LCD (MODO LARIOS_MULTIPLEX) #DEFINE LCD_E GPIO,1 ;Enable + RESISTOR 18K COM CAPACITOR A MASSA DE 100nF AO 'RS' PINO 6 #DEFINE LCD_DB6 GPIO,0 ;SAIDA - LCD data line DB6 + RESISTOR 18K COM CAPACITOR A MASSA DE 100nF AO 'DB4' PINO 7 #DEFINE LCD_DB7 GPIO,2 ;SAIDA - LCD data line DB7 + RESISTOR 18K COM CAPACITOR A MASSA DE 100nF AO 'DB5' PINO 5 ;COMPARTILHAMENTO DE PORTAS #DEFINE SW_LC GPIO,0 ;ENTRADA - CHAVE PARA IDENTIFICAR SE ESTÁ MEDINDO CAPACITANCIA OU INDUTANCIA (SW1B) 0 = INDUTÂNCIA PINO 7 #DEFINE RELE GPIO,0 ;SAIDA - LIGA TRANSISTOR NPN , COM RELE NO COLETOR, COM CAPACITOR DE REFERENCIA NO CONTATO - PINO 7 #DEFINE SW_CCAL GPIO,1 ;BOTÃO DE AJUSTE FINO DO VALOR DE CCAL' PINO 6 ;FLAGS GERAIS #DEFINE FLCD_RS FLAGS,7 ; FLAG RS comando/dado #DEFINE FLAGC FLAGS,6 ; FLAG 'C' #DEFINE FLAGF FLAGS,5 ; FLAG 'CONTROLE DE FLUXO' #DEFINE FLAGNIB FLAGS,4 ; FLAG 'ENVIA ASC OU HEX' #DEFINE FLAGL FLAGS,3 ; FLAG 'IND/CAP' #DEFINE FLAGNZ FLAGS,2 ; FLAG 'NÃO ZERO' #DEFINE FLAGPIL FLAGS,1 ; FLAG 'PONTO INSERIDO INDUTANCIA' #DEFINE FLAGPIC FLAGS,0 ; FLAG 'PONTO INSERIDO CAPACITANCIA' #DEFINE _C STATUS,C ; RENOMEIA PARA BIBLIOTECA DE PONTO FLUTUANTE #DEFINE _Z STATUS,Z ; RENOMEIA PARA BIBLIOTECA DE PONTO FLUTUANTE ;CONSTANTES V_OUT EQU B'111000' ;COMO SAIDAS PARA O LCD V_IN EQU B'111011' ;COMO ENTRADAS DAS CHAVES 'CAL'(GPIO,0 - PINO 7) E 'LC'(GPIO,2 - PINO 5) ;CONSTANTES PARA MATEMÁTICA DE PONTO FLUTUANTE EXP equ AEXP TEMP equ TEMPB0 B0 equ 0 B1 equ 1 B2 equ 2 B3 equ 3 B4 equ 4 B5 equ 5 B6 equ 6 B7 equ 7 MSB equ 7 LSB equ 0 EXPBIAS equ D'127' IOV equ 0 ; bit0 = integer overflow flag FOV equ 1 ; bit1 = floating point overflow flag FUN equ 2 ; bit2 = floating point underflow flag FDZ equ 3 ; bit3 = floating point divide by zero flag NAN equ 4 ; bit4 = not-a-number exception flag DOM equ 5 ; bit5 = domain error exception flag RND equ 6 ; bit6 = floating point rounding flag, 0 = truncation ; 1 = unbiased rounding to nearest LSB SAT equ 7 ; bit7 = floating point saturate flag, 0 = terminate on ; exception without saturation, 1 = terminate on ; exception with saturation to appropriate value ;================================================================================== ;MACROS FACILITADORES SWAP MACRO X,Y ;FAZER TROCA DE DADOS ENTRE 2 REGISTRADORES MOVFW X XORWF Y,f XORWF Y,w XORWF Y,f MOVWF X ENDM COPIAR MACRO ESTE,PARA ;COPIA DE REGISTRADOR PARA OUTRO MOVF ESTE,W MOVWF PARA ENDM LINHA1 MACRO ;ESCREVE NA LINHA1 CALL LINE1 ENDM LINHA2 MACRO ;ESCREVE NA LINHA 2 CALL LINE2 ENDM LIMPA MACRO ;LIMPA TELA DO LCD CALL LCDCLEAR ENDM TEMPO_APRESENTAÇÃO MACRO ;TEMPO DE APRESENTAÇÃO CALL DELAYW_2 ENDM DEBOUNCE MACRO CALL DELAYW_2 ENDM ;=========================================================================== ORG 0X00 ; INICIO DO PROGRAMA POR OCASIÃO DO 'RESET' INICIO CLRF GPIO ;ZERA AS SAIDAS DA PORTA MOVLW .7 ;CARGA MOVWF CMCON ;DESLIGA COMPARADORES LIBERANDO AS IO'S CLRF FLAGS ;APAGA FLAGS GERAIS BANK1 ;TROCA DE BANCO MOVLW B'100111' MOVWF WPU ;PULL UP'S DESATIVADO MOVLW B'10110111' ;TIMER 0 COM PRESCALLER MAX 1/255 MOVWF OPTION_REG BANK0 ;TROCA DE BANCO CALL OUT ;ACERTA PINOS DO LCD PARA SAIDA CALL DELAY1 ;TEMPO DE NORMALIZAÇÃO CALL LCDINIT ;INICIALIZAÇÃO DO LCD ;============================================================================ ; NA SEQUENCIA, VERIFICA SE DEVE PROCEDER ROTINA DE ALTERAÇÃO DO VALOR DE CCAL ;TESTANDO O BOTÃO 'SW_CAL'. O BOTÃO 'SW_LC', DETERMINARÁ SE DEVERÁ OCORRER UM ;INCREMENTO OU DECREMENTO DO VALOR DE CCAL (CAP. PADRÃO) NA EEPROM, SENDO LOGO ;APÓS UM RESET. (OBRIGATÓRIO DAR UM 'RESET' COM BOTÃO 'SW_CAL' APERTADO PARA ;ENTRAR NESTE MODO DE SERVIÇO. ;OBS. SERÁ MOSTRADO EM HEXADECIMAL EX. 2710 = 10.000 PF/10 = 1 NF ;(LEMBRANDO, QUE A FREQUÊNCIA É LIDA EM 1/10 DE SEGUNDOS) VSET9 CALL IN ;TORNA GPIO ENTRADA PARA TESTE DE BOTÕES BCF FLAGL ;ZERA FLAGL BTFSC SW_LC ;TESTA BOTÃO INDUTANCIA/CAPACITANCIA BSF FLAGL ;SETA FLAGL BTFSS SW_CCAL ;TESTA SE BOTÃO DE SERVIÇO FOI ACIONADO GOTO MAIN1 ;NÃO FOI, VAI PARA ROTINA MAIN1 (PRINCIPAL) CALL OUT ;FOI ACIONADO, ENTRA EM MODO DE SERVIÇO. CALL DELAY1 ;TEMPO DE ESTABILIZAÇÃO LIMPA ;APAGA LCD MOVLW VC_CAL - 0X2100 ;PEGA ENDEREÇO DA MENSAGEM A SER MOSTRADA CALL EE_DISP ;MOSTRA 'CCAL = OX' MOVLW CAL - 0X2100 ;MOSTRA A PARTE HIGH DO CCAL CALL ENV_H ;ROTINA DE LEITURA DA EEPROM E ENVIO PARA LCD MOVFW CCAL0 ;DESLOCA CONTEUDO DE CCAL0 MOVWF CCAL1 ;PARA O REGISTRADOR CCAL1 MOVLW CAL + 1 - 0X2100 ;MOSTRA A PARTE LOW DO CCAL CALL ENV_H ;ROTINA DE LEITURA DA EEPROM E ENVIO PARA LCD TEMPO_APRESENTAÇÃO ;MACRO DE TEMPO DA APRESENTAÇÃO NO LCD BTFSS FLAGL ;TESTA FLAGL:POSIÇÃO DE INDUTANCIA DECREMENTA CCAL GOTO INC_CCAL ;POSIÇÃO EM 'INDUTANCIA' DECFSZ CCAL0,F ;POSIÇÃO EM 'CAPACITANCIA' (INCREMENTA CCAL) GOTO SALVA_CCAL0 ;SALVA CCAL LOW NA EEPROM DECF CCAL1,F ;DECREMENTA SE CCAL0 CHEGOU A '0' GOTO SALVA_CCAL ;SALVA CCAL HIGH NA EEPROM INC_CCAL ;ROTINA DE INCREMENTO DE CCAL INCFSZ CCAL0,F ;INCREMENTA CCAL1 GOTO SALVA_CCAL0 ;SALVA CCAL LOW NA EEPROM INCF CCAL1,F ;SE CCAL0 CHEGOU A '0' , INCREMENTA CCAL1 GOTO SALVA_CCAL ;SALVA CCAL HIGH NA EEPROM ENV_H ;ROTINA QUE LE EEPROM E ENVIA PARA O LCD CALL EE_R ;LE EEPROM MOVWF CCAL0 ;SALVA VALOR DO CAPACITOR PADRÃO MOVWF AUX ;SALVA TEMPORARIAMENTE EM 'AUX' SWAPF AUX,W ;INVERTE O NIBLLE CALL BIN_ASC_ED ;CONVERTE ASC HEXA E ENVIA P/ LCD MOVFW AUX ;PEGA O OUTRO NIBLLE GOTO BIN_ASC_ED ;CONVERTE ASC HEXA E ENVIA P/ LCD ;(3) USANDO 'GOTO' AO INVÉS DE 'CALL' PARA ECONOMIA DE 'RETURN' ;RETURN ;RETORNA A ROTINA ANTERIOR SALVA_CCAL ;ROTINA QUE SALVA VALOR DO INCREMENTO DIRETO NA EEPROM BANK1 ;TROCA DE BANCO DECF EEADR,F ;DECREMENTA O ENDEREÇO DA EEPROM BANK0 ;TROCA DE BANCO MOVFW CCAL1 ;PEGA VALOR DE CCAL1 CALL EE_W ;ESCREVE BYTE HIGH NA EEPROM BANK1 ;TROCA DE BANCO INCF EEADR,F ;INCREMENTA O ENDEREÇO DA EEPROM BANK0 ;TROCA DE BANCO SALVA_CCAL0 ;ROTINA QUE SALVA A PARTE LOW DE CCAL MOVFW CCAL0 ;PEGA VALOR DE CCAL0 CALL EE_W ;ESCREVE BYTE LOW NA EEPROM GOTO VSET9 ;RETORNA PARA TESTAR SE BOTÕES FORAM LIBERADOS ; FIM DA ROTINA DE VERIFICAÇÃO E AJUSTE DE CCAL (ROTINA DE SERVIÇO) ;=========================================================================================== MAIN1 LIMPA ;APAGA DISPLAY MOVLW NOMEPROG - 0X2100 ;PEGA A POSIÇÃO DA MENSAGEM A ENVIAR AO LCD CALL EE_DISP ;MOSTRA TITULO DO APARELHO 'LC_METER_TINY' LINHA2 ;TROCA DE LINHA NO LCD (DE BAIXO) MOVLW BLOG - 0X2100 ;PEGA A POSIÇÃO DA MENSAGEM A ENVIAR AO LCD CALL EE_DISP ;MOSTRA FRASE 'LARIOS.TECNOLOGIA.WS' TEMPO_APRESENTAÇÃO ;TEMPO DE APRESENTAÇÃO DO TITULO LIMPA ;APAGA DISPLAY MOVLW UPP - 0X2100 ;PEGA A POSIÇÃO DA MENSAGEM A ENVIAR AO LCD CALL EE_DISP ;MOSTRA FRASE 'SE 'L'UNIR PONTAS' NO LCD TEMPO_APRESENTAÇÃO ;TEMPO QUE MENSAGEM SERÁ EXIBIDA LIMPA ;APAGA DISPLAY MOVLW CALIBRANDO - 0X2100 ;PEGA A POSIÇÃO DA MENSAGEM A ENVIAR AO LCD CALL EE_DISP ;MOSTRA FRASE 'CALIBRANDO' NO LCD TEMPO_APRESENTAÇÃO ;TEMPO QUE MENSAGEM SERÁ EXIBIDA GOTO F1_FCAL ;VAI PARA ROTINA F1/FCCAL LOOP1 ;LOOP PRINCIPAL PARA AS MEDIÇÕES SUCESSIVAS F1_FX BCF FLAGF ;APAGA FLAG DE CONTROLE DE FLUXO CALL MED_FREQ ;MEDE FREQUENCIA C/ CAP DESCONHECIDO E CONVERTE CALL COPIAR_A_B ;SALVA RESULTADO NO BANCO DE REGISTRADORES 'B' MOVFW F1EXP ;RECUPERA F1 PARA O BANCO DE REGISTRADORES 'A' MOVWF AEXP MOVFW F1 MOVWF AARGB0 MOVFW F1A MOVWF AARGB1 GOTO X2 ;PULA PARA ROTINA X2 F1_FCAL BSF FLAGF ;SETA FLAG DE CONTROLE DE FLUXO BSF RELE ;ACIONA RELE COM CAPACITOR PADRÃO DEBOUNCE ;TEMPO DE ESTABILIZAÇÃO CALL MED_FREQ ;MEDE FREQUENCIA COM CAPACITOR PADRÃO 1NF E CONVERTE CALL COPIAR_A_B ;SALVA RESULTADO NO BANCO DE REGISTRADORES 'B' BCF RELE ;DESLIGA RELE COM CAPACITOR PADRÃO DEBOUNCE ;ESTABILIZA O OSCILADOR CALL MED_FREQ ;MEDE FREQUENCIA LIVRE F1 E CONVERTE PONTO FLUTUANTE MOVFW AEXP ;SALVA RESULTADO NO BANCO DE REGISTRADORES 'F1' MOVWF F1EXP MOVFW AARGB0 MOVWF F1 MOVFW AARGB1 MOVWF F1A X2 CALL FPD24 ;DIVIDE BANCO 'A' POR 'B' CALL COPIAR_A_B ;COPIA RESULTADO NO BANCO 'B' CALL FPM24 ;ELEVA AO QUADRADO POR MULTIPLICAR 'A' COM 'B' CLRF BARGB2 ;COPIA EQUIVALENTE A '1' EM PONTO FLUTUANTE PARA 'B' CLRF BARGB0 CLRF BARGB1 MOVLW 0X7F MOVWF BEXP CALL FPS24 ;SUBTRAI 'A' - 'B' BTFSS FLAGF ;TESTA FLAG DE FLUXO GOTO SEG10X ;SE '0' , VAI PARA SEG10X CALL SWAP_A_C ;SE '1' , SALVA RESULTADO EM 'C' (C= [(F1:F_CCAL)^2] -1) GOTO F1_FX ; VAI PARA ROTINA QUE OBTEM F1/FX SEG10X CALL COPIAR_A_B ;AJUSTA BANCOS CALL COPIAR_C_A ; .... CALL SWAP_A_B ;PARA POSIÇÃO CORRETA ;============================================================================================= ; VAI DEFINIR SE MEDIRÁ ' L ' OU ' C ' TESTANDO BOTÃO SW_LC CALL IN ;MUDA TRISIO PARA ENTRADA BTFSS SW_LC ;TESTA BOTÃO SELETOR, SENDO 1=C 0=L GOTO CALCULA_LX ;VAI MEDIR INDUTANCIA CALCULA_CX ;VAI MEDIR CAPACITANCIA BCF FLAGL ;APAGA FLAGL LIMPA ;LIMPA LCD MOVLW CAP - 0X2100 ;POSICIONA PARA MENSAGEM CALL EE_DISP ;MOSTRA 'C = ' NO LCD CALL FPD24 ;DIVIDE 'A' POR 'B' CALL COPIAR_A_B ;SALVA RESULTADO EM 'B' CALL PEGA_VALOR_CAP ;PEGA VALOR DO CAP PADRÃO E CONVERTE P/FLUTUANTE CALL FPM24 ;MULTIPLICA 'A' POR 'B' V_SHOW ;ROTINA DE PREPARAÇÃO PARA APRESENTAÇÃO DE RESULTADOS MOVLW '-' ;PRECARGA DO SINAL '-' BTFSS AARGB0,7 ;TESTA BIT DE SINAL MOVLW ' ' ;SINAL '+' MOVWF SINAL ;SALVA VALOR NO REGISTRADOR 'SINAL' BCF AARGB0,7 ;TORNA RESULTADO SEMPRE POSITIVO CALL INT2424 ;CONVERTE DE PONTO FLUTUANTE PARA INTEIRO MOVF FPE,F ;TESTA SE HOUVE ERROS NA MATEMÁTICA E OVERFLOW BTFSS STATUS,Z ;SE '0' PULA GOTO ERRO_CONTA ;'1', ENTÃO HOUVE ERRO CALL BCD_TO_DEC ;'0'= OK , SEGUE A APRESENTAÇÃO DOS RESULTADOS CALL SHOW_LCD ;ENVIA PARA O LCD VER19 TEMPO_APRESENTAÇÃO ;TEMPO DE APRESENTAÇÃO DO RESULTADO GOTO LOOP1 ;RETORNA NO LOOP PRINCIPAL PARA NOVA MEDIÇÃO ERRO_CONTA LIMPA ;APAGA LCD MOVLW F_FAIXA - 0X2100 ;PEGA ENDEREÇO DA MENSAGEM CALL EE_DISP ;MENSAGEM: ' L ?' CLRF FPE ;LIMPA REGISTRADOR DE ERRO GOTO VER19 ;VAI PARA O TEMPO DE APRESENTAÇÃO E LOOP PRINCIPAL BIN_ASC_ED ;ROTINA DE BINARIO PARA HEX 0-F COM ENVIO PARA LCD ANDLW 0X0F ;LIMITA 0-F ADDLW 0XF6 ;SOMA 0XF6 BTFSC STATUS,C ;TESTA CARRY ADDLW 0X07 ;C=1 ,ENTÃO SOMA + 7 ADDLW 0X3A ;SOMA 0X3A GOTO ED ;ENVIA PARA O LCD E RETORNA PARA O PONTO DE CHAMADA ;================================================================== ;ROTINA PARA CALCULAR A INDUTANCIA ; FORMULA USADA -> (((F1/FX)^2-1) X ((F1/FCCAL)^2 -1) X LSCALE ) / CCALL CALCULA_LX BSF FLAGL ;SETA FLAGL LIMPA ;LIMPA LCD MOVLW IND - 0X2100 ;PEGA ENDEREÇO DA MENSAGEM CALL EE_DISP ;MOSTRA ' L = ' CALL FPM24 ;MULTIPLICA (F1/FX)^2-1) X (F1/FCCAL)^2 -1) MOVLW 0xB8 ;CARREGA 'B' COM 2.53303e+17 (P/2 CASAS) MOVWF BEXP MOVLW 0x60 ; 1/(4*PI*PI) * ESCALA PARA INDUTANCIA MOVWF BARGB0 MOVLW 0xFA MOVWF BARGB1 CALL FPM24 ;MULTIPLICA 'A' POR 'B' CALL COPIAR_A_B ;SALVA EM 'B' CALL PEGA_VALOR_CAP ;PEGA VALOR DO CAP PADRÃO E CONVERTE EM FLUTUANTE EM 'A' CALL SWAP_A_B ;TROCA O CONTEUDO DOS BANCOS ENTRE SI CALL FPD24 ;DIVIDE POR VALOR DO CAPACITOR PADRÃO DE 1NF CALL SWAP_A_B ;SALVA RESULTADO EM 'B' CALL PEGA_F1 ;POEM F1 EM 'A' CALL SWAP_A_B ;TROCA O CONTEUDO DOS BANCOS ENTRE SI CALL FPD24 ;DIVIDE POR F1 CALL FPD24 ;DIVIDE POR F1 (DE NOVO) MOVLW 0X80 ;DESTACA BIT 7 (SIGN) XORWF AARGB0,F ;INVERTE SINAL PARA LX GOTO V_SHOW ;VAI PARA ROTINA QUE MOSTRA RESULTADO NO LCD PEGA_F1 ;ROTINA QUE RECUPERA VALOR DA FREQUENCIA 1 MOVFW F1 ;COLOCA DO BANCO 'F1' NO BANCO 'A' MOVWF AARGB0 MOVFW F1A MOVWF AARGB1 MOVFW F1EXP MOVWF AEXP RETURN ;=============================================================================================== ;PEGA VALOR DO CAPACITOR PADRÃO DA EEPROM PEGA_VALOR_CAP MOVLW CAL - 0X2100 ;PEGA O ENDEREÇO DO VALOR NA EEPROM CALL EE_R ;LE NA EEPROM MOVWF AARGB1 ;COLOCA NO BANCO 'A' HIGH MOVLW CAL - 0X2100 + 1 ;PEGA O ENDEREÇO DO VALOR NA EEPROM CALL EE_R ;LE NA EEPROM MOVWF AARGB2 ;COLOCA NO BANCO 'A' LOW CLRF AARGB0 ;APAGA 'A' UPPER GOTO FLO2424 ;CONVERTE P/ PONTO FLUT. E RETORNA P/ PONTO DE CHAMADA ;================================================================================================ ;INICIA A MEDIÇÃO USANDO O TEMPO DE 1 MILISEGUNDO PARA A CONTAGEM ;RESULTADO DA MEDIÇÃO VAI PARA OS 2 REGISTRADORES SEQUENCIAS APONTADOS ;POR FSR, PARA AARGB1...B2. MED_FREQ CLRF AARGB0 ;LIMPA RESULTADOS CLRF AARGB2 CLRF TMR0 ;INICIA A MEDIÇÃO BCF INTCON,T0IF ;APAGA FLAG OV TIMER0 BANK1 ;TROCA DE BANCO BSF TRISIO,2 ;VIRA ENTRADA NO PINO 5, COMEÇA A MEDIÇÃO CALL DELAY_100MS ;TEMPO DA MEDIÇÃO BCF TRISIO,2 ;VIRA SAIDA '0' NO PINO 5 (PARANDO A CONTAGEM) BANK0 ;TROCA DE BANCO MOVFW TMR0 ;SALVA CONTAGEM DO TIMER 0 MOVWF AARGB1 ;NO CONTADOR DO BANCO 'A' MOVLW 0XFF ;PRECARGA PARA 'ERRO' BTFSC INTCON,T0IF ;SE FREQ >655KHZ MOVWF FPE ;CARREGA O 'ERRO' EM FPE BTFSC STATUS,Z ;SE FREQ <2560 HZ MOVWF FPE ;CARREGA O 'ERRO' EM FPE ;===================================================================================== ; EXTRAI O CONTEUDO DO PRESCALLER VP4 BANK1 BCF OPTION_REG,5 ;PULSA ENTRE CLOCK INTERNO E ENTRADA ATERRADA BSF OPTION_REG,5 BANK0 DECF AARGB2,F ;DECREMENTA A PARTE LOW DO RESULTADO DA MEDIÇÃO MOVFW AARGB1 ;PEGA VALOR ANTERIOR DO TMR0 PARA COMPARAÇÃO SUBWF TMR0,W ;COMPARA SE HOUVE INCREMENTO EM TMR0 BTFSC STATUS,Z ;TESTA DIFERENÇA GOTO VP4 ;NÃO HOUVE, RETORNA PARA PULSAR MAIS UMA VEZ GOTO FLO2424 ;CONVERTE PARA PONTO FLUTUANTE E SAI DESTA ROTINA ;RETLW 0X00 ;HOUVE, ENTÃO SAI DA ROTINA ;================================================================================= ; ROTINAS DE DELAYS ;================================================================================= DELAYW_2 MOVLW .2 ;ROTINA DE DELAY PARA DEBOUNCE/APRESENTAÇÃO GOTO DELAYW DELAYW_10 MOVLW .10 DELAYW MOVWF TEMP0 VJ1 CALL DELAY1 DECFSZ TEMP0,F GOTO VJ1 DELAY1 MOVLW .255 ;DELAY PARA VISUALIZAÇAO DELAY ;LCDDELAY MOVWF LC+1 ;CARGA LLoop NOP DECFSZ LC+0,F ;DECREMENTA GOTO LLoop DECFSZ LC+1,F ;DECREMENTA GOTO LLoop RETURN ;============================================================================= WAIT_XuS ;TEMPO DE DESCARGA DOS CAPACITORES DO LCD MOVLW .200 ;MIN=150 (ACHADO POR TENTATIVA E ERRO) WAIT_uS MOVWF LC WAIT_uS_A DECFSZ LC, F GOTO WAIT_uS_A RETURN ;============================================================================ ; ROTINA DE DELAY DE 100 MILISEGUNDOS PARA MEDIÇÃO DE FREQUENCIA ;============================================================================ DELAY_100MS MOVLW .110 MOVWF TEMP0 PL1 MOVLW .181 MOVWF TEMP1 PL2 CLRWDT CLRWDT DECFSZ TEMP1, F GOTO PL2 DECFSZ TEMP0, F GOTO PL1 PD1 GOTO PD2 PD2 GOTO PD3 PD3 CLRWDT RETURN ;================================================================================= ;ROTINAS DE CONTROLE DO LCD ;================================================================================= LCDINIT ;ENVIA 0011 POR 3 VEZES E DEPOIS 0010 POR 1 VEZ PARA MODO DE 4 BITS BCF LCD_E ;APAGA LINHAS DE CONTROLE DO LCD BCF LCD_DB6 ;APAGA DB6 (OU SEJA, APAGA 'DB4' POR DESCARGA DO CAPACITOR) BCF LCD_DB7 ;APAGA DB7 (OU SEJA, APAGA 'DB5' POR DESCARGA DO CAPACITOR) MOVLW .30 ;ESPERA POR 30 ms CALL DELAY ;ROTINA DE DELAY BSF LCD_DB6 ;CARREGA CAPACITOR EM 'DB4' (1) BSF LCD_DB7 ;CARREGA CAPACITOR EM 'DB5'(1) CALL WAIT_XuS ;TEMPO PARA COMPLETAR A CARGA EM 'DB4 E DB5' BCF LCD_DB6 ;RAPIDAMENTE, MUDE O VALOR PARA 'DB6' BCF LCD_DB7 ;IDEM CALL PULSO_E ;ENVIA 0011 POR 3 VEZES CALL PULSO_E CALL PULSO_E MOVLW .2 ;ESPERA POR 2MS PARA DESCARGA DOS CAPACITORES CALL DELAY BCF LCD_DB6 ;DESCARREGA CAPACITOR EM 'DB4' (0) BSF LCD_DB7 ;CARREGA CAPACITOR EM 'DB5' (1) CALL WAIT_XuS ;TEMPO PARA CARGA/DESCARGA DOS CAPACITORES BCF LCD_DB7 ;RAPIDAMENTE , APAGA 'DB7'('DB6' JÁ ESTÁ APAGADO) CALL LCD_PULSE_E ;ENVIA 0010 PARA O LCD BCF LCD_E ;APAGA LINHAS DE COMANDO DO LCD BCF LCD_DB6 ;0011->48 BCF LCD_DB7 MOVLW .2 ;ESPERA POR 2 MS PARA DESCARGA DOS CAPACITORES CALL DELAY ;ROTINA DE ATRASO MOVLW 28H ;AJUSTA PARA MODO DE ENVIO POR 4 BITS CALL EC ;ENVIA COMANDO EM 'W' MOVLW 06H ;MODO INCREMENTO SEM DESLOCAMENTO CALL EC MOVLW 0CH ;LIGA DISPLAY,DESLIGA CURSOR E PISCA CALL EC LCDCLEAR MOVLW 01H ;LIMPA DISPLAY CALL EC ;ENVIA O COMANDO MOVLW .2 ;ESPERA POR 2 MS GOTO DELAY ;ROTINA DE DELAY ;RETURN ;USANDO GOTO AO INVÉS DE CALL PARA ECONOMIZAR PULSO_E ;PULSA 'E' DO LCD E 'EMPURRA DADO/COMANDO' BSF LCD_E ;Enables LCD NOP BCF LCD_E ;Disabled LCD RETURN ;================================================================================== ;PEGA MENSAGENS DA EEPROM E ENVIA PARA O LCD EE_DISP CALL EE_R ;ROTINA DE LEITURA DA EEPROM RTK33 SKPNZ ; SE FOR '0' FINALIZA A ROTINA RETURN ; RETORNA CALL ED ; MOSTRA NO DISPLAY O CARACTER TRAZIDO DA EEPROM BANK1 INCF EEADR,F ;INCREMENTA ENDERÊÇO CALL EE_P ;ROTINA DE LEITURA DA EEPROM GOTO RTK33 ;LOOP ;================================================================================= EE_R ;LER DADOS NA E2PROM DADO=W ENDEREÇO = EEADR BANK1 MOVWF EEADR ; APONTA REGISTRO DE ENDEREÇO DA EEPROM EE_P BSF EECON1,RD ;LEITURA MOVF EEDATA,W BANK0 RETURN ;================================================================================= EE_W ;ESCREVE NA E2PROM DADO=W /ENDEREÇO=EEADR (PRÉ-CARREGUE ENDEREÇO ANTES!) BANK1 MOVWF EEDATA ;CARREGA DADO DE 'W' ;BCF INTCON,GIE ;DESLIGA INTERRUPÇÕES GERAIS BSF EECON1,WREN ;SETA MOVLW 0X55 ;SEQUENCIA PADRÃO MOVWF EECON2 MOVLW 0XAA MOVWF EECON2 BSF EECON1,WR ;HABILITA ESCRITA BCF EECON1,WREN BTFSC EECON1,WR ;TESTA SE JÁ TERMINOU A ESCRITA GOTO $ - 1 ;AINDA NÃO BANK0 ;TROCA DE BANCO RETURN ;RETORNA AO TERMINO ;================================================================================ ;ROTINA DE ENVIO DE DADO/COMANDO PARA O LCD ;USE 'ASC_ED' PARA ENVIAR 0..9 PARA O LCD ;USE 'ED'PARA ENVIAR 'DADOS' ;USE 'EC'PARA ENVIAR 'COMANDOS' ASC_ED ANDLW 0X0F ;APAGA NIBLLE HIGH ADDLW 0X30 ;SOMA 0X30 PARA NUMEROS 0 A 9 ASCII ED BSF FLCD_RS ;SETA FLAG PARA ENVIAR 'DADOS'' GOTO ENV_B LINE1 MOVLW 0X80 ;ENVIA COMANDO PARA MUDAR PARA LINHA 1 GOTO EC LINE2 MOVLW 0XC0 ;ENVIA COMANDO PARA MUDAR PARA LINHA 2 EC BCF FLCD_RS ;APAGA FLAG PARA ENVIAR 'COMANDO' ENV_B MOVWF TREG ;SALVA DADO/COMANDO A ENVIAR CALL OUT ;ACERTA PARA 'SAIDA' BCF LCD_E ;DESCARREGA CAPACITOR EM 'RS' BCF LCD_DB7 ;DESCARREGA CAPACITOR EM 'DB5' BCF LCD_DB6 ;DESCARREGA CAPACITOR EM 'DB4' MOVLW .1 ;AGUARDA 1 MS P/ DESCARGA COMPLETA QUANDO EM 'IN' CALL DELAY ;ROTINA DE ATRASO BTFSC TREG,4 ;TESTA BITS DO COMANDO/DADO A ENVIAR BSF LCD_DB6 ; E AJUSTA AS SAIDAS PARA O LCD BTFSC TREG,5 BSF LCD_DB7 BTFSC FLCD_RS ;FLAG RS BSF LCD_E ;SETA 'E' PARA CARREGAR CAPACITOR E SETAR 'RS' CALL WAIT_XuS ;TEMPO PARA CARGA/DESCARGA DOS CAPACITORES BCF LCD_DB6 ;RAPIDAMENTE, ACERTA 'DB6' E 'DB7' BTFSC TREG,6 BSF LCD_DB6 BCF LCD_DB7 BTFSC TREG,7 BSF LCD_DB7 CALL LCD_PULSE_E ;ENVIA UM NIBLLE (BITS 4 A 7) PARA O LCD BTFSC TREG,0 ;TESTA BSF LCD_DB6 ;CARGA PARA 'DB4' BTFSC TREG,1 BSF LCD_DB7 ;CARGA PARA 'DB5' BTFSC FLCD_RS ;FLAG RS BSF LCD_E ;SETA PARA CARREGAR CAPACITOR E SETAR 'RS' CALL WAIT_XuS ;TEMPO PARA CARGA/DESCARGA DOS CAPACITORES BCF LCD_DB6 BTFSC TREG,2 BSF LCD_DB6 BCF LCD_DB7 BTFSC TREG,3 BSF LCD_DB7 ;ENVIA O SEGUNDO NIBLLE (BIT 0 A 3) PARA O LCD LCD_PULSE_E CALL PULSO_E ;ROTINA DE ENVIO DE PULSO DE COMANDO PARA LCD (E) BCF LCD_DB7 BCF LCD_DB6 ;DESCARREGA CAPACITORES MOVLW .2 ;ATRASO DE 2MS GOTO DELAY ;CONTA TEMPO E RETORNA PARA A ROTINA DE CHAMADA ;==================================================================================== ;MUDANÇA DE IN/OUT ;======================================================================================== OUT MOVLW V_OUT GOTO TRISIOX IN MOVLW V_IN TRISIOX BANK1 ;TROCA DE BANCO MOVWF TRISIO ;ENTRADA OU SAIDA BANK0 RETURN ;======================================================================================= ;========================================================================================== ; ROTINA DE CONVERSÃO HEXA PARA DECIMAL HEXA EM C2,C1,C0 E DECIMAL EM RES3,RES2,RES1,RES0 ;COLOCAR NA DECLARAÇÃO DE RAM NA SEQUENCIA AARGB2...B0,RES3...RES0 , PARA FUNCIONAR. BCD_TO_DEC B2BCD MOVLW .24 ; PARA 24 BIT DE RESULTADO MOVWF TEMP0 ; CONTADOR TEMPORÁRIO CLRF RES0 ; APAGA RESULTADOS CLRF RES1 CLRF RES2 CLRF RES3 VRP1X MOVLW RES3 ; APONTA PARA INICIO DOS REGISTRADORES MOVWF FSR MOVLW .4 MOVWF TEMP1 ; ROTINA DO MIKE: VRP2X MOVLW 0x33 ADDWF INDF,f ; SOMA BTFSC INDF,3 ; TESTA SE RESULTADO > 7 ANDLW 0xf0 ; RESULTADO LOW >7 SOMA 3 BTFSC INDF,7 ; TESTA SE RESULTADO É > 7 ANDLW 0x0f ; MAIOR QUE 7 ENTÃO OK SUBWF INDF,f ; RESULTADO <= 7 RETORNA RETORNA VALOR ANTERIOR INCF FSR,f ; APONTA PARA O PRÓXIMO DECFSZ TEMP1,f GOTO VRP2X BCF STATUS,C RLF AARGB2,f ; DESLOCA RLF AARGB1,f RLF AARGB0,f RLF RES0,f ;LSB (RESULTADOS) RLF RES1,f RLF RES2,f RLF RES3,f ;MSB DECFSZ TEMP0,F ; CONVERSÃO CHEGOU AO FIM? GOTO VRP1X ; RETORNA PARA CONVERÇÃO RETURN ; RETORNA COM EXITO ;========================================================================= SHOW_LCD ;MOSTRA RESULTADOS NO LCD MOVFW SINAL ;CARGA DO SINAL CALL ED ;MOSTRA NO LCD SWAPF RES3,W CALL TESTA_SE_ZER0_E_ENVIA ;ENVIA RES3 NIBLLE HIGH MOVFW RES3 CALL TESTA_SE_ZER0_E_ENVIA ;ENVIA RES3 NIBLLE LOW SWAPF RES2,W CALL TESTA_SE_ZER0_E_ENVIA ;ENVIA RES2 NIBLLE HIGH CALL L_PONTO ;TESTA POR PONTO NA MEDIDA DE INDUTANCIA (L)ESCALA mH MOVFW RES2 ;ENVIA RES2 NIBLLE LOW CALL TESTA_SE_ZER0_E_ENVIA CALL C_PONTO ;TESTA POR PONTO NA MEDIDA DE CAPACITANCIA (C)ESCALA nF SWAPF RES1,W CALL TESTA_SE_ZER0_E_ENVIA ;ENVIA RES1 NIBLLE HIGH GOTO L_SAIDA ;TESTA POR SAIDA ANTECIPADA EM INDUTANCIA (2 CASAS APÓS VIRGULA) SANT2 MOVFW RES1 BTFSS FLAGL CALL TESTA_SE_ZER0_E_ENVIA BTFSC FLAGL CALL ASC_ED GOTO C_SAIDA ;TESTA POR SAIDA ANTECIPADA EM CAPACITANCIA (2 CASAS APÓS VIRGULA) SANT1 BTFSS FLAGL GOTO FD1 MOVLW '.' ;SE FOR 'L' ENVIA PONTO (SE CASA ANTERIOR NÃO FOR '0') CALL ED FD1 SWAPF RES0,W ;ENVIA RES0 NIBLLE HIGH CALL ASC_ED BTFSC FLAGL GOTO FD2 MOVLW '.' ;SE FOR 'C' ENVIA PONTO (SE CASA ANTERIOR NÃO FOR '0') CALL ED FD2 MOVFW RES0 ;ENVIA RES0 NIBLLE LOW CALL ASC_ED MOVLW UUH - 0X2100 ;ENVIA SUFIXO DE ESCALA (uH) SE FOR 'L' BTFSS FLAGL MOVLW UPF - 0X2100 ;ENVIA SUFIXO DE ESCALA (pF) SE FOR 'C' CALL EE_DISP SM1 MOVLW 0XF0 ANDWF FLAGS,F ;APAGA TODOS FLAGS USADOS NA APRESENTAÇÃO DE RESULTADOS RETURN ;FINALIZA ROTINA E RETORNA L_SAIDA BTFSS FLAGPIL GOTO SANT2 ;RETORNA PARA MOSTRAR PRÓXIMAS CASAS GOTO SAI_MAIOR ;SAIDA ANTECIPADA COM 2 CASAS APÓS VIRGULA C_SAIDA BTFSS FLAGPIC GOTO SANT1 SAI_MAIOR MOVLW UMH - 0X2100 ;ENVIA SUFIXO DE ESCALA (MH) SE FOR 'L' BTFSS FLAGL MOVLW UNF - 0X2100 ;ENVIA SUFIXO DE ESCALA (nF) SE FOR 'C' CALL EE_DISP GOTO SM1 ;VAI APAGAR FLAGS E SAIR TESTA_SE_ZER0_E_ENVIA ;TESTA SE PRECISA INSERIR PONTO ANDLW 0X0F BTFSS STATUS,Z GOTO NAO_ZERO BTFSC FLAGNZ GOTO NAO_ZERO RETURN NAO_ZERO BSF FLAGNZ GOTO ASC_ED ;ENVIA PARA LCD E RETORNA C_PONTO BTFSC FLAGL RETURN GOTO TFLAGNZ L_PONTO BTFSS FLAGL ;TESTAS SE É INDUTOR OU CAPACITOR RETURN TFLAGNZ BTFSS FLAGNZ ;TESTA SE NUMERO ANTERIOR ERA ZERO RETURN MOVLW '.' CALL ED BTFSS FLAGL ;TESTA SE É INDUTOR OU CAPACITOR BSF FLAGPIC ;SETA FLAG DE PONTO INCLUIDO C BTFSC FLAGL BSF FLAGPIL ;SETA FLAG DE PONTO INCLUIDO L RETURN ;FIM DA ROTINA DE ENVIO DE RESULTADOS PARA O LCD ;======================================================================== ;OPERAÇÕES ENTRE BANCOS DE REGISTRADORES 'A','B' E 'C' COPIAR_A_B ;COPIA BANCO 'A' EM 'B' COPIAR AEXP,BEXP COPIAR AARGB0,BARGB0 COPIAR AARGB1,BARGB1 RETURN SWAP_A_B ;TROCA CONTEUDO ENTRE BANCO 'A' E 'B' SWAP AEXP,BEXP SWAP AARGB0,BARGB0 SWAP AARGB1,BARGB1 RETURN SWAP_A_C ;TROCA CONTEUDO ENTRE BANCO 'A' E 'C' SWAP AEXP,CEXP SWAP AARGB0,CARGB0 SWAP AARGB1,CARGB1 RETURN COPIAR_C_A ;COPIA BANCO 'C' EM 'A' COPIAR CEXP,AEXP COPIAR CARGB0,AARGB0 COPIAR CARGB1,AARGB1 RETURN ;********************************************************************************************** ; SEGUE A BIBLIOTECA DE PONTO FLUTUANTE FORNECIDA PELA MICROCHIP COM ALTERAÇÕES PARA REDUZIR ; O TAMANHO, SENDO DELETADO PARTES NÃO NECESSÁRIAS. ;********************************************************************************************** ; ; 24 bit floating point representation ; ; EXPONENT 8 bit biased exponent ; It is important to note that the use of biased exponents produces ; a unique representation of a floating point 0, given by ; EXP = HIGHBYTE = LOWBYTE = 0x00, with 0 being the only ; number with EXP = 0. ; ; HIGHBYTE 8 bit most significant byte of fraction in sign-magnitude representation, ; with SIGN = MSB, implicit MSB = 1 and radix point to the right of MSB ; ; LOWBYTE 8 bit least significant byte of sign-magnitude fraction ; ; EXPONENT HIGHBYTE LOWBYTE ; ; xxxxxxxx S.xxxxxxx xxxxxxxx ; ; | ; RADIX ; POINT ; ;********************************************************************************************** ;********************************************************************************************** ; Integer to float conversion ; Input: 16 bit 2's complement integer right justified in AARGB0, AARGB1 ; Use: CALL FLO1624 or CALL FLO24 ; Output: 24 bit floating point number in AEXP, AARGB0, AARGB1 ; Result: AARG <-- FLOAT( AARG ) ; Max Timing: 11+72 = 83 clks SAT = 0 ; 11+77 = 88 clks SAT = 1 ; Min Timing: 7+14 = 21 clks AARG = 0 ; 7+18 = 25 clks ; PM: 11+26 = 37 DM: 6 ;---------------------------------------------------------------------------------------------- ;FLO1624 ;FLO24 MOVLW D'15'+EXPBIAS ; initialize exponent and add bias ; MOVWF EXP ; MOVF AARGB0,W ; MOVWF SIGN ; BTFSS AARGB0,MSB ; test sign ; GOTO NRM2424 ; COMF AARGB1,F ; if < 0, negate and set MSB in SIGN ; COMF AARGB0,F ; INCF AARGB1,F ; BTFSC _Z ; INCF AARGB0,F ;********************************************************************************************** ; Normalization routine ; Input: 24 bit unnormalized floating point number in AEXP, AARGB0, AARGB1, ; with sign in SIGN,MSB and other bits zero. ; Use: CALL NRM2424 or CALL NRM24 ; Output: 24 bit normalized floating point number in AEXP, AARGB0, AARGB1 ; Result: AARG <-- NORMALIZE( AARG ) ; Max Timing: 10+6+7*7+7 = 72 clks SAT = 0 ; 10+6+7*7+1+11 = 77 clks SAT = 1 ; Min Timing: 14 clks AARG = 0 ; 5+9+4 = 18 clks ; PM: 26 DM: 6 ;---------------------------------------------------------------------------------------------- NRM2424 NRM24 CLRF TEMP ; clear exponent decrement MOVF AARGB0,W ; test if highbyte=0 BTFSS _Z GOTO NORM2424 MOVF AARGB1,W ; if so, shift 8 bits by move MOVWF AARGB0 BTFSC _Z ; if highbyte=0, result=0 GOTO RES024 CLRF AARGB1 BSF TEMP,3 NORM2424 MOVF TEMP,W SUBWF EXP,F BTFSS _Z BTFSS _C GOTO SETFUN24 BCF _C ; clear carry bit NORM2424A BTFSC AARGB0,MSB ; if MSB=1, normalization done GOTO FIXSIGN24 RLF AARGB1,F ; otherwise, shift left and RLF AARGB0,F ; decrement EXP DECFSZ EXP,F GOTO NORM2424A GOTO SETFUN24 ; underflow if EXP=0 FIXSIGN24 BTFSS SIGN,MSB BCF AARGB0,MSB ; clear explicit MSB if positive RETLW 0 RES024 CLRF AARGB0 ; result equals zero CLRF AARGB1 CLRF AARGB2 ; clear extended byte CLRF EXP RETLW 0 ;********************************************************************************************** ;********************************************************************************************** ; Integer to float conversion ; Input: 24 bit 2's complement integer right justified in AARGB0, AARGB1, AARGB2 ; Use: CALL FLO2424 ; Output: 24 bit floating point number in AEXP, AARGB0, AARGB1 ; Result: AARG <-- FLOAT( AARG ) ; Max Timing: 14+94 = 108 clks RND = 0 ; 14+103 = 117 clks RND = 1, SAT = 0 ; 14+109 = 123 clks RND = 1, SAT = 1 ; Min Timing: 6+28 = 34 clks AARG = 0 ; 6+22 = 28 clks ; PM: 14+51 = 65 DM: 7 ;---------------------------------------------------------------------------------------------- FLO2424 MOVLW D'23'+EXPBIAS ; initialize exponent and add bias MOVWF EXP CLRF SIGN BTFSS AARGB0,MSB ; test sign GOTO NRM3224 COMF AARGB2,F ; if < 0, negate and set MSB in SIGN COMF AARGB1,F COMF AARGB0,F INCF AARGB2,F BTFSC _Z INCF AARGB1,F BTFSC _Z INCF AARGB0,F BSF SIGN,MSB ;********************************************************************************************** ; Normalization routine ; Input: 32 bit unnormalized floating point number in AEXP, AARGB0, AARGB1, ; AARGB2, with sign in SIGN,MSB ; Use: CALL NRM3224 ; Output: 24 bit normalized floating point number in AEXP, AARGB0, AARGB1 ; Result: AARG <-- NORMALIZE( AARG ) ; Max Timing: 21+6+7*8+7+4 = 94 clks RND = 0 ; 21+6+7*8+20+4 = 103 clks RND = 1, SAT = 0 ; 21+6+7*8+19+11 = 109 clks RND = 1, SAT = 1 ; Min Timing: 22+6 = 28 clks AARG = 0 ; 5+9+4+4 = 22 clks ; PM: 51 DM: 7 ;---------------------------------------------------------------------------------------------- NRM3224 CLRF TEMP ; clear exponent decrement MOVF AARGB0,W ; test if highbyte=0 BTFSS _Z GOTO NORM3224 MOVF AARGB1,W ; if so, shift 8 bits by move MOVWF AARGB0 MOVF AARGB2,W MOVWF AARGB1 CLRF AARGB2 BSF TEMP,3 ; increase decrement by 8 MOVF AARGB0,W ; test if highbyte=0 BTFSS _Z GOTO NORM3224 MOVF AARGB1,W ; if so, shift 8 bits by move MOVWF AARGB0 CLRF AARGB1 BCF TEMP,3 ; increase decrement by 8 BSF TEMP,4 MOVF AARGB0,W ; if highbyte=0, result=0 BTFSC _Z GOTO RES024 NORM3224 MOVF TEMP,W SUBWF EXP,F BTFSS _Z BTFSS _C GOTO SETFUN24 BCF _C ; clear carry bit NORM3224A BTFSC AARGB0,MSB ; if MSB=1, normalization done GOTO NRMRND3224 RLF AARGB2,F ; otherwise, shift left and RLF AARGB1,F ; decrement EXP RLF AARGB0,F DECFSZ EXP,F GOTO NORM3224A GOTO SETFUN24 ; underflow if EXP=0 NRMRND3224 BTFSC FPFLAGS,RND BTFSS AARGB1,LSB GOTO FIXSIGN24 BTFSS AARGB2,MSB ; round if next bit is set GOTO FIXSIGN24 INCF AARGB1,F BTFSC _Z INCF AARGB0,F BTFSS _Z ; has rounding caused carryout? GOTO FIXSIGN24 RRF AARGB0,F ; if so, right shift RRF AARGB1,F INCF EXP,F BTFSC _Z ; check for overflow GOTO SETFOV24 GOTO FIXSIGN24 ;********************************************************************************************** ;********************************************************************************************** ; Float to integer conversion ; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1 ; Use: CALL INT2424 ; Output: 24 bit 2's complement integer right justified in AARGB0, AARGB1, AARGB2 ; Result: AARG <-- INT( AARG ) ; Max Timing: 41+6*7+6+16 = 105 clks RND = 0 ; 41+6*7+6+24 = 113 clks RND = 1, SAT = 0 ; 41+6*7+6+26 = 115 clks RND = 1, SAT = 1 ; Min Timing: 5 clks ; PM: 82 DM: 6 ;---------------------------------------------------------------------------------------------- INT2424 CLRF AARGB2 MOVF EXP,W ; test for zero argument BTFSC _Z RETLW 0x00 MOVF AARGB0,W ; save sign in SIGN MOVWF SIGN BSF AARGB0,MSB ; make MSB explicit MOVLW EXPBIAS+D'23' ; remove bias from EXP SUBWF EXP,F BTFSS EXP,MSB GOTO SETIOV24 COMF EXP,F INCF EXP,F MOVLW 8 ; do byte shift if EXP >= 8 SUBWF EXP,W BTFSS _C GOTO TSHIFT2424 MOVWF EXP RLF AARGB2,F ; rotate next bit for rounding MOVF AARGB1,W MOVWF AARGB2 MOVF AARGB0,W MOVWF AARGB1 CLRF AARGB0 MOVLW 8 ; do another byte shift if EXP >= 8 SUBWF EXP,W BTFSS _C GOTO TSHIFT2424 MOVWF EXP RLF AARGB2,F ; rotate next bit for rounding MOVF AARGB1,W MOVWF AARGB2 CLRF AARGB1 MOVLW 8 ; do another byte shift if EXP >= 8 SUBWF EXP,W BTFSS _C GOTO TSHIFT2424 MOVWF EXP RLF AARGB2,F ; rotate next bit for rounding CLRF AARGB2 MOVF EXP,W BTFSS _Z BCF _C GOTO SHIFT2424OK TSHIFT2424 MOVF EXP,W ; shift completed if EXP = 0 BTFSC _Z GOTO SHIFT2424OK SHIFT2424 BCF _C RRF AARGB0,F ; right shift by EXP RRF AARGB1,F RRF AARGB2,F DECFSZ EXP,F GOTO SHIFT2424 SHIFT2424OK BTFSC FPFLAGS,RND BTFSS AARGB2,LSB GOTO INT2424OK BTFSS _C GOTO INT2424OK INCF AARGB2,F BTFSC _Z INCF AARGB1,F BTFSC _Z INCF AARGB0,F BTFSC AARGB0,MSB ; test for overflow GOTO SETIOV24 INT2424OK BTFSS SIGN,MSB ; if sign bit set, negate RETLW 0 COMF AARGB0,F COMF AARGB1,F COMF AARGB2,F INCF AARGB2,F BTFSC _Z INCF AARGB1,F BTFSC _Z INCF AARGB0,F RETLW 0 IRES024 CLRF AARGB0 ; integer result equals zero CLRF AARGB1 CLRF AARGB2 RETLW 0 SETIOV24 BSF FPFLAGS,IOV ; set integer overflow flag BTFSS FPFLAGS,SAT ; test for saturation ; RETLW 0xFF ; return error code in WREG GOTO SAI_ERRO; return error code in WREG CLRF AARGB0 ; saturate to largest two's BTFSS SIGN,MSB ; complement 24 bit integer MOVLW 0xFF MOVWF AARGB0 ; SIGN = 0, 0x 7F FF FF MOVWF AARGB1 ; SIGN = 1, 0x 80 00 00 MOVWF AARGB2 RLF SIGN,F RRF AARGB0,F ;RETLW 0xFF ; return error code in WREG GOTO SAI_ERRO; return error code in WREG ;********************************************************************************************** ;********************************************************************************************** ; Floating Point Multiply ; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1 ; 24 bit floating point number in BEXP, BARGB0, BARGB1 ; Use: CALL FPM24 ; Output: 24 bit floating point product in AEXP, AARGB0, AARGB1 ; Result: AARG <-- AARG * BARG ; Max Timing: 25+15*16+15+18 = 298 clks RND = 0 ; 25+15*16+15+29 = 309 clks RND = 1, SAT = 0 ; 25+15*16+15+33 = 313 clks RND = 1, SAT = 1 ; Min Timing: 6+5 = 11 clks AARG * BARG = 0 ; 24+15*11+14+15 = 218 clks ; PM: 80 DM: 11 ;---------------------------------------------------------------------------------------------- FPM24 MOVF AEXP,W ; test for zero arguments BTFSS _Z MOVF BEXP,W BTFSC _Z GOTO RES024 M24BNE0 MOVF AARGB0,W XORWF BARGB0,W MOVWF SIGN ; save sign in SIGN MOVF BEXP,W ADDWF EXP,F MOVLW EXPBIAS-1 BTFSS _C GOTO MTUN24 SUBWF EXP,F BTFSC _C GOTO SETFOV24 ; set multiply overflow flag GOTO MOK24 MTUN24 SUBWF EXP,F BTFSS _C GOTO SETFUN24 MOK24 MOVF AARGB0,W MOVWF AARGB2 ; move result to AARG MOVF AARGB1,W MOVWF AARGB3 BSF AARGB2,MSB ; make argument MSB's explicit BSF BARGB0,MSB BCF _C CLRF AARGB0 ; clear initial partial product CLRF AARGB1 MOVLW D'16' MOVWF TEMP ; initialize counter MLOOP24 BTFSS AARGB3,LSB ; test next bit GOTO MNOADD24 MADD24 MOVF BARGB1,W ADDWF AARGB1,F MOVF BARGB0,W BTFSC _C INCFSZ BARGB0,W ADDWF AARGB0,F MNOADD24 RRF AARGB0,F RRF AARGB1,F RRF AARGB2,F RRF AARGB3,F BCF _C DECFSZ TEMP,F GOTO MLOOP24 BTFSC AARGB0,MSB ; check for postnormalization GOTO MROUND24 RLF AARGB2,F RLF AARGB1,F RLF AARGB0,F DECF EXP,F MROUND24 BTFSC FPFLAGS,RND BTFSS AARGB1,LSB GOTO MUL24OK BTFSS AARGB2,MSB ; round if next bit is set GOTO MUL24OK INCF AARGB1,F BTFSC _Z INCF AARGB0,F BTFSS _Z ; has rounding caused carryout? GOTO MUL24OK RRF AARGB0,F ; if so, right shift RRF AARGB1,F INCF EXP,F BTFSC _Z ; check for overflow GOTO SETFOV24 MUL24OK BTFSS SIGN,MSB BCF AARGB0,MSB ; clear explicit MSB if positive RETLW 0 SETFOV24 BSF FPFLAGS,FOV ; set floating point underflag BTFSS FPFLAGS,SAT ; test for saturation ;RETLW 0xFF ; return error code in WREG GOTO SAI_ERRO; return error code in WREG MOVLW 0xFF MOVWF AEXP ; saturate to largest floating MOVWF AARGB0 ; point number = 0x FF 7F FF MOVWF AARGB1 ; modulo the appropriate sign bit RLF SIGN,F RRF AARGB0,F ;RETLW 0xFF ; return error code in WREG GOTO SAI_ERRO; return error code in WREG ;********************************************************************************************** ;********************************************************************************************** ; Floating Point Divide ; Input: 24 bit floating point dividend in AEXP, AARGB0, AARGB1 ; 24 bit floating point divisor in BEXP, BARGB0, BARGB1 ; Use: CALL FPD24 ; Output: 24 bit floating point quotient in AEXP, AARGB0, AARGB1 ; Result: AARG <-- AARG / BARG ; Max Timing: 32+13+15*26+25+12 = 472 clks RND = 0 ; 32+13+15*26+25+34 = 494 clks RND = 1, SAT = 0 ; 32+13+15*26+25+38 = 498 clks RND = 1, SAT = 1 ; Min Timing: 7+5 = 12 clks ; PM: 120 DM: 11 ;---------------------------------------------------------------------------------------------- FPD24 MOVF BEXP,W ; test for divide by zero BTFSC _Z GOTO SETFDZ24 MOVF AEXP,W BTFSC _Z GOTO RES024 D24BNE0 MOVF AARGB0,W XORWF BARGB0,W MOVWF SIGN ; save sign in SIGN BSF AARGB0,MSB ; make argument MSB's explicit BSF BARGB0,MSB TALIGN24 CLRF TEMP ; clear align increment MOVF AARGB0,W MOVWF AARGB2 ; test for alignment MOVF AARGB1,W MOVWF AARGB3 MOVF BARGB1,W SUBWF AARGB3, f MOVF BARGB0,W BTFSS _C INCFSZ BARGB0,W SUBWF AARGB2, f CLRF AARGB2 CLRF AARGB3 BTFSS _C GOTO DALIGN24OK BCF _C ; align if necessary RRF AARGB0,F RRF AARGB1,F RRF AARGB2,F MOVLW 0x01 MOVWF TEMP ; save align increment DALIGN24OK MOVF BEXP,W ; compare AEXP and BEXP SUBWF EXP,F BTFSS _C GOTO ALTB24 AGEB24 MOVLW EXPBIAS-1 ADDWF TEMP,W ADDWF EXP,F BTFSC _C GOTO SETFOV24 GOTO DARGOK24 ; set overflow flag ALTB24 MOVLW EXPBIAS-1 ADDWF TEMP,W ADDWF EXP,F BTFSS _C GOTO SETFUN24 ; set underflow flag DARGOK24 MOVLW D'16' ; initialize counter MOVWF TEMPB1 DLOOP24 RLF AARGB3,F ; left shift RLF AARGB2,F RLF AARGB1,F RLF AARGB0,F RLF TEMP,F MOVF BARGB1,W ; subtract SUBWF AARGB1,F MOVF BARGB0,W BTFSS _C INCFSZ BARGB0,W SUBWF AARGB0,F RLF BARGB0,W IORWF TEMP,F BTFSS TEMP,LSB ; test for restore GOTO DREST24 BSF AARGB3,LSB GOTO DOK24 DREST24 MOVF BARGB1,W ; restore if necessary ADDWF AARGB1,F MOVF BARGB0,W BTFSC _C INCF BARGB0,W ADDWF AARGB0,F BCF AARGB3,LSB DOK24 DECFSZ TEMPB1,F GOTO DLOOP24 DROUND24 BTFSC FPFLAGS,RND BTFSS AARGB3,LSB GOTO DIV24OK BCF _C RLF AARGB1,F ; compute next significant bit RLF AARGB0,F ; for rounding RLF TEMP,F MOVF BARGB1,W ; subtract SUBWF AARGB1,F MOVF BARGB0,W BTFSS _C INCFSZ BARGB0,W SUBWF AARGB0,F RLF BARGB0,W IORWF TEMP,W ANDLW 0x01 ADDWF AARGB3,F BTFSC _C INCF AARGB2,F BTFSS _Z ; test if rounding caused carryout GOTO DIV24OK RRF AARGB2,F RRF AARGB3,F INCF EXP,F BTFSC _Z ; test for overflow GOTO SETFOV24 DIV24OK BTFSS SIGN,MSB BCF AARGB2,MSB ; clear explicit MSB if positive MOVF AARGB2,W MOVWF AARGB0 ; move result to AARG MOVF AARGB3,W MOVWF AARGB1 RETLW 0 SETFUN24 BSF FPFLAGS,FUN ; set floating point underflag BTFSS FPFLAGS,SAT ; test for saturation ;RETLW 0xFF ; return error code in WREG GOTO SAI_ERRO; return error code in WREG MOVLW 0x01 ; saturate to smallest floating MOVWF AEXP ; point number = 0x 01 00 00 CLRF AARGB0 ; modulo the appropriate sign bit CLRF AARGB1 RLF SIGN,F RRF AARGB0,F ; RETLW 0XFF GOTO SAI_ERRO; return error code in WREG SETFDZ24 BSF FPFLAGS,FDZ ; set divide by zero flag ; RETLW 0xFF GOTO SAI_ERRO ;********************************************************************************************** ;********************************************************************************************** ; Floating Point Subtract ; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1 ; 24 bit floating point number in BEXP, BARGB0, BARGB1 ; Use: CALL FPS24 ; Output: 24 bit floating point sum in AEXP, AARGB0, AARGB1 ; Result: AARG <-- AARG - BARG ; Max Timing: 2+197 = 199 clks RND = 0 ; 2+208 = 210 clks RND = 1, SAT = 0 ; 2+213 = 215 clks RND = 1, SAT = 1 ; Min Timing: 2+12 = 14 clks ; PM: 2+112 = 114 DM: 11 ;---------------------------------------------------------------------------------------------- FPS24 MOVLW 0x80 XORWF BARGB0,F ;********************************************************************************************** ; Floating Point Add ; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1 ; 24 bit floating point number in BEXP, BARGB0, BARGB1 ; Use: CALL FPA24 ; Output: 24 bit floating point sum in AEXP, AARGB0, AARGB1 ; Result: AARG <-- AARG - BARG ; Max Timing: 25+28+6*6+5+31+72 = 197 clks RND = 0 ; 25+28+6*6+5+42+72 = 208 clks RND = 1, SAT = 0 ; 25+28+6*6+5+42+77 = 213 clks RND = 1, SAT = 1 ; Min Timing: 8+4 = 12 clks ; PM: 112 DM: 11 ;---------------------------------------------------------------------------------------------- FPA24 MOVF AARGB0,W ; exclusive or of signs in TEMP XORWF BARGB0,W MOVWF TEMP CLRF AARGB2 ; clear extended byte CLRF BARGB2 MOVF AEXP,W ; use AARG if AEXP >= BEXP SUBWF BEXP,W BTFSS _C GOTO USEA24 MOVF BEXP,W ; use BARG if AEXP < BEXP MOVWF AARGB4 ; therefore, swap AARG and BARG MOVF AEXP,W MOVWF BEXP MOVF AARGB4,W MOVWF AEXP MOVF BARGB0,W MOVWF AARGB4 MOVF AARGB0,W MOVWF BARGB0 MOVF AARGB4,W MOVWF AARGB0 MOVF BARGB1,W MOVWF AARGB4 MOVF AARGB1,W MOVWF BARGB1 MOVF AARGB4,W MOVWF AARGB1 USEA24 MOVF BEXP,W ; return AARG if BARG = 0 BTFSC _Z RETLW 0x00 MOVF AARGB0,W MOVWF SIGN ; save sign in SIGN BSF AARGB0,MSB ; make MSB's explicit BSF BARGB0,MSB MOVF BEXP,W ; compute shift count in BEXP SUBWF AEXP,W MOVWF BEXP BTFSC _Z GOTO ALIGNED24 MOVLW 8 SUBWF BEXP,W BTFSS _C ; if BEXP >= 8, do byte shift GOTO ALIGNB24 MOVWF BEXP MOVF BARGB1,W ; keep for postnormalization MOVWF BARGB2 MOVF BARGB0,W MOVWF BARGB1 CLRF BARGB0 MOVLW 8 SUBWF BEXP,W BTFSS _C ; if BEXP >= 8, BARG = 0 relative to AARG GOTO ALIGNB24 MOVF SIGN,W MOVWF AARGB0 RETLW 0x00 ALIGNB24 MOVF BEXP,W ; already aligned if BEXP = 0 BTFSC _Z GOTO ALIGNED24 ALOOPB24 BCF _C ; right shift by BEXP RRF BARGB0,F RRF BARGB1,F RRF BARGB2,F DECFSZ BEXP,F GOTO ALOOPB24 ALIGNED24 BTFSS TEMP,MSB ; negate if signs opposite GOTO AOK24 COMF BARGB2,F COMF BARGB1,F COMF BARGB0,F INCF BARGB2,F BTFSC _Z INCF BARGB1,F BTFSC _Z INCF BARGB0,F AOK24 MOVF BARGB2,W ADDWF AARGB2,F MOVF BARGB1,W BTFSC _C INCFSZ BARGB1,W ADDWF AARGB1,F MOVF BARGB0,W BTFSC _C INCFSZ BARGB0,W ADDWF AARGB0,F BTFSC TEMP,MSB GOTO ACOMP24 BTFSS _C GOTO NRMRND3224 RRF AARGB0,F ; shift right and increment EXP RRF AARGB1,F RRF AARGB2,F INCFSZ AEXP,F GOTO NRMRND3224 GOTO SETFOV24 ACOMP24 BTFSC _C GOTO NRM3224 ; normalize and fix sign COMF AARGB2,F COMF AARGB1,F ; negate, toggle sign bit and COMF AARGB0,F ; then normalize INCF AARGB2,F BTFSC _Z INCF AARGB1,F BTFSC _Z INCF AARGB0,F MOVLW 0x80 XORWF SIGN,F GOTO NRM24 SAI_ERRO IORWF FPE,F RETLW 0XFF ; FIM DA BIBLIOTECA DE PONTO FLUTUANTE (ADAPTADA) ;==================================================================================== ;CARGA PRÉVIA DA EEPROM ORG 0x2100 NOMEPROG de " LC_METER_TINY ",0 BLOG de "LARIOS.TECNOL.WS",0 F_FAIXA de " L ?",0 UNF de " nF",0 UPF de " pF",0 UMH de " mH",0 UUH de " uH",0 CAP de "C = ",0 IND de "L = ",0 CALIBRANDO de "...CALIBRANDO!!!",0 VC_CAL de "C_Cal = 0X",0 CAL de 0X27,0X10,0 ;2710 UPP de "SE'L'UNIR PONTAS",0 ;2710 ;===================================================================================== END ;FIM DO PROGRAMA (UFA! QUASE QUE NÃO COUBE EM 1024 BYTES!)