TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: Resistencio en 17 de Marzo de 2007, 02:32:19
-
Hola, muchachos, muchachas, chicos, chicas, señoras y señores...soy relativamente nuevo en esto de los PIC´s, de hecho todavia tengo el "celofan" puesto...lo cierto es que el ASM es lo unico que aprendi, y de hecho, creanme, para mi que aprendi electronica, con el "cerebro magico" o con la "Lupin", como lei por ahi...es mucho decir...
Como les decia, aprendi, de tanto leer codigo...y ahora, de leerlos a ustedes...quizas alguien pueda decirme si esto es ASM, y si asi es, como se entiende, que significa, lo que sigue abajo...
El codigo tiene que ver con la siguiente MACRO:
;DELAY CYCLES instruction cycles
Delay macro Time
if (Time==1)
nop
exitm
endif
if (Time==2)
goto $+1
exitm
endif
if (Time==3)
nop
goto $+1
exitm
endif
if (Time==4)
goto $+1
goto $+1
exitm
endif
Asi hasta:
if (Time==7)
goto $+1
goto $+1
goto $+1
nop
exitm
endif
Despues:
if (Time%4==0)
movlw (Time-4)/4
call Delay_us
exitm
endif
if (Time%4==1)
movlw (Time-5)/4
call Delay_us
nop
exitm
endif
if (Time%4==2)
movlw (Time-6)/4
call Delay_us
goto $+1
exitm
endif
if (Time%4==3)
movlw (Time-7)/4
call Delay_us
goto $+1
nop
exitm
endif
endm
Bueno esa es la MACRO, que esta en medio de ASM, que si entiendo...
En el programa llama a esta MACRO, con:
Delay11 o Delay21 o Delay45 o Delay8
Lo cual parecen ser las variables de alguna demora...
La rutina Delay_us es:
;Delay 4w+4 cycles (including call.return and movlw) (0=256)
Delay_us ADDLW -1 ;precise delays used in I/O (esto esta buenisimo de sumar -1)
btfss STATUS,Z
goto Delay_us
return
Estas rutinas estan en un soft para emular un mouse por PS/2...
Si alguien puede explicarme como anda la MACRO, si es ASM o es un "trozo" de BASIC ???
Si consideran que falta algun otro dato, por favor avisenme !!!
Bueno, me voy a comer un alfajor y espero algun "cerebro inteligente", que me responda...tambien puede ser alguien inspirado...o simplemente con ganas de escribirme...comparto el "alfajor" :-) con el primero que me de una pista !!! :mrgreen:
-
Lo que expones es codigo ASM y es una MACRO.
Lo que hace con tantos "IF" es intentar simular una especie de "SWITCH"(en C y similares) o "CASE"(VB y similares) para seleccionar el retardo segun el valor "Time" Recibido.
Ejemplo: si en el programa pongo: Delay 7
Lo que en realidad se "ensambla" en el PIC es:
goto $+1
goto $+1
goto $+1
nop
goto es una instruccion de 2 ciclos de ejecucion. Por lo que si hay 3 gotos y un nop, en total tenes 7 ciclos de instruccion. Si usas un cristal de 4mhz esto equivale a 7us.
Hay hasta Time = 7 porque son tan pequeñas las demoras que no se puede hacer un caso general para ellas.
Si la demora es mayor, entonces si podes y por eso surge por ejemplo:
if (Time%4==1)
movlw (Time-5)/4
call Delay_us
nop
exitm
endif
El % en este lenguaje si mal no me equivoco es el resto(mod) de una division con cociente entero.
Ejemplo: 41%4= 1 porque 40/4 es 10, pero el resto es 1. Y eso es lo que interesa en este caso. El resto.El mod.
Si dividis a cualquier numero por 4, podes obtener un resto igual a 0,1,2 o 3. Si o si esas son todas las oportunidades.
Lo unico que hace esa MACRO es calcular los tiempos de demora segun el delay que desees.
-
Bien, BRUNO, ya tengo una pista...ahora, entre tanta MACRO, como sabe el valor que debe tomar la demora...por ejemplo si en el programa, llamo a esta MACRO con DELAY 21, que valores toma ??? (aca parece que la demora sera de 21 us) pero como construye, esos 21 us ???
Por otro lado, el MAPLAB, reconoce IF, como ASM???...pregunto esto por que en otro "hilo", alguien preguntaba como emular el IF en ASM, y le dieron el siguiente ejemplo:
movfw VAR
sublw 0x05
SKPNZ
call funcion
Osea si, VAR=5 va a FUNCION (IF VAR=5 va a FUNCION)
Es este IF simulado igual al que se escribe en esta MACRO ??? sobre la que pregunto !!!
Porque en lugar de dar ese ejemplo, de como simular IF con ASM...no le respondieron, a quien pregunto...PONE "IF" directamente y dejate de RLP (romper las pe_o__s), me explio, BRUNO !!!
Que otros comandos como el IF, reconoce el MPLAB ???
SALUDOS y ya puse medio alfajor en una cajita, con destino a Rosario, lo mando por Flecha Bus ???
-
Antes que nada, poné los mates y las facturitas porque te puede llevar un ratito leer esto:
Bien, BRUNO, ya tengo una pista...ahora, entre tanta MACRO, como sabe el valor que debe tomar la demora...por ejemplo si en el programa, llamo a esta MACRO con DELAY 21, que valores toma ??? (aca parece que la demora sera de 21 us) pero como construye, esos 21 us ???
No hay que confundir lo que es una MACRO, con lo que es código puro.
Si pongo en mi programa antes del END:
movlw 0x01
estaré ocupando 1 posición de memoria FLASH en el PIC.
Eso creo que está claro.
En lugar de lo anterior, podría poner en mi código esto:
PONER1ENW MACRO
movlw 0x01
ENDM
¿Cuánta memoria en el PIC ocupará eso?
Tal vez te sorprendas, pero no ocupará nada.
¿Por qué? Las MACROS sólo son utiles para generar código ASM variable(a veces no es variable), pero no ocupan por si mísmas memoria en el PIC ni generan código.
Ahora veamos cuándo ocupa memoria una "MACRO" en el PIC:
PONER1ENW MACRO
movlw 0x01
ENDM
PONER1ENW
Aquí, al escribir PONER1ENW estoy haciendo referencia a mi MACRO. El ensamblador se fija qué hay dentro de la macro y reemplaza:
PONER1ENW
por:
movlw 0x01
por lo que escribir "PONER1ENW" ocupa 1 posicion de memoria en el PIC.
Muchas veces se usan para ejecutar un grupete de instrucciones que usas muy a menudo ya que resulta tedioso escribirlas una y otra vez.
Ejemplo:
En el programa cambio constantemente el puertob de salidas a entradas, segun corresponde.
Como lo cambio a ratos es mas facil poner asi:
PUERTOBENTRADA macro
bsf STATUS,RP0
clrf TRISB
bcf STATUS,RP0
endm
Y directamente en mi programa cada vez que quiero cambiar el puertob a entrada en lugar de escribir esas tres lineas, escribo directamente:
PUERTOBENTRADA
y voilá. El ensamblador me remplaza "PUERTOBENTRADA" por las 3 lineas de codigo dentro de la macro correspondiente.
Entonces, la macro es un recurso de un poco más alto nivel de programación que nos ofrece el MPASM, para crear configuraciones y demás cosas de manera mucho más simple, pero sus condiciones(los IF por ejemplo) solo se ejecutan ANTES de ensamblar el archivo y sirven para seleccionar qué porciones de codigo deben reemplazarse o no.
Ahora un ejemplo práctico para que lo veas más claramente:
SEMAFORO macro Valor ;Creo una macro, Valor indica que la MACRO recibe sólo un parámetro y lo llamo Valor.
if(Valor < .80) ;Si el parametro recibido es menor a 80...
bsf PORTA,0 ;Encender lampara Verde
bcf PORTA,1 ;Apagar lampara Amarilla
bcf PORTA,1 ;Apagar lampara Roja
endif
if(Valor >= .80) && (Valor < .160) ;Si el parametro recibido es igual o mayor a 80 Y menor a 160...
bcf PORTA,0 ;Apagar lampara Verde
bsf PORTA,1 ;Encender lampara Amarilla
bcf PORTA,1 ;Apagar lampara Roja
endif
if(Valor > .160) ;Si el parametro recibido es mayor a 160...
bcf PORTA,0 ;Apagar lampara Verde
bcf PORTA,1 ;Apagar lampara Amarilla
bsf PORTA,2 ;Encender lampara Roja
endif
endm
org 0x000 ;Vector de inicio de memoria FLASH del PIC.
bsf STATUS,RP0
clrf TRISA ;puertoA todo como salida
bcf STATUS,RP0
SEMAFORO 100
end
Cuando ensamblas esto, sucede lo siguiente:
El MPASM al detectar el "SEMAFORO 40" sabe que haces referencia a la MACRO de arriba. Entonces se fija el codigo que hay dentro de la macro y lo ejecuta como si se tratara de un lenguaje de programacion de alto nivel.
Comienza revisando el primer IF, el cual no se cumple.Ignora todo código dentro del IF.
Luego sigue con el segundo IF, que se cumple, entonces agrega en la posicion actual del programa ensamblado las lineas que estan dentro de este IF que se cumple,quedando como si tu originalmente hubieses puesto directamente:
org 0x000
bsf STATUS,RP0
clrf TRISA
bcf STATUS,RP0
bcf PORTA,0
bsf PORTA,1
bcf PORTA,1
Luego sigue con el tercer IF, el cual tampoco se cumple. Lo ignora y termina la macro. Detecta el END, quedando en realidad esto:
org 0x000
bsf STATUS,RP0
clrf TRISA
bcf STATUS,RP0
bcf PORTA,0
bsf PORTA,1
bcf PORTA,1
end
Esto que te dije es para verlo de manera facil. Probablemente el MPASM vaya pasando a formato hexadecimal el codigo a medida que lo va produciendo pero lo puse asi para que lo veas mas facilmente.
Conclusion:
Las MACRO, DEFINE, etc no ocupan memoria en el PIC por el hecho de estar escritos dentro de un archivo a ensamblar.
Lo que puede generar y ocupar lineas de codigo es cuando utilizas esas MACRO, DEFINE, etc haciendo referencia/s a ella en el programa.
Saber usar bien las MACROS significa poder crear, por ejemplo un único programa compatible por ejemplo para 1 entre 5 modelos de PICs distintos, para 1 entre 20 tipos de pantallas LCD, etc etc etc.
Por otro lado, el MAPLAB, reconoce IF, como ASM???...pregunto esto por que en otro "hilo", alguien preguntaba como emular el IF en ASM, y le dieron el siguiente ejemplo:
movfw VAR
sublw 0x05
SKPNZ
call funcion
Osea si, VAR=5 va a FUNCION (IF VAR=5 va a FUNCION)
Es este IF simulado igual al que se escribe en esta MACRO ??? sobre la que pregunto !!!
Porque en lugar de dar ese ejemplo, de como simular IF con ASM...no le respondieron, a quien pregunto...PONE "IF" directamente y dejate de RLP (romper las pe_o__s), me explio, BRUNO !!!
El IF se produce a la hora de ensamblar el codigo y sirve para que el ensamblador analice la condicion y en base a eso actue y genere tanto codigos como advertencias o incluso errores PERO NO SE EJECUTA NI EXISTE SIQUIERA JAMAS EN EL PIC.
La macro sirve principalmente solo para ahorrarse escribir rutinas repetidas o bien para que el ensamblador genere codigo asm distinto de salida analizando las condiciones,etc dentro de cada macro.
Los IFs en ASM deben hacerse, por ejemplo, de la forma que expusiste:
movfw VAR
sublw 0x05
SKPNZ
call funcion
Aunque, hablando de Roma...SKPNZ es una MACRO! A diferencia de la que expusiste vos llamada DELAY, esta ya viene con el MPASM.
Escribir:
movfw VAR
sublw 0x05
SKPNZ
call funcion
En realidad es lo mismo que escribir:
movfw VAR
sublw 0x05
btfsc STATUS,Z
call funcion
No hay diferencia alguna, es sólo que escribir SKPNZ(Skip if No Zero) es mas fácil que recordar(tal vez :mrgreen:) btfsc STATUS, Z.
Resumiendo, poner:
'Defino que Variable hace referencia a la posicion 0x20 de la RAM.
Variable EQU 0x20
if(Variable == 0)
call EsCero
endif
NO significa que el ensamblador lo transforma al codigo asm correspondiente:
movf Variable,F
btfsc STATUS,Z
call EsCero
El primero codigo es analizado como:
if(0x20 == 0)
call EsCero
endif
por lo que no se cumple la condicion, y no agrega nada al asm "de salida".
Vos cuando me decis eso de ¿por qué no directamente ponen IF en el programa en lugar de todo ese codigo "feo"?
Sencillamente porque el MPASM no transforma el IF a instrucciones del PIC. Solamente revisa la condicion y actua en base a eso, pero solo en tu PC, y solo para generar el codigo asm final antes de ser ensamblado.
Lo que no impide que vos crees una MACRO que transforme el IF en codigo ASM, y de esta manera en lugar de poner todo ese codigo "feo" directamente pongas:
SIESMAYOR macro Nombre1 Nombre2
movf Nombre1,W
subwf Nombre2,W
btfsc STATUS,C
endm
SIESMAYOR PEPITO PEDRO
y el MPASM luego transforme eso a:
movf PEPITO,W
subwf PEDRO,W
btfsc STATUS,C
Y si haces y haces rutinas para simplificarte la vida, te encontraras con que acabas de crear, prácticamente un nuevo compilador parecido a lo que podría ser el PIC BASIC PRO, el CCS, C18 o lo que fuere.
Fin.
Es bastante dificil explicar esto de las MACRO sin pizarrón y el aprendiz enfrente ;) . Si no quedó claro intento explicarme mejor.
Voy a hacer un pequeño apendice para explicar la diferencia entre una MACRO y una subrutina(funcion), y mi firme postura que definiré como:
"CASI SIEMPRE ES MUCHO MAS EFICIENTE UTILIZAR UNA SUBRUTINA EN LUGAR DE UNA MACRO"...
Supongamos que hago un programa, y necesito apagar y encender cuatro luces en un puerto:
Podria crear dos macros de la siguiente manera:
APAGAR macro
bcf PORTB,0
bcf PORTB,1
bcf PORTB,2
bcf PORTB,3
endm
ENCENDER macro
bsf PORTB,0
bsf PORTB,1
bsf PORTB,2
bsf PORTB,3
endm
y en el programa poner:
ENCENDER
call demora
APAGAR
call demora
ENCENDER
call demora
APAGAR
call demora
ENCENDER
call demora
APAGAR
call demora
ENCENDER
call demora
APAGAR
call demora
O podria haber hecho lo mismo creando dos subrutinas:
APAGAR bcf PORTB,0
bcf PORTB,1
bcf PORTB,2
bcf PORTB,3
return
ENCENDER bsf PORTB,0
bsf PORTB,1
bsf PORTB,2
bsf PORTB,3
return
Y en el codigo poner:
call ENCENDER
call demora
call APAGAR
call demora
call ENCENDER
call demora
call APAGAR
call demora
call ENCENDER
call demora
call APAGAR
call demora
call ENCENDER
call demora
call APAGAR
call demora
¿Cuál es la diferencia?
Bueno, usando MACROS, el asm que crea el MPASM antes de proceder al proceso de transformación en .hex es:
bcf PORTB,0
bcf PORTB,1
bcf PORTB,2
bcf PORTB,3
call demora
bsf PORTB,0
bsf PORTB,1
bsf PORTB,2
bsf PORTB,3
call demora
bcf PORTB,0
bcf PORTB,1
bcf PORTB,2
bcf PORTB,3
call demora
bsf PORTB,0
bsf PORTB,1
bsf PORTB,2
bsf PORTB,3
call demora
bcf PORTB,0
bcf PORTB,1
bcf PORTB,2
bcf PORTB,3
call demora
bsf PORTB,0
bsf PORTB,1
bsf PORTB,2
bsf PORTB,3
call demora
bcf PORTB,0
bcf PORTB,1
bcf PORTB,2
bcf PORTB,3
call demora
bsf PORTB,0
bsf PORTB,1
bsf PORTB,2
bsf PORTB,3
call demora
Mientras que usando las subrutinas el codigo generado no se agranda. Es el mismo que el expuesto anteriormente:
call ENCENDER
call demora
call APAGAR
call demora
call ENCENDER
call demora
call APAGAR
call demora
call ENCENDER
call demora
call APAGAR
call demora
call ENCENDER
call demora
call APAGAR
call demora
Usando macros, ese trozo de codigo ocupa 40 words en la FASH del PIC, mientras que usando subrutinas ocupa solo 16 words en la FLASH del PIC.
Entonces, la diferencia es que usando MACROS, muchas veces se desperdicia demasiada memoria FLASH del PIC en vano.
Que otros comandos como el IF, reconoce el MPLAB ???
Creo si mal no recuerdo que es el único que el MPASM acepta(en la actualidad).
SALUDOS y ya puse medio alfajor en una cajita, con destino a Rosario, lo mando por Flecha Bus ???
Jeje nooo por favor, que estoy a dieta. :P
-
Espectacular, sorprendente, magistral, garcias BRUNO, entendi a la perfeccion esto de las MACROS, sus pro y sus contras...llevo poco tiempo en este FORO, y me sorprende gratamente, la molestia que te has tomado en escribirme, y explicar esto de las MACROS...(no digo explicarme, porque esta exposicion, tan detallada, sera patrimonio del FORO de ahora en mas).
En definitiva, el programa de donde saque esto...llama a esa MACRO, con:
DELAY 21 (a cual le da bolilla ??? - a las otras, ya entendi que las pasa de largo)
DELAY 28 (lo mismo !!!)
DELAY 48 (este es el mas raro)
DELAY 5 (esta parece la mas facil) creo que esta llamada ejecutara
if (Time==5)
goto $+1
goto $+1
nop
exitm
endif
Lo que no me "avivo", es como se resuelven las otras cuentas para que den 8 - 11 - 21 - 28 - 45 - 48 y estas llamadas, sí, estan hechas en el programa... ( quiero decir, no las puse yo, como ejemplos al azar...)
Ademas, se puede llamar a esta MACRO con otros valores, o solo se llama con los valores que puede atender ??? (segun lo que interprete en tu post, la respuesta es NO, pero confirmame, plz...)
En algun lado lei que estan disponibles, como el IF en las MACROS...los operandos, como los de tu ejemplo >, <, =, &, /...estare estudiando algo de eso y si me surgen dudas (casi con seguridad que asi pasara...) te estare consultando...tambien lei sobre THEN, ELSE, pero no estoy 100% seguro que tenga relacion con el ASM...
Hasta ahora en el RANKING del ALMACEN del ASM, mis posiciones son:
1º - DIOS
2º - BRUNO
3º - TODO LO DEMAS (sin ofender a nadie) tambien lei algo de CHARLY, que te pelea el puesto cuerpo a cuerpo !!! :D
Como el "barba", no me contesta (anda con otros "kilombetes"), para mi sos el GURU del ALMACEN...Bueno BRUNO, me voy a sacar la segunda "pava" de la hornalla...Ahi tengo una ROSAMONTE DESPALADA, a estrenar...ahi te paso un amargo !!!
Hasta la proxima...GRACIAS !!! :)
DANIEL !!!
"Justo a mi, me toco ser YO" (creo que es de QUINO !!!) :-)
-
Y seguí con los mates nomás, hasta que quedes verde. :D
Mis explicaciones son muchas veces muy extensas, porque me gusta ir pasito a pasito, "baby steps"
Espectacular, sorprendente, magistral, garcias BRUNO, entendi a la perfeccion esto de las MACROS, sus pro y sus contras...llevo poco tiempo en este FORO, y me sorprende gratamente, la molestia que te has tomado en escribirme, y explicar esto de las MACROS...(no digo explicarme, porque esta exposicion, tan detallada, sera patrimonio del FORO de ahora en mas).
En definitiva, el programa de donde saque esto...llama a esa MACRO, con:
DELAY 21 (a cual le da bolilla ??? - a las otras, ya entendi que las pasa de largo)
DELAY 28 (lo mismo !!!)
DELAY 48 (este es el mas raro)
DELAY 5 (esta parece la mas facil) creo que esta llamada ejecutara
if (Time==5)
goto $+1
goto $+1
nop
exitm
endif
Lo que no me "avivo", es como se resuelven las otras cuentas para que den 8 - 11 - 21 - 28 - 45 - 48 y estas llamadas, sí, estan hechas en el programa... ( quiero decir, no las puse yo, como ejemplos al azar...)
OK. Me fui tanto por las ramas que ovidé explicar lo que sucede con DELAY 21...jeje
La MACRO que expones tal vez no es la más simple para comprender. Posee varias "cositas" bien calculadas que dificultan su compresiòn si no tenes bien claro el tema de los IF.
Fijate que la MACRO arranca primero comparando Time con 1, luego con 2, 3,4,5,6 y 7. Luego recién viene el otro conjunto de IFs que resolverán cualquier número entre 8 y 0(si. Digo 0 y no 255 porque en este caso poniendo 0 SUPONGO que obtenés el mayor tiempo de retardo posible: es decir, 256us @4Mhz).
¿Es esto casualidad? ¿Se podría invertir el orden de las comparaciones(IFs) y obtener el mísmo código asm de salida para cada valor de "Time"?
La respuesta es NO.
¿Por qué no?
Los casos cuando Time vale de 1 a 7 son fáciles. Los otros cuatro IFs son los que abarcan cualquier número. ¡Cualquiera! Inclusive del 1 al 7 también.
Como ya expliqué, el símbolo % signifíca en este lenguaje MOD. MOD es el resto de una división.
Si tengo por ejemplo: 1%4, entonces el resto de esa división es 1.
Si tengo: 2%4, entonces el resto de esa división es 2.
Si tengo: 3%4, entonces el resto de esa división es 3.
Si tengo: 4%4, entonces el resto de esa división es 0.
Si tengo: 5%4, entonces el resto de esa división es 1.
... ...
Entonces, generalizando: el resultado de hacer X%Y es siempre un valor entre 0 e (Y-1).
Como están contemplados dentro de esta MACRO los cuatro casos posibles de restos de una divisón por 4(nótese que se contemplan los casos para resto 0,1,2 y 3), esto significa que CUALQUIER valor de TIME satisfacerá uno y sólo uno de estos 4 casos de resto.
Ahora vamos con un ejemplo para ver la diferencia si invierto el orden de los IFs.
Hagamos primero el caso por ejemplo: DELAY 5
Si los dejo como los expones vos:
if (Time==1)...
if (Time==2)...
if (Time==3)...
if (Time==4)...
if (Time==5)...
if (Time==6)...
if (Time==7)...
if (Time%4==0)...
if (Time%4==1)...
if (Time%4==2)...
if (Time%4==3)...
Más allá de lo que se vaya a ejecutar dentro de la MACRO o no, podemos analizar a simple vista que el número 5 satisface dos Ifs:
Satisface tanto:
if (Time==5)...
como este:
if (Time%4==1)...
Entonces, fijate en la MACRO original y verás que al satisfacerse el if (Time==5) el MPASM agregará todo el código dentro del IF al archivo a ensamblar.
Pero aquí viene la línea crucial, y es que aparece dentro de IF, un endm (end macro). Esto hace que inmediatamente el MPASM salga de la MACRO, impidiendo que revise el resto de los otros IFs restantes.
¿Por qué? Porque el código necesario para crear un DELAY de 5US ya está dentro del if (Time==5). Si no saliera de la macro usando el endm, entonces también se cumpliría if (Time%4==1) produciendo más código y una demora errónea.
Entonces el código asm generado por la macro para DELAY 5 es:
goto $+1
goto $+1
nop
Lo que es correcto ya estas 3 líneas consumen 5 ciclos de ejecución, y a 4mhz son 5us.
Ahora, si los invierto:
if (Time%4==0)...
if (Time%4==1)...
if (Time%4==2)...
if (Time%4==3)...
if (Time==1)...
if (Time==2)...
if (Time==3)...
if (Time==4)...
if (Time==5)...
if (Time==6)...
if (Time==7)...
Se va a cumplir primero (Time%4==1)
Veámos qué hay dentro de este IF...:
movlw (Time-5)/4
call Delay_us
nop
Reemplacemos Time por 5 para obtener el verdadero código asm que ensamblará.
movlw (5-5)/4
call Delay_us
nop
Entonces, el asm resultante será:
movlw 0
call Delay_us
nop
Lo que ya sería erróne. Esas líneas @ 4mhz por más rápida que sea la subrutina Delay_us, llevaría 6 ciclos de ejecución(1 del movlw + 2 del call + 2 del return + 1 del nop)
Fijate que también hay endm en estos IFs, por lo que el MPASM enseguida sale de la MACRO sin revisar los restantes, pero ya el error está cometido(aunque no he analizado la subrutina Delay_us para precisar en cuántos us).
Entonces, el orden de los IFs, en este caso, altera el resultado.Por eso están como están.
Vayamos ahora al caso del ya famoso: DELAY 21
PRIMERO OJO!!!!
DELAY 21 NO NECESARIAMENTE ES LO MISMO QUE DELAY .21!!!!
Por defecto el MPLAB trabaja en formato hexadecimal, por lo que si pones: DELAY 21, en realidad está haciendo DELAY .33 en sistema decimal!!!
Lo mísmo se aplica al resto de los casos. Yo voy a suponer que estamos hablando en sistema decimal. ¿Ok?
Ahora, ¿qué condición se cumple?
Se cumple sólo ésta:
if (Time%4==1)...
Ya que 21/4= 5 y resto 1. Y el resto es lo único que le interesa a la función MOD(%).
Entonces...vemos que en este caso el MPASM generaría esto:
movlw (.21-5)/4
call Delay_us
nop
Lo que finalmente sería:
movlw 4
call Delay_us
nop
Oh casualidad! analicemos un poco. Necesito hacer 25us de retardo.
Veámos si mis premoniciones son verdaderas o falsas:
Tengo un movlw que ya me consume 1 ciclo, y tengo un call y un return que ya me consumen 4 ciclos más y luego un NOP que me consume 1 ciclo más.
En total sin contar lo que suceda o no dentro de la subrutina Delay_us, ya tengo seguro 6 ciclos(ya lo había mencionado arriba :D ).
Entonces el lo que sea que suceda entre que llamo al Delay_us y antes de que salga de él me debe llevar 15 ciclos de ejecución.
Veámos si entonces se cumple mi "premonición":
Delay_us ADDLW -1 ;precise delays used in I/O (esto esta buenisimo de sumar -1)
btfss STATUS,Z
goto Delay_us
return
Dijiste: "esto esta buenisimo de sumar -1".
Esto exíste para simplificarte la vida. Lo que no quiere decir que efectivamente sume -1 ya que los negativos no existen "naturalmente" en estos microcontroladores.
Pero puedo decir que: ADDLW -1 es lo mísmo que decir ADDLW .255, es decir, 256- 1 ;) Esto debe ser precisamente lo que hace el MPASM. Es mucho más fácil cometer errores restando que sumando.
Veamos la subrutina:
W ingresa valiendo 4(véase anteriormente movlw 4)
Entonces voy a "estirar" todo el ciclo que genera esto:
Delay_us ADDLW .3 ;precise delays used in I/O (esto esta buenisimo de sumar -1)
btfss STATUS,Z
goto Delay_us
Delay_us ADDLW .2 ;precise delays used in I/O (esto esta buenisimo de sumar -1)
btfss STATUS,Z
goto Delay_us
Delay_us ADDLW .1 ;precise delays used in I/O (esto esta buenisimo de sumar -1)
btfss STATUS,Z
goto Delay_us
Delay_us ADDLW .0 ;precise delays used in I/O (esto esta buenisimo de sumar -1)
btfss STATUS,Z
;salta al return y sale.
Ahora sumo la cantidad de ciclos que lleva cada una(por dios! que de 15! :D :D )
Delay_us ADDLW .3 ;+1
btfss STATUS,Z ;+1
goto Delay_us ;+2
Delay_us ADDLW .2 ;+1
btfss STATUS,Z ;+1
goto Delay_us ;+2
Delay_us ADDLW .1 ;+1
btfss STATUS,Z ;+1
goto Delay_us ;+2
Delay_us ADDLW .0 ;+1
btfss STATUS,Z ;+2
;salta al return y sale.
Sumamos y da: 15!!!!!
Entonces en total tenemos: 6 ciclos + 15 = 21! Uau! lo hemos logrado! y con tan poquito código! qué bonito! ;)
Si miras sucederá de manera similar lo mísmo para los otros casos DELAY 8, DELAY 11, DELAY28, DELAY 45, DELAY 48.
¿Puedo expresar cuántos ciclos lleva la subrutina Delay_us en función de el valor con el que ingresa W?
Si.
Su función es:
Cantidad de ciclos de Delay_us = (W - 1) x 4 + 3
¿Bien?
Ahora, podría dedicarme a complicarte un poco el asunto, y unirte los cuatro caso de MOD en uno sólo que valga para todos haciendo:
DELAY macro Time
if (Time==1)...
if (Time==2)...
if (Time==3)...
if (Time==4)...
if (Time==5)...
if (Time==6)...
if (Time==7)...
movlw (Time-4-Time%4)/4
call Delay_us
if ((Time%4)%2==1)
nop
endif
endm
Ese caso vale para generar el mísmo código que generan los 4 en la MACRO original. No es necesario que lo estudies, simplemente son manías mías ;)
Pero si decidís usarlo en reemplazo de los otros 4 casos, deberías obtener el mísmo código final.(Ensamblá el .asm con em MPLAB y andá a menú View --> Dissasembly Listing para ver qué código generó).
Espero que haya quedado claro.
Ademas, se puede llamar a esta MACRO con otros valores, o solo se llama con los valores que puede atender ??? (segun lo que interprete en tu post, la respuesta es NO, pero confirmame, plz...)
Se puede llamar con absolutamente cualquier valor natural entre 0 y 255.
En algun lado lei que estan disponibles, como el IF en las MACROS...los operandos, como los de tu ejemplo >, <, =, &, /...estare estudiando algo de eso y si me surgen dudas (casi con seguridad que asi pasara...) te estare consultando...tambien lei sobre THEN, ELSE, pero no estoy 100% seguro que tenga relacion con el ASM...
En el MPLAB ,anda a HELP -> Topics -> MPASM Assembler y buscá que ahí tenés explicado todo el potencial del MPASM que muchas veces es ignorado por completo por la gente que lo usa.
Hasta ahora en el RANKING del ALMACEN del ASM, mis posiciones son:
1º - DIOS
2º - BRUNO
3º - TODO LO DEMAS (sin ofender a nadie) tambien lei algo de CHARLY, que te pelea el puesto cuerpo a cuerpo !!! lol
Como el "barba", no me contesta (anda con otros "kilombetes"), para mi sos el GURU del ALMACEN...Bueno BRUNO, me voy a sacar la segunda "pava" de la hornalla...Ahi tengo una ROSAMONTE DESPALADA, a estrenar...ahi te paso un amargo !!!
Jajaja no creo que haya rankings aquí. Todos aportamos lo que podemos en las áreas que más sabemos, y entre todos logramos formar este gigante, este coloso que es Todopic.
Al mate te lo acepto, pero dulce :) :)
Apéndice:
¿Qué pasa si pongo DELAY 0?
¿No generará demora alguna? ¿Generará 256 us¿ ¿O generará otra demora?
Analicemos:
Veremos que el único IF que se cumple para Time = 0 es:
if (Time%4==0)
movlw (Time-4)/4
call Delay_us
exitm
endif
Entonces nos quedaría:
movlw (0-4)/4
call Delay_us
exitm
Y oh! que pasa si hacemos 0-4?
Se produce un numero negativo -3. Pero los negativos no existen aqui!
Entonces...El MPASM transformarà el -3 en: 256 - 3.
Quedandonos: .253
Volvamos entonces a la macro:
movlw (.253)/4
call Delay_us
exitm
Esa división no da como resultado un número entero. El MPASM elimina la parte decimal, de esta manera queda:
movlw .63
call Delay_us
exitm
Ahora apliquemos la formulita que habia creado anteriormente:
Cantidad de ciclos de Delay_us = (W - 1) x 4 + 3 = (.63 - 1) x 4 + 3 = .251
Ahora, sumemosle 1 del movlw, 2 del call, y 2 mas del return:
= .251+ .5 = .256 us.
Ahora si puedo afirmar que el DELAY 0 es el mayor retardo posible y su duración es 256 us.
Tal vez decir DELAY 0 para implicar 256 us parece dificil de asociar.
Pues podrìas hacer DELAY .256 en su lugar y obtendrías exactamente el mísmo retardo(y de regalo te sale una advertencia del MPASM diciendo que se usarán sólo los bits menos significativos del .256 :D )
Ahora si. Fin.
Exitos.
-
BRUNO, esto es impecable...invalorable...estuve leyendo esta porcion de codigo hace semanas, hasta que descubri este FORO, y me lo arreglaste en 1 dia...la explicacion es "brillante" y no te hagas el "humilde"...si pude entenderlo yo, mas aun podran hacerlo los mas jovenes, que ahora se vienen "reload" de neuronas...
Tengo poco tiempo con los UC, y empece por casualidad, lo unico que conozco es el ASM, porque soy "fierrero" en electronica, y este lenguaje, me permite asociar facilmente los conceptos con los resultados...
Estuve considerando que usar estas MACROS, como alternativa frecuente, para el calculo de "demoras", es una solucion, elegante y facil para futuros programas...haciendo los calculos necesarios para otros "clock" de micro...Lo que me pregunto ahora, es porque no se estandariza este metodo, para todas las aplicaciones...muchos "foristas" encontrarian una solucion a los problemas de calcular demoras, ya que hay muchos que preguntan, sobre el tema !!!
Demas esta decirte que podes contar conmigo para lo que necesites desde aqui (BA - Capital)...No conozco tu especialidad, pero aveces la brecha comercial, entre nuestras ciudades, hace mas facil conseguir las cosas aqui...asi es que si necesitas algo, que se hace dificil conseguir alli, no tenes mas que avisarme...
No puedo decirte que podes preguntarme, sobre micros, ya que mis recursos son escasos, comparados con los tuyos...pero no solo de "micros" vive el hombre...
Aradezco una vez mas, tan desinteresado aporte, y te mando un abrazo, junto con un "azucarado" mate...HASTA LA PROXIMA !!! SALUDOS !!!
Lo del "ranking" es una broma, no dudo que aqui hay gente que como vos, sabe lo suficiente, para ocupar el TOP TEN !!!
================================
"Justo a mi, me toco ser YO" QUINO...
-
BRUNO, esto es impecable...invalorable...estuve leyendo esta porcion de codigo hace semanas, hasta que descubri este FORO, y me lo arreglaste en 1 dia...la explicacion es "brillante" y no te hagas el "humilde"...si pude entenderlo yo, mas aun podran hacerlo los mas jovenes, que ahora se vienen "reload" de neuronas...
Tengo poco tiempo con los UC, y empece por casualidad, lo unico que conozco es el ASM, porque soy "fierrero" en electronica, y este lenguaje, me permite asociar facilmente los conceptos con los resultados...
Jeje...debo decirte que a mi parecer una gran parte de esta comunidad descubrimos los uC por casualidad.
Estuve considerando que usar estas MACROS, como alternativa frecuente, para el calculo de "demoras", es una solucion, elegante y facil para futuros programas...haciendo los calculos necesarios para otros "clock" de micro...Lo que me pregunto ahora, es porque no se estandariza este metodo, para todas las aplicaciones...muchos "foristas" encontrarian una solucion a los problemas de calcular demoras, ya que hay muchos que preguntan, sobre el tema !!!
Se podría estandarizar. Se podrían hacer conjuntos de algoritmos standart(y exísten muchas veces en los archivos .inc para asm).
Creo que no se ha masificado porque eso es justamente lo lindo del ASM: la libertad. El control al 100% de tu código. Tu optimización linea a linea del código, cosa que en otros lenguajes queda en manos más del compilador que del usuario programador.
Por supuesto que podes hacer un conjunto de rutinas para usar las demoras incluso a distintos Mhz.
Demas esta decirte que podes contar conmigo para lo que necesites desde aqui (BA - Capital)...No conozco tu especialidad, pero aveces la brecha comercial, entre nuestras ciudades, hace mas facil conseguir las cosas aqui...asi es que si necesitas algo, que se hace dificil conseguir alli, no tenes mas que avisarme...
No puedo decirte que podes preguntarme, sobre micros, ya que mis recursos son escasos, comparados con los tuyos...pero no solo de "micros" vive el hombre...
Te agradezco el ofrecimiento. Lo mejor que podes hacer es aportar vos al foro ayudando a otros en las áreas que sepas. :D
Mi especialidad es la informática, no la electrónica.
Venga ese mate, ahora si. ;)
Hasta pronto.
P.D. Muy linda la frase jejeje
-
Hasta aqui, podria decirse que esto es como la biblia de las MACROS...estuve bajando unos TXT y lei mas sobre el tema...logicamente me cuesta asociar cuales "instrucciones" se interpretan en el programa principal y cuales en los "BLOCK"...
A simple vista y por lo que estuve viendo, hay varias directivas...lo que se refiere a las 32 instrucciones basicas, no tengo duda que seran interpretadas en el programa principal...pero la IF, por ejemplo se interpretan en los "block" o en MACROS (todo esto lo digo a riesgo de equivocarme !!! )
Aparecieron entonces otras condicionales como ELSE, WHILE, EXTERN, PAGESEL...he visto que PAGESEL o DT pueden ir sin problemas en el programa principal...pero no he visto que se usara ELSE o WHILE...
Tambien lei sobre operadores aritmeticos, como *, /, -, +, >>, <<, <, <, ==, !=, etc, etc, etc...ya he visto que el ==, %, ), (, se usan en el ejemplo de la MACRO que abre este "hilo"...pero no los demas (quizas porque no hacen falta en este ejemplo...
La pregunta es:
Suponiendo que tengo un REGISTRO EQU 0x15
Podria escribirse:
movwf (registro * 2) - 1 , en el programa principal...estos operandos aritmeticos harian:
movwf (0x15 * 2) - 1 osea:
movwf (0x2A) - 1 osea:
movwf 0x29
En fin, tengo mas dudas que ADAN el dia de la madre...cuales se pueden usar, para que los interprete el compilador en el programa principal, y cuales se usan solo en BLOCKS...
Los resultados, producto de usar estos operandos, son para posiciones de memoria, (en el ejemplo de arriba, parece que el contenido de W se copia en la posicion 0x29, donde habra algun registro, predefinido ) o se pueden usar como resultados matematicos, para multiplicar o lo que sea, varios byte ???
po ej:
Se podria escribir
movlw (reg1 * reg2) osea cargar a W con el resultado de esta multiplicacion ???
Quizas estoy preguntando una tremenda "bol__ez", ya que parece facil multiplicar asi en lugar de hacer RLF o sumas sucesivas !!!
No se si se trato este tema en algun otro lado, pero hice busquedad avanzada, en el ALMACEN ASM, y no encontre nada...me parecio que si hay algo en C...pero de C, noC...SALUDOS y gracias por leer !!!
_______________________________
"Justo a mi, me toco ser Yo" - QUINO
-
Hasta aqui, podria decirse que esto es como la biblia de las MACROS...estuve bajando unos TXT y lei mas sobre el tema...logicamente me cuesta asociar cuales "instrucciones" se interpretan en el programa principal y cuales en los "BLOCK"...
A simple vista y por lo que estuve viendo, hay varias directivas...lo que se refiere a las 32 instrucciones basicas, no tengo duda que seran interpretadas en el programa principal...pero la IF, por ejemplo se interpretan en los "block" o en MACROS (todo esto lo digo a riesgo de equivocarme !!! )
Aparecieron entonces otras condicionales como ELSE, WHILE, EXTERN, PAGESEL...he visto que PAGESEL o DT pueden ir sin problemas en el programa principal...pero no he visto que se usara ELSE o WHILE...
Tambien lei sobre operadores aritmeticos, como *, /, -, +, >>, <<, <, <, ==, !=, etc, etc, etc...ya he visto que el ==, %, ), (, se usan en el ejemplo de la MACRO que abre este "hilo"...pero no los demas (quizas porque no hacen falta en este ejemplo...
En todo lenguaje de programación existe un conjunto de palabras reservadas.
Estas palabras al ser reservadas implican que sólo podrán ser usadas para ciertos fines, pero no para el resto. Ej. No puedo declarar una variable como "movlw" ya que movlw es una palabra reservada del MPASM y significa Move Literal to W.
No confundamos el set(o conjunto) de instrucciones del PIC, con el set de instrucciones del MPASM.
El set de instrucciones del PIC dependerá de la familia del mísmo. A mayor familia, seguramente mayor cantidad(y complejidad) de instrucciones.
En cambio, el set de instrucciones del MPASM es muchísimo mas amplio que el set de instrucciones de cualquier PIC.
El MPASM posee un mayor conjunto de palabras reservadas para facilitar y posibilitar la programación de un microcontrolador PIC. Palabras como include, #define, macro, block,if, else, error,errorlevel,etc... son exclusívas para uso dentro del MPASM. Pero estas palabras ayudarán y posiblemente afectarán, tal vez, al archivo .hex final a generar que será cargado en el PIC.
El MPASM ofrece un abanico de instrucciones que tienen un espacio de influencia determinado:
Hay instrucciones como la "error" que sólo sirven para PROVOCAR un error en el proceso de ensamblado, para evitar que se genere un .hex con ciertos parámetro erróneos.
Hay otras(como los IF) que sólo se usan para que el MPASM ejecute la condición y en base a eso ejecute( o no) lo que hay dentro del IF. Un IF puede ir en cualquier lado del código. Escribir un IF en un archivo a ensamblar sólo tiene significado para el MPASM, no para el PIC.
Voy a intentar explicar el IF de una forma que tal vez resulte más fácil comprender.
Cuando envías a ensamblar un archivo, el MPASM comienza a recorrer linea a línea el código del archivo.
Si se topa con un IF, se fija si se cumple la condición. Si se cumple, entonces ingresa al IF y sigue ensamblando todo código que pudiese haber dentro. Si la condición no se cumple, se fija si existe "else". Si existe, ensambla todo código dentro de el. Si no existe el "else", "salta" hasta el endif y esquiva(no ensambla) toda línea anterior a esa.
Ejemplo(familia 16F):
#DEFINE LIMPIAR .1
org 0x000
if (LIMPIAR == 1)
clrf 0x03
else
messg "Recuerde: Es una mala costumbre no limpiar el registro STATUS al inicio del programa!"
endif
Defino una variable limpiar con valor 1.
Fijémonos cómo se comportará el MPASM en este caso:
El MPASM encuentra primero el org 0x000. Eso le indica al MPASM que todo código ASM será grabado a partir de la posición 0x0.
Luego se topa con el IF. aquí el MPASM revisa la condición y se pregunta: ¿Es LIMPIAR igual a 1?
Si la condición se cumple, el MPASM sigue leyendo lo que haya dentro de el IF, pero esquivará todo código que se encuentre en el else(si existiere).
Entonces se topa con clrf 0x03.
El MPASM reconoce la instrucción clrf. Sabe que es una de las 35 instrucciones que un PIC 16F tiene implementada, entonces a esta sí, la ensambla y prepara para el archivo .hex final.
¿Dónde la ubicará dentro de la memoria flash del PIC? Pues con la intrucción que pusimos arriba(ORG 0x000)
le pedimos que la ubicara comenzando desde la posicion 0x00.
Entonces, el MPASM creará el .hex de manera que la instrucción clrf 0xXX quede en la posición 0x00.
Como se cumplió la condición, esquiva todo lo que haya dentro del else, y busca el final del if(endif) y continúa ensamblando y no se detiene hasta no encontrar la directiva END.
Veamos ahora el caso en que no se cumple la condicion(copie todo el codigo, pero lo unico que cambia es el valor que le asigno a "LIMPIAR"):
#DEFINE LIMPIAR .0
org 0x000
if (LIMPIAR == 1)
clrf 0x03
else
messg "Recuerde: Es una mala costumbre no limpiar el registro STATUS al inicio del programa!"
endif
Aqui pasa lo mismo. Primero detecta el ORG ...y sabe que debe comenzar a ubicar toda instruccion que encuentre a partir de la posicion 0x00 de la FLASH.
Luego se hace la pregunta y en este caso no se cumple, por lo que busca el "else"(si es que existe.Si no existe directamente "salta" hasta el endif). Dentro del else hay una directiva que el MPASM reconoce: la messg. Esta directiva es sólamente útil para enviar un mensaje al MPLAB en la ventana "OUTPUT". Se usa para avisar de algo al usuario que ensambla el archivo, pero NO tiene nada que ver con las 35 instrucciones del PIC, por lo que no se ensambla ni genera código alguno en el .hex final.
¿Se comprendió?
La pregunta es:
Suponiendo que tengo un REGISTRO EQU 0x15
Podria escribirse:
movwf (registro * 2) - 1 , en el programa principal...estos operandos aritmeticos harian:
movwf (0x15 * 2) - 1 osea:
movwf (0x2A) - 1 osea:
movwf 0x29
En fin, tengo mas dudas que ADAN el dia de la madre...cuales se pueden usar, para que los interprete el compilador en el programa principal, y cuales se usan solo en BLOCKS...
Efectivamente. Quedaría eso. Pero acá viene la parte que me parece te tiene confundido y este ejemplo va a servir para aclarartela.
Vos podés usar los operadores y directivas que el MPASM te ofrece, tal cual lo estás haciendo ahí pero el resultado ES UN MOVWF CC donde CC es una CONSTANTE. En este caso CC es 0x29. En el PIC sólo se graba la instruccion movlw referida a la posicion de memoria 0x29. ¡Nada de multiplicaciones o restas!
Entonces:
No creas que por hacer sumas. multiplicaciones,IFs realmente se van a "ensamblar" tal cual, es decir, conservando su función. El PIC admite sólo un determinado conjunto de instrucciones, y no puede salir de eso.
Si yo quisiese realmente que el PIC haga lo que querès tal cual lo pusiste ahí en código, tengo que usar el set de 35 instrucciones de esta familia:
W_TEMP EQU 0x20
REGISTRO EQU 0x15
movwf W_TEMP ;guardo el valor de W temporalmente en una variable W_TEMP
movlw 0x15 ;W=0x15
movwf REGISTRO ;REGISTRO= W = 0x15
bcf STATUS,C ;asegurar multiplicacion exacta por dos.
rlf REGISTRO,F ;REGISTRO = REGISTRO * 2
decf REGISTRO,W ;W = REGISTRO - 1
movwf FSR ;Apuntar a la posicion de memoria a modificar:
movf W_TEMP,W ;Recuperar valor original de W
movwf INDF ;Y copiarlo en posicion de memoria correcta.
No pretendo que comprendas el código, ya que probablemente haya un par de cosas que son nuevas para vos. Ese código realmente tomaría el valor que contenga la variable REGISTRO, lo multiplicaria por 2, le restaria uno y copiaria el valor que tenia W en esa posicion de memoria resultante.
¿Podes apreciar la diferencia entre el simple(e invariable) movlw 0x29 que genera el uso de *,-,etc en el MPASM y el código que realmente haría que variara la posición de memoria en donde volcar W?
Entonces, hacé de cuenta que las directivas "adicionales" que te ofrece el MPASM pueden modificar el código asm, pero NO generan verdaderos IFs, ni verdaderas multiplicaciones, sumas,etc de manera que puedan ser interpretadas luego por el PIC mientras funciona, ¿ok?
Sería,simplificadamente(faltan muchos pasos, pero no nos interesan) un proceso asi:
Código original asm --> MPASM interpreta las directivas(IFs,MACROs,etc) y puede modificar/agregar código asm adicional --> se genera el código asm final --> MPASM ensambla código asm final --> archivo .hex generado listo para grabar en PIC.
Los resultados, producto de usar estos operandos, son para posiciones de memoria, (en el ejemplo de arriba, parece que el contenido de W se copia en la posicion 0x29, donde habra algun registro, predefinido ) o se pueden usar como resultados matematicos, para multiplicar o lo que sea, varios byte ???
por ej:
Se podria escribir
movlw (reg1 * reg2) osea cargar a W con el resultado de esta multiplicacion ???
Quizas estoy preguntando una tremenda "bol__ez", ya que parece facil multiplicar asi en lugar de hacer RLF o sumas sucesivas !!!
Si leiste bien lo que dije anteriormente, deberias estar en condiciones de auto-responderte:
Si haces movlw (reg1 * reg2) lo único que va a hacer el MPASM es fijarse cuánto vale en ese momento reg1 y reg2, multiplicarlos y hacer que quede finalmente movlw XX donde XX es el resultado de multiplicar reg1 * reg2
Ejemplo:
reg1 EQU 0x0C
reg2 EQU 0x0D
...
movlw (reg1 * reg2)
El MPASM transforma esto inmediatamente en:
movlw 0x9C
Por lo que termina siendo un valor constante. La multiplicacion existe sólo para el MPASM, pero desaparece para el PIC. Ok?
Para que el PIC pueda multiplicar realmente reg1 * reg2 y guardar ese resultado en W necesitas efectivamente un algoritmo que multiplique ambos usando sumas sucesivas,rotaciones o lo que sea.
Nada que ver una cosa con la otra, ¿no?.
Si vos lo que querés es programar fácil, usando IFs, multiplicaciones, divisiones, etc. Entonces, te recomiendo que mires el CCS(u otro), que es un compilador en lenguaje C para PICs, y en el cual sí podés poner directamente por ejemplo:
unsigned char reg1;
unsigned char reg2;
long resultado;
resultado = reg1*reg2;
y realmente transformar esa multiplicación en código asm que el PIC comprenda y pueda procesar durante su ejecución. Digamos que el CCS genera el codigo de esas "rotaciones" o "sumas sucesivas" automáticamente, necesarias para que el PIC sepa cómo multiplicar esos dos valores en cualquier momento.
Esa es la principal diferencia(hay muchas otras) entre un ENSAMBLADOR y un COMPILADOR:
El ensamblado es mas bien una TRADUCCION del código original a codigo máquina.
El compilado es una verdadera TRANSFORMACION del código original a código asm, que luego será ensamblado para pasar a ser finalmente código máquina.
No se si se trato este tema en algun otro lado, pero hice busquedad avanzada, en el ALMACEN ASM, y no encontre nada...me parecio que si hay algo en C...pero de C, noC...SALUDOS y gracias por leer !!!
Es un tema bastante extenso, difícil de explicar por ahí si no tenes al menos experiencia con algun lenguaje de programación anteriormente.
La mayoría de las personas que trabajan con asm no usan cosas "raras". Nada de IFs, nada de operadores lógicos,etc. ya que la mayoría desconoce su existencia( y su increíble potencial si se utilizan inteligentemente).
Éxitos.
-
BRUNO, me estoy secando las lagrimas, lo entendi perfectamente...me parecia tan curioso que no se usaran estas instrucciones, no entendia la difrencia entre las que son del PIC y las del MPASM...de todos modos me parece un recurso interesante para ser explotado (pero me parece que hay que tener unas cuantas "horas de vuelo", por decirlo de algun modo, en programacion...)
Como supones, no tengo experencia con casi ningun lenguaje de programacion...digo casi ninguno, porque ya no cuento lo que aprendi en los ultimos años de colegio (me acuerdo que vi 2 horas de BASIC, para Z80, creo...yo, ensaye algo con el "debug" de mi primer XT, y eso si, varias horas de magnetrones y vavulas...lo que de alguna manera habla de mi edad... :D)
No tengo una rutina u orden para aprender sobre programacion, y entonces quizas este pegando saltos enormes...aun asi, pude entender lo que explicaste...lo dejare para mas adelante, si hiciera falta...ya que segun decis, quien elige este lenguaje, no acostumbra a manejar operandos aritmeticos o condicionales...
Lo unico que me quedaria por averiguar ahora, es cuales, afectan al .hex y cuales no...aunque por regla general, voy a desestimarlos para arrancar a programar algo y quizas mas adelante incorpore alguno...con los años me he convertido en "autodidacto" (palabra que tiene genero, apesar de que suene mal, y casi nadie la escriba asi) y con la increible posibilidad de internet (o de la internet), esta mania se ha reafirmado en mi...
A pesar de ello, me gustaria saber si podes recomendarme algun libro...ya que esto, sera mucho mas facil para vos, que contestarme a cada inquietud...digo esto porque no quiero abusar, se que esto demanda tiempo y concentracion...
Lamentablemente para los forista, segun estuve reflexionando, y dada mi condicion de "principiante", solo podran esperar de mi; preguntas, preguntas y mas preguntas...si bien es cierto que estoy leyendo hace casi 4 o 5 dias, todo el "almacen", hay algunas respuestas que no estan totalmente aclaradas, para mi apetito de aprendizaje, y me veo, penosamente obligado a preguntar...espero sepan disculpar tal atrevimiento, y aguardar, hasta que alguna vez sea Yo, quien pueda hacer algun aporte constructivo...
Quizas surgan nuevas dudas, tratare de encontrar las respuestas en algun lado del FORO, solo sino las encontrara, me animare a hacer alguna pregunta (aunque creo, que dado el excelente nivel manifiesto en el lugar, eso me cueste muchisimo, y quiera aprovecharlo, directamente con algun interlocutor... :-))
BRUNO, te agradezco infinitamente la molestia de responderme, con tanta claridad y urgencia...esto tiene para mi un valor incalculable, ya que son las primeras herramientas en el tema, esas que son en definitiva las fundamentales, para aprender bien...luego podre incurrir en miles de errores, pero sabre donde estan y como solucionarlos...y sino, siempre estaran ustedes para tenderme alguna mano... :mrgreen:
Entre tanto COLOMBIANO, PERUANO, ECUATORIANO, CHILENO, URUGUAYO, ESPAÑOLES, DOMINICANOS, etc, etc, etc (pase por el censo del FORO)...hasta me parece que estoy escribiendo como en las telenovelas...(en NEUTRO :D :D :D)
Les mando un saludos a todos mis hermanos del FORO...Gracias por leer !!!
=================================================================
"Que otros se jacten de las páginas que han escrito; a mí me enorgullecen las que he leído." (J. L. B.)
=================================================================
_______________________________
"Justo a mi, me toco ser YO" - QUINO
-
Bruno todavía no termino de leer tu explicación, pero te quedó impecable :)
-
Gracias Pedrito ;)
Resistencio:(resistencia también tiene género y no lo sabía? :P )
Gracias por los halagos.
Te motivo a que busques en el foro, y si no encontrás respuesta a tus inquietudes, preguntes aquí en el foro ya que mucha gente podrá ayudarte.
Muchos me preguntan por un libro...realmente yo no tengo idea de libros en este tema. Al asm lo aprendí solito. Primero para la PC, luego en la Universidad y luego por casualidad para los PICs.
Te puedo sí recomendar que estudies hasta el hartazgo lo que significa un bit y un byte. Si no comprendés con plenitud su significado, imposíble comprender las instrucciones de un PIC.
Recién se me ocurrió una idea muy piola, tal vez me ponga y haga un librito de bolsillo sobre asm, como para tenerlo a mano cuando uno se está iniciando en ASM en este apasionante mundo de los PICs.
Saludos y nos escribimos ;)
-
Hola BRUNO, estuve leyendo atentamente tu explicacion...y puedo decir que la entiendo en un 90%...en realidad me tienen un poco confundidos algunos de tus ejemplos (estoy desestimando lo errores de tipeo, como los que estan en el ejemplo del semaforo...)
En tema viene a raiz de la preconceptualizacion que tengo, con respecto a lo que es un valor de registro y su posicion en memoria...
Por ejemplo...yo preguntaba por ahi si se podia hacer:
predefiniendo a "registro equ 0x15" (esto para mi es posicion de memoria, NO valor contenido en el registro)
movwf (registro * 2) - 1 , en el programa principal...estos operandos aritmeticos harian:
movwf (0x15 * 2) - 1 osea:
movwf (0x2A) - 1 osea:
movwf 0x29
Entonces, esto para mi es como cargar el valor de W (aca no puse ninguno, pero podemos poner movlw 0xFF), y despues de la cuentita con los (*) y los (-), en la posicion de memoria 0X29, que deberia ocupar otro registro...
Quiza esto es un error conceptual mio, pero asi es como lo entendia...
En tu ejemplo, vos escribis:
=========================================================================
Si yo quisiese realmente que el PIC haga lo que querès tal cual lo pusiste ahí en código, tengo que usar el set de 35 instrucciones de esta familia:
W_TEMP EQU 0x20
REGISTRO EQU 0x15
movwf W_TEMP ;guardo el valor de W temporalmente en una variable W_TEMP
movlw 0x15 ;W=0x15
movwf REGISTRO ;REGISTRO= W = 0x15
bcf STATUS,C ;asegurar multiplicacion exacta por dos.
rlf REGISTRO,F ;REGISTRO = REGISTRO * 2
decf REGISTRO,W ;W = REGISTRO - 1
movwf FSR ;Apuntar a la posicion de memoria a modificar:
movf W_TEMP,W ;Recuperar valor original de W
movwf INDF ;Y copiarlo en posicion de memoria correcta.
=============================================================================
Aca suponiendo que el valor de W que se carga en W_TEMP (sea 0XFF, como en mi ejemplo), lo que sigue es una cuenta que carga a REGISTRO (que esta en posicion 0x15 de RAM) con un valor ((0x15*2)-1)= 0x29, que al pasar a FSR, se convierte en posicion de memoria y cargara alli, el valor 0xFF que le precargue al reg. W_TEMP (que esta en posicion 0x20 de RAM)...un terrible despelote lo que escribi, pero leelo despacio, por favor !!! :-) :-) :-)
En definitiva es muy diferente a lo que puse Yo como ejemplo !!! :D
Lo que mas me confundio con este concepto, fue el ejemplo que dice:
===============================================================================
Ejemplo:
reg1 EQU 0x0C
reg2 EQU 0x0D
...
movlw (reg1 * reg2)
El MPASM transforma esto inmediatamente en:
movlw 0x9C
Aca parece que estoy cargando un valor literal 0x9C a W...NO ENTIENDO DE DONDE SALE ESTA CUENTA, como valor literal...
===========================================================================
Con todo esto, y en base a mis conceptos, para mi, es mas facil cargar el valor 0xFF en la posicion 0x29, con el primer metodo, es decir:
registro equ 0x15 ;declaro un registro llamado "registro" en posicion 0x15
movlw 0xFF ; cargo a W con 0xFF
movwf ((registro * 2) - 1) osea:
movwf ((0x15 * 2) - 1) osea:
movwf (0x2A) - 1 osea:
movwf 0x29 ; cargo 0xFF en posicion 0x29 (que es la posicion de algun registro, que no defini o declare, no se que termino se usa...)
==============================================================================
Bueno...BRUNO, como siempre...todo esto lo digo a riesgo de equivocarme...he invito a cualquiera que lea, a responder su punto de vista, y a indicarme posible errores...estoy arrancando con esto, asi que estoy a tiempo de modificar conceptos...GRACIAS POR LEER !!!
PDTA: podras explicar algun ejemplito con WHILE ??? POR FAVOR !!!
________________________________
"Justo a mi, me toco ser YO " QUINO.
-
Hola Resistencio.
Esos ejemplos fueron meramente demostrativos. Intenté aproximar su funcionamiento a lo más parecido posible. No te guíes por esos códigos. Eran sólo para que veas la diferencia claramente.
Obviamente es mucho más fácil hacer como decís, pero es porque ahora ya comprendés el tema.
El while...
Realmente no sé hasta dónde hay aplicación práctica del while. El while es un bucle, y como todo bucle, puede generar demasiadas líneas asm sin sentido. En fin:
Ejemplo:
una macro que rota un registro a la izq X veces:
ROTAIZQ macro Registro, Rotaciones
if (Registro>0x6F)
error El registro supera la posición máxima(0x6f)
exitm
endif
variable i
i = 0
while (i != Rotaciones)
rlf Registro,F
i += 1
endw
endm
Y lo uso por ejemplo asi:
MiReg EQU 0x23
...
...
...
ROTAIZQ MiReg, 5 'roto a la izquierda MiReg 5 veces.
Si miramos al "Disassembly Listing" que genera el MPASM al llamar a la esa macro es:
0DA3 RLF 0x23, F XX: ROTAIZQ MiReg,5
0DA3 RLF 0x23, F
0DA3 RLF 0x23, F
0DA3 RLF 0x23, F
0DA3 RLF 0x23, F
"i" es una variable. Fijate que justamente la declaré como variable. Es una variable AUXILIAR y es completamente ajena al PIC. Se usa sólo para poder realizar cálculos temporales auxiliares.
Espero haya quedado claro. Saludos.
-
P.D.
¿Errores de tipeo en el semáforo? ¡No me doy cuenta!.
Saludos.
-
Hola BRUNO, es una pavada, por eso no hice mayores acotaciones al repecto, no hace a la cuestion de fondo que esta perfectamente clara...mi problema es lo otro que escribo...
En una partecita del codigo, cuando se prenden y apagan las luces verdes - rojas y amarillas, se hace bcf o bsf (segun) sobre una mismao salida del puerto (el PORTA,01)...No vale la pena ni hablar del tema...el concepto de tu explicacion es brillante...el que lo haya dicho, espero sirva para que veas, que he leido todo lo que escribiste, con paciencia, y absoluto detenimiento (y mas de una vez)...
Aun asi, y como digo siempre, puede estar equivocado, correjime si hace falta, por favor !!!
=============================================================================
SEMAFORO macro Valor ;Creo una macro, Valor indica que la MACRO recibe sólo un parámetro y lo llamo Valor.
if(Valor < .80) ;Si el parametro recibido es menor a 80...
bsf PORTA,0 ;Encender lampara Verde
bcf PORTA,1 ;Apagar lampara Amarilla
bcf PORTA,1 ;Apagar lampara Roja
endif
if(Valor >= .80) && (Valor < .160) ;Si el parametro recibido es igual o mayor a 80 Y menor a 160...
bcf PORTA,0 ;Apagar lampara Verde
bsf PORTA,1 ;Encender lampara Amarilla
bcf PORTA,1 ;Apagar lampara Roja
endif
if(Valor > .160) ;Si el parametro recibido es mayor a 160...
bcf PORTA,0 ;Apagar lampara Verde
bcf PORTA,1 ;Apagar lampara Amarilla
bsf PORTA,2 ;Encender lampara Roja
endif
endm
============================================================================
Espero impaciente, alguna respuesta tuya, apelando al buen criterio y a la didactica en las explicaciones...solo si estas inspirado y con ganas...Lo mismo corre para los demas integrantes del FORO...SALUDOS y gracias por leer !!!
______________________________
"Justo a mi, me toco ser YO! QUINO
-
Ah si. Tenés razón. Yo andaba buscando el error en otro lado...jeje.
Si..eso me pasa por usar tanto copy & paste.
Espero impaciente, alguna respuesta tuya, apelando al buen criterio y a la didactica en las explicaciones...solo si estas inspirado y con ganas...Lo mismo corre para los demas integrantes del FORO...SALUDOS y gracias por leer !!!
¿Qué me falta explicar? Fijate que arriba creo haber respondido al asunto del while. ¿Me perdí de algo?
Saludos.
-
Te dije que era una pavada BRUNO, se entiende clarisimo...lo del WHILE todavia no lo leo...sí, explicas lo de ELSE...sigo mirando, haber por donde anda...SALUDOS y gracias !!!
_____________________________
"Justo a mi, me toco ser Yo" QUINO
-
Me parece que voy a imprimir este hilo, Bruno es todo un maestro. :-/ :-/
La cuestión es si sería factible establecer una ubicación facilmente localizable de estos temas clarificadores para no depender excesivamente del buscador en el que el éxito depende de como se formule.
-
Si te es de utilidad, me parece bárbaro que lo tengas como material tangible. A mi me molesta muchas veces tener que hacer lectura "electronica".
Lo que sí es extraño, Resistencio, es tu gran curiosidad e interés por las MACROS y las estructuras de control en el MPASM. Generalmente los "novatos" no prestan atención a esto, ni siquiera aún luego, cuando tienen un poco más claro el assembler.
Saludos.
-
Hola BRUNO, antes de preguntar algo en este FORO, estuve leyendolo en OFF, durante 1 mes y medio...empece a estudiar el ASM, por iniciativa de un amigo, quien finalmente me convencio de hacerlo...en realidad no me sentia capaz de interpretar nada, me recibi apenas de tecnico hace mas de 2 decadas (hoy piso los 40)...y no vi, ni me enseñaron nada de programacion...termine mis estudios secundarios con solo 3 años de electronica, ya que venia de un colegio, con orientacion a la mecanica...
Lo que paso luego de encontrar estos "bichitos", es casi obvio !!! la fascinacion absoluta por la versatilidad, la economia de espacios y de desarrollo...hace que hoy no pueda pensar, en diseños con "discreta"...
Lo cierto es que he prestado mucha atencion a los manuales del F84, que me imprimi por completo, y del cual saque una base, como para poder "interfacearme" con ustedes...luego descubri en internet un monton de curiosidades, de las cuales entendi la mitad y finalmente este interesantisimo FORO, del cual aprendo a diario...fijate el horario de mis preguntas, a veces estos hasta entrada la madrugada...
De todas estas curiosidades, la mas llamativas, son para mi las MACROS, quizas por eso tanto interes...pero no es el unico, tengo ganas de preguntar de todo, pero a menudo, siento que abuso de este medio y espero que alguien pregunte por mi...
Empece, tambien a preguntar algo a AITOPES, sobre el PIC SIMULATOR IDE, he hice algunas simulaciones, sencillas...poco a poco voy viendo las diferencias entre los lenguajes y sus posibilidades...Seguramente es mas facil para los estudiante actuales, la interpretacion de estas cuestiones...para mi es absolutamente nuevo (y eso que hace unos 3 o 4 meses que vengo leyendo a diario sobre PICS)...
Como no tengo un organigrama de estudios, me aparecen cosas nuevas todos los dias, y en lugar de estudiarlas con algun criterio u orden, las incorporo tipo "MORE INPUT - del famoso NUMBER FIVE" (la pelicula !!! te acordas)...
Es asi que encontre la MACRO que inicio este hilo (hasta esto de escribir "hilo", "post", "topico", me resulta nuevo...), ya que mi sistema de aprendisaje es la lectura y la interpretacion...lo cual puede resultar peligroso, sino se coteja con alguien, que sepa...Fijate lo que me esta pasando con los conceptos de posiciones de memoria y valor de carga, sobre los registros !!!
En fin, seguire de cerca cualquier aporte que este FORO pueda hacerme, y seguire aprendiendo hasta donde me resulte posible...Sin extenderme mas, mira lo que encontre en la pagina de MIKE !!!
Here is a good, generic Delay Macro that does not change "w" or the STATUS Flag. Note that it assumes that the "DlayCount" variable is equal to zero upon code entry.
DlayMacro Macro Cycles ; Delay Macro for Edges
variable i, TCycles, Value, TFlag
TCycles = Cycles
Value = 1 << 7
i = 7
TFlag = 0
if (TCycles > 5)
while (i >= 0)
if ((TFlag == 0) && ((Value * 3) <= TCycles))
bsf DlayCount, i
TFlag = 1
TCycles = TCycles - (Value * 3)
else
if ((TFlag != 0) && (((Value * 3) + 1) <= TCycles))
bsf DlayCount, i
TCycles = TCycles - ((Value * 3) + 1)
endif
endif
Value = Value >> 1
i = i - 1
endw
if (TCycles > 3)
Error "Delay Cycles too Large for Macro"
endif
decfsz DlayCount, f
goto $ - 1
endif
while (TCycles > 1)
goto $ + 1
TCycles = TCycles - 2
endw
if (TCycles == 1)
nop ; Delay the Last Cycle
endif
endm
Parece una "joyita", pero hay que desentrañarla...incluye WHILE...
Porque, te parece que los estudiantes del ASM, no usan las MACROS o no le prestan la debida atencion, como decis ???
Te mando un saludo y gracias por los aportes...
PD1: Actualmente trabajo como tecnico en electromedicina, me especializo en sistemas tomograficos (dignostico por imagenes, en sistemas SPECT, o planares...adquisicion por emision gamma...la famosa camara gamma que lo dejo verde al pobre "HULK"...cualquier curiosidad que tengas al respecto, tocame timbre...)
PD2: Bruno, recien estoy viendo tu explicacion del WHILE, gracias no la habia visto, se me paso de largo...la escribiste el dia 29/03/07...al mediodia, casi...perdoname, no me di cuenta, por eso te preguntaba sobre algun ejemplo...ahora la reviso y veo si saco algo en limpio...de todos modos, siempre entro a este ALMACEN DEL ASM y veo este hilo, en particular...GRACIAS !!! :-/
______________________________
"Justo a mi, me toco ser YO" QUINO
-
BRUNO, podria hacerse algo similar con una MACRO que emule el ejemplo de WHILE, (que explicas...), asi ???
PEPE equ 0x20
Org 0x00
ROTAIZQ macro
RLF PEPE,F
RLF PEPE,F
RLF PEPE,F
RLF PEPE,F
RLF PEPE,F
endm
...
...
...
movlw 0x01
movwf PEPE
ROTAIZQ
...
...
...
end
========================
No se si esta faltando o sobrando algo...el ejemplo del WHILE, me cuesta, porque se incorporo el tema de la variable i (i +=1)... :shock: mamita !!! :-) :-) :-) :D :-) :-) :-)
Vamos de apoco...GRACIAS !!!
SALUDOS !!!
_____________________________
"Justo a mi, me toco ser Yo" QUINO
-
me parece que resistencio está iniciando el estudio de una manera ordenada, yo también estoy aprendiendo con los conocimientos de macros que expone bruno (de hecho lo he usado muy poco). incluso usando sentencias que ni sabía que formaba parte de un macro.
cuando me inicié en el mundo de los pic, fué a los trancazos, y me salté muchas cosas, por lo que he ido llenando esas lagunas cuando me toca enfrentar un problema práctico. así como lo estas haciendo resistencio me parece bien, recorreras un laargo camino cuando vayas desglosando los otros modulos de los PIC, y los muchos detalles que la arquitectura ofrece pero una cosa si es segura, ya no tendras que iniciar estudios de temas anteriores cuando te toque escribir un código.
...
me recibi apenas de tecnico hace mas de 2 decadas (hoy piso los 40)...y no vi, ni me enseñaron nada de programacion
...
eso me hace recordar un ingeniero electronico ya jubilado que me hablaba que en sus tiempo no había nada de eso de microcontroladores, y que cuando le tocaba hacer un proyecto todo era a punta de transistores y compuertas logicas...
para nosotros los mas jovenes me atrevería decir que no me imagino como era aquella época :D
la tecnología de hoy dia ha facilitado muchas cosas sobre todo para los pequeños aficionados y hobbystas.
-
Gracias PEDRO por los conceptos... :mrgreen:
"Me gusta la gente de criterio, la gente que no traga entero. La gente que no se avergüenza de reconocer que no sabe algo, o que se equivocó, y la que, al aceptar sus errores, se esfuerza constructivamente para no volver a cometerlos.
Me gusta la gente que piensa que el trabajo en equipo, entre amigos, produce más que los caóticos esfuerzos individuales.
Me gusta la gente capaz de criticarme constructivamente y de frente. " BENEDETTI
Esto mismo se lo postie a COS, que me ha ayudado con otro tema...cada integrante de este FORO, es un buen amigo...GRACIAS !!!
______________________________
"Justo a mi, me toco ser Yo" QUINO
-
BRUNO, podria hacerse algo similar con una MACRO que emule el ejemplo de WHILE, (que explicas...), asi ???
PEPE equ 0x20
Org 0x00
ROTAIZQ macro
RLF PEPE,F
RLF PEPE,F
RLF PEPE,F
RLF PEPE,F
RLF PEPE,F
endm
...
...
...
movlw 0x01
movwf PEPE
ROTAIZQ
...
...
...
end
========================
No se si esta faltando o sobrando algo...el ejemplo del WHILE, me cuesta, porque se incorporo el tema de la variable i (i +=1)... :shock: mamita !!! :-) :-) :-) :D :-) :-) :-)
Esta perfecto. La diferencia es que esa macro no genera código de salida variable. Las estructuras de control(Ej. while) permiten justamente desviar el código generando distinto código de salida.
i es una variable auxiliar que tuve que crear. La necesitaba para poder contar la cantidad de rotaciones comparandola con el parámetro recibido.
-
Hola BRUNO, antes de preguntar algo en este FORO, estuve leyendolo en OFF, durante 1 mes y medio...empece a estudiar el ASM, por iniciativa de un amigo, quien finalmente me convencio de hacerlo...en realidad no me sentia capaz de interpretar nada, me recibi apenas de tecnico hace mas de 2 decadas (hoy piso los 40)...y no vi, ni me enseñaron nada de programacion...termine mis estudios secundarios con solo 3 años de electronica, ya que venia de un colegio, con orientacion a la mecanica...
Me parece genial que hayas comenzado a aprender un lenguaje de programación. ¡Nunca es tarde para aprender!¡Nunca!
Lo que paso luego de encontrar estos "bichitos", es casi obvio !!! la fascinacion absoluta por la versatilidad, la economia de
espacios y de desarrollo...hace que hoy no pueda pensar, en diseños con "discreta"...
Una vez que arrancas con esto, ni pensás en usar un 555 alguna vez. La electrónica discreta pasa a ser prácticamente de apoyo solamente. El cerebro es el uC.
Lo cierto es que he prestado mucha atencion a los manuales del F84, que me imprimi por completo, y del cual saque una base, como para poder "interfacearme" con ustedes...luego descubri en internet un monton de curiosidades, de las cuales entendi la mitad y finalmente este interesantisimo FORO, del cual aprendo a diario...fijate el horario de mis preguntas, a veces estos hasta entrada la madrugada...
¡Bienvenido! Y no te preocupes por los horarios...todos los tenemos bastante dados vuelta.
De todas estas curiosidades, la mas llamativas, son para mi las MACROS, quizas por eso tanto interes...pero no es el unico, tengo ganas de preguntar de todo, pero a menudo, siento que abuso de este medio y espero que alguien pregunte por mi...
Bueno, justamente eso me resultó extraño pero me parece perfecto que te intereses.
Como no tengo un organigrama de estudios, me aparecen cosas nuevas todos los dias, y en lugar de estudiarlas con algun criterio u orden, las incorporo tipo "MORE INPUT - del famoso NUMBER FIVE" (la pelicula !!! te acordas)...
Jaja ¡cómo no!
Es asi que encontre la MACRO que inicio este hilo (hasta esto de escribir "hilo", "post", "topico", me resulta nuevo...), ya que mi sistema de aprendisaje es la lectura y la interpretacion...lo cual puede resultar peligroso, sino se coteja con alguien, que sepa...Fijate lo que me esta pasando con los conceptos de posiciones de memoria y valor de carga, sobre los registros !!!
Si necesitas aclarar conceptos sobre eso decime, que no hay problema.
En fin, seguire de cerca cualquier aporte que este FORO pueda hacerme, y seguire aprendiendo hasta donde me resulte posible...Sin extenderme mas, mira lo que encontre en la pagina de MIKE !!!
Here is a good, generic Delay Macro that does not change "w" or the STATUS Flag. Note that it assumes that the "DlayCount" variable is equal to zero upon code entry.
DlayMacro Macro Cycles ; Delay Macro for Edges
variable i, TCycles, Value, TFlag
TCycles = Cycles
Value = 1 << 7
i = 7
TFlag = 0
if (TCycles > 5)
while (i >= 0)
if ((TFlag == 0) && ((Value * 3) <= TCycles))
bsf DlayCount, i
TFlag = 1
TCycles = TCycles - (Value * 3)
else
if ((TFlag != 0) && (((Value * 3) + 1) <= TCycles))
bsf DlayCount, i
TCycles = TCycles - ((Value * 3) + 1)
endif
endif
Value = Value >> 1
i = i - 1
endw
if (TCycles > 3)
Error "Delay Cycles too Large for Macro"
endif
decfsz DlayCount, f
goto $ - 1
endif
while (TCycles > 1)
goto $ + 1
TCycles = TCycles - 2
endw
if (TCycles == 1)
nop ; Delay the Last Cycle
endif
endm
Parece una "joyita", pero hay que desentrañarla...incluye WHILE...
Bueno, esta que pasás es un poco más rebuscada que la otra, pero son similares. En realidad se complejiza porque la rutina no afecta ni el STATUS ni siquiera el registro W.
Asi a la pasada, un tip: ¿por qué aparece tanto "el número 3" en la MACRO? ¿Será porque...
decfsz DlayCount, f
goto $ - 1
es un bucle que por cada pasada demora 3 instrucciones de ejecución?
Veo una instrucción en especial a la que quiero que prestes atención:
bsf DlayCount, i
Ojo con esto..."no todo lo que brilla es oro"
Ojalá pudiese yo meter eso asi nomás al uC y que funcione como desearía...
Reseña histórica: Cuando comencé con el asm recuerdo que necesitaba hacer justamente eso:
necesitaba poner a 1 un determinado bit de un registro en particular.
El problema era que el número de bit que debía poner a 1 no era siempre el mísmo, entonces...Podría haber hecho la fácil y haber hecho 8 casos para los posibles 8 bits de un registro(despilfarro de memoria FLASH a lo cual me opongo por completo).
Pero un día dije:
¿Y por qué demonios no pongo directamente "bsf MiRegistro,i" y que "i" contenga el valor del número de bit que quiero setear?
Algo así por ejemplo:
i EQU 0x20
movlw .3
movwf i
bsf MiRegistro,i
La emoción duró poco. El MPASM no me lo permitía. Me decía que el el valor debía estar comprendido entre 0 y 7.
Obviamente se estaba refiriendo a lo que estaba en el lugar del "i".
¿Pero qué demonios!? Si a "i" la cargué con valor 3 y 0<3<7!!! ...entonces ¿qué pasa?
Lo que pasa es justamente, que al MPASM no le interesa el valor que tenga esa posición de memoria a la que apunta "i". Sino que le interesa sólamente el "i" y su valor declarado(en este caso, es la posición de memoria a la que se refiere)
Es decir que el MPASM traduce:
bsf MiRegistro,i
a:
bsf MiRegistro,0x20
Entonces era lógico que sucediera el error.
Bueno, entonces el problema era cómo hacer para que me lo tomara como una variable realmente.
Resumiendo: la respuesta es que no se puede hacer así de fácil.
Para hacer un algoritmo que setee un determinado bit de un registro, el algoritmo es muy distinto y poco más complejo.
Esa macro que exponés hace todo ese embrollo de setear los bits para no modificar el valor del acumulador(W).
Entonces, aca va la tarea que te dejo para que hagas:
Realizá(en la menor cantidad de líneas posibles, mejor) una subrutina que setee un bit determinado de un registro.
Ejemplo:
MiReg EQU 0x20
...
...
movf NumeroBit,W 'NumeroBit contiene un valor entre 0 y 7(el numero de bit a setear del registro MiReg)
call SETEARBIT 'A este momento, W contiene el numero de bit a setear.
SETEARBIT 'esta es la subrutina que quiero que setee el numero de bit X del registro MiReg.
...
...
...
RETURN
Porque, te parece que los estudiantes del ASM, no usan las MACROS o no le prestan la debida atencion, como decis ???
Sinceramente no lo sé.
Probablemente sea porque muchos no se dedican a estudiar el MPASM. Simplemente se limitan a estudiar el datasheet del uC que usan.
PD1: Actualmente trabajo como tecnico en electromedicina, me especializo en sistemas tomograficos (dignostico por imagenes, en sistemas SPECT, o planares...adquisicion por emision gamma...la famosa camara gamma que lo dejo verde al pobre "HULK"...cualquier curiosidad que tengas al respecto, tocame timbre...)
Gracias ;) te voy a tener en cuenta.
PD2: Bruno, recien estoy viendo tu explicacion del WHILE, gracias no la habia visto, se me paso de largo...la escribiste el dia 29/03/07...al mediodia, casi...perdoname, no me di cuenta, por eso te preguntaba sobre algun ejemplo...ahora la reviso y veo si saco algo en limpio...de todos modos, siempre entro a este ALMACEN DEL ASM y veo este hilo, en particular...GRACIAS !!! :-/
Jeje no hay problema. Se vé que ya te están agarrando los primeros mareos provocados por el assembler.
Saludos.
-
Interesante ejercicio, voy a intentar sacarlo.
Recién se me ocurrió una idea muy piola, tal vez me ponga y haga un librito de bolsillo sobre asm, como para tenerlo a mano cuando uno se está iniciando en ASM en este apasionante mundo de los PICs.
Y que no falten los capitúlos correspondientas al MPASM :-/ :-/ :-/ :-/
-
Esto lo hice usando solo ASM (no "raro")...como quise simularlo y lo unico que pude bajar fue el PIC SIMULATOR IDE, esta preparado para la simulacion...por eso hay valores precargados...
MIREG EQU 0x20
AUXA EQU 0x21
ORG 0x00
BSF STATUS,RP0
MOVLW 0xFF ;configuro PORTA con *11111*
MOVWF TRISA
MOVLW 0x00 ;configuro PORTB todos *00000000*
MOVWF TRISB
BCF STATUS,RP0
CLRF PORTA
CLRF PORTB
CLRF AUXA
MOVLW 0x01
MOVWF MIREG
MOVWF FSR
A BTFSS PORTA,02 ;arranca al apretar este boton (para el simulador)
GOTO A
CALL SETBIT
MOVFW MIREG
MOVWF PORTB ;lo quise ver en el PORTB (en el simulador)
MOVLW 0x01
MOVWF MIREG
INCF AUXA ;aca deberia escribirse el Nº de BIT a setear
MOVFW AUXA ;lo hago automatico para el simulador
MOVWF FSR
GOTO A
SETBIT BCF STATUS,C
RLF MIREG
DECFSZ FSR
GOTO $-2
RETURN
END
Estan precargados en 0X01 para comenzar, y despues automaticamente incrementa un contador, para no estar apretando a cada rato el boton que puse para que arranque...Esto es algo absolutamente conceptual, en el simulador anda (la primera vuelta esta condicionada por el valor de carga, asi que arranca prendiendome el PORTB,01) luego sigue bien...
Digo conceptual, porque la idea que se me ocurrio, era que se rote MIREG tantas veces como posicion de BIT quiera setear...En este caso, habra que escribir el Nº del BIT en el W y llevarlo al FSR (que parece un reg. que puede usarse para cualquier cosa, ademas de ser el clasico puntero del INDF)...
Bueno, seguire pensando otros metodos, para mejorarlo (seguro tiene errores, NO lo tomen como valido !!!)...
SALUDOS !!!
_____________________________
"Justo a mi me toco ser Yo" QUINO
-
Hola Resistencio. Me parece que comprendiste mal mi idea.
La idea era hacer un algoritmo que setee un bit determinado de MiReg.
Ej:
MiReg vale al momento: b'10001111'
y necesito un algoritmo tal que yo pueda setear el bit deseado de ese registro, pero SIN MODIFICAR EL RESTO DE SUS BITS.
Entonces, deberia poder decir, por ej:
movlw .6
call SeteaBit
y la subrutina SeteaBit deberia setear el bit 6 de MiReg, quedando entonces MiReg = b'11001111'
¿Se entendió?
Tu subrutina rota el registro MiReg, e inyecta ceros por la derecha. Entonces estas destruyendo los bits restantes del registro MiReg, cosa que no deberia suceder.
Igualmente tu funcion cambiando la variable a rotar y agregando una IOR haría lo pedido.
Saludos.
-
:-/ :-/ :-/
GRANDIOSO Bruno!, una explicación magnifica! :-/
Un gran abrazo!
Norberto
-
Hola BRUNO, aca intento algo como lo que pedis...hay un poco de codigo al "pepe", porque lo quise simular...
MIREG EQU 0x20
AUXA EQU 0x21
AUXB EQU 0x22
ORG 0x00
BSF STATUS,RP0
MOVLW 0xFF ;configuro PORTA con *11111*
MOVWF TRISA
MOVLW 0x00 ;configuro PORTB todos *00000000*
MOVWF TRISB
BCF STATUS,RP0
CLRF PORTA
CLRF PORTB
CLRF AUXA
BSF STATUS,C ;para que vaya rotando en AUXA
MOVLW 0x88 ;cargue MIREG con 10001000
MOVWF MIREG ;a efectos de verlo en el simulador
MOVWF PORTB
A BTFSS PORTA,02 ;esto es para el simulador se puede sacar
GOTO A
CLRF AUXA
MOVLW 0x07 ;aca se escribe el BIT a setear, en este caso el 7
MOVWF AUXB
INCF AUXB ;le sumo uno al valor expresado entonces 7 es el MSB (y 0 el LSB)
CALL SETBIT
MOVFW AUXA
IORWF MIREG ;lo carga sin alterar (eso creo, simule algunos valores y dio bien)
MOVFW MIREG
MOVWF PORTB ;esto es para simulador (se puede sacar)
BTFSC PORTA,02 ;para simulador se puede sacar
GOTO $-1
GOTO A
SETBIT RLF AUXA
DECFSZ AUXB
GOTO $-2
RETURN
END
Fijate BRUNO y decime que te parece...tambien se podia hacer con TABLAS con los valores precargados...
Mi pregunta (a pesar de que comentas en ROJO, que se puede agregar IF, THEN, etc en cualquier parte del programa) es: si esas instrucciones, necesariamente tienen que ser parte de una macro, o se las puede llamar con CALL (es decir como subrutinas)...no se si lo aclaraste, puntualmente en algun lado...la verdad es que repase todo y no lo vi...por eso puntualizo la pregunta...
PD: me parece que en algun lugar debo limpiar el CARRY...tendria que ver como hacer para que si quiero modificar el bit 0, modifique el LSB del AUXA, quizas si le sumara 1, cuando entra en el CALL...(paciencia, ya veo como...es una de las primeras cosas que hago...)
SALUDOS...
______________________________
"Justo a mi me toco ser YO" QUINO"
-
Así a lo bruto me sale una subrutina de unas 32 líneas con código ASM además de necesitar de un fichero auxiliar de la RAM
Supongo que habrán opciones más eficientes.
-
:-/ :-/ :-/
GRANDIOSO Bruno!, una explicación magnifica! :-/
Un gran abrazo!
Norberto
Gracias Norberto ;)
Hola BRUNO, aca intento algo como lo que pedis...hay un poco de codigo al "pepe", porque lo quise simular...
MIREG EQU 0x20
AUXA EQU 0x21
AUXB EQU 0x22
ORG 0x00
BSF STATUS,RP0
MOVLW 0xFF ;configuro PORTA con *11111*
MOVWF TRISA
MOVLW 0x00 ;configuro PORTB todos *00000000*
MOVWF TRISB
BCF STATUS,RP0
CLRF PORTA
CLRF PORTB
CLRF AUXA
BSF STATUS,C ;para que vaya rotando en AUXA
MOVLW 0x88 ;cargue MIREG con 10001000
MOVWF MIREG ;a efectos de verlo en el simulador
MOVWF PORTB
A BTFSS PORTA,02 ;esto es para el simulador se puede sacar
GOTO A
CLRF AUXA
MOVLW 0x07 ;aca se escribe el BIT a setear, en este caso el 7
MOVWF AUXB
INCF AUXB ;le sumo uno al valor expresado entonces 7 es el MSB (y 0 el LSB)
CALL SETBIT
MOVFW AUXA
IORWF MIREG ;lo carga sin alterar (eso creo, simule algunos valores y dio bien)
MOVFW MIREG
MOVWF PORTB ;esto es para simulador (se puede sacar)
BTFSC PORTA,02 ;para simulador se puede sacar
GOTO $-1
GOTO A
SETBIT RLF AUXA
DECFSZ AUXB
GOTO $-2
RETURN
END
Fijate BRUNO y decime que te parece...tambien se podia hacer con TABLAS con los valores precargados...
Te felicito. Parece funcionar correctamente.
Sin embargo, me gustaría hacer un par de comentarios:
La parte que está "peligrosa" es la del CARRY. Si entre que lo seteás y haces las rotaciones aparece alguna instrucción que afecte al CARRY, tu algoritmo no va a funcionar como es debido.
Para asegurar que la subrutina funcione correctamente, podria ser algo asi:
LIST P=16F877A
INCLUDE P16F877A.INC
ERRORLEVEL -302
MIREG EQU 0x20
AUXA EQU 0x21
AUXB EQU 0x22
ORG 0x00
BSF STATUS,RP0
MOVLW 0xFF ;configuro PORTA con *11111*
MOVWF TRISA
MOVLW 0x00 ;configuro PORTB todos *00000000*
MOVWF TRISB
BCF STATUS,RP0
CLRF PORTA
CLRF PORTB
CLRF AUXA
BSF STATUS,C ;para que vaya rotando en AUXA
;MOVLW 0x88 ;cargue MIREG con 10001000
CLRF MIREG ;a efectos de verlo en el simulador
;MOVWF PORTB
A ;BTFSS PORTA,02 ;esto es para el simulador se puede sacar
;GOTO A
MOVLW 0x01 ;aca se escribe el BIT a setear, en este caso el 1
CALL SETBIT
MOVFW AUXA
IORWF MIREG,F ;lo carga sin alterar (eso creo, simule algunos valores y dio bien)
MOVFW MIREG
MOVWF PORTB ;esto es para simulador (se puede sacar)
BTFSC PORTA,02 ;para simulador se puede sacar
GOTO $-1
GOTO A
SETBIT
MOVWF AUXB
MOVLW 0x01
MOVWF AUXA
LOOPROT
MOVF AUXB,F
BTFSC STATUS,Z
RETURN
BCF STATUS,C ;asegurar que ingresen ceros por la derecha.
RLF AUXA,F
DECF AUXB,F
GOTO LOOPROT
END
Mi pregunta (a pesar de que comentas en ROJO, que se puede agregar IF, THEN, etc en cualquier parte del programa) es: si esas instrucciones, necesariamente tienen que ser parte de una macro, o se las puede llamar con CALL (es decir como subrutinas)...no se si lo aclaraste, puntualmente en algun lado...la verdad es que repase todo y no lo vi...por eso puntualizo la pregunta...
Call es una instrucción perteneciente al PIC. NO AL MPASM. Es directa. Por lo tanto, no podés llamar a un IF.
La Call llama a una posición de memoria(ROM).
Ejemplos:
#define LimpiarW .1
...
call MiFuncion
MiFuncion
if LimpiarW == 0
movlw 0xFF
else
clrw
endif
return
Otro ejemplo: está permitido, pero derrocha memoria FLASH(macro):
#define Valor .1
...
MiFuncion
MiFuncion MACRO
if Valor != 0
movlw Valor
else
clrw
endif
ENDM
Eso no es correcto:
call MiFuncion
MiFuncion MACRO
...
...
endm
Así a lo bruto me sale una subrutina de unas 32 líneas con código ASM además de necesitar de un fichero auxiliar de la RAM
Supongo que habrán opciones más eficientes.
Sería bueno que lo postearas farfet, así lo analizamos, ¿te parece?
Saludos.
-
Se entendio BRUNO...mira asi !!!
A BTFSS PORTA,02 ;boton para el simulador
GOTO A
CLRF AUXA
MOVLW 0x04 ;BIT a setear
MOVWF AUXB
INCF AUXB
BSF STATUS,C ;ensucia CARRY
CALL SETBIT
BCF STATUS,C ;limpia CARRY
MOVFW AUXA
IORWF MIREG
MOVFW MIREG
MOVWF PORTB
GOTO A
SETBIT RLF AUXA
DECFSZ AUXB
GOTO $-2
RETURN
END
Voy a ver si me sale con las MACROS que incluyen IF y WHILE...SALUDOS
______________________________
"Justo a mi, me toco ser YO" QUINO
-
Ahora si lo pongo, estaba esperando que contestara el amigo Resistencio, aqui estoy de mirón y que aproveche este hilo para aprender cosas no me autoriza a chafarlo.
Ahi va, pero seguro que es mejorable
-----------------------------------------------------------------------------------------------------------
MiReg EQU 0x20
Auxil EQU 0x21 ;mi registro auxiliar
............
............
movf NuBit,1 ;valor entre 0x07 y 0x00 inclusives
call SETEARBIT
............
............
SETEARBIT
addlw 0xF8 ;Pasa a 0xFF (para 0x07) y 0xf8 (para 0x00)
movwf Auxil ;Copio valor incrementado a Auxili
incfsc Auxil,1 ;+1 y pregunto si rebasa 0xFF-->0x00
goto BIT6 ;si no hay rebase ir a probar BIT6
bsf MiReg,7 ;si hay rebase Nubit es 7
goto SALIR ;misión cumplida, ir a SALIR
BIT6
incfsc Auxil,1 ;ya es +2, pregunto si rebasa 0xFF-->0x00
goto BIT5 ;si no hay rebase ir a probar BIT5
bsf MiReg,6 ;si hay rebase Nubit es 6
goto SALIR ;misión cumplida, ir a SALIR
BIT5
incfsc Auxil,1 ;ya es +3, pregunto si rebasa 0xFF-->0x00
goto BIT4 ;si no hay rebase ir a probar BIT4
bsf MiReg,5 ;si hay rebase Nubit es 5
goto SALIR ;misión cumplida, ir a SALIR
BIT4
incfsc Auxil,1 ;ya es +4, pregunto si rebasa 0xFF-->0x00
goto BIT3 ;si no hay rebase ir a probar BIT3
bsf MiReg,4 ;si hay rebase Nubit es 4
goto SALIR ;misión cumplida, ir a SALIR
BIT3
incfsc Auxil,1 ;ya es +5, pregunto si rebasa 0xFF-->0x00
goto BIT2 ;si no hay rebase ir a probar BIT2
bsf MiReg,3 ;si hay rebase Nubit es 3
goto SALIR ;misión cumplida, ir a SALIR
BIT2
incfsc Auxil,1 ;ya es +6, pregunto si rebasa 0xFF-->0x00
goto BIT6 ;si no hay rebase ir a probar BIT1
bsf MiReg,2 ;si hay rebase Nubit es 2
goto SALIR ;misión cumplida, ir a SALIR
BIT1
incfsc Auxil,1 ;ya es +7, pregunto si rebasa 0xFF-->0x00
goto BIT0 ;si no hay rebase NuBit es 0
bsf MiReg,1 ;si hay rebase Nubit es 1
goto SALIR ;misión cumplida, ir a SALIR
BIT0
bsf MiReg,0 ;es ya la única posibilidad
SALIR
return
------------------------------------------------------------------------------------------------------------
Una subrutina con 32 líneas de código ASM y un fichrero auxiliar
-
Se entendio BRUNO...mira asi !!!
A BTFSS PORTA,02 ;boton para el simulador
GOTO A
CLRF AUXA
MOVLW 0x04 ;BIT a setear
MOVWF AUXB
INCF AUXB
BSF STATUS,C ;ensucia CARRY
CALL SETBIT
BCF STATUS,C ;limpia CARRY
MOVFW AUXA
IORWF MIREG
MOVFW MIREG
MOVWF PORTB
GOTO A
SETBIT RLF AUXA
DECFSZ AUXB
GOTO $-2
RETURN
END
Ahí está perfect! ;)
Ahora si lo pongo, estaba esperando que contestara el amigo Resistencio, aqui estoy de mirón y que aproveche este hilo para aprender cosas no me autoriza a chafarlo.
Ahi va, pero seguro que es mejorable
-----------------------------------------------------------------------------------------------------------
MiReg EQU 0x20
Auxil EQU 0x21 ;mi registro auxiliar
............
............
movf NuBit,1 ;valor entre 0x07 y 0x00 inclusives
call SETEARBIT
............
............
SETEARBIT
addlw 0xF8 ;Pasa a 0xFF (para 0x07) y 0xf8 (para 0x00)
movwf Auxil ;Copio valor incrementado a Auxili
incfsc Auxil,1 ;+1 y pregunto si rebasa 0xFF-->0x00
goto BIT6 ;si no hay rebase ir a probar BIT6
bsf MiReg,7 ;si hay rebase Nubit es 7
goto SALIR ;misión cumplida, ir a SALIR
BIT6
incfsc Auxil,1 ;ya es +2, pregunto si rebasa 0xFF-->0x00
goto BIT5 ;si no hay rebase ir a probar BIT5
bsf MiReg,6 ;si hay rebase Nubit es 6
goto SALIR ;misión cumplida, ir a SALIR
BIT5
incfsc Auxil,1 ;ya es +3, pregunto si rebasa 0xFF-->0x00
goto BIT4 ;si no hay rebase ir a probar BIT4
bsf MiReg,5 ;si hay rebase Nubit es 5
goto SALIR ;misión cumplida, ir a SALIR
BIT4
incfsc Auxil,1 ;ya es +4, pregunto si rebasa 0xFF-->0x00
goto BIT3 ;si no hay rebase ir a probar BIT3
bsf MiReg,4 ;si hay rebase Nubit es 4
goto SALIR ;misión cumplida, ir a SALIR
BIT3
incfsc Auxil,1 ;ya es +5, pregunto si rebasa 0xFF-->0x00
goto BIT2 ;si no hay rebase ir a probar BIT2
bsf MiReg,3 ;si hay rebase Nubit es 3
goto SALIR ;misión cumplida, ir a SALIR
BIT2
incfsc Auxil,1 ;ya es +6, pregunto si rebasa 0xFF-->0x00
goto BIT6 ;si no hay rebase ir a probar BIT1
bsf MiReg,2 ;si hay rebase Nubit es 2
goto SALIR ;misión cumplida, ir a SALIR
BIT1
incfsc Auxil,1 ;ya es +7, pregunto si rebasa 0xFF-->0x00
goto BIT0 ;si no hay rebase NuBit es 0
bsf MiReg,1 ;si hay rebase Nubit es 1
goto SALIR ;misión cumplida, ir a SALIR
BIT0
bsf MiReg,0 ;es ya la única posibilidad
SALIR
return
------------------------------------------------------------------------------------------------------------
Una subrutina con 32 líneas de código ASM y un fichrero auxiliar
La logica del este programa también está bien. Es perfectamente posible. Tal vez podríamos reducir la cantidad de lineas...
¿Y si hacemos una tablita? :D
Ej:
movlw 0x06 ;indicar bit 6 a setear:
pagesel MiTabla
call MiTabla
MiTabla
andlw 0x07 ;forzar a que el valor recibido en W sea < 8(evitemos errores)
movwf AUX
addwf AUX,W ;AUX = W*2
addwf PCL,F
bsf MiReg,0
return
bsf MiReg,1
return
bsf MiReg,2
return
bsf MiReg,3
return
bsf MiReg,4
return
bsf MiReg,5
return
bsf MiReg,6
return
bsf MiReg,7
return
Suerte!!! Y sigan programando.
-
Hola FARTET, esta es la prueba que se puede hacer de varias maneras...no la revise todavia, voy a tratar de simularlo...
Estas seguro de " incfsc " ??? yo tengo " incfsz "...no se si es igual...esperemos a BRUNO, que "pilotea con una mano" esto del ASM... :D
SALUDOS !!!
______________________________
"Justo a mi, me toco ser Yo" QUINO
-
Estas seguro de " incfsc " ??? yo tengo " incfsz "...no se si es igual...esperemos a BRUNO, que "pilotea con una mano" esto del ASM... :D
Sisi. Efectivamente es incfsz. ;)
Saludoss!!!
-
FARTET, hasta ahi esta aclarado lo del INCFSZ...me parece que ademas, deberias entrar al CALL, con el W limpio (CLRW)...Que te parece ???
SALUDOS...
______________________________
"Justo a mi, me toco ser Yo" QUINO
-
Bueno, hay un errorcito pero no debe entrar con W limpio Resistencio.
movf NuBit,1 ;valor entre 0x07 y 0x00 inclusives
deberia ser:
movf NuBit,0 ;valor entre 0x07 y 0x00 inclusives
Saludos.
-
Claro BRUNO, ya me parecia que algo estaba raro...me confunde el tema de que los destinos de los valores de registro son, para 0=W y 1=F...
y hablando de ese tema, alguna vez escribistes por ahi, algo que en principio me confundio un poco...cuando crei tnerlo aclarado, me surgieron las mismas dudas...tiene que ver con las EQU...Yo sostenia que las EQU, servian solo para elegir alguna posicion donde declarar un REGISTO...asi, si escribia MIREG EQU 0X20, el registro MIREG ocupaba esa posicion de RAM...
Sin embargo, para mi sorpresa, en otras ocasiones he leido cosas como:
RP0 EQU 5
RP1 EQU 6
IRP EQU 7
Z EQU 2
C EQU 0
Donde parece que aqui las EQU, especifican la posicion del BIT en el registro !!! :shock: :shock: :shock:
Pero en algunos casos se repiten estan declaraciones, y en el mismo encabezado encuentro redundancias (O NO), como:
PORTA equ 5 (fijate que arriba ya se habia usado para el RP0 equ 5) :shock:
Parece que unas son EQUATES de REGISTROS y otras de BITS o algo asi...
Incluso vi cosas como:
RELOJ equ 4000000
En fin, curiosidades, por ahora...
Estoy muy interesado en la posibilidad de medir el tiempo de los pulsos de entradas...lei algo relacionado con un tacometro, donde se usa el TIMER, con lo cual se me ocurrio que podria a partir de un solo puerto de entrada, tener varios botones conectados a el, que hagan cosas diferentes...cada uno tendria una constante de tiempo diferente, para poder ser identificados...lo que no se es cual deberia ser la precision de esos pulsos o con que precision mide el micro esos tiempos...
Otra idea que vi es la de medir diferentes niveles de tension, medibles luego de ser convertidos por los AD de un micro...pero me interesa la primera opcion...tengo que ver con cuidado, si entre tanto info que hay en este FORO, hay algo concreto, para por lo menos, rescatar los comceptos primarios...
En estos momentos, y producto solamente de mi ignorancia, se me ocurre preguntar, cuales son los principios ordenados, minimos, necesarios y que protocolos se deben encausar, para lograr interactuar con un programador (o analista de sistemas)...se me ocurre que en alguna medida, la labor de un ingeniero electronico (o idoneo en electronica), es una disciplina que dista bastante de la de un analista, que maneja conceptos mas abstractos...Por otro lado, no creo que sea una condicion, necesaria para los analistas, el conocer de electronica y a la inversa...por lo cual estas actividades son a mi entender, absolutamente interdiscipliniarias...
Por ejemplo: Hace varios años que trabajo haciendo electromedicina, y conozco a la perfeccion el funcionamiento de sistemas de ECG o EEG...pero no tengo la mas minima pista de como hacer un software, que pueda presentarse en PC, para estos sistemas...Es decir, que tiene que conocer como minimo un programador, para hacer un soft a medida ???
Quien decide la interface de entrada, sistema de comunicacion, formato de pantalla, etc, etc, etc...
Ahora con el recurso de los micros, estoy decidido a reformar algunos dispositivos de electromedicina, que ya estan bastante pasados de moda...a los fines de los sistemas puramente electronicos, dificilmente necesite recursos, demasiados complicados de instrumentar...pero por si asi fuera, seguire aprendiendo sobre MICROS !!!
SALUDOS...y espero que las cosas mejoren pronto en Santa Fe...
______________________________
"Justo a mi, me toco ser YO" QUINO
-
Claro BRUNO, ya me parecia que algo estaba raro...me confunde el tema de que los destinos de los valores de registro son, para 0=W y 1=F...
y hablando de ese tema, alguna vez escribistes por ahi, algo que en principio me confundio un poco...cuando crei tnerlo aclarado, me surgieron las mismas dudas...tiene que ver con las EQU...Yo sostenia que las EQU, servian solo para elegir alguna posicion donde declarar un REGISTO...asi, si escribia MIREG EQU 0X20, el registro MIREG ocupaba esa posicion de RAM...
Si pones MIREG EQU 0x20, lo unico que estas haciendo es decirle al MPASM:
"mirá, cada vez que aparezca escrito por en mi programa MIREG, reemplazalo por 0x20"
Entonces, en ese caso funcionaría como un puntero a la posición de memoria 0x20.
Sin embargo, para mi sorpresa, en otras ocasiones he leido cosas como:
RP0 EQU 5
RP1 EQU 6
IRP EQU 7
Z EQU 2
C EQU 0
Donde parece que aqui las EQU, especifican la posicion del BIT en el registro !!! :shock: :shock: :shock:
Nuevamente, lo unico que hace el MPASM ahi es remplazar el nombre definido por su valor.
Decir bsf STATUS,C
Se traduce a bsf 0x03,0
NO ES NECESARIO DECLARAR LOS BITS Y REGISTROS ESPECIALES DE UN PIC SI INCLUIS EL ARCHIVO .INC DEL uC A UTILIZAR: Ej:
INCLUDE P16F877A.INC
(abri el archivo P16F877A.INC con el bloc de notas y fijate lo que tiene dentro asi comprendes mejor)
Pero en algunos casos se repiten estan declaraciones, y en el mismo encabezado encuentro redundancias (O NO), como:
PORTA equ 5 (fijate que arriba ya se habia usado para el RP0 equ 5) :shock:
Es dos formas distintas de apuntar al mísmo NUMERO.
Es como decir x = y = 5, sólo que algunas veces es más fácil(y adecuado) usar el nombre x y otras el y según el caso.
Entonces, vos podrias perfectamente poner:
bsf PORTA,PORTA
o lo que sería lo mísmo:
bsf RP0,RP0
Ambos serían traducidos a:
bsf 0x05,0x05
¿Pero sería muy poco legible el código, no? Por eso mejor ponerle distintos nombres al mísmo número y usar el nombre adecuado según corresponda
Incluso vi cosas como:
RELOJ equ 4000000
En fin, curiosidades, por ahora...
Más de lo mísmo. No importa que exceda el valor .255. Se utilizará para realizar probablemente cálculos en el programa(probablemente en alguna MACRO).
Estoy muy interesado en la posibilidad de medir el tiempo de los pulsos de entradas...lei algo relacionado con un tacometro, donde se usa el TIMER, con lo cual se me ocurrio que podria a partir de un solo puerto de entrada, tener varios botones conectados a el, que hagan cosas diferentes...cada uno tendria una constante de tiempo diferente, para poder ser identificados...lo que no se es cual deberia ser la precision de esos pulsos o con que precision mide el micro esos tiempos...
Depende de varias cosas. La precisión depende de muchas cosas: el modelo de PIC, la velocidad del cristal, las ppm del mísmo, el Timer del pic a utilizar,etc...
Si me preguntás cuál es el valor mínimo a 4mhz que puede, por ejemplo, contar el Timer0 del 16F84A no puedo decirte con precisión, pero no creo que supere los 10us o 20us.
El máximo puede arreglarse y "estirarse" usando registros auxiliares.
Las fórmulas para calcular el tiempo de desbordamiento de los Timers están en el foro muchísimas veces repetidas y dependen de cuál Timer pensés usar.
Otra idea que vi es la de medir diferentes niveles de tension, medibles luego de ser convertidos por los AD de un micro...pero me interesa la primera opcion...tengo que ver con cuidado, si entre tanto info que hay en este FORO, hay algo concreto, para por lo menos, rescatar los comceptos primarios...
Es posible. Tal vez para un producto REALMENTE SERIO debas recurrir a un ADC externo, ya que el del PIC puede dejar mucho que desear si se necesitan muchas conversiones o bien mucha precisión.
En estos momentos, y producto solamente de mi ignorancia, se me ocurre preguntar, cuales son los principios ordenados, minimos, necesarios y que protocolos se deben encausar, para lograr interactuar con un programador (o analista de sistemas)...se me ocurre que en alguna medida, la labor de un ingeniero electronico (o idoneo en electronica), es una disciplina que dista bastante de la de un analista, que maneja conceptos mas abstractos...Por otro lado, no creo que sea una condicion, necesaria para los analistas, el conocer de electronica y a la inversa...por lo cual estas actividades son a mi entender, absolutamente interdiscipliniarias...
Bueno, básicamente debés definir qué puerto/s de la computadora deseas utilizar(los más populares son: paralelo, serie y USB)y su configuración. Luego el protocolo de comunicación a utilizar, que puede ser a medida o bien respetando protocolos existentes. Y luego el resto, ya entrando en mayor detalle.
Por ejemplo: Hace varios años que trabajo haciendo electromedicina, y conozco a la perfeccion el funcionamiento de sistemas de ECG o EEG...pero no tengo la mas minima pista de como hacer un software, que pueda presentarse en PC, para estos sistemas...Es decir, que tiene que conocer como minimo un programador, para hacer un soft a medida ???
Quien decide la interface de entrada, sistema de comunicacion, formato de pantalla, etc, etc, etc...
Mínimamente seguramente debas aprende algún lenguaje de programación para PC.
Te recomiendo el VB6 para que te resulte fácil poder aprender a programar rápido para PC.
Generalmente lo decide el empleador. Si ambos(el electronico y el programador) son empleados de un 3ero o socios, deberán ponerse de acuerdo entre ellos. Aunque seguramente el programador esté más capacitado y familiarizado con qué cosa conviene hacer en cada caso y cómo debería ser visualizada en pantalla.
Ahora con el recurso de los micros, estoy decidido a reformar algunos dispositivos de electromedicina, que ya estan bastante pasados de moda...a los fines de los sistemas puramente electronicos, dificilmente necesite recursos, demasiados complicados de instrumentar...pero por si asi fuera, seguire aprendiendo sobre MICROS !!!
Si pensás utilizarlo en electromedicina, me parece bárbaro que te hayas inclinado hacia el ASM. Si un programa está bien hecho en ASM, es la mayor seguridad que podés obtener con un PIC.
"Mayor seguridad que podés obtener con un PIC" digo porque si bien los PICs son estables, la electromedicina es un área crítica en cuanto a errores. Tus dispositivos deberían ser MUY estables, incluso con ruidos cercanos o cualquier sorpresita que pueda ocurrir en el medio ambiente. Es un área muy delicada.
SALUDOS...y espero que las cosas mejoren pronto en Santa Fe...
Esperemos que si...
Saludos.
-
Gracias BRUNO, siempre aportando algo util... (sos profesor o maestro, en algun establecimiento ??? )
Conozco muy poco de lenguajes, pero por lo que refiere la mayoria en terminos de control, el ASM es mejor...el BASIC, me parece lo que sigue en este orden...de lo demas no hablo porque no conozco...imagino que a mayor nivel de lenguaje (lo que en realidad significa alejarse mas del MICRO), se resolveran algoritmos mas complejos con menos instrucciones del lenguaje usado...Pero para mi es mucho mas directo y controlable el ASM...mi pregunta anterior, estaba fundada en este razonamiento, me parece que los que eligen lenguajes de mas nivel, estan mas abstraidos de la electronica y por ello mas alejados de la funcionabilidad del hadware (usando el mismo criterio, que expongo mas arriba)...esto lo digo a riesgo de equivocarme, y sin intencion de polemizar al respecto, ni de herir suceptibilidades u ofender a nadie...es solo una apreciacion personal...
Asi como digo que la mayoria refiere el ASM, como ideal para manejar parametros electronicos con mejor precision...lei comentarios de que los MOTOROLA son micros mas estables o inmunes a EMI o ruido electricos o artefactos (artificios)...por lo cual de estar esto confirmado de alguna manera, me serviran mejor para algunas aplicaciones donde se necesitan filtrar ciertos espureos...personalmente creo que es un mito...dada la avanzada de MICROCHIP con estos "bichitos", no me parece que sea real tal afirmacion, y que solo se trata de aliados a esos micros, por cuestiones de escuela o lo que sea...es decir sin mayores fundamentos...
Me gustaria conocer tu opinion al respecto, si es que tenes alguna formada...o la de algun forista que haya tenido oportunidad de trabajar con ellos...
Hoy escuche atento a las noticias, que se estan encausando los desbordes, pero que en varios sitios, hara falta el uso de bombas de aspiracion, por saturacion de los suelos (y porque no hay nada desbordado, es pura saturacion)...encima los gobiernos de turno, se afanaron las bombas...tercermundistas a full...esperemos el milagro de la solidaridad entre hermanos, que es lo que realmente, nunca falla... :?
Un ABRAZO !!!
_____________________________
"Justo a mi, me toco ser Yo" QUINO
-
Todo aclarado. Por cierto me ha gusta la solución usando tablas. :-/ :-/ :-/
-
Hola..aca he hecho una recopilacion de algunos de los ejemplos que tan bien expone BRUNO en este hilo...
Ademas cumple con el desafio de poder SETEAR un BIT a voluntad sin alterar el contenido original del REGISTRO...!!!
Estuve ensayando con el SIMULADOR del MPLAB (tengo la version 5.00.00000000000000000000000 pero anda bien !!!)...ahi se ve casi todo lo que esta pasando...por ahora solo interpreto la ventana de los SFR, desde ahi pude verificar el siguiente programa...
LIST P=16F84, F=INHX8M
include <P16F84a.inc>
ERRORLEVEL -302 , -305
RADIX DEC
FIJATE macro Valor
if(Valor < .20)
bsf PORTA,00
bcf PORTA,01
bsf PORTA,02
endif
if(Valor >= .20) && (Valor < .30)
bcf PORTA,00
bsf PORTA,01
bcf PORTA,02
endif
if(Valor > .30)
bcf PORTA,00
bcf PORTA,01
bsf PORTA,02
endif
endm
PONEUNO macro Registro, Rotaciones
if (Registro>0x6f) ;NO SE BIEN PORQUE ESTE VALOR ES EL MAXIMO ???
error El registro supera la posición máxima(0x6f)
else
BSF STATUS,C
endif
variable i
i = 0
while (i != Rotaciones)
rlf Registro,F
i += 1
endw
endm
org 0x000 ;Vector de inicio de memoria FLASH del PIC.
BSF STATUS,RP0
CLRF TRISA ;puertoA todo como salida
CLRF TRISB
BCF STATUS,RP0
CLRF PORTA
CLRF PORTB
CLRF FSR
FIJATE .15 ;MANDA A COMPARAR VALORES, PARA AJUSTAR PA
movfw PORTA
movwf PORTB
BCF STATUS,C
PONEUNO FSR,4 ;EL BIT A SETEAR ES EL CUARTO, NO ALTERA PB
BCF STATUS,C
MOVFW FSR
IORWF PORTB
LOOP GOTO LOOP
end
Todo esto era chino "mandarin" para mi hace un mes, ahora y alentado por ustedes, puede comprender, aunque sea un poco...parte de esto se lo debo a BRUNO...GRACIAS !!!
SALUDOS !!!
_____________________________
"Justo a mi, me toco ser Yo" QUINO
-
Hola nuevamente resitencio.
Sigue estando el detalle que siempre te comento. Es resto está muy bien.
El problema no surge si llamas a la macro PONEUNO sólo una vez. Pero puede surgir si no tomas ciertas precauciones y usas esa macro mas de una vez en tu programa.
El error potencialmente presente no es tan visible a primera vista, entonces te lo demuestro de manera practica:
Luego de llamar a la macro SETEOUNO FSR,4 el FSR = b'00010000'
¿Bien?
Si ahora llamo de nuevo a la macro haciendo por ej. SETEOUNO FSR,6
vas a poder apreciar que el bit que estaba seteado de la llamada anterior(el bit 4) va a ensuciar tu registro FSR, quedando: FSR = b'01000100'(segun calculo a simple vista).
Te invito a que lo pruebes y me comentes si estoy en lo cierto.
Entonces, o bien limpias el registro FSR antes de comenzar a realizar las rotaciones, o bien podes tambien poner la linea: bcf STATUS,C LUEGO DE rlf Registro,F.
¿Se entendió?
Saludos! ;)
-
De a poco lo voy "lijando", porque esta con varias "astillas" este codigo...Cuando ponia FSR,4, me seteaba el bit Nº3, por eso sumo 1 en el ELSE, el cual me sirve para ir haciendo las ROTACIONES...Creo que ahi va queriendo !!!
PONEUNO macro Registro, Rotaciones
if (Registro>0x6f)
error El registro supera la posición máxima(0x6f)
else
CLRF FSR
INCF FSR
BCF STATUS,C
endif
variable i
i = 0
while (i != Rotaciones)
rlf Registro,F
i += 1
endw
endm
org 0x000 ;Vector de inicio de memoria FLASH del PIC.
BSF STATUS,RP0
CLRF TRISA ;puertoA todo como salida
CLRF TRISB
BCF STATUS,RP0
CLRF PORTA
CLRF PORTB
CLRF FSR
PONEUNO FSR,5 ;EL BIT A SETEAR ES EL quinto, NO ALTERA PB
BCF STATUS,C
MOVFW FSR
IORWF PORTB
LOOP GOTO LOOP
end
Sigo aprendiendo, por ahora no queme nada ni a nadie, :D pienso tomarme todo este año para ir mejorando estos detalles...Hare caso a esas palabras, que dijeron "NUNCA es tarde para aprender"... :lol: :-) :lol: :-) :lol:
Porque tomas a 0x6F como limite maximo, quise cambiarlo, pero el compilador sugiere ese mismo numero, de donde sale ???
Que significado tiene en la columna del simulador, identificada como CHAR, el @ - E - / - + ,etc... ???
SALUDOS !!!
______________________________
"Justo a mi, me toco ser Yo" QUINO
-
Ahora otro que deja el Nº de BIT "a pedido" el Nº que se escribe es el que se setea, sin necesidad de hacer INCF FSR...pero ROTANDO a la drecha...Guarda con "MURRAY", que la viene "cazando" !!!
PONEUNO macro Registro, Rotaciones
if (Registro>0x6f)
error El registro supera la posición máxima(0x6f)
else
CLRF FSR
BSF STATUS,C
endif
variable i
i = 8
while (i != Rotaciones)
rrf Registro,F
i -= 1
endw
endm
PONEUNO FSR,7 ;EL BIT A SETEAR ES EL septimo, NO ALTERA PB
BCF STATUS,C
MOVFW FSR
IORWF PORTB
LOOP GOTO LOOP
end
SALUDOS !!! (espero posibles correcciones, sugerencias, acotaciones...!!! :))
______________________________
"Justo a mi, me toco ser Yo" QUINO
-
Hola Resistencio.
Veo que vas encontrando distintas variantes para hacer lo mismo, lo que es muy bueno para agilizar la mente.
Debo recordarte que hay que tener cuidado a la hora de elegir qué debería ser macro y qué función, ya que un abuso de macros van a producir seguramente que te devores la memoria FLASH sin sentido.
Cometí un error. El valor correcto es 0x7F. No te guíes tanto por eso.
Lo puse más que nada para enseñarte a generar errores cuando no querés que se compile el programa por un error "grosso".Igualmente te voy explicar el significado y sus limitaciones.
El 0x7F obliga a que la posicion de memoria que pasás por referencia sea menor a 0x80.
Si por ejemplo TRISA = 0x85, entonces hacer PONEAUNO TRISA,4 va a producir un error ya que 0x85 > 0x7F.
Sin embargo es perfectamente factible hacer PONEAUNO TRISA,4, por lo que esa limitación que puse sería errónea(¡cuidado! que como 0x85 excede el valor 0x7F habrá que estar en el banco de memoria correcto para afectar realmente a dicha posicion de memoria).
Veo que ya vas agarrandole la mano a esto. Espero ver pronto algun proyecto tuyo.
Saludos.
-
Gracias BRUNO, como siempre, claro y preciso !!!
Estoy probando como anda el simulador, que parece util para ver que le pasa a los registros declarados y a los SFR...tambien lei un post tuyo del año 2003, donde decias que no es muy confiable el simulador de MPLAB, por lo menos el de aquellos años (te recuerdo que estoy usando una version de ese entonces la 5.00...recientemente baje la 7.50...pero aun no la use...)
Aun, y muy a pesar de todas las explicaciones que me diste, me confunde un poco el valor que toma un registro y su relacion con la posicion de memoria que ocupa...asi que estuve simualndo eso para ver que sucede...
Tengo declarado el reg AUXA en posicion 0E de RAM y hago lo siguiente...
MOVLW ((4 / 2) * (2 / 2 + 4)) ;esto es para probar que hacen esos benditos operandos :-)
MOVWF AUXA ;aca el reg AUXA toma el valor de .10 (lo que parece esperable y/o correcto...)
BCF STATUS,C
MOVLW (AUXA + 1 + 2) ;aca que esperaba que tomara el valor de .13, toma el valor 0E + 1 + 2 = 17
MOVWF AUXA ;es decir el valor de posicion 0E mas 3 = 17
Esto me tiene "loco", no me "avivo" porque pasa esto...la conclusion pareceria ser que cuando lo fuerzo, se carga con ese valor y cuando lo asumo precargado, toma el valor de su posicion...es probable que este exponiendo una incoherencia, pero es producto de lo novedoso para mi (extraño las 6DQ6) :D...no encuentro en ningun lado, salvo en este FORO y en tus explicaciones, la claridad que preciso...
Por otro lado se me ocurre pensar que posicion toma la variable (i) ???, en algun lado debe alojarse...el simulador pone ADDRESS 05, igual que el PORTA...sera correcto ???
Porque no hay ejemplos de como usar los otros operandos en ningun lado... ???
Como se pueden usar y donde los "operators":
>> Right Shitf (val=flags >>1)..................que sera esto ??? :shock:
>>=3 Right Shitf, set equal (flags>>=3)..................por ahora chino "cantones) !!! :shock:
Y asi unos cuantos mas !!!
Estoy tratando de leer algo de BASIC, por la similitud de estos operandos y ver si se me pueden aclarar un poco estos conceptos...Pero todo me resulta empirico...lo escribo en el ensamblador y veo que hacen, asi me paso horas...
Bueno, BRUNO, una vez mas, gracias por tu paciencia y por la buena onda, en contestar estas "liviandades", que imagino para vos ya estan mas que superadas !!!
SALUDOS !!!
______________________________
"Justo a mi, me toco ser YO" QUINO
-
Antes que nada, perdoná la demora.
Gracias BRUNO, como siempre, claro y preciso !!!
Estoy probando como anda el simulador, que parece util para ver que le pasa a los registros declarados y a los SFR...tambien lei un post tuyo del año 2003, donde decias que no es muy confiable el simulador de MPLAB, por lo menos el de aquellos años (te recuerdo que estoy usando una version de ese entonces la 5.00...recientemente baje la 7.50...pero aun no la use...)
Yo he tenído algunos problemas con el MPASM en los que no se comportaba como debía, pero en las ultimas versiones no he visto errores tan "grossos". Usalo. Es muy útil.
Aun, y muy a pesar de todas las explicaciones que me diste, me confunde un poco el valor que toma un registro y su relacion con la posicion de memoria que ocupa...asi que estuve simualndo eso para ver que sucede...
Tengo declarado el reg AUXA en posicion 0E de RAM y hago lo siguiente...
MOVLW ((4 / 2) * (2 / 2 + 4)) ;esto es para probar que hacen esos benditos operandos :-)
MOVWF AUXA ;aca el reg AUXA toma el valor de .10 (lo que parece esperable y/o correcto...)
BCF STATUS,C
MOVLW (AUXA + 1 + 2) ;aca que esperaba que tomara el valor de .13, toma el valor 0E + 1 + 2 = 17
MOVWF AUXA ;es decir el valor de posicion 0E mas 3 = 17
Esto me tiene "loco", no me "avivo" porque pasa esto...la conclusion pareceria ser que cuando lo fuerzo, se carga con ese valor y cuando lo asumo precargado, toma el valor de su posicion...es probable que este exponiendo una incoherencia, pero es producto de lo novedoso para mi (extraño las 6DQ6) :D...no encuentro en ningun lado, salvo en este FORO y en tus explicaciones, la claridad que preciso...
Bueno.Seguimos dando vueltas alrededor de lo mismo.
No te hagas más lío.
Si vos ponés:
MiReg EQU 0x0E
CADA VEZ QUE ESCRIBAS MiReg en el programa, el MPASM lo va a reemplazar por 0x0E. Escribir MiReg o escribir 0x0E es exactamente lo mísmo.
NO CREAS QUE POR USAR EL EQU Y ASIGNARLE UN VALOR, EL MPASM CREA UN VINCULO ESTRICTO CON ESA POSICION DE MEMORIA A LA QUE HACE REFERENCIA.
QUE VOS USES EL MiReg PARA REFERIRTE A LA POSICION DE MEMORIA RAM 0x0E ES UNO DE LOS TANTOS USOS QUE PODES DARLE.
PODRIAS TAMBIEN PONER POR EJEMPLO: movlw MiReg, LO CUAL SERIA INTERPRETADO POR EL MPASM COMO movlw 0x0E.
Volviendo al código que expusiste, fijate cómo sería para que haga lo que querés(usando un simulador o el PIC):
MOVLW ((4 / 2) * (2 / 2 + 4)) ;esto es para probar que hacen esos benditos operandos
MOVWF AUXA ;aca el reg AUXA toma el valor de .10 (lo que parece esperable y/o correcto...)
BCF STATUS,C
MOVF AUXA,W
ADDLW 1 + 2
MOVWF AUXA ;es decir el valor de posicion 0E mas 3 = 17
El resto de los lenguajes de programacion de más alto nivel(como el BASIC) sí hacen lo que vos quisiste hacer, pero esto es debido a que poseen un compilador que se encarga de transformar esas lineas a assembler.
Si vos querés desligarte por completo de las instrucciones del PIC(es decir, las 35 de la familia 16F) entonces te recomiendo cualquier otro lenguaje de programacion para PICs existente, excepto el assembler. Si decidís seguir con el ASM, entonces deberías saberte esas 35 instrucciones a rajatabla.
Por otro lado se me ocurre pensar que posicion toma la variable (i) ???, en algun lado debe alojarse...el simulador pone ADDRESS 05, igual que el PORTA...sera correcto ???
La variable i es una variable auxiliar que usamos sólo con meros propósitos algebraicos o comparacionales.
La variable i es creada por el MPASM, y si tu interés es saber dónde se aloja esa variable i, pues la respuesta es, seguramente, en la RAM DE LA PC. El MPLAB la crea para que le sirva de apoyo al usuario programador durante sus calculos auxiliares. Una vez realizados los calculos necesarios, el MPASM la destruye. NO TIENE NADA QUE VER CON LA MEMORIA DEL PIC.
Porque no hay ejemplos de como usar los otros operandos en ningun lado... ???
Probablemente sea porque la mayoría de los que programan ni siquiera saben que están disponibles para su uso.
Como se pueden usar y donde los "operators":
>> Right Shitf (val=flags >>1)..................que sera esto ??? :shock:
>>=3 Right Shitf, set equal (flags>>=3)..................por ahora chino "cantones) !!! :shock:
Y asi unos cuantos mas !!!
Nunca las usé pero por lo que sé(me parece que lo correcto es "Shift") sirven para rotar variables.
Su función debe ser muy similar a las RLF y RRF, pero la diferencia radica en que estas instrucciones se aplican a variables que no pertenecen a la memoria del PIC. Sino que se aplican sobre variables utilizadas durante el proceso de ensamblado del archivo .hex (como por ejemplo, la ya famosa variable "i").
Estoy tratando de leer algo de BASIC, por la similitud de estos operandos y ver si se me pueden aclarar un poco estos conceptos...Pero todo me resulta empirico...lo escribo en el ensamblador y veo que hacen, asi me paso horas...
Conseguite algun compilador demo de PBP y fijate cuando compilas el archivo el código asm que genera. Por ahí te traiga nuevas dudas, pero te resuelva muchas otras.
Saludos.
-
Y si, el tipo es cabeza dura nomas !!! Pero hasta que no me cierran las cosas, ando a los golpes !!!
Finalmente pude comprerder el concepto del significado de una declaracion de "RAM locations"...
Ahora lo que creo, es que Yo, te volvi loco a vos BRUNO :D...juro que no fue mi intencion !!!
Entiendo lo que decis que hace el MPSAM, de reemplazar el nombre de un registro declarado, por una posicion de RAM...pero mi duda se generaba, cuando asociaba al registro, con los valores que pudiera cargarle (sino no servirian para nada, es decir serian como constantes...)
Hice varios ensayos con los simuladores de MPLAB, y tanto en las versiones viejas (5.0) como en las mas recientes (7.50) obtuve los resultados, que esperaban y cierran con mis conceptos...
Para poder interpretar todo esto, tome tu propio ejemplo y ensaye sobre el...ahi aparecio mi respuesta...Los registros se pueden efectivamente, y como Yo creia, cargar con cualquier valor (eso les da algun motivo de servicio, sino, como digo antes, no sirven para nada...serian constantes !!! :D)
Ej: sobre lo que yo mismo expuse...
MOVLW ((4 / 2) * (2 / 2 + 4))
MOVWF AUXA ;aca el reg AUXA toma el valor de .10 (lo que parece esperable y/o correcto...)
Entonces es valido decir, que el registro AUXA, que se encuentra mapeado en la posicion 0x0E (hex) de la memoria RAM (porque yo asi lo declare...) tiene cargado el valor 10 (decimal)...
La respuesta me la dio el REGISTRO DE TRABAJO, es gracias a el, que yo puedo cargar a los registros con los valores que desee...y fijate que sino hubiera prestado atencion debida a tu ejemplo, hubiera seguido con la misma confusion...ya que me decis, que:
MOVLW ((4 / 2) * (2 / 2 + 4)) ;esto es para probar que hacen esos benditos operandos
MOVWF AUXA ;aca el reg AUXA toma el valor de .10 (lo que parece esperable y/o correcto...)
BCF STATUS,C
MOVF AUXA,W
ADDLW 1 + 2
MOVWF AUXA ;es decir el valor de posicion 0E mas 3 = 17
Y esto esta mal, BRUNO...porque cuando moves el AUXA al W (este vale 10), independientemente de que se halle en posicion 0X0E de la RAM (eso es otra cuestion)...entonces ahora W = 10 +1+2 osea 13 y no 17...que era lo que queria...(corregime si me equivoco, por favor !!!)
A mi me daba 17, porque yo hacia:
MOVLW ((4 / 2) * (2 / 2 + 4))
MOVWF AUXA ;aca el reg AUXA toma el valor de .10 (lo que parece esperable y/o correcto...)
BCF STATUS,C
MOVLW (AUXA + 1 + 2) ;aca como cargo literales, W si apunta a 0X0E + 1 + 2 = 17
MOVWF AUXA ;es decir el valor de posicion 0E mas 3 = 17
Porque no pasé el valor previo de AUXA (= 10) a W...entonces ahi si hace lo que decis, reemplaza a AUXA por su posicion de memoria RAM (0X0E) y le suma 3 = 17...
No se si lo explique bien, pero finalmente lo entiendo...a mi me estaba faltando la instruccion MOVLF para solucionarme todo...ahi lo hubiera entendido de primera...voy a mandar una queja a Microchip, esto es una barbaridad !!! :D
Te agradezco el valiosisimo aporte, ya que gracias a el, pude salir de esta maraña...lo que no quiere decir que me desdiga, inmediatamente, ya que todo esto, lo digo a riesgo de equivocarme...pero me cierra bastante mejor de esta forma...Espero que el resto de los foristas, puedan sacar esto en claro...estoy como siempre receptivo a comentarios o acotaciones y/o correciones que deban hacerse, para no confundir a nadie !!!
Tambien me parecio interesante poder usar la posicion address del registro, como valor conocido para otras necesidades de programa...
POR EJ:
movlw auxa+auxa
movwf auxa
Aca cargo a AUXA con 0X0E+0x0E = 0x1C
O BIEN:
movlw porta+portb
movwf auxa
Aca lo cargue con 0x05+0x06 = 0x0B
En fin...asi con todas las variables que quiera y conozca...voy a probar con los BITS de c/registro a ver que pasa...despues te cuento !!!
SALUDOS y gracias por leer !!! :-) :-) :-)
______________________________
"Justo a mi, me toco ser Yo" QUINO
-
Hola. Si efectivamente estaba equivocado...Perdona. Ando a las corridas y no siempre lucido.
Efectivamente, W exíste ya que es imprescindible para poder cargar a los registros con valores o bien interactuar entre dos registros.
Espero que me comentes nuevas experiencias.
Saludos.
-
Gracias BRUNO, esto era lo que venia preguntando desde un principio (entre otras cosas)...ahora viste porque me considero un autodidacto, seguramente esto se explica en el colegio o en la universidad o donde sea que se estudie el manejo de este lenguaje...Yo me tengo que romper el "coco" y hacer mis propias experiencias para darme cuenta de las cosas...valoro enormemente tu colaboracion para lograrlo...Esta cuestion siempre me ha sido criticada por mis amigos, ya que pareceria que siempre estoy reinventando la rueda...
Con el paso de los dias, estoy incorporando nuevas herramientas y conocimientos...mis primeras conclusiones, son que el micro, me va a resultar util, como parte de futuros proyectos, pero nunca como parte fundamental de los mismos...mi vision es que, es una herramienta perfecta para manejar un monton de cuestiones logicas (digitales), lo que me evitara el uso de electronica discreta...esta semana comienzo entonces con algunas ideas, para "versatilizar" algunos modulos de control (que se usan para reconstruccion de imagenes)...
Todavia no se donde podre usar alguna vez una division por 4,5 o por 32 o por 3,8 o una SQR o lo que sea...pero seguro en algun lado se usan...digo esto ultimo, porque, he leido que los estudiantes aprenden sobre esos fundamentos, de divisiones o calculos...En ASM, todo me parece mas claro, mas directo con la electronica...por eso alguna vez comentaba la increible asociacion que se hace entre la ing. electronica y la abstraccion que logran los programadores, para poder aunar recursos interdisciplinarios...Divages, solamente, BRUNO !!!
Esto no implica, que no siga con algunas dudas...supongo algunas se iran despejando con el tiempo y otras habra que preguntar, nomas...espero que nadie se moleste...SALUDOS !!!
PDA: Aca esta la MACRO (instruccion que les pedi a MICROCHIP que incluyan en las 35...se vienen las 36 ??? :D )
MOVLF MACRO VALOR, REGISTRO
MOVLW VALOR
MOVWF REGISTRO
ENDM
movlf 124,auxa
_____________________________
"Justo a mi, me toco ser Yo" QUINO