Autor Tema: Sublw,subwf y simbolo (-).  (Leído 386 veces)

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

Desconectado NicaUnlock

  • PIC10
  • *
  • Mensajes: 10
Sublw,subwf y simbolo (-).
« en: 01 de Marzo de 2017, 21:01:59 »
Buenas tardes a todos primeramente me disculpan si es SPAM pero no he encontrado algo similar. :x

Estoy estudiando la libreria LCD_4BIT.INC del libro del PIC16F84A para control de display LCD bueno mi duda es al final de esta libreria hay una subrutina que se llama LCD_Nibble.

LCD_EnviaByteLetra
   movf   LCD_Auxiliar1,W
   addlw   'A'-0x0A         ; Sí, por tanto, se le suma el ASCII de la 'A'.
LCD_FinVisualizaDigito
   goto   LCD_Caracter         ; Y visualiza el carácter. Se hace con un "goto"
                  ; para no sobrecargar la pila.

Como ven hay una parte en donde se le suma al registro W 'A'-0x0A al valor ASCII de la A se le resta A en hexadecimal que es 10 quedando el valor en 55 mi duda es: Para la resta existen los dos demonicos SUBLW y SUBWF no sabia que podia usar este simbolo (-) y hacer ese tipo de restas? por otro lado por que en vez de confundir poniendo addlw    'A'-xx0A por que no poner directamente el valor 55 --> addlw   .55?

De antemano les agradezco la verdad lo que mas me confunde es el uso del simbolo (-) no sabia que lo podia usar.

Gracias y saludos!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 5846
Re:Sublw,subwf y simbolo (-).
« Respuesta #1 en: 01 de Marzo de 2017, 23:38:46 »
Si el SUBLW y el SUBWF son operaciones del microcontrolador, en los cuales intervienen los registros internos del microcontrolador, aca no es el caso, es una resta que realiza el compilador, este lo reconoce y lo transforma en un simple numero ( .55 ). Eso luego se transforma en ADDLW .55 (ya que es un valor FIJO), por que escribirlo asi? es mas "informativo".

Como bien decis hacer 'A'-.10 o 'A'-0xA, es lo mismo que hacer .55 = 0x37 y seguramente lo hace para indicar algo.

A vos te confunde que use el signo menos y le reste algo. Pero peor seria que aparezca un .55 y no sepas exactamente por que ese 55!. En este caso es mejor, al menos con lo leído tenemos que como se trata de una letra (por el label de esa rutina) tiene que tener una base 'A', pero hay un problema ya sea por manejo del LCD, direcciones, o que se hizo antes,etc tiene 10 posiciones de desfase,

Es muy dificil saber porque lo hace cuando esta de forma incompleta, tal ves el driver del LCD es asi, lo cual es raro, pero puede serlo, tal ves antes hace un manejo raro al detectar que es una letra y procede a sumarle 10, pueden ser varias causas.

Pero en si... El que se escriba 'A'-0xA ayuda a comprender lo que se intento hacer ( si es que se sigue lo anterior ). Si hubiera sido un .55 no se sabría el porque de ese invento ( me refiero al numero 55).

Desconectado NicaUnlock

  • PIC10
  • *
  • Mensajes: 10
Re:Sublw,subwf y simbolo (-).
« Respuesta #2 en: 02 de Marzo de 2017, 00:28:53 »
HOla KILLERJC y muchas gracias por la ayuda!  ((:-)) Tienes toda la razon de esa forma el 'A'-0X0A para dar a entender mejor lo que está haciendo lo que pasa que hasta ahorita lo veo  :x esa subrutina es para mostrar el el display LCD codigos en hexadecimal a continuacion te dejo esa subrutina:

Código: [Seleccionar]
; Subrutinas "LCD_ByteCompleto" y "LCD_Byte" --------------------------------------------
;
; Subrutina "LCD_ByteCompleto", visualiza el byte que almacena el registro W en el
; lugar actual de la pantalla. Por ejemplo, si (W)=b'10101110' visualiza "AE".
;
; Subrutina "LCD_Byte" igual que la anterior, pero en caso de que el nibble alto sea cero
; visualiza en su lugar un espacio en blanco. Por ejemplo si (W)=b'10101110' visualiza "AE"
; y si (W)=b'00001110', visualiza " E" (un espacio blanco delante).
;
; Utilizan la subrutina "LCD_Nibble" que se analiza más adelante.
;
LCD_Byte
movwf LCD_Auxiliar2 ; Guarda el valor de entrada.
andlw b'11110000' ; Analiza si el nibble alto es cero.
btfss STATUS,Z ; Si es cero lo apaga.
goto         LCD_VisualizaAlto ; No es cero y lo visualiza.
movlw ' '         ; Visualiza un espacio en blanco.
call        LCD_Caracter
goto        LCD_VisualizaBajo

LCD_ByteCompleto
movwf    LCD_Auxiliar2 ; Guarda el valor de entrada.
LCD_VisualizaAlto
swapf LCD_Auxiliar2,W ; Pone el nibble alto en la parte baja.
call LCD_Nibble         ; Lo visualiza.
LCD_VisualizaBajo
movf LCD_Auxiliar2,W ; Repite el proceso con el nibble bajo.
; call         LCD_Nibble ; Lo visualiza.
; return

; Subrutina "LCD_Nibble" ----------------------------------------------------------------
;
; Visualiza en el lugar actual de la pantalla, el valor hexadecimal que almacena en el nibble
; bajo del registro W. El nibble alto de W no es tenido en cuenta. Ejemplos:
; - Si (W)=b'01010110', se visualizará "6".
; - Si (W)=b'10101110', se visualizará "E".
;
LCD_Nibble
andlw b'00001111' ; Se queda con la parte baja.
movwf LCD_Auxiliar1 ; Lo guarda.
sublw 0x09 ; Comprueba si hay que representarlo con letra.
btfss STATUS,C
goto         LCD_EnviaByteLetra
movf LCD_Auxiliar1,W
addlw '0'         ; El número se pasa a carácter ASCII sumándole
goto LCD_FinVisualizaDigito ; el ASCII del cero y lo visualiza.
LCD_EnviaByteLetra
movf LCD_Auxiliar1,W
addlw 'A'-0x0A         ; Sí, por tanto, se le suma el ASCII de la 'A'.
LCD_FinVisualizaDigito
goto  LCD_Caracter ; Y visualiza el carácter. Se hace con un "goto"
                ; para no sobrecargar la pila.

Por otro lado si no es mucha molestia me podrias dar la diferencia entre los registros internos (nemonicos) de resta del microcontrolador y las que usa el compilador? disculpa la pregunta es que he buscado informacion al respecto pero no he encontrado, y si tiene para resta (-) tendra para suma (+) el compilador? por que asi en algunas ocaciones sale mejor hacer una resta con (-) que con los respectivos registros.

Muchas gracias nuevamete!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 5846
Re:Sublw,subwf y simbolo (-).
« Respuesta #3 en: 02 de Marzo de 2017, 19:52:58 »
Si lees bien dice que la rutina esa hace que te muestre el valor hexadecimal en el LCD

Supongamos que tenes el valor 1010 que seria 0xA o 10 en decimal, vos debes mostrar una 'A', Como harias para hacer eso ?

Puedo hacer una especie de "tabla" para guiarme:

.10 o 0xA  esto me tiene que dar -> 'A' = 65 o 0x41
.11 o 0xB  esto me tiene que dar -> 'B' = 66 o 0x42
.12 o 0xC  esto me tiene que dar -> 'C' = 67 o 0x43
.13 o 0xD  esto me tiene que dar -> 'D' = 68 o 0x44
.14 o 0xE  esto me tiene que dar -> 'E' = 69 o 0x45
.15 o 0xF  esto me tiene que dar -> 'F' = 70 o 0x46

Estaria bueno si usamos como base el valor de 'A' es que 0xA sume 0 a esa base, para 0xB sume 1 solo y asi, si observas es solo restarle 10 al nibble.

.0 o 0xA  esto me tiene que dar -> 'A' = 65 o 0x41
.1 o 0xB  esto me tiene que dar -> 'B' = 66 o 0x42
.2 o 0xC  esto me tiene que dar -> 'C' = 67 o 0x43
.3 o 0xD  esto me tiene que dar -> 'D' = 68 o 0x44
.4 o 0xE  esto me tiene que dar -> 'E' = 69 o 0x45
.5 o 0xF  esto me tiene que dar -> 'F' = 70 o 0x46

Lo bueno es que ahora yo puedo tomar la base a el valor 'A' o 65, si antes tenia un 0b1010 ( que es 10 decimal y es una A hexadecimal a representar en el LCD) y le resto 10, me queda en 0, ahora si a eso le sumo la base que es 'A' voy a obtener simplemente 'A', para el caso de 'B' quedaria 'A' + 1 lo cual me daria ese 'B'.
Esto se podria escribir en formula asi:

Nibble - 10 + 'A'

Si lo tuviera que hacer en el micro esto significa que al valor del nibble deberia restarle 10 y luego sumarle 'A' ( y hacerlo en W para no modificar nada)

MOVF Valor, W
ANDLW 0xF       ;Nibble bajo
SUBLW 0xA
ADDLW 'A'

Pero la suma/resta es conmutativa, por lo cual puedo escribirlo asi ( y luego le agrego un parentesis para que se note mas):

Nibble + 'A' - 10
Nibble + ('A' - 10)

Entonces si yo al valor en hexadecimal (obviamente solo para las letras A,B,C,D,E y F) le sumo ( 'A'-10  o 'A'-0xA ) me estaria dando el valor en ASCII de esa letra. El mismo resultado que antes con una instruccion menos.

MOVF Valor, W
ANDLW 0xF       ;Nibble bajo
ADDLW 'A'-0xA

Espero que hubieras logrado seguirme en el hilo de pensamiento. Y ahi tenes el por que le agrega ese 0xA.


--------------------------------------------------

El otro tema es que tenes que diferenciar entre lo que genera el compilador y las instrucciones del microcontrolador.
Cuando hacemos:

ADDLW 'A'-0xA

El compilador primero revisa todo el codigo, y detecta que 'A'-0xA lo puede hacer un solo numero, entonces procede a reemplazarlo por un solo numero, es decir a la salida del compilador o en realidad la instruccion que va a ir en el microcontrolador y que se encuentra en el .hex es:

ADDLW .55
(en realidad es un opcode que genera el compilador, pero ese opcode es la instruccion esa)

Esto por que son constantes. Pero por ejemplo vos no podrias hacer esto:

ADDLW 'A' - W

Por que el compilador no sabe que es W, el compilador lo unico que hace es checkear que no hay errores, y generar un codigo "objeto" acomodar los saltos, etc. Luego agarra el linker y lo acomoda en la memoria.
Otra cosa es que no tiene nada que ver con las instrucciones, por ejemplo puedo usar la directiva EQU y hacer:

Salida EQU 1+1

el compilador sabria que el texto "Salida" es lo mismo que 2 en el texto del codigo. Pero esta "instruccion" no va en el microcontrolador, es simplemente una directiva que posee el compilador para simplificar la vida al programador
Tambien quiero que veas que todos los ejemplos claramente apuntan que los valores usados sean valores constantes como dije, y no registros ni nada por el estilo.


Hago un ejemplo mas rapido para que veas la diferencia y en donde podes usarlo. Suponete que a un registro le tenes que sumar 10 y luego 20, podes hacerlo en 2 pasos, o simplemente sumar 30. Pero supongamos que esos 10 hacen referencia a algo antes, y esos 20 a otra cosa, entonces la idea es que lo sepa el que lee el codigo

Código: ASM
  1. MOVF Registro, W
  2. ADDLW .10         ; 10 de esto
  3. ADDLW .20         ; 20 del otro
  4.  
  5. ; o hacer
  6.  
  7. MOVF Registro, W
  8. ADDLW .30        ; 10 de una cosa y 20 de otra cosa
  9.  
  10. ; o hacer
  11.  
  12. MOVF Registro, W
  13. ADDLW .10+.20    ; 10 por xxxxx cosa, y 20 por la otra cosa, esto bla bla bla bla

Los 3 ejemplos hacen lo mismo, en el primer caso uso una instruccion mas en el microcontrolador, es decir tengo 2 ADDLW, en el 2do y 3ro pueden parecer distinto, pero luego de que pase el  compilador quedan iguales, lo unico que ganas es legibilidad del codigo.

Desconectado NicaUnlock

  • PIC10
  • *
  • Mensajes: 10
Re:Sublw,subwf y simbolo (-).
« Respuesta #4 en: 04 de Marzo de 2017, 20:59:09 »
Amigo te agradezco mucho por tan buena explicacion sos excelente! ((:-)) la verdad que he quedado muy claro de todo.

Mil gracias y saludos!


 

anything