Foros
Nuevos mensajes
Buscar en foros
Novedades
Nuevos mensajes
Nuevos recursos
Última actividad
Recursos
Últimas revisiones
Buscar recursos
Acceder
Registrarse
Novedades
Buscar
Buscar
Buscar sólo en títulos
De:
Nuevos mensajes
Buscar en foros
Menú
Acceder
Registrarse
Install the app
Instalar
Diseño digital
Microcontroladores y sistemas embebidos
LCD VU Meter
JavaScript está desactivado. Para una mejor experiencia, por favor, activa JavaScript en el navegador antes de continuar.
Estás usando un navegador obsoleto. No se pueden mostrar este u otros sitios web correctamente.
Se debe actualizar o usar un
navegador alternativo
.
Responder al tema
Mensaje
[QUOTE="lahmun, post: 1355221, member: 473687"] Hola a todos, Encontré este código en Internet, pero esto funciona solo para LED, no para LCD, entonces, ¿cómo podemos convertirlo para que funcione en LCD VU Meter? Esperando la respuesta de tu maestro. Lahmun, [CODE]' Stereo peak-hold/decay VU meter (2x10 or 2x16 LEDs), version 2.0 ' on-the-fly switchable mode (style) jumper ' Filename: VU_2x16_BarJp.bas ' Written for the Proton BASIC compiler v3.6.0.3, © Istvan K, 2017 '$define WIDTH 10 ' 2x10-led $define WIDTH 16 ' 2x16-led ' peak hold time (also see below): $define PHOLDTIME 500 ' ms, max 255*4=1020 ms (phold is a 8-bit counter) '----------- Device = 16F88 ' a 18-pin PIC Declare Xtal = 8 ' int osc ' not HS_OSC but INTRC_IO, config word: 0x3F10 Config INTRC_IO, WDT_OFF, MCLR_OFF, LVP_OFF, _ PWRTE_ON, BODEN_OFF, CP_OFF, DEBUG_OFF ' intosc (8 Mhz), RA6 and RA7 (ext osc pins) are IOs, MCLR disabled (input) ' Define ADC parameters: $if WIDTH = 10 Declare Adin_Res = 8 ' 8-bit result $else Declare Adin_Res = 10 ' have to set right justify (ADFM_bit = 1) $endif Declare Adin_Tad = FRC ' RC OSC Declare Adin_Stime = 50 ' 50us sample time Declare Dead_Code_Remove On Declare Reminders OFF Declare Optimiser_Level 2 On_Hardware_Interrupt TMR2_IT ' 1 ms for exact mux timing ' IT timed led multiplexing, using four 5-led groups ('quintets') ' If WIDTH = 16 then four 8-led groups are used (4 'octets') ' Circuit: VU_2x16_BarJp.DSN, input is a real stereo wav file. ' RA0, RA1, RA6, RA7 = mux outputs (ON = 0) ' RA2, RA4 = AN_R, AN_L (AN2 and AN4) ' RA3 = REF (VREF+), set by a pot, sensitivity (level) ' RA5 = MODE jumper: 0 = POINTER, 1 = BAR (standard mode) ' RB3..RB7 = L0...L4 = common 5-bit Led port (5 anodes of all quintets) ' if WIDTH = 16 then the full 8-bit PORTB is used (RB0..7 = L0..7) ' Four pins to drive the common cathodes of the 4 groups (quintets/octets): ' RcH 'R'ight 'c'athodes 'H'igh (group drive pin, active 0) ' RcL 'L'ow ' LcH 'L'eft ' LcL $define RcH PORTA.0 $define RcL PORTA.7 $define LcH PORTA.1 $define LcL PORTA.6 $define LED_Port PORTB ' on-the-fly switchable mode (style) jumper (BAR_JP, open = 1: BAR mode) ' jumper closed: running led pointer, not bar (plus the lastpeak if any) ' open: a standard VU meter will be displayed (filled bar) ' ie all the LEDs on the left side of the mpeak will also turn on $define BAR_JP PORTA.5 ' different (own) variables for R and L channels: Dim R_peak As Byte Dim R_phold As Byte Dim R_dhold As Byte Dim L_peak As Byte Dim L_phold As Byte Dim L_dhold As Byte ' common variables: Dim mpeak As Byte ' momentary peak position Dim lastpeak As Byte Dim pos As Byte Dim barbits As Word ' 10 bar positions > 16-bit var, leftmost pos. > bit 6 ' 16 bar positions > 16-bit var, leftmost pos. > bit 0 $if WIDTH = 10 Dim adval As Byte Dim LogTable[10] As Byte ' array in RAM, for speed $else ' width = 16 Dim adval As Word Dim LogTable[16] As Word $endif Symbol TMR2_ON T2CON.2 'GoTo main ' CMCON = 7 (comparators OFF, automatically placed by the compiler) 'main: ' HW init OSCCON = %01110000 ' Internal clock at 8 MHz ANSEL = %00011100 ' set RA2, RA3 (VREF+) and RA4 as analog input Repeat Until OSCCON.2 = 1 ' IOFS bit, wait until INTOSC frequency stable TRISA = %00111100 ' mux pins are outputs TRISB = 0 ' tris reg of LED_Port (PORTB), all outputs ' leds off PORTA = 0xFF ' all mux pins are off (1) LED_Port = 0 ADCON1.5 = 1 ' VCFG1 = 1 (use RA3 as VREF+), it remains 1 $if WIDTH = 16' only for 10-bit AD: ADCON1.7 = 1 ' ADFM = 1: right justified (missing in Proton ADin) $endif ' init timer2 for mux timing: period = 1 ms ' a channel calculation is max 300 us (without timer2 waiting) ' Prescaler=1:1, PostScaler=1:8, Period = 1 ms (8 MHz clock) ' 1 ms/group, the whole loop is 4 ms (250 Hz refresh rate) PR2 = 250 ' Timer2 Match value T2CON = %00111100 ' enable Timer2 with 1:8 postscaler, 1:1 prescaler PIR1.1 = 0 ' clear TMR2IF PIE1 = %10 ' only TMR2IE = 1 (enable Timer2 IT) INTCON = 0xC0 ' Enable global (GIE) and periferial (PEIE) ITs 'init variables: R_peak = 0 R_phold = 0 R_dhold = 0 L_peak = 0 L_phold = 0 L_dhold = 0 $if WIDTH = 10 ' 10-stage log table in RAM, 6 then 3 dB/step, can be modified :-) ' 2, 4, 8, 16, 32, 64, 90, 128, 180, 255 ' -36 -30 -24 -18 -12 -6 -3 0 +3 +6 dB ' fill the table: LogTable[0] = 2 LogTable[1] = 4 LogTable[2] = 8 LogTable[3] = 16 LogTable[4] = 32 LogTable[5] = 64 LogTable[6] = 90 LogTable[7] = 128 LogTable[8] = 180 LogTable[9] = 255 $else ' 16-stage WORD log table in RAM, 3 dB/step ' 6, 8, 11, 16, 23, 32, 45, 64, 90, 127, 180, 255, 361, 510, 721, 1020 '-39 -36 -33 -30 -27 -24 -21 -18 -15 -12 -9 -6 -3 0 +3 +6 dB ' fill the table: LogTable[0] = 6 LogTable[1] = 8 LogTable[2] = 11 LogTable[3] = 16 LogTable[4] = 23 LogTable[5] = 32 LogTable[6] = 45 LogTable[7] = 64 LogTable[8] = 90 LogTable[9] = 127 LogTable[10] = 180 LogTable[11] = 255 LogTable[12] = 361 LogTable[13] = 510 LogTable[14] = 721 LogTable[15] = 1020 $endif $define LOOPTIME 4 ' 4 ms repeating (loop) time (used below) ' 4 mS/loop (using 1 ms timer2 IT) = 250 Hz refresh rate at 8 MHz clock While 1=1 ' infinite loop adval = ADIn 2 ' sample AN2 (channel R) GoSub R_PosCalc ' calculate the momentary mpeak and lastpeak GoSub Set_BarBits ' update barbits using mpeak and lastpeak ' Execution time of the above three routines varies (depends on audio level) ' but this is compensated by the timer2 waiting, so every mux step will be ' exactly 1 ms (to get same brightness for the four led-groups). ' The mux order is: RcH RcL LcH LcL Repeat Until TMR2_ON = 0 ' wait for timer2 IT (max 1 ms to timer2 off) TMR2_ON = 1 ' restart timer2 LcL = 1 ' mux off (switch off the lastly switched mux pin) LED_Port = barbitsH ' R higher quintet/octet RcH = 0 ' actual (here: the first) mux pin ON $if WIDTH = 10 ' ie not 16 barbits = barbits >> 3 ' calculate the R lower quintet (see below) $endif Repeat Until TMR2_ON = 0 TMR2_ON = 1 RcH = 1 LED_Port = barbits ' R lower quintet/octet RcL = 0 ' calculate mpeak, lastpeak and barbits (for channel L) adval = ADIn 4 ' appr 107 us GoSub L_PosCalc ' max 82 us GoSub Set_BarBits ' 87-90 us Repeat Until TMR2_ON = 0 TMR2_ON = 1 RcL = 1 LED_Port = barbitsH ' L higher quintet/octet LcH = 0 $if WIDTH = 10 barbits = barbits >> 3 $endif Repeat Until TMR2_ON = 0 TMR2_ON = 1 LcH = 1 LED_Port = barbits ' L lower quintet/octet LcL = 0 Wend ' infinite loop ' --------------------- end of main ' subroutines: TMR2_IT: Context Save ' how to disable it (in this case nothing to save) ???? PIR1.1 = 0 ' clear TMR2IF (IT flag) TMR2_ON = 0 ' stop TMR2, examined (and set) in the main loop Context Restore ' peak hold/decay timings (in reality other values may be needed, try it!) ' starting value of the counters, decremented once per each main loop: $define PHOLDCNT PHOLDTIME/LOOPTIME ' countdown before the first decay ' = 125, ie the peak bit stays for 125*4=500 ms before decay begins $define DHOLDCNT PHOLDCNT/13 ' countdown before the next decay ' = 9, ie the decay repeating time is 9*4=36 ms (for my Proteus !!) ' the above values depend on the speed of the PC so you have to try R_PosCalc: ' input: adval, output: mpeak and lastpeak variables mpeak = WIDTH - 1 ' position loop in reversed order, to find mpeak Do ' comparing adc value to the actual table value If adval >= LogTable[mpeak] Then ' momentary max position (mpeak) found If mpeak > R_peak Then ' new, greater peak (pos 0 is excluded) R_peak = mpeak ' preserve it for the next call ' now lastpeak will be peak, so clear prev. lastpeak if any: lastpeak.7 = 1 ' invalid (too large) value ' prepare peak hold/decay counters: R_phold = PHOLDCNT ' (re)start peak hold time (also preserved) R_dhold = 0 ' if phold is expired, this will be DHOLDCNT Return ' end of function EndIf ' end new peak Break ' exit loop EndIf ' end of compare Dec mpeak Loop While mpeak.7 = 0 ' If the loop ran through, mpeak will be 0xFF (invalid value: not found) ' calculate peak hold and decay If R_phold != 0 Then Dec R_phold ' previous (last) peak bit (led) remains Else ' phold time is expired, repeating peak decay begins If R_dhold != 0 Then Dec R_dhold ElseIf R_peak != 0 Then ' Repeat peak decay until zero (or a new, greater peak) Dec R_peak ' zero peak: end of repeating decay R_dhold = DHOLDCNT ' re)start decay time EndIf EndIf ' lastpeak displayed if it is greater than mpeak (the momentary max) lastpeak = R_peak If lastpeak = 0 Then ' zero lastpeak is invalid (excluded) lastpeak.7 = 1 ' surely too large value EndIf Return ' end of R_PosCalc L_PosCalc: ' same as R_PosCalc but with L_ prefixes mpeak = WIDTH - 1 Do If adval >= LogTable[mpeak] Then If mpeak > L_peak Then L_peak = mpeak lastpeak.7 = 1 L_phold = PHOLDCNT L_dhold = 0 Return EndIf Break EndIf Dec mpeak Loop While mpeak.7 = 0 If L_phold != 0 Then Dec L_phold Else If L_dhold != 0 Then Dec L_dhold ElseIf L_peak != 0 Then Dec L_peak L_dhold = DHOLDCNT EndIf EndIf lastpeak = L_peak If lastpeak = 0 Then lastpeak.7 = 1 EndIf Return ' end of L_PosCalc ' Set_BarBits: ' as the name shows, it only sets the "barbits" variable, that you ' have to send to the appropriate PIC ports to drive the LEDs. ' Its result: ' ****** If WIDTH = 10: '< barbitsH > < barbits > '7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 bit numbers (x = undetermined, not used) 'H H H H H L L L L L x x x x x x H = higher quintet, L = lower quintet ' the higher quintet is ready in barbitsH (bit7-3, PORTB.2..0 are not used) '*** after three right-shifts (barbits >> 3): '< barbitsH > < barbits > '7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 '0 0 0 H H H H H L L L L L x x x ' the lower quintet = barbits.7-3 (bit2..0 are not used, too) ' ****** If WIDTH = 16: '< barbitsH > < barbits > '7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 bit numbers 'H H H H H H H H L L L L L L L L H = higher octet, L = lower octet ' both octets are ready in barbits (barbitsH, barbits) Set_BarBits: ' input: mpeak and lastpeak, output: barbits pos = 0 ' position of the leftmost bar LED ' after 10 rshifts it will be the barbits.6 Do ' pos loop 0..(WIDTH-1) ' rshifted and barbitsH.7 = 0 which means that bit (led) is off: barbits = barbits >> 1 ' compare position with the actual (valid) mpeak and lastpeak: If BAR_JP = 0 Then ' pointer mode (running led) If pos = mpeak Then set_led ElseIf mpeak.7 = 0 Then ' valid mpeak ' filled bar (standard display) If pos <= mpeak Then set_led EndIf If pos = lastpeak Then set_led: barbitsH.7 = 1 ' bit (led) is on EndIf Inc pos Loop While pos < WIDTH Return ' end of Set_BarBits '----------- end of program, 357 rom, 59 ram (optimiser = 2) [/CODE] [/QUOTE]
Verificación
Responder
Diseño digital
Microcontroladores y sistemas embebidos
LCD VU Meter
Arriba