torres.electronico
Well-known-Alfil
El compañero tiene razón, puede que no todos usen el mismo visualizador de pdf o estén en el movil, desde KiCad exporte con trazar para que todo el texto del pdf sea seleccionable. aun así les comparto el hex para que lo tengan a la mano.
no compartí código y simulación porque mi intensión era que no lidien con el compilador o el simulador como en las respuestas anteriores y puedan simplemente armarlo. por las limitaciones del 628A no veo que mas se pueda mejorar a parte de variar el tiempo de peak o barra si es el caso. el 628A espacio tiene, pero pines ya no, a menos sino se quiere usar hardware adicional.
El programa lo desarrolle en MPLAB X actual, no uso CSS u PicPRO asi que estoy perdido en eso y no domino mucho C. mi entención inicial era compartir el codigo completo por eso esta comentado y dedicado al Foro como al autor a modo de agradecimiento por todo lo que aprendi pero asm no es muy común hoy en día, asi que se me ocurrio meter todo en el pdf, en fin.
respecto al uso del comparador y el mux interno tuve que leerme varias veces el manual ya que cada modificación en CMON debe esperar 10uS y seguir una secuencia o las 4 entradas se mezclaran con datos uno del otro, como pueden deducir se tiene 4 canales de ADC de 4 bits ya que la configuración del MUX interno te obliga a usar todas las entradas que ya no podrán ser salidas digitales, por eso esos pines en el PCB esta a gnd es mejor leer 0 a un valor aleatorio si llegase a suceder por error claro esta, asi como otras de cosas varias, como usar Power-up. el autor usa ISR eso ayuda a que el programa siga incrementandose es decir puedes implementar mas cosas y dejar el vumetro trabajar. podria explicar mas cosas pero temo se extienda mas la respuesta que de por si ya lleva codigo abajo.
un ejemplo usando las 4 entradas, el 595 superior son los teclados, el inferior las entrada con señal, cada uno cubre 4bits de los 16bits que suma ambos 595. mejor lo adjunto tambien para que puedan simularlo.
Ver el archivo adjunto 339436
pero bueno... servido esta, comparto el código completo en asm y simulación del VU12LD628AV2. disculpen el espanglish y la falta de mas comentarios en el código eso lo deje a medias.
Código:;--------------------------------------------------------; ; VU meter estéreo - 2x12 LED (multiplexado) ; ; con el PIC16F628A ; ;--------------------------------------------------------; ; Datos ajustables: ; ; - Seleccionable entre Punto/barra con o sin peak. ; ; - guarda el modo seleccionado en la EEPROM. ; ;--------------------------------------------------------; ; Basado en el algoritmo de s-o.webnode.cz ; ; para fines no comerciales. ; ; www.Forosdelectronia.com ; ;--------------------------------------------------------; ; Versión : 1.1A2 KSST 07/25 ; ;--------------------------------------------------------; PROCESSOR 16F628A #include <xc.inc> CONFIG FOSC = INTOSCIO ; Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) CONFIG WDTE = ON ; Watchdog Timer Enable bit (WDT enabled) CONFIG PWRTE = ON ; Power-up Timer Enable bit (PWRT enabled) CONFIG MCLRE = OFF ; RA5/MCLR/VPP PinS Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) CONFIG BOREN = OFF ; Brown-out Detect Enable bit (BOD disabled) CONFIG LVP = OFF ; Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) CONFIG CPD = OFF ; Data EE Memory Code Protection bit (Data memory code protection off) CONFIG CP = OFF ; Flash Program Memory Code Protection bit (Code protection off) C equ STATUS_C_POSITION Z equ STATUS_Z_POSITION PSECT udata_bank0 Position: DS 1 ; Position Multiplex (anodos PORTA) LLSB: DS 1 ; LSB 8 LED L LMSB: DS 1 ; MSB 4 LED L RLSB: DS 1 ; LSB 8 LED R RMSB: DS 1 ; MSB 4 LED R PNT1: DS 1 ; nivel general de point para L y R PNT2: DS 1 ; BAR1: DS 1 ; nivel general de bar para L y R BAR2: DS 1 ; LPNT1: DS 1 ; sobreescribe RAM (descenso artificial de L) LPNT2: DS 1 ; LBAR1: DS 1 ; dato a mostrar del cátodo L LBAR2: DS 1 ; LRAM1: DS 1 ; RAM peak L LRAM2: DS 1 ; RPNT1: DS 1 ; sobreescribe RAM (descenso artificial de R) RPNT2: DS 1 ; RBAR1: DS 1 ; dato a mostrar del cátodo R RBAR2: DS 1 ; RRAM1: DS 1 ; RAM peak R RRAM2: DS 1 ; LPRM1: DS 1 ; RAM point L LPRM2: DS 1 ; RPRM1: DS 1 ; RAM point R RPRM2: DS 1 ; LBRM1: DS 1 ; RAM bar L LBRM2: DS 1 ; RBRM1: DS 1 ; RAM bar R RBRM2: DS 1 ; LPSV1: DS 1 ; dato a mostrar para punto L LPSV2: DS 1 ; RPSV1: DS 1 ; dato a mostrar para punto R RPSV2: DS 1 ; LTML: DS 1 ; timer PAM L (la primera vez con 500ms) LTMH: DS 1 ; RTML: DS 1 ; timer PAM R (LTMx x2) RTMH: DS 1 ; LPTM: DS 1 ; point time RPTM: DS 1 ; LBRM: DS 1 ; bar time RBRM: DS 1 ; DTMODE: DS 1 ; Mode dato de 2bits SWPPCB: DS 1 ; SWAP de bits (cátodos) para el PCB V12LD628AV2 PSECT udata_shr MemSTATUS: DS 1 ; Guarda STATUS temporal MemPCLATH: DS 1 ; Guarda PCLATH temporal EEADRp: DS 1 ; EEPROM Auxiliary address MemW: DS 1 ; REG W data memory saved SVData: DS 1 ; EEPROM data to be saved JMPSL: DS 1 ; Selector de Modo TEMP: DS 1 ; Valor de AN1 ANNDRL: DS 1 ; Valor de AN0 ANNDRR: DS 1 ; Valor de AN0 CTCOMP: DS 1 ; contador de VRCON 0-F TPCM: DS 1 ; Valor Temporal de CMCON ;************************************************* ; EEPROM Address = 0x0E | default = bar + peak ; |-------------------------------------------| ; | bar | point | peak+pt | peak+bar | ; |----------|----------|----------|----------| ; | xxxxxx00 | xxxxxx01 | xxxxxx10 | xxxxxx11 | ; |-------------------------------------------| ;************************************************* PSECT PM1, class=code,delta=2,abs ; PIC10/12/16 ORG 0x0000 GOTO PM1 PSECT ISR, class=code,delta=2,abs,reloc=4 ORG 0x0004 ;-------------------------------------------; ; Guarda PCL ; ;-------------------------------------------; MOVWF MemW SWAPF STATUS,W CLRF STATUS MOVWF MemSTATUS MOVF PCLATH,W MOVWF MemPCLATH ;-------------------------------------------; BTFSC INTCON,2 ;TMR0=1? GOTO ITMR0 ;si GOTO EINT ITMR0: BCF INTCON,2 ;off TMR0IF ; SWAPF LMSB,F ;intercambia bytes LSB a MSB ;(solo aplica para el PCB V12LD628A) ;-------------------------------------------; ; solo aplica para el orden de cátodos en ; ; anodo RA4 para el PCB V12LD628AV2 ; ;-------------------------------------------; MOVF LMSB,W MOVWF SWPPCB RLF SWPPCB,F RRF LMSB,F RLF SWPPCB,F RRF LMSB,F RLF SWPPCB,F RRF LMSB,F RLF SWPPCB,F RRF LMSB,F RLF SWPPCB,F RRF LMSB,F RLF SWPPCB,F RRF LMSB,F RLF SWPPCB,F RRF LMSB,F RLF SWPPCB,F RRF LMSB,F SWAPF RMSB,F MOVF RMSB,W MOVWF SWPPCB RLF SWPPCB,F RRF RMSB,F RLF SWPPCB,F RRF RMSB,F RLF SWPPCB,F RRF RMSB,F RLF SWPPCB,F RRF RMSB,F RLF SWPPCB,F RRF RMSB,F RLF SWPPCB,F RRF RMSB,F RLF SWPPCB,F RRF RMSB,F RLF SWPPCB,F RRF RMSB,F ;-------------------------------------------; ;Memory Peak L DECFSZ LTML,F ;LTML=0? GOTO NXT1 ;no DECFSZ LTMH,F ;LTMH=0? GOTO NXT1 ;no BSF STATUS,C RRF LRAM2,F ;rotar derecha L MSB RRF LRAM1,F ;rotar derecha L LSB(deciende peak) MOVLW 45 ;timeL MOVWF LTML ;(40ms) MOVLW 1 ;timeH MOVWF LTMH ;(xms) ;Memory Peak R NXT1: DECFSZ RTML,F ;RTML=0? GOTO NXT2 ;no DECFSZ RTMH,F ;RTMH=0? GOTO NXT2 ;no BSF STATUS,C RRF RRAM2,F ;rotar derecha R MSB RRF RRAM1,F ;rotar derecha R LSB(deciende peak) MOVLW 45 ;timeL MOVWF RTML ;(40ms) MOVLW 1 ;timeH MOVWF RTMH ;(xms) ;Memory point L NXT2: DECFSZ LPTM,F ;LPTM=0? GOTO NXT3 ;no BSF STATUS,C RRF LPRM2,F ;rotar derecha R LSB RRF LPRM1,F ;rotar derecha R MSB MOVLW 40 ;timeL MOVWF LPTM ;(40ms) ;Memory point R NXT3: DECFSZ RPTM,F ;RPTM=0? GOTO NXT4 ;no BSF STATUS,C RRF RPRM2,F ;rotar derecha R LSB RRF RPRM1,F ;rotar derecha R MSB MOVLW 40 ;timeL MOVWF RPTM ;(40ms) ;Memory bar L NXT4: DECFSZ LBRM,F ;LBRM=0? GOTO NXT5 ;no BSF STATUS,C RRF LBRM2,F ;rotar derecha R LSB RRF LBRM1,F ;rotar derecha R MSB MOVLW 20 ;timeL MOVWF LBRM ;(40ms) ;Memory bar R NXT5: DECFSZ RBRM,F ;RBRM=0? GOTO NXT6 ;no BSF STATUS,C RRF RBRM2,F ;rotar derecha R LSB RRF RBRM1,F ;rotar derecha R MSB MOVLW 20 ;timeL MOVWF RBRM ;(40ms) NXT6: MOVLW 0b00001111 MOVWF PORTA ;turn off all Anode MOVLW LLSB ;Dirección de FSR (LLSB es 0x23 FSR). MOVWF FSR ;FSR apunta a valor inicial de Position. MOVF Position,W ;guarda valor incial. ADDWF FSR,F ;actualiza Position. MOVF INDF,W ;Lee FSR. MOVWF PORTB ;carga el valor de 8bit o 4bit del VU (cátodos). CALL Anode ;Carga el nuevo valor de Anode MOVWF PORTA ;al PORTA (anodos). INCF Position,F ;incremeta Position. MOVLW 0x03 ;limitador de 2 bits (0-3) ANDWF Position,F ;recorta bits 4-7 en Position. ;-------------------------------------------; ; Restauración de PCL ; ;-------------------------------------------; EINT: MOVF MemPCLATH,W MOVWF PCLATH SWAPF MemSTATUS,W MOVWF STATUS SWAPF MemW,F SWAPF MemW,W RETFIE ;-------------------------------------------; ;-------------------------------------------; ; ////////////// Rutinas ///////////// ;-------------------------------------------; ;position tabla (Anodos) Anode: MOVF Position,W ANDLW 0x03 ADDWF PCL,F RETLW 0b10000000 ;Anode0 = L LSB RETLW 0b00010000 ;Anode1 = L MSB RETLW 0b01000000 ;Anode2 = R LSB RETLW 0b00010000 ;Anode3 = R MSB ; PORTx 76543210 ;-------------------------------------------; ;Leer EEPROM ERead: CLRWDT BANKSEL EEADR MOVF EEADRp,W MOVWF EEADR BANKSEL EECON1 BSF EECON1,0 BTFSC EECON1,0 GOTO $-1 BANKSEL EEDATA MOVF EEDATA,W BANKSEL EEADRp RETURN ;-------------------------------------------; ;Escribir EEPROM EWrite: CLRWDT BANKSEL EEADR MOVLW 0x0E MOVWF EEADR BANKSEL SVData MOVF SVData,W BANKSEL EEDATA MOVWF EEDATA BANKSEL EECON1 BSF EECON1,2 MOVLW 0x55 MOVWF EECON2 MOVLW 0xAA MOVWF EECON2 BSF EECON1,1 BTFSC EECON1,1 GOTO $-1 BCF EECON1,2 BCF EECON1,7 BANKSEL EEADRp RETURN ;------------------------------------ ;Logaritmo conversor de adc a nivel LOG: CLRWDT MOVLW 0xFF ;todo en OFF MOVWF PNT1 ; MOVWF PNT2 ; CLRF BAR1 ;00000000, Todo en ON MOVLW 0xF0 ;mascara de 1111 al MSB (4 bit) MOVWF BAR2 ;11110000, solo se usan 12bits MOVLW 0x0E ; SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT2,3 ;ON RETURN BSF BAR2,3 ;OFF MOVLW 0x0D SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT2,3 ;ON RETURN BSF BAR2,3 ;OFF MOVLW 0x0C SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT2,2 ;ON RETURN BSF BAR2,2 ;OFF MOVLW 0x0B SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT2,2 ;ON RETURN BSF BAR2,2 ;OFF MOVLW 0x0A SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT2,1 ;ON RETURN BSF BAR2,1 ;OFF MOVLW 0x09 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT2,0 ;ON RETURN BSF BAR2,0 ;OFF MOVLW 0x08 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT1,7 ;ON RETURN BSF BAR1,7 ;OFF MOVLW 0x07 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT1,6 ;ON RETURN BSF BAR1,6 ;OFF MOVLW 0x06 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT1,5 ;ON RETURN BSF BAR1,5 ;OFF MOVLW 0x05 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positive? GOTO $+3 ;no carry BCF PNT1,4 ;ON RETURN BSF BAR1,4 ;OFF MOVLW 0x04 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT1,3 ;ON RETURN BSF BAR1,3 ;OFF MOVLW 0x03 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carrys BCF PNT1,2 ;ON RETURN BSF BAR1,2 ;OFF MOVLW 0x02 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT1,1 ;ON RETURN BSF BAR1,1 ;OFF MOVLW 0x02 SUBWF TEMP,W ;TEMP - constante BTFSS STATUS,C ;positivo? GOTO $+3 ;no carry BCF PNT1,0 ;ON RETURN BSF BAR1,0 ;OFF RETURN ;-------------------------------------------; ; ////////// Fin de Rutinas ///////////// ;-------------------------------------------; ;-------------------------------------------; ; Configuraciones de Puertos y Flags ; ;-------------------------------------------; PM1: BANKSEL TRISA CLRF INTCON MOVLW 0b00001011 ; Configuración de OSC MOVWF PCON ; Interno 4MHz BSF TRISA,0 ; AN0/RA0=Input L BSF TRISA,1 ; AN1/RA1=Input R BSF TRISA,2 ; sin uso BSF TRISA,3 ; sin uso BCF TRISA,4 ; Anodo 2,3 compartido (MSB de L y R 4bits) BSF TRISA,5 ; Selector de modo -> Peak/bar/Point (pulsador) BCF TRISA,6 ; Anodo 0 (LSB=L 8bts) BCF TRISA,7 ; Anodo 1 (LSB=R 8bts) MOVLW 0b00000000 ; 0=Output/1=Input MOVWF TRISB ; PORTB=Output 8bits MOVLW 0b10000001 ; prescaler 1:4 TMR0 / pull-ups off MOVWF OPTION_REG ; (1ms) TMR0 @ 4Mhz internal OSC MOVLW 0b00000000 ; (EEW,CCP1,USART,TMR1,TMR2...) MOVWF PIE1 ; interrupciones de PIE1=off BANKSEL PORTA BCF PORTA,4 ; BCF PORTA,6 ; Apagamos anodos BCF PORTA,7 ; MOVLW 0b00000101 ; prescaler 1:1 (TMR1 sin uso) MOVWF T1CON MOVLW 0b10100000 ; Enable INT TMR0 MOVWF INTCON MOVLW 0xFF ; Apagamos cátodos (logica inversa) MOVWF LRAM1 MOVWF LRAM2 MOVWF RRAM1 MOVWF RRAM2 MOVWF LPRM1 MOVWF LPRM2 MOVWF RPRM1 MOVWF RPRM2 MOVWF LBRM1 MOVWF LBRM2 MOVWF RBRM1 MOVWF RBRM2 MOVWF PORTB CLRF Position MOVLW 0x0E ; Dirección de EEPROM donde guarda el modo MOVWF EEADRp ; por defecto lee 0xFF (memoria vacia). CALL ERead ; rutina que Lee EEPROM. MOVWF DTMODE ; valor fijo del modo. MOVWF JMPSL ; valor variable del modo a usar. BSF JMPSL,2 ; bit de enclavamiento. ;-------------------------------------------; ; Programa Principal - Loop ; ;(ISR interrumpe el loop cada 1ms y regresa); ;-------------------------------------------; ; para CMCOM=0x02 se tiene del manual: ; ; 0 = C2INV: VREF menor que AN1 (VIN-) ** ; 0 = C1INV: VREF menor que AN0 (VIN-) ** ; 0 = C2: Output not inverted ; 0 = C1: Output not inverted ; 0 = CIS: Comparator Input Switch bit ; C1: VIN- connects to RA0 ; C2: VIN- connects to RA1 ; 010 = CM<2:0> ; Four Inputs Multiplexed ; to Two Comparators. ; ; (**) para menor sensibilidad CMCOM = 0xC2 ;-------------------------------------------; START: CLRWDT BTFSS JMPSL,0 ; selector de modo bar/point GOTO Point ;Carga datos del modo Bar de L y R. Barh: MOVF LBAR1,W ; cátodo L LSB 8bits MOVWF LLSB ; MOVF LBAR2,W ; cátodo L MSB 4bits MOVWF LMSB ; MOVF RBAR1,W ; cátodo R LSB 8bits MOVWF RLSB MOVF RBAR2,W ; cátodo R MSB 4bits MOVWF RMSB GOTO Mode ;Carga datos del modo punto de L y R. Point: MOVF LPSV1,W ; cátodo L LSB 8bits MOVWF LLSB ; MOVF LPSV2,W ; cátodo L MSB 4bits MOVWF LMSB ; MOVF RPSV1,W ; cátodo R LSB 8bits MOVWF RLSB MOVF RPSV2,W ; cátodo R MSB 4bits MOVWF RMSB ;Lee RA5 Selector de modos. Mode: BTFSS JMPSL,2 ; JMPSL,2= 0? -> JMPSL,2 inicia en 1. GOTO SAFE ; ;bit de enclavamiento. BTFSC PORTA,5 ; selector de modo. GOTO NXT0 ; continua por defecto. DECF DTMODE,F ; si se presiona RA5 continua aqui. MOVLW 0x03 ; selecciona filtrando de 0xFF de DTMODE ANDWF DTMODE,F ; mascara entre 3 - 0 y lo carga en JMPSL. MOVF DTMODE,W ; MOVWF JMPSL ; MOVWF SVData ; Guarda el valor de modo en EEPROM. CALL EWrite ; rutina escribir EEPROM 6ms aprox. BCF JMPSL,2 ; activa el bit de enclavamiento. SAFE: BTFSS PORTA,5 ; logica invertida si se sigue presionado RA5. GOTO NXT0 ; sigue. BSF JMPSL,2 ; desactiva el bit de enclavamiento. NXT0: NOP ; Tiempo de compensación al NOP ; guardar en la EEPROM dentro de Mode. NOP ; (no incluye CALL EWrite) NOP NOP NOP NOP NOP NOP NOP ;-------------------------------- ;Lectura del Comparador AN0 COMRead: MOVLW 0x02 ; Comparador modo Mux interno (Vref=0x02). MOVWF TPCM ; MOVWF CMCON ; carga el modo Mux en CMCON. BANKSEL VRCON ; MOVLW 0xA0 ; (VREN=ON,VROE=OFF,VRR=ON,U-0=Unimplemented bit) MOVWF VRCON ; Configura VRCON (ver figura 11-1 del manual). BANKSEL CMCON MOVLW 0x0F ; 0 to F -> 4bits (resolución del comparador). MOVWF CTCOMP ; LOOP2: MOVF TPCM,W ; MOVWF CMCON ; Configuración de CMCOM NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP BTFSC CMCON,6 ; C1OUT=1? AN0 GOTO AN0 ; yup BANKSEL VRCON ; nop INCF VRCON,F ; ADC 4bits BANKSEL CMCON CLRF CMCON ; Limpia C1 y C2. DECFSZ CTCOMP,F ; limitador a 4bits. GOTO LOOP2 AN0: BANKSEL VRCON MOVF VRCON,W ; se obtiene lectura ANDLW 0x0F ; MOVWF ANNDRL ; 4bits ADC de VRCON BANKSEL CMCON LOUT: MOVF ANNDRL,W MOVWF TEMP CALL LOG ;-------------------------------- MOVF BAR1,W ; nuevo nivel de Bar LSB MOVWF LBAR1 ; MOVF BAR2,W ; nuevo nivel de Bar MSB MOVWF LBAR2 ; MOVF PNT1,W ; nuevo nivel de Punto LSB MOVWF LPNT1 ; MOVWF LPSV1 ; MOVF PNT2,W ; nuevo nivel de Punto MSB MOVWF LPNT2 ; MOVWF LPSV2 ;------------------------------------ ; logica de tiempo para peak ;------------------------------------ MOVF LRAM2,W ; nivel MSB guardada (peak) SUBWF LPNT2,W ; nivel MSB actual BTFSS STATUS,C ; positivo? C=1 LPNT2-LRAM2 GOTO LCHANGEDT ; nivel actual es menor que nivel guardado en MSB BTFSS STATUS,Z ; igual? Z=1 salta uno instrucción. GOTO LJOINDT ; nivel actual es mayor que nivel guardado MOVF LPNT1,W ; nivel LSB actual SUBWF LRAM1,W ; nivel LSB guardada LRAM1-LPNT1 BTFSC STATUS,C ; negativo? C=0 salta uno instrucción. GOTO LCHANGEDT ; nivel actual es menor que nivel guardado en LSB LJOINDT: BTFSS JMPSL,1 ; L peak on/off GOTO LPTTM ; mantiene el valor de peak MOVF LRAM1,W ; actualiza LSB de peak guardado MOVWF LPNT1 MOVF LRAM2,W ; actualiza MSB de peak guardado MOVWF LPNT2 GOTO LPTTM ; actualiza nivel guardado (nivel guardado es menor que señal actual) LCHANGEDT: MOVF LPNT1,W ; actualiza LSB de peak guardado MOVWF LRAM1 MOVF LPNT2,W ; actualiza MSB de peak guardado MOVWF LRAM2 MOVLW 244 ; inicia la primera vez con (500ms) MOVWF LTML ; memory timer L MOVLW 2 MOVWF LTMH ; memory timer H ;------------------------------------ ; logica de tiempo para punto ;------------------------------------ LPTTM: MOVF LPRM2,W SUBWF LPSV2,W ;LPSV2-LPRM2 BTFSS STATUS,C ;positivo? C=1 GOTO LPTSWP BTFSS STATUS,Z ;igual? Z=1 GOTO LJNPT MOVF LPSV1,W SUBWF LPRM1,W ;LPRM1-LPSV1 BTFSC STATUS,C ;negativo? C=0 GOTO LPTSWP LJNPT: MOVF LPRM1,W MOVWF LPSV1 MOVF LPRM2,W MOVWF LPSV2 GOTO NXTPL LPTSWP: MOVF LPSV1,W MOVWF LPRM1 MOVF LPSV2,W MOVWF LPRM2 MOVLW 40 MOVWF LPTM ;memory time NXTPL: BTFSS JMPSL,1 ;L peak on/off GOTO LBRTM MOVF LRAM2,W ANDWF LPSV2,F MOVF LRAM1,W ANDWF LPSV1,F ;------------------------------------ ; logica de tiempo para barra ;------------------------------------ LBRTM: MOVF LBRM2,W SUBWF LBAR2,W ;LBAR2-LBRM2 BTFSS STATUS,C ;positivo? C=1 GOTO LBRSWP BTFSS STATUS,Z ;igual? Z=1 GOTO LJNBR MOVF LBAR1,W SUBWF LBRM1,W ;LBRM1-LBAR1 BTFSC STATUS,C ;negativo? C=0 GOTO LBRSWP LJNBR: MOVF LBRM1,W MOVWF LBAR1 MOVF LBRM2,W MOVWF LBAR2 GOTO NXTBL LBRSWP: MOVF LBAR1,W MOVWF LBRM1 MOVF LBAR2,W MOVWF LBRM2 MOVLW 20 MOVWF LBRM NXTBL: BTFSS JMPSL,1 ;L peak on/off GOTO ROUT MOVF LRAM1,W ANDWF LBAR1,F MOVF LRAM2,W ANDWF LBAR2,F ;------------------------------------ ;Lectura del Comparador AN1 ROUT: MOVLW 0x02 ; Comparador modo Mux interno (Vref=0x02). MOVWF TPCM ; MOVWF CMCON ; carga el modo Mux en CMCON. BANKSEL VRCON ; MOVLW 0xA0 ; (VREN=ON,VROE=OFF,VRR=ON,U-0=Unimplemented bit) MOVWF VRCON ; Configura VRCON (ver figura 11-1 del manual). BANKSEL CMCON MOVLW 0x0F ; 0 to F -> 4bits (resolución del comparador). MOVWF CTCOMP ; LOOP1: MOVF TPCM,W ; MOVWF CMCON ; Configuración de CMCOM NOP ; 10uS según el manual (Example 11-1 pag. 70) NOP NOP NOP NOP NOP NOP NOP NOP NOP BTFSC CMCON,7 ; C2OUT AN1 GOTO AN1 ; termina si VREF es menor que AN1 (CMCON=0x02) BANKSEL VRCON INCF VRCON,F ; ADC 4bits incrementa de 0000 a 1111 en VR3-VR0. BANKSEL CMCON CLRF CMCON ; Limpia C1 y C2. DECFSZ CTCOMP,F ; limitador a 4bits. GOTO LOOP1 AN1: BANKSEL VRCON MOVF VRCON,W ; se extrae y filtra solo VR3-VR0. ANDLW 0x0F ; MOVWF ANNDRR ; 4bits ADC del Comparador AN1 BANKSEL CMCON MOVF ANNDRR,W MOVWF TEMP CALL LOG ;------------------------------------ MOVF BAR1,W ;new BAR MOVWF RBAR1 ; MOVF BAR2,W ; MOVWF RBAR2 ; MOVF PNT1,W ;new POINT MOVWF RPNT1 ; MOVWF RPSV1 ; MOVF PNT2,W ; MOVWF RPNT2 ; MOVWF RPSV2 ; ;------------------------------------ ; logica de tiempo para peak ;------------------------------------ MOVF RRAM2,W SUBWF RPNT2,W ;RPNT2-RRAM2 BTFSS STATUS,C ;positivo? GOTO RCHANGEDT BTFSS STATUS,Z ;igual? Z=1 GOTO RJOINDT MOVF RPNT1,W SUBWF RRAM1,W ;RRAM1-RPNT1 BTFSC STATUS,C ;negativo? GOTO RCHANGEDT RJOINDT: BTFSS JMPSL,1 ;L peak on/off GOTO RPTTM MOVF RRAM1,W ;sobreescribe RAM MOVWF RPNT1 ; MOVF RRAM2,W ; MOVWF RPNT2 ; GOTO RPTTM RCHANGEDT: MOVF RPNT1,W ;sobreescribe RAM MOVWF RRAM1 ; MOVF RPNT2,W ; MOVWF RRAM2 ; MOVLW 244 ;inicia con (500ms) la primera vez MOVWF RTML ; tiempo de retensión time L y H MOVLW 2 MOVWF RTMH GOTO RPTTM ;------------------------------------ ; logica de tiempo para punto ;------------------------------------ RPTTM: MOVF RPRM2,W SUBWF RPSV2,W ;RPSV2-RPRM2 BTFSS STATUS,C ;positivo? C=1 GOTO RPTSWP BTFSS STATUS,Z ;igual? Z=1 GOTO RJNPT MOVF RPSV1,W SUBWF RPRM1,W ;RPRM1-RPSV1 BTFSC STATUS,C ;negativo? C=0 GOTO RPTSWP RJNPT: MOVF RPRM1,W MOVWF RPSV1 MOVF RPRM2,W MOVWF RPSV2 GOTO NXTPR RPTSWP: MOVF RPSV1,W MOVWF RPRM1 MOVF RPSV2,W MOVWF RPRM2 MOVLW 40 MOVWF RPTM ;memory time NXTPR: BTFSS JMPSL,1 ;L peak on/off GOTO RBRTM MOVF RRAM1,W ANDWF RPSV1,F MOVF RRAM2,W ANDWF RPSV2,F ;------------------------------------ ; logica de tiempo para barra ;------------------------------------ RBRTM: MOVF RBRM2,W SUBWF RBAR2,W ;RBAR2-RBRM2 BTFSS STATUS,C ;positivo? C=1 GOTO RBRSWP BTFSS STATUS,Z ;igual? Z=1 GOTO RJNBR MOVF RBAR1,W SUBWF RBRM1,W ;RBRM1-RBAR1 BTFSC STATUS,C ;negativo? C=0 GOTO RBRSWP RJNBR: MOVF RBRM1,W MOVWF RBAR1 MOVF RBRM2,W MOVWF RBAR2 GOTO NXTBR RBRSWP: MOVF RBAR1,W MOVWF RBRM1 MOVF RBAR2,W MOVWF RBRM2 MOVLW 20 MOVWF RBRM ;memory time NXTBR: BTFSS JMPSL,1 ;L peak on/off GOTO START MOVF RRAM1,W ANDWF RBAR1,F MOVF RRAM2,W ANDWF RBAR2,F GOTO START END
lo que si me olvide era compartir la traducción a C del código original en asm que hice, que me parece necesario para que cualquiera pueda implementarlo donde desee. mi traducción trata de respetar el orden y logica que tiene el codigo asm original, para no tener problemas de la obtensión de datos en el tiempo asi como la multiplexión. los expertos lo sabran mejorar. temo aclarar que el autor envia tanto punto como barra directamente a la multiplexión eso genera mas de un punto o barras erraticas que en lo personal no me gusta, y el codigo del 628A lo corregía. pero bueno eso es a gusto de cada uno.
como me parecio un desperdicio usar un PIC DIP-40 como el 877A solo para un vumetro lo deje como ejemplo y no tiene implementado la opción guardar en la EEPROM el modo seleccionado y tiene pocos comentarios, sepan disculpar.
C:// PIC16F877A Configuration Bit Settings // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #include <xc.h> #include <stdint.h> #define _XTAL_FREQ 8000000 uint8_t registro[4]; #define LLSB registro[0] #define LMSB registro[1] #define RLSB registro[2] #define RMSB registro[3] uint16_t PeakR = 0xFFFF; uint16_t PeakL = 0xFFFF; uint8_t tiempoR = 244; // 500ms @ 8Mhz uint8_t tiempoL = 244; uint8_t pocision = 0; uint8_t lectura_AN0; uint8_t lectura_AN1; uint8_t valor_adc; uint16_t mezcla; uint16_t punto; uint16_t barra; uint8_t Temp01,Temp02,Temp03,Temp04; uint8_t JMPSL = 0b00000100; // bit Enclavamiento bit2 = 1 uint8_t DTMODE = 0; // registro temporal const uint8_t Tabla_Log[16] = { 0x02, 0x08, 0x0E, 0x13, 0x19, 0x1F, 0x26, 0x2D, 0x36, 0x3E, 0x4A, 0x58, 0x6B, 0x89, 0xB4, 0xF8}; const uint8_t Anodos[4] = {0x01, 0x02, 0x04, 0x08}; void Logaritmo(uint8_t valor_adc) { punto = 0xFFFF; barra = 0x0000; for (int i = 15; i >= 0; i--) { if (valor_adc >= Tabla_Log[i]){ punto &= ~(1U << i); break; } else { barra |= (1U << i); } } } void __interrupt() ISR(void) { if (TMR0IF) { TMR0IF = 0; PORTE = 0x00; // anodos en 0 if (tiempoL > 0){ tiempoL--; } if (tiempoL == 0) { if (PeakL < 0xFFFF) { PeakL = (uint16_t)((PeakL >> 1) | 0x8000); } tiempoL = 20; } if (tiempoR > 0){ tiempoR--; } if (tiempoR == 0) { if (PeakR < 0xFFFF) { PeakR = (uint16_t)((PeakR >> 1) | 0x8000); } tiempoR = 20; } PORTD = registro[pocision]; // nuevo cátodo PORTE = Anodos[pocision]; // nuevo anodo pocision++; pocision &= 0x03; PORTB = Temp03; PORTC = Temp04; } } void main(void) { OPTION_REG = 0b01000011; ADCON0 = 0b01000011; // | ADCS1 = 0| ADCS0 = 1 | CHS2-CHS1-CHS0 | GO/DONE = 1 | ? | ADON = 1 | ADCON1 = 0b01100101; // | ADFM = 0 | ADCS2 = 1 |-U-|-U-| PCFG3-0 = xxDD-ADAA | TRISA = 0b00001111; // 1=in 0=out // PORTX = --76543210 TRISB = 0x00; TRISC = 0x00; TRISD = 0x00; TRISE = 0x00; PORTB = 0x00; PORTC = 0x00; PORTD = 0x00; PORTE = 0x00; T1CON = 0b00000101; INTCON = 0b10100000; DTMODE = 0xFF; // EEPROM por default lee 0xFF JMPSL = DTMODE; JMPSL |= 0x04; // iniciamos con 1 el bit de enclavamiento PORTA = (PORTA & ~0x30)|(uint8_t)(JMPSL << 4); // arreglo de prueba while(1) { LLSB = Temp01; LMSB = Temp02; RLSB = Temp03; RMSB = Temp04; if ((JMPSL & 0x04) != 0) { // bit de enclavamiento (inicia con 1) if ((PORTA & 0x04) == 0) { // RA2 ( pueden aprovechar los PICs DTMODE--; // con RA5/MCLR que son solo entrada) DTMODE &= 0x03; // Mascara 0bxxxx-xx11 JMPSL = DTMODE; // intercambio de dato (sin uso) JMPSL &= ~0x04; // bit de enclavamiento en 0 PORTA = (PORTA & ~0x30)|(uint8_t)(JMPSL << 4); } // arreglo de prueba RA4,RA5 } else { if ((PORTA & 0x04) != 0) { // RA2 liberado? (dejo de presionar) JMPSL |= 0x04; // restaura en 1 el bit } } ADCON0bits.CHS0 = 0; __delay_us(20); GO_nDONE = 1; while(GO_nDONE); lectura_AN0 = ADRESH; ADCON0bits.CHS0 = 1; __delay_us(20); GO_nDONE = 1; while(GO_nDONE); lectura_AN1 = ADRESH; Logaritmo(lectura_AN0); if (punto <= PeakL){ PeakL = punto; tiempoL = 244; } switch(JMPSL&0x03) { case 0x00: mezcla = punto; break; case 0x01: mezcla = barra; break; case 0x02: mezcla = punto & PeakL; break; case 0x03: mezcla = barra & PeakL; break; } Temp01 = (uint8_t)(mezcla & 0xFF); Temp02 = (uint8_t)((mezcla >> 8) & 0xFF); Logaritmo(lectura_AN1); if (punto <= PeakR){ PeakR = punto; tiempoR = 244; } switch(JMPSL&0x03) { case 0x00: mezcla = punto; break; case 0x01: mezcla = barra; break; case 0x02: mezcla = punto & PeakR; break; case 0x03: mezcla = barra & PeakR; break; } Temp03 = (uint8_t)(mezcla & 0xFF); Temp04 = (uint8_t)((mezcla >> 8) & 0xFF); } }
Saludos.
Ahora si se esta poniendo lindo el tema
Llego a casa y lo miro con detenimiento