Autor Tema: Uso del DIV32  (Leído 11935 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Mario

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 873
Uso del DIV32
« en: 02 de Octubre de 2006, 19:00:59 »
Hola.

En el foro me he dado cuenta que casi nadie (si es que nadie) utiliza la instrucción DIV32 que provee PBP desde la versión 2.42 (creo).

Esta instrucción nos sirve esencialmente para una cosa:
Dividir 31 bits entre 15 bits.

Si se van al manual del PBP les muestra el acondicionamiento de esta.


Una breve explicación:

El compilador crea variables o registros propios para hacer operaciones. Si observamos, nos daremos cuenta que existen nombres de registros que no podemos usar (creo R0,R1...).

PBP realiza operaciones de multiplicación y división de 16X16 bits, dando como resultado una operación de 32 bits.

Sin embargo, no era posible accesar de golpe a esos 32 bits, necesitaba uno hacer dos multiplicaciones o divisiones para tomar los 16 de mayor peso (** o /) y los 16 de menor peso (* o //).

La DIV32 nos permite usar esos bits (31) y dividir el resultado entre una cantidad de 15 bits de un solo golpe.

La ventaja, desde mi punto de vista, es que podemos usar los 31 bits (2,147,483,647 en decimal) y realizar operaciones que requieran decimales o fracciones.

Cuando PBP hace cualquier operación, utiliza 4 registros para hacer una operación (multiplicar o dividir) y el resultado se almacena en esos registros.
Como estos registros se utilizan para otras cosas (las cuales no sé pero creo que para los tiempos y demas) el resultado de 31 bits desaparece para dar cabida a lo nuevo.

La DIV32 debe ser utilizada inmediatamente después de la operación deseada (como lo marca el ejemplo en el manual de PBP) para aprovechar esos 31 bits.


Un ejemplo en concreto.

El FAMOSÍSIMO voltímetro con el AD del µicro.

Si tomamos el valor de cada bit para 10 bits sería= 5v/10bits= 5v/1024= 4.88 milivolts redondeando.

Sacamos su función de transferencia y nos daría algo como esto:
V(o) = 4.88 mV (AD en bits)

Lo cual nos supone a nosotros que utilizaremos decimales........ pero PBP no lo puede hacer con decimales.


Qué sucede si metemos esa ecuación en PBP:
el 4.88 se convierte en 4 y nuestro cálculo será erroneo.

¿Pero qué sucede si le metemos 488?
Nosotros sabemos que es 4.88 pero PBP no lo sabe.

Si hacemos esto tendremos:
para AD = 0; V(o)=0
para AD = 1024; V(o)=499,712

499,712 por el redondeo utilizado no es 500,000 de los 5 volts. Perdemos presición.

499,712 es menor a 2,147,483,647; cumplimos con el requisito.

499,712 lo dividimos entre 10 y nos queda:
49,971 porque PBP no acepta decimales; lo dividimos entre 10 para que quepa dentro de los registros máximos de PBP que son 16 bits (word=65,535).
10 es menor a 32,768 que son los 15 bits en los cuales se puede dividir.


¿Qué cantidad es?
pues nosotros sabemos que es 4.9971 volts, perdemos 29 diesmilésimas de volt por el redondeo (lo cual es muuuuuy aceptable).


Este es un programa que siempre les pongo a los alumnos para utilizar el DIV32 con el AD ya que la mayoría de los proyectos usan transductores que proporcionan voltaje, corriente o resistividad.

'****************************************************************
'*  Name    : Convertidor A/D 10 bits con 4 decimales y contador                  *
'*                 en hardware de timer1.BAS                                                    *
'*  Author  : Mario Alberto Camarillo Ramos                                                 *
'*  Date    : 21/11/2005                                                                             *
'*  Notes   : Este es con 4 decimales. Se puede agregar más lí-                     *
'*                neas de ADCIN alternando canales                                            *
'****************************************************************


define  OSC         20
DEFINE  LCD_DREG    PORTB
DEFINE  LCD_DBIT    4
DEFINE  LCD_RSREG   PORTB
DEFINE  LCD_RSBIT   1
DEFINE  LCD_EREG    PORTB
DEFINE  LCD_EBIT    2
DEFINE  LCD_BITS    4
DEFINE  LCD_LINES   2

define  NO_CLRWDT   1

Define  ADC_BITS        10        ' Set number of bits in result
Define  ADC_CLOCK       3         ' Set clock source (3=rc)
Define  ADC_SAMPLEUS    50        ' Set sampling time in uS

adval      var   word     ' Create adval to store result
adval1      var   word     ' para guardar la conversión ya con la fórmula

conejillo   var   byte     ' para hacer trampa

    TRISA = %11111111     ' Set PORTA to all input
    ADCON1 = %10000010     ' Set PORTA analog and right justify result (para
                                                  ' tomar todos los 10 bits; justificado a la izquierda
                                                  ' solo se toman los 8 de mayor peso)
  
loop:    ADCIN 0, adval        ' Read channel 0 to adval

   conejillo = 488 * adval   ' multiplicamos para obtener 1024*488=499712;
                ' internamente el compilador usa 16x16 resultando
                                                    ' en un valor de 31 bits de resolución

   adval1   = DIV32 10        ' usamos div32 inmediatamente ya que se cuenta con
                                                         ' el valor TOTAL DE 31 BITS, si no se hace así, el
                                                         ' resultado de 32 bits se destruiría. De esta
                                                         ' forma acomodamos para obtener 31 bits de resolu-
                                                         ' ción ó 2,147,483,647 y dividimos /10 para mover
                                                         ' el punto a 49971.2 descartando el 2 y quedándo--
                                                         ' nos con 49971=4.9971 volts 49971 < 65535

   Lcdout $FE,1, DEC adval1 dig 4,".", dec adval1 dig 3, dec adval1 dig 2, dec adval1 dig 1, dec adval1 dig 0

pause 2000

goto loop

End


Como ven, ADVAL1 tomará el valor de los cuatro registros (31 bits) divididos entre 10.

En este caso se presentan registros para cada operación, para efectos de explicación. Pero solo necesitamos uno solo (nos ahorramos RAM):

    ADCIN 0, adval

   adval = 488 * adval

                adval = DIV32 10

Observen que inmediatamente después de 488*AD se utliza la DIV32, esto es porque si se hace cualquier otra operación, el resultado se destruye (el de los 31 bits).

El programa propuesto genera 404 palabras para un 16F877 (que es el que más usan por aquí en el foro).

Un voltímetro con 4 decimales con 404 palabras y con LCD y todo....... no está mal.


Von Newman dijo (creo) que un programador no necesita punto flotante porque sabe exactamente dónde está el punto en su cabeza............. yo no soy programador, si tuviera punto flotante lo usaría pero como no tengo, uso lo que pueda  :D.

Las rutinas de FP de Microchip son útiles y tengo entendido que si funcionan (¿navaismo?) pero creo que alguna vez las observé y requieren crear registros para decimales y enteros, sin mencionar el movedero que hacen para acomodar el punto.

Si navaismo puede compilar ese mismo programa (o el que sea  :mrgreen:, no necesita ser navaismo) utilizando las FP de microchip para un 16F877 hágalo y comente los resultados.


Perdímos 29 diesmilésimas de volt en el cálculo por el redondeo inicial y porque tomamos 2 decimales solamente, ¿y si tomamos mas?.


Utilizando 4 decimales tenemos 4.8828 mV/bit

para el peor de los casos:
     0; V(o)=0
1024; V(o)= 49,999,872

Dividimos entre 1000 (DIV32 1000)
49,999---> 4.9999 volts

49,999,872 < 2,147,483,647    y
         1000 < 32768

Para 5 decimales--->4.88281
     0; V(o)=0
1024; V(o)= 499,999,744

Dividimos entre 10,000 (DIV32 10000)
49,999.744---> 4.9999 volts.

Para mas decimales se pasa de 2,147,483,647.


Es muy buena esta herramienta para "sacarle la vuelta" a los decimales, no es propiamente punto flotante porque nosotros debemos saber dónde está el punto pero, ayuda :).

Solo necesitamos linealizar un transductor, o sacar su función de transferencia y listo.

Como vieron, 4 decimales es mas que suficiente de la ecuación original para obtener un resultado óptimo.


Imaginen un AD en ensamblador con 4 puntos decimales; yo ni lo pienso (corrimientos, BTFSS al Status........ y muchas cosas mas).


Bueno, navaismo, ahi está  :D.


PD: No estaré disponible la noche del Lunes y todo el Martes (tarea de maestria  :x y trabajo  :().
« Última modificación: 02 de Octubre de 2006, 19:06:57 por Mario »
La buena administración es utilizar el sentido común y la regla de oro; aunque el sentido común no es tan común como quisiéramos que fuera y, quien tiene el oro, hace las reglas.
George Terry

"A loser will defeat a genius with hard work"
Rock Lee

Desconectado Mario

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 873
Re: Uso del DIV32
« Respuesta #1 en: 02 de Octubre de 2006, 19:16:36 »
Una cosa mas:


Con esta instrucción se han creado varios proyectillos para un montón de transductores, solo se saca la función de transferencia y de de ser posible, se linealiza.

Los que se me vienen a la mente:
ACS752SCA-50, HM1500LF, FAMOSÍSIMO LM35, y varios mas.
La buena administración es utilizar el sentido común y la regla de oro; aunque el sentido común no es tan común como quisiéramos que fuera y, quien tiene el oro, hace las reglas.
George Terry

"A loser will defeat a genius with hard work"
Rock Lee

Desconectado Mario

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 873
Re: Uso del DIV32
« Respuesta #2 en: 02 de Octubre de 2006, 19:17:43 »
Una última cosa:

La explicación no fue TAN breve  :D
La buena administración es utilizar el sentido común y la regla de oro; aunque el sentido común no es tan común como quisiéramos que fuera y, quien tiene el oro, hace las reglas.
George Terry

"A loser will defeat a genius with hard work"
Rock Lee

Desconectado navaismo

  • Jubilado Todopic
  • PIC24H
  • ****
  • Mensajes: 1973
Re: Uso del DIV32
« Respuesta #3 en: 03 de Octubre de 2006, 01:24:45 »
Hola Mario, gracias por la explicacion, es muy util y como lo dices no compite con las rutinas de FP ya que es muy poco el codigo.

Ahora con tu ejemplo aun tengo problemas, mas que nada por aquello de que no lo se usar muy bien. Lo pobre para mostrar solo el dato o la conversion de 1V a decimal con el comando ADCIN solito es 205 decimal. con tu ejemplo me da algo como 0.0002 lo hice asi: (lo mas problable es que este mal como lo adapte.)

Citar
ADCIN termo, sensor

sensor=488*sensor

sensor = div32 10

 Lcdout $FE,1, DEC  sensor dig 4,".", dec sensor dig 3, dec sensor dig 2, dec sensor dig 1, dec sensor dig 0

Lo mas seguro es que falle a la ora de usar el lcd ahora que lo veas me comentas.
"Mi tercer deseo, que otra cosa podría ser, poner un final a todo el sufrimiento, que sólo con mi propia extinción el planeta podrá ser aliviado. Pobre de mí, Si tuviera tres deseos hoy, la elección no sería dificil para mí, Sólo tres deseos serían suficientes, No tendría uso para más."

"He sido un hombre que busca y aun lo sigo siendo, pero ya no busco en las estrellas y en los libros, sino en las enseñanzas de mi sangre."

Desconectado navaismo

  • Jubilado Todopic
  • PIC24H
  • ****
  • Mensajes: 1973
Re: Ahora yo te comento lo de las rutinas FP
« Respuesta #4 en: 03 de Octubre de 2006, 02:21:34 »
dejame usar el documento de las rutinas de microchip para intentar explicar su uso:

Citar
"El compilador PicBasic tiene varios tipos de datos incorporados: bit, byte y word, junto con arreglos de cada uno. Todos estos tipos son enteros sin signo. Esto significa que no hay punto así que los números reales o flotantes no pueden ser representados. Hay varios metodos para esto, incluyendo multiplicar cada valor por 10 o 100 para los cálculos y dividiviendo  cuando es hora de mostrar el valor.

Microchip ha desarrollado varias  rutinas de punto flotante en ensamblador. Estas rutinas pueden ser integradas en un programa de PicBasic y ser llamadas, si la coma flotante es una necesidad. No es dificl, pero cómo hacer este trabajo correctamente. El código  fuente necesario de PicBasic para integrar  24-bit o rutinas 32-bit de la coma flotante de microchip en su programa se contiene en los archivos siguientes:

FP0C.BAS            24-bit floating point for 16F84(A)
FP0C32.BAS          32-bit floating point for 16F84(A)
FP20.BAS            24-bit floating point for most other 14-bit core devices
FP2032.BAS          32-bit floating point for most other 14-bit core devices
FP17.BAS            24-bit floating point for 17Cxxx
FP1732.BAS          32-bit floating point for 17Cxxx
FP18.BAS            24-bit floating point for 18Xxxx
FP1832.BAS          32-bit floating point for 18Xxxx

Es importante observar que las rutinas de 32-bit no convertirán valores con signo, y que las rutinas 24-bit convierten siempre f valores con signo. Por lo tanto, las rutinas 32-bit convertirán valores a partir de la 0 a 65535, mientras que las rutinas 24-bit convertirán valores a partir de la -32767 a +32767.

Además, las rutinas apropiadas del ensamblador deben ser incluidas. Los archivos siguientes son versiones modificadas de los archivos de AN575 del microchip. Los archivos de microchip trabajarán, pero no compilarán con el P.M. como el ensamblador, y no incluyen muchos de los más nuevos dispositivos de PICmicro. FP24.A18, FP32.A18, y MATH18.INC no eran parte de AN575. Fueron creados para apoyar los dispositivos de PIC18Xxxx. Los archivos son:

DEV_FAM.INC
FP24.A16
FP24.A17
FP24.A18
FP32.A16
FP32.A17
FP32.A18
MATH16.INC
MATH17.INC
MATH18.INC
.............................................. bueno sin mas rollo como se usan


lo primero si usamos un 877 para compilar debemos añadir esta linea:
 Define  __16F877  1

los nombres de las subrutinas son:

itofa          Convert integer aint to floating point aarg
itofb          Convert integer bint to floating point barg

estas convierten un numero en numero decimal

fpadd          Perform floating point addition: aarg + barg
fpsub          Perform floating point subtraction: aarg - barg
fpmul          Perform floating point multiplication: aarg * barg
fpdiv          Perform floating point division: aarg / barg
ftoia          Convert floating point aarg to integer aint

y estas son las rutinas de suma resta multiplicacion y division y la ultima convierte a entero

los pics soportados son:
12C671, 12C672, 12CE673, 12CE674, 12F508, 12F509, 12F629, 12F675, 12F683

14000

16C432, 16C433

16C554, 16C557, 16C558, 16C61, 16C62(AB), 16C620(A), 16C621(A), 16C622(A),
16C63(A), 16C64(A), 16C642, 16C65(AB), 16C66, 16C662, 16C67, 16C71, 16C710,
16C711, 16C712, 16C715, 16C716, 16C717, 16C72(A), 16C73(AB), 16C74(AB),
16C745, 16C76, 16C765, 16C77, 16C770, 16C771, 16C773, 16C774, 16C781, 16C782,
16C84, 16C923, 16C924, 16C925, 16C926, 16CE623, 16CE624, 16CE625, 16F505,
16F54, 16F57, 16F627(A), 16F628(A), 16F630, 16F648A, 16F676, 16F684, 16F688,
16F716, 16F72, 16F73, 16F737, 16F74, 16F747, 16F76, 16F767, 16F77, 16F777,
16F818, 16F819, 16F83, 16F84(A), 16F87, 16F870, 16F871, 16F872, 16F873(A),
16F874(A), 16F876(A), 16F877(A), 16F88

17C42A, 17C43, 17C44, 17C752, 17C756(A), 17C762, 17C766

18C242, 18C252, 18C442, 18C452, 18C601, 18C658, 18C801, 18C858, 18F1220,
18F1320, 18F2220, 18F2320, 18F2331, 18F242, 18F2431, 18F2439, 18F248, 18F2515,
18F252, 18F2525, 18F2539, 18F258, 18F2585, 18F2610, 18F2620, 18F2680, 18F4220,
18F4320, 18F4331, 18F442, 18F4431, 18F4439, 18F448, 18F4515, 18F452, 18F4525,
18F4539, 18F458, 18F4585, 18F4610, 18F4620, 18F4680, 18F6410, 18F6490,
18F6520, 18F6525, 18F6585, 18F6620, 18F6621, 18F6680, 18F6720, 18F8410,
18F8490, 18F8520, 18F8525, 18F8585, 18F8620, 18F8621, 18F8680, 18F8720


y este es un ejejmplo usando todas las operaciones

Código: [Seleccionar]

' Floating point test program
'
' Defined for the LAB-X1 using 16F877.  If need to use different LCD connections or a
' different chip, you must change the Define statements.  If your target device doesn't
' have ADC, remove the ADCON1=7 statement.
'
' Include only one of the following. Note that the 32 bit routines are not listed
' because they will not yield signed results.

      include "fp20.bas"      ' Include file for most 14-bit core PICmicros (24-bit)
'       include "fp17.bas"      ' Include file for 17Cxxx (24-bit)
' include "fp18.bas" ' Include file for 18Cxxx (24-bit)

' Define LCD registers and bits
Define  LCD_DREG        PORTD
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTE
Define  LCD_RSBIT       0
Define  LCD_EREG        PORTE
Define  LCD_EBIT        1

' Define the target device for PM assembler
Define  __16F877        1       ' Only use for PM, MPASM will define this by itself

fpplaces  var  byte ' Used to define number of decimal places in fpdisplay,fpdisplayr
ahold    var   word ' Required by fpdisplay
bhold    var   word ' Required by fpdisplay
' spin var   PORTC.6 ' Use for serial output pin
' sbaud  var   396 ' Use for serial output mode

resulthold var word ' Used to store results of previous calculations

resulthold = 22 ' This becomes the intitial value of aint


ADCON1 = 7      ' Set PORTA and PORTE to digital
Low PORTE.2      ' LCD R/W line low (W)
Pause 500        ' Wait for LCD to start



' Demonstrate floating point addition.

loop: aint = resulthold
Gosub itofa ' Convert aint to float

bint = 14
Gosub itofb ' Convert bint to float

Gosub fpadd ' FP add (+14)

Lcdout $fe,1, sdec resulthold, " + 14 = " ' Clear display, display equation
fpplaces = 2 : Gosub fpdisplayr ' Call display routine

' Serout2 spin,sbaud,[sdec resulthold, " + 14 = ", sdec aint] ' Use for 2400 bps serial output

Pause 3000



' Demonstrate floating point subtraction

resulthold = aint ' Hold for later
Gosub itofa ' Convert aint to float - aint=result from add

bint = 17
Gosub itofb ' Convert bint to float

Gosub fpsub ' FP subtract (-17)

Lcdout $fe, 1, sdec resulthold, " - 17 = " ' Clear display, display equation
fpplaces = 2 : Gosub fpdisplayr ' Call display routine

' Serout2 spin,sbaud,[sdec resulthold, " - 17 = ", sdec aint] ' Use for 2400 bps serial output
Pause 3000



' Demonstrate floating point multiply

resulthold = aint
        Gosub itofa      ' Convert aint to float  aint=result from subtract

        bint = 6
        Gosub itofb      ' Convert int to float

        Gosub fpmul      ' FP multiply (*6)

        Lcdout $fe, 1, sdec resulthold, " * 6 = " ' Clear display, display equation
fpplaces = 2 : Gosub fpdisplayr ' Call display routine

' Serout2 spin,sbaud,[sdec resulthold, " * 6 = ", sdec aint] ' Use for 2400 bps serial output
        Pause 3000



' Demonstrate floating point divide

resulthold = aint
        Gosub itofa      ' Convert int back to float - aint=result from multiply

        bint = 7
        Gosub itofb      ' Convert int to float

        Gosub fpdiv      ' FP divide (/7)

        Lcdout $fe, 1, sdec resulthold, " / 7 = " ' Clear display and output equation
' Serout2 spin,sbaud,[sdec resulthold, " / 7 = "] ' Use for 2400 bps serial output

fpplaces = 2 : Gosub fpdisplayr ' Call display routine

Pause 3000

resulthold = aint ' Store integer portion of result for next loop
        Goto loop ' Do it forever



' The fpdisplayr routine checks for number of places, then adds the appropriate
' value to achieve rounding.  To save RAM space, the values are hard coded
' in floating point format.

fpdisplayr: If fpplaces=0 Then ' Set floating point barg to 0.5
bexp = $7E
bargb0 = $00
bargb1 = $01
Endif
If fpplaces=1 Then ' Set floating point barg to 0.05
bexp = $7A
bargb0 = $4C
bargb1 = $CD
Endif
If fpplaces=2 Then ' Set floating point barg to 0.005
bexp = $77
bargb0 = $23
bargb1 = $D8
Endif
If fpplaces=3 Then ' Set floating point barg to 0.0005
bexp = $74
bargb0 = $03
bargb1 = $13
Endif
If fpplaces=4 Then ' Set floating point barg to 0.00005
bexp = $70
bargb0 = $51
bargb1 = $B7
Endif

If aargb0.7 Then ' Check the floating point sign bit
Gosub fpsub ' If negative, subtract barg from aarg
Else
Gosub fpadd ' If positive, add barg to aarg
Endif


' The fpdisplay routine outputs the signed value of aarg in decimal floating point format. It
' can display an absolute value of 32767, and decimals to 4 places. The number of decimal
' places should be stored in fpplaces before calling the routine. The routine reads the
' floating point value of aarg. This value should NOT be converted to an integer before
' calling fpdisplay. The integer conversion will be perfomed as part of this routine, and
' aint will be returned to the calling program just as from the itofa routine.

fpdisplay: bexp = aexp ' Store the FP value of aarg to the barg variables
bargb0 = aargb0
bargb1 = aargb1

Gosub ftoia ' Convert aarg to integer
ahold = aint ' Save this value for the final display

Gosub itofa ' Convert integer back to float

Swap aexp,bexp ' Swap the FP values of aarg and barg before subtraction
Swap aargb0,bargb0
Swap aargb1,bargb1

Gosub fpsub ' Subtract the integer portion from the full number


bint = 10 ' Make bint = 10 E fpplaces
If fpplaces=2 Then
bint = 100
Endif
If fpplaces=3 Then
bint = 1000
Endif
If fpplaces=4 Then
bint = 10000
Endif

bhold = bint ' Save the integer value of bint for zeros loop

Gosub itofb ' Convert bint to integer prior to FP multiply
Gosub fpmul ' Multiply the decimal portion x 10 E fpplaces

Gosub ftoia ' Convert result to aint integer


If (ahold.15) OR (aint.15) Then ' Check for negative integer or decimal
Lcdout "-" ' Display minus

' Serout2 spin,sbaud,["-"] ' Use for 2400 bps serial output
Endif

Lcdout dec abs ahold ' Display integer portion

' Serout2 spin,sbaud,[dec abs ahold] ' Use for 2400 bps serial output

If fpplaces > 0 Then
Lcdout "."
' Serout2 spin,sbaud,["."] ' Use for 2400 bps serial output

zeros: bhold = bhold / 10 ' Set bhold to be next place to right
If (abs aint < bhold) AND (bhold > 1) Then ' Check for leading zero in decimal
Lcdout "0" ' Display leading zero
' Serout2 spin,sbaud,["0"] ' Use for 2400 bps serial output
Goto zeros ' loop to check for another zero
Endif

Lcdout dec abs aint ' Display the rest of the decimal portion

' Serout2 spin,sbaud,[dec abs aint] ' Use for 2400 bps serial output

Endif

aint = ahold ' Restore the original value of aint

Return


comom veras no compite con tu modo ya que ocupa mas memoria, pero nos evita el pensar :D tambien se pueden definir cuantos decimales quieres usar.


si te fijas en mi ejemplo de uso con el termometro lo unico que hago es a la variable sensor multiplicarla por 104 y meterla en RESULTHOLD que es donde se guarda la informacion y despues ese valor lo divido entre 213 usando las rutinas de FP y ya es todo lo demas lo hacen las rutinas.

Veras que no es dificil usar esto, y es confiable segun su uso, yo lo recomiendo siempre porque solo igualas tu variable a resulthold y usas la subrutina dependiendo de la operacion a usar y listo. no necesitas mucho para entender

saludos  :-/

ojala esto amplie a los que quieran usar punto decimal en PBP, lo unico que intentamos mario y yo es ayudar y no confundir :-) 8)

se me olvidaba para compilar los archivos deben estar en la misma carpeta.
« Última modificación: 03 de Octubre de 2006, 03:37:34 por navaismo »
"Mi tercer deseo, que otra cosa podría ser, poner un final a todo el sufrimiento, que sólo con mi propia extinción el planeta podrá ser aliviado. Pobre de mí, Si tuviera tres deseos hoy, la elección no sería dificil para mí, Sólo tres deseos serían suficientes, No tendría uso para más."

"He sido un hombre que busca y aun lo sigo siendo, pero ya no busco en las estrellas y en los libros, sino en las enseñanzas de mi sangre."

Desconectado Mario

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 873
Re: Uso del DIV32
« Respuesta #5 en: 03 de Octubre de 2006, 04:51:35 »
Ya terminé la tarea (12:43 AM aqui). :ni)

Navaismo:

Revisando el código me parece que está bien.

Creo que por aqui has mencionado que usas proteus, yo no lo sé usar pero sé que se usa para simular.

Carga todo el programa asi como está (el que se propone) y pruébalo en Proteus.

El programa debe funcionar porque es el mismo que se explica desde Octubre del 2004 en la materia de microcontroladores II, en el Instituto Tecnológico de Méxicali.


Una cosa mas:

Si quitan el código del LCD y compilan, se darán cuenta que la pura rutina de la ecuación consume 145 palabras de un 16F877  :o.

Voy a revisar el código de punto flotante de microchip.

Navaismo, ¿tendrás tu código original de ese sensor?
Si lo tienes escribelo o adjúntalo para quemarlo en un micro y ver trabajando la rutina de punto flotante.

La buena administración es utilizar el sentido común y la regla de oro; aunque el sentido común no es tan común como quisiéramos que fuera y, quien tiene el oro, hace las reglas.
George Terry

"A loser will defeat a genius with hard work"
Rock Lee

Desconectado dexhk

  • PIC10
  • *
  • Mensajes: 1
Colocarle punto decimal al LCD
« Respuesta #6 en: 04 de Octubre de 2006, 22:39:23 »
Bueno, este es mi primer mensaje en un foro, ojala sirva de ayuda para muchos!!! :mrgreen:

Lo siguiente consiste en poder visualizar resultados en un LCD con punto decimal que a veces nos hace falta para que todo quede de maravilla. En PICBasic existe una instruccion que es DIG la cual dice que:

"DIG devuelve el valor de un dígito decimal . Simplemente se le indica el número de dígito a conocer ( 0 - 4 , siendo 0 el primero de la derecha) y ya está."

                      B0 = 123 ´ setea B0 en 123

                      B1 = B0 DIG 1 ´ setea B1 en 2 (dígito 1 de 123)

Supongamos que queremos visualizar un voltaje ya convertido con el A/D, con un una resoluccion de 8 bits, entonces 5/255=0,019607, y queremos que nos apareza por ejemplo  2.9 voltios en el LCD, entonces hacemos primero lo siguiente:

RESULTADO A/D * (19607/100) = VALOR CONVERTIDO A VOLTAJE

Donde RESULTADO A/D, es lo que nos entrega el modulo de conversion y es un numero de 0 a 255, supongamos que es 150, y donde VALOR CONVERTIDO A VOLTAJE seria lo que mostrariamos en el LCD.

150*(19607/100)=29410,5, este ultimo seria el voltaje, pero nunca lo veremos con el ,5, sino hasta el 0, entonces queremos que de alguna forma se vea como decimal, y ademas sabiendo que en realidad el resultado es 2.94105 v. Entonces aplicando DIG podemos hacer lo siguiente:

Declaramos tres variales como palabras

                MOSTRAR1     VAR        WORD
                MOSTRAR2     VAR        WORD
                MOSTRAR3     VAR        WORD


                RESULTADO A/D * (19607/100) = VALOR EN DECIMAL
                MOSTRAR1=RESULTADO A/D DIG 3
                MOSTRAR2=RESULTADO A/D DIG 2
                MOSTRAR3=RESULTADO A/D DIG 1

                LCDOUT       "VALOR: ", #MOSTRAR1,".",#MOSTRAR2,#MOSTRAR3

Y listo, tendremos nuestro valor 29410,5, convertido en 2.94105 voltios, claro que hay que tener en cuenta que en realidad muestra es 2.94 por la cnatida de valores usados con DIG, y recuerden que solo permite hasta 4.

Bueno no siendo mas, espero que haya servido un poco de ayuda lo que hoy pude descubrir leyendo el manual. Cualquier duda sobre la explicacion me preguntan!!! y gracias por las respuestas de los que postean en este foro, la verdad me ha servido de mucho.

Exitos! :lol:

DeXHK

Desconectado navaismo

  • Jubilado Todopic
  • PIC24H
  • ****
  • Mensajes: 1973
Re: Colocarle punto decimal al LCD
« Respuesta #7 en: 05 de Octubre de 2006, 01:51:01 »
Gracias por la explicacion. Ahora una peticion a nuestro moderador, LORDLAFEBRE: podris mover este post que va de la mano con el post que hizo Mario del DIV32 creo que ese post quedaria bueno para explicar las rutinas de punto flotante.
"Mi tercer deseo, que otra cosa podría ser, poner un final a todo el sufrimiento, que sólo con mi propia extinción el planeta podrá ser aliviado. Pobre de mí, Si tuviera tres deseos hoy, la elección no sería dificil para mí, Sólo tres deseos serían suficientes, No tendría uso para más."

"He sido un hombre que busca y aun lo sigo siendo, pero ya no busco en las estrellas y en los libros, sino en las enseñanzas de mi sangre."

Desconectado LordLafebre

  • Moderador Global
  • DsPIC30
  • *****
  • Mensajes: 3529
    • Micros & micros
Re: Uso del DIV32
« Respuesta #8 en: 05 de Octubre de 2006, 12:35:58 »
Hola:

Listo, ya los he unido, y que lastima no pder seguir ahora muchos temas, ahora trabajo en otro lado mas, pero siempre paso por aqui, ya no como antes pero en el tiempito que tengo hago lo que puedo.  :mrgreen:

Desconectado masterpiano

  • PIC10
  • *
  • Mensajes: 3
duda sobre precision en los pic
« Respuesta #9 en: 04 de Enero de 2011, 15:08:24 »
  :-/
hola amigos feliz año 2011
ya resolvi un gran problema de los voltimetros y los decimales
pero me surge la siguiente pregunta

como hacer para que la medicion sea perfecta o lo mas precisa posible

aca les dejo un codigo para ver en que me pueden ayudar

e lvoltimetro es de 0 a 15 voltios pero la medicion en el LCD es de 15,30

intente restar lo00,30  pero no me da,ojala puedan ayudarme

gracias

Desconectado Sacahe

  • PIC12
  • **
  • Mensajes: 68
Re: Uso del DIV32
« Respuesta #10 en: 15 de Enero de 2012, 12:41:58 »
Hola Navaismo!!!

Me podrias explicar el metodo que tu expones pero en un ejemplo mas sencillo (el que colocas me enreda :huh: ). Por ejemplo sumar dos numeros de 24 bits cada uno, con o sin signo. y las librerias que mencionas de donde las bajo?

Te agradezco!!!

Desconectado MossGallagher

  • PIC10
  • *
  • Mensajes: 2
Re: Uso del DIV32
« Respuesta #11 en: 15 de Enero de 2012, 17:30:24 »
 :angel: Hola Mario, este mensaje solo es para agradecerte enormemente por tu post, solo tenia este inconveniente para terminar mi tesis, y gracias a ti lo logré, espero seguir leyendo mas post como los tuyos, y claro yo publicaré mis conocimientos que si pocos o muchos espero algún día ayuden a alguien como tu conmigo. Un abrazo desde México que estes de lo mejor!
 ;-)

Desconectado Sacahe

  • PIC12
  • **
  • Mensajes: 68
Re: Uso del DIV32
« Respuesta #12 en: 19 de Enero de 2012, 18:59:12 »
Aun me resulta un poco complicado utilizar las rutinas de FP para integrarlas a mis proyectos con PBP. Sera que pueden colocar un ejemplo sencillo digamos de division, donde se divida dos numeros, un decimal con un entero.

Por ejemplo: Dividir 125.32 / 12 y obtener el resultado que seria 10.44. La idea es solo utilizar lo especifico de las librerias FP para realizar esta operacion.

Les agradezco mucho!!!