List p=18f458
 #include "p18f458.inc"
V1     equ 0x100  ; Registro para guardar ADRESH del conv AD..corresponidente a V1
V1H    equ 0x101
V1L    equ 0x102 
V2     equ 0x103  ;Registro para guardar ADRESH del conv AD..corresponidente a V2
V2H    equ 0x104
V2L    equ 0x105
V3     equ 0x106  ;Registro para guardar ADRESH del conv AD..corresponidente a V3
V3H    equ 0x107
V3L    equ 0x108
I1     equ 0x109  ;Registro para guardar ADRESH del conv AD..corresponidente a I1
I1H    equ 0x10A  
I1L    equ 0x10B
I2     equ 0x10C  ;Registro para guardar ADRESH del conv AD..corresponidente a I2
I2H    equ 0x10D
I2L    equ 0x10E
I3     equ 0x10F  ;Registro para guardar ADRESH del conv AD..corresponidente a I3
I3H    equ 0x110
I3L    equ 0x111
COUNT  equ 0x112 ; Registro contador para retardo y espera del tiempo de adquisición
A1     equ 0x113 ; W1 byte menos significativo(1)
A2     equ 0x114 ; W1 byte (2)
A3     equ 0x115 ; W1 Byte (3)
A4     equ 0x116 ; W1 byte(4):
B1     equ 0x117 ; W2 byte menos significativo (1)
B2     equ 0x118 ; W2 byte (2)
B3     equ 0x119 ; W2 byte (3)
B4     equ 0x11A ; W2 byte (4).
C1     equ 0x11B ; W3 byte menos significativo (1)
C2     equ 0x11C ; W3 byte (2)
C3     equ 0x11D ; W3 byte (3)
C4     equ 0x11E ; W3 byte (4).
AUX1   equ 0x11F ; Suma W1+W2(A+B).byte (1).
AUX2   equ 0x120 ; suma W1+W2 (A+B).byte (2)
AUX3   equ 0x121 ; suma W1+W2 (A+B).byte (3)
AUX4   equ 0x122 ; suma W1+W2 (A+B).byte (4).
D1     equ 0x123 ; WT byte (1) .
D2     equ 0x124 ; WT byte (2)
D3     equ 0x125 ; WT byte (3)
D4     equ 0x126 ; WT byte (4). 
CARRY  equ 0x127 ; Registro de acarreo para la suma (A+B) W1+W2
ACARREO equ 0x128; Registro de acarreo para la suma de (AUX + C)= WT.  
BCD_0    equ  0x129
BCD_1    equ  0x12A 
BCD_2    equ  0x12B
BCD_3    equ  0x12C  ; Registros para almacenar dato BCD de 8 digitos..Este dato corresponde a la potencia Total q se enviará Via USART
MSNIB    equ  0x12D  ; registro para conteo de bits en la conv BIN to BCD
LSNIB   equ  0x12E
delay   equ  0x12F
PDel0   equ  0x130
PDel1   equ  0x131
PDel2   equ  0x132
data1 equ 0x133
data2 equ 0x134
data3 equ 0x135
data4 equ 0x136
conta equ 0x137
DATO  equ 0x138
 ORG 0x0000
 goto INICIO
; org 0x0008
 ;goto inter
 ORG 0X001A
TX_DATO   bcf   PIR1,TXIF
          movwf TXREG
          
          banksel TXSTA
TX_DAT    clrwdt
          btfss   TXSTA,TRMT
          goto    TX_DAT
          return
RECIBE			movf	RCREG,W		;Limpia el registro receptor
				bcf	PIR1,RCIF	;Restaura el flag del receptor
Leer_Car_Wait	clrwdt
				btfss	PIR1,RCIF	;Se ha recibido un carácter ?
				goto	Leer_Car_Wait	;Todavía no, esperar
				movf	RCREG,W		;Si, leer el carácter
				movwf	DATO	;Salvarlo
				return
;***************************
INICIO 
         clrwdt 
		 banksel PORTC        
         clrf     PORTC
         clrf     PORTB
         clrf     PORTD
         clrf     TRISB ; PUERTA B COMO SALIDA
         clrf     TRISD ; PUERTA D COMO SALIDA
         movlw    b'10111111'
         movwf    TRISC  ; RC7/RX como entrada, RC6/TX como salida.
         movlw    b'00100100'
         movwf    TXSTA       ; TX ON, modo asincrono 8 bits 
         movlw     .25
         movwf    SPBRG       ; 9600 baudios con Fosc=4Mhz...asincrono
         bsf      PIE1,RCIE    ; habilita interrupción en la recepción
         movlw    b'10010000'
         movwf    RCSTA         ; USART ON , recepción continua,sincrono
         bsf      INTCON,PEIE   ;HAB INTERRUPCION DE PERIFERICOS
         bsf      INTCON,GIE    ; ACTIVA INTERRUPCIONES GLOBALES
         clrf conta
;loop     clrwdt
 ;        goto loop     
           
;*************  PROGRAMA PRINCIPAL *****************************
;*************CONVERSION DE CANAL CERO(0) ANALOGICO************
           
           movlw   0xFF    
           movwf   TRISA      ; Pines PortA como entradas
           movlw   b'00000001'
           movwf   TRISE      ; ----RE0 ENTRADA Y RE1 RE2 COMO SALIDAS----
;*////////////////////////////////////// 
;*****INICIA RECEPCION DE DATOS DESDE TX*******************
BUCLE                       CALL 	            RECIBE   ; recibe byte 1
		CALL    TX_DATO  ; envia para visualizar en PC
		clrwdt
		call    RECIBE ; recibe byte 2
        CALL TX_DATO
        CLRWDT
        CALL RECIBE  ; recibe byte 3
        CALL TX_DATO
        clrwdt
       ; CALL RECIBE ; recibe byte 4
        ;CALL TX_DATO
           
           movlw   b'10001001';            
           movwf   ADCON1     ; AD justificado a la derecha.pines AN0-AN5 como pines 
           clrwdt
           movlw   b'01000001'
           movwf   ADCON0      ; HAB A/D.CANAL 0. Fosc/8
           bcf     PIR1,ADIF ; Borra el flag de fin de conv AD
           banksel COUNT     ; ubicacion en el banco de COUNT
           movlw   0x30
           movwf   COUNT       ; carga 0x06 al registro COUNT
LOOP       decfsz  COUNT,f    ; decrementa y guarda en COUNT y salta si COUNT=0
           goto    LOOP        ; ESPERA TIEMPO DE ADQUISICION
           banksel ADCON0
           bsf     ADCON0,GO  ; da la orden de INICIO de CONVERSION
ADC_WAIT   CLRWDT
           btfss   PIR1,ADIF ;  Fin de conversión?
           goto    ADC_WAIT   ; aún no!
           call    MOV_V1     ; subrutina para mover  el valor obtenido al registro V1
;******** CONVERSIÓN DE CANAL 1 ANALÓGICO***************
           banksel ADCON0
           movlw   b'01001001' 
           movwf   ADCON0 ; HAB A/D . canal 1. Fosc /8
           bcf     PIR1,ADIF ; borra flag  de fin de conc AD
           banksel COUNT
           movlw   0x30
           movwf   COUNT
LOOP1      decfsz  COUNT,f ; decrementa COUNT y guarda en COUNT. salta si COUNT =0
           goto    LOOP1    ; ESPERA TIEMPO DE ADQUISICION
           banksel ADCON0
           bsf     ADCON0,GO; orden de inicio de conversión.
ADC_WAIT1  CLRWDT
           btfss   PIR1,ADIF ; fin de conversión?
           goto    ADC_WAIT1 ; aún no!
           call    MOV_I1    ; subrutina para mover  el valor obtenido al registro I1
;**********CONVERSION DE  CANAL 2 ANALOGICO***************
           banksel ADCON0
           movlw   b'01010001' 
           movwf   ADCON0 ; HAB A/D . canal 2. Fosc /8
           bcf     PIR1,ADIF ; borra flag  de fin de conc AD
           banksel COUNT
           movlw   0x30
           movwf   COUNT
LOOP2      decfsz  COUNT,f ; decrementa COUNT y guarda en COUNT. salta si COUNT =0
           goto    LOOP2    ; ESPERA TIEMPO DE ADQUISICION
           banksel ADCON0
           bsf     ADCON0,GO; orden de inicio de conversión.
ADC_WAIT2  CLRWDT
		   btfss   PIR1,ADIF ; fin de conversión?
           goto    ADC_WAIT2 ; aún no!
           call    MOV_V2     ; subrutina para mover  el valor obtenido al registro V2
;**************CONVERSIÓN DE CANAL 3 ANALÓGICO********************
           banksel ADCON0
           movlw   b'01011001' 
           movwf   ADCON0 ; HAB A/D . canal 3. Fosc /8
           bcf     PIR1,ADIF ; borra flag  de fin de conc AD
           banksel COUNT
           movlw   0x30
           movwf   COUNT
LOOP3      decfsz  COUNT,f ; decrementa COUNT y guarda en COUNT. salta si COUNT =0
           goto    LOOP3    ; ESPERA TIEMPO DE ADQUISICION
           banksel ADCON0
           bsf     ADCON0,GO; orden de inicio de conversión.
ADC_WAIT3  CLRWDT
           btfss   PIR1,ADIF ; fin de conversión?
           goto    ADC_WAIT3 ; aún no!
           call    MOV_I2     ; subrutina para mover  el valor obtenido al registro I2
;*******CONVERSIÓN CANAL 4 ANALÓGICO*****************************
          banksel ADCON0
           movlw   b'01100001' 
           movwf   ADCON0 ; HAB A/D . canal 4. Fosc /8
           bcf     PIR1,ADIF ; borra flag  de fin de conc AD
           banksel COUNT
           movlw   0x30
           movwf   COUNT
LOOP4      decfsz  COUNT,f    ; decrementa COUNT y guarda en COUNT. salta si COUNT =0
           goto    LOOP4      ; ESPERA TIEMPO DE ADQUISICION
           banksel ADCON0
           bsf     ADCON0,GO  ; orden de inicio de conversión.
ADC_WAIT4  CLRWDT
           btfss   PIR1,ADIF  ; fin de conversión?
           goto    ADC_WAIT4  ; aún no!
           call    MOV_V3     ; subrutina para mover  el valor obtenido al registro V3
;******CONVERSION CANAL 5 ANALÓGICO*********************************
           banksel ADCON0
           movlw   b'01101001' 
           movwf   ADCON0    ; HAB A/D . canal 5. Fosc /8
           bcf     PIR1,ADIF ; borra flag  de fin de conc AD
           banksel COUNT
           movlw   0x30
           movwf   COUNT
LOOP5      decfsz  COUNT,f   ; decrementa COUNT y guarda en COUNT. salta si COUNT =0
           goto    LOOP5      ; ESPERA TIEMPO DE ADQUISICION
           banksel ADCON0
           bsf     ADCON0,GO  ; orden de inicio de conversión.
ADC_WAIT5  CLRWDT
           btfss   PIR1,ADIF  ; fin de conversión?
           goto    ADC_WAIT5  ; aún no!
           call    MOV_I3     ; subrutina para mover  el valor obtenido al registro 
; ****LLAMA A LAS SUBRUTINAS PARA MULTIPLICAR LOS RESULTADOS DE V*I Y OBTENER LA POTENCIA TOTAL
           call    MULT       ; subrutina de acondicionamiento de la señal.. se multiplica V*100 e I*200 para obtener un máx
                              ; de 220V y 1A(por cada mv respectivamente.
           call    OBT_A      ; Multiplica V1H-L*I1H-L---->A =W1         
           call    OBT_B      ; Mutiplica  V2H-L*I2H-L---->B =W2
           call    OBT_C      ; Multiplica V3H-L*I3H-L---->C =W3
           call    OBT_AUX    ; suma W1+W2(a+b)->AUX
           call    OBT_Wtotal ; suma Aux+C-> D  
           banksel ADCON0
           CLRWDT
           
         
           goto    BUCLE     ; INICIA LA RECEPCION Y CONVERSION DE DATOS EN CADA CANAL NUEVAMENTE
;*********************************************************************
; ******************* SUBRUTINAS *************************************** 
MOV_V1                          ;========= Mueven a V1,V2,V3 e I1 I2 I3 el valor obtenido en ADRESL==========
         banksel ADRESL         ;=================se garantiza un valor max de 255 a traves del hardware (1.2Vinmax)===
         movff   ADRESL,V1; ADRESL->V1
         return  ; retorna a la siguiente instrucción, ubicada despues de la llamada a subrutina
MOV_I1   
         banksel ADRESL
         movff   ADRESL, I1; ADRESL->I1
         return
MOV_V2   
         banksel ADRESL
         movff   ADRESL, V2; ADRESL->V2
         return
MOV_I2   
         banksel ADRESL
         movff   ADRESL,I2; ADRESL->I2
         return  ; retorna a la siguiente instrucción, ubicada despues de la llamada a subrutina
 
MOV_V3   
         banksel ADRESL
         movff   ADRESL,V3;  ADRESL->V3
         return  ; retorna a la siguiente instrucción, ubicada despues de la llamada a subrutina
MOV_I3   
         banksel ADRESL
         movff   ADRESL,I3; ADRESL->I3
         return  ; retorna a la siguiente instrucción, ubicada despues de la llamada a subrutina
;********************************************************************
MULT    
        banksel V1
        movlw   .96  ; *********************    ADvoltaje*48*2 debido a la resolución!
        mulwf   V1 ; V1*96  -> PRODH_L          ; ADintensidad *48 
        banksel PRODH                           ; al multiplicar V*I se obtiene W en unidades de ((mW)).... 
        movff   PRODH,V1H ; PRODH->V1H          ; 
        movff   PRODL,V1L ; PRODl->V1L           
        banksel I1
        movlw   .48  ;*******************
        mulwf   I1    ; I1*48 -> PRODH_L
        banksel PRODH
        movff   PRODH,I1H ; PRODH->I1H
        movff   PRODL,I1L ; PRODL-> I1L
;****************************V2(48*2) e I2(48)**************************************
        banksel V2
        movlw   .96; *********************
        mulwf   V2 ; V2*96-> PRODH_L
        banksel PRODH
        movff   PRODH,V2H ; PRODH->V2H
        movff   PRODL,V2L ; PRODL->V2L
        banksel I2
        movlw   .48   ;*******************
        mulwf   I2 ; I2*48 -> PRODH_L
        banksel PRODH
        movff   PRODH,I2H ; PRODH->I2H
        movff   PRODL,I2L ; PRODL->I2L
;***************************V3(48*2) e I3(48)********************************
        banksel V3
        movlw   .96; *********************
        mulwf   V3 ; V3*96-> PRODH_L
        banksel PRODH
        movff   PRODH,V3H ; PRODH->V3H
        movff   PRODL,V3L ; PRODl->V3L
        banksel I3
        movlw   .48    ;*******************
        mulwf   I3 ; I3*48 -> PRODH_L
        banksel PRODH
        movff   PRODH,I3H ; PRODH->I3H
        movff   PRODL,I3L ; PRODL-> I3L
       return ; fin de subrutina
;====== SUBRUTINA PARA OBTENER A=W1(V1H_L * I1H_L) A4 MSbyte============
OBT_A
       banksel V1L
       movf     V1L,W
       mulwf    I1L
       movff    PRODH,A2
       movff    PRODL,A1
       movf     V1H,W
       mulwf    I1H
       movff    PRODH,A4
       movff    PRODL,A3
   
      movf      V1L ,W
      mulwf     I1H
 
       movf     PRODL,W
       addwf    A2
       movf     PRODH,W
       addwfc   A3
       clrf     WREG
       addwfc   A4
       
       movf     V1H,W
       mulwf    I1L
       movf     PRODL,W
       addwf    A2
       movf     PRODH,W
       addwfc    A3,1
       clrf     WREG
       addwfc   A4
 return; fin de subrutina
;====SUBRUTINA PARA OBTENER B=W2(V2H_L * I2H_L)  B4 MSByte======
OBT_B
       banksel V2L
       movf     V2L,W
       mulwf    I2L
       movff    PRODH,B2
       movff    PRODL,B1
       movf     V2H,W
       mulwf    I2H
       movff    PRODH,B4
       movff    PRODL,B3
   
      movf      V2L ,W
      mulwf     I2H
 
       movf     PRODL,W
       addwf    B2
       movf     PRODH,W
       addwfc    B3
       clrf     WREG
       addwfc   B4
       
       movf     V2H,W
       mulwf    I2L
       movf     PRODL,W
       addwf    B2
       movf     PRODH,W
       addwfc    B3
       clrf     WREG
       addwfc   B4
 return; fin de subrutina
;==SUBRUTINA PARA OBTENER C=W3 (V3H_L * I3H_L) C4 MSByte =============
OBT_C
       banksel V3L
       movf     V3L,W
       mulwf    I3L
       movff    PRODH,C2
       movff    PRODL,C1
       movf     V3H,W
       mulwf    I3H
       movff    PRODH,C4
       movff    PRODL,C3
   
      movf      V3L ,W
      mulwf     I3H
 
       movf     PRODL,W
       addwf    C2
       movf     PRODH,W
       addwfc    C3
       clrf     WREG
       addwfc   C4
       
       movf     V3H,W
       mulwf    I3L
       movf     PRODL,W
       addwf    C2
       movf     PRODH,W
       addwfc    C3
       clrf     WREG
       addwfc   C4
 return; fin de subrutina
;***********-----Aux=A+B------- *********************
OBT_AUX  
         banksel CARRY
         clrf    CARRY
         banksel A1
         movf    A1,W
         addwf   B1,W
         movwf   AUX1
         btfsc   STATUS,C   ; acarreo?
         goto    INC_CARRY1 ; Si!
UNO      movf    A2,W       ; NO
         addwf   B2,W  
         movwf   AUX2
         btfsc   STATUS,C ; ACARREO?
         goto    INC_CARRY2 ; si!
DOS      movf    A3, W
         addwf   B3,W
         movwf   AUX3
         btfsc   STATUS,C; acarreo?
         goto    INC_CARRY3 ;SI!
TRES     movf    A4,W
         addwf   B4,W
         movwf   AUX4
         btfsc   STATUS,C; acarreo?
         incf    CARRY
         goto    FINISH
INC_CARRY1 incf A2
           btfsc STATUS,Z; acarreo?
           incf A3 ; si!
           goto UNO ; NO
INC_CARRY2 incf A3
           btfsc STATUS,Z; acarreo?
           incf A4
           goto DOS
INC_CARRY3 incf A4
           btfsc STATUS,Z ; acarreo?
           incf CARRY
           goto TRES 
FINISH     return
;****************------D=Aux+C=Wtotal--------***********************
OBT_Wtotal
           banksel AUX1
           movf AUX1,W
           addwf C1, W
           movwf D1
           btfsc STATUS,C ; acarreo?
           goto CARRY1
ONE        movf AUX2,W
           addwf C2,W
           movwf D2
           btfsc STATUS,C; ACARREO?
           goto CARRY2
TWO        movf AUX3, W
           addwf C3,W
           movwf D3
           btfsc STATUS,C
           goto CARRY3
THREE      movf AUX4,W
           addwf C4,W
           movwf D4
           btfsc STATUS,C; acarreo?
           incf ACARREO 
           goto FIN
CARRY1    incf AUX2
          btfsc STATUS,Z; acarreo?
          incf AUX3
          goto ONE
 
CARRY2    incf AUX3
          btfsc STATUS,Z; acarreo?
          incf AUX4
          goto TWO
CARRY3    incf AUX4
          btfsc STATUS,Z; acarreo?
          incf ACARREO
          goto THREE
FIN       return 
           
 end ; fin del programa