Autor Tema: error #define del MPASM  (Leído 292 veces)

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

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1863
    • www.ingeniopic.com
error #define del MPASM
« en: 12 de Julio de 2017, 10:59:29 »
hola.ya hace tiempo que se me da una circunstancia que hasta ahora no le di importancia.ya que lo solucionaba poniendo los valores en el programa principal.
me refiero a lo siguiente:

cuando programo en asm.me gusta nombrar al programa principal  con la extension .asm
y a los restantes archivos vinculados al programa.como por ejemplo librerias con la extension .inc

resulta que si defino variables en los .inc   por ejemplo (#define CS   LATC,0)  esta definicion solo la puedo gestionar desde el propio archivo .inc
pero no lo puedo hacer desde el programa principal asm

como podria vincular estos valores para compatibilizar las librerias que creo.con cualquier programa que realize en .asm ?

un saludo.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6040
Re:error #define del MPASM
« Respuesta #1 en: 12 de Julio de 2017, 12:17:07 »
No entiendo cual es el problema.

Si es porque no funciona: Acabo de realizar estos codigos.

un archivo que es el main/librerias:

Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.  
  3.     INCLUDE <p16f84a.inc>
  4.     INCLUDE "test.inc"
  5.  
  6.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  7.    
  8.    
  9.     ORG 0
  10.     GOTO PRINCIPAL
  11.  
  12.     ORG 4
  13.     RETURN
  14.  
  15. PRINCIPAL:
  16.     BSF  TEST
  17.     GOTO PRINCIPAL
  18.    
  19.     END

Y el archivo con el define (test.inc):

Código: ASM
  1. #define TEST PORTA,0
(Es todo lo que posee)

El codigo generado concuerda exactamente


Citar
       Line      Address       Opcode      Label            DisAssy         
       1     000           2805                    GOTO 0x5                 
       2     001           3400                    RETLW 0x0               
       3     002           3400                    RETLW 0x0               
       4     003           3FFF                    ADDLW 0xFF               
       5     004           0008                    RETURN                   
       6     005           1405                    BSF PORTA, 0x0           
       7     006           2805                    GOTO 0x5     


Si tu problema es que tenes que definirlos en multiples archivos la solucion es simple:
Tenes que crear un .inc con todas tus definiciones sobre tu proyecto, y eso lo podes compartir en todos los que quieras.

O tal ves tenes problemas con que se define multiples veces. En tal caso deberas crear un proteccion muy parecido a lo que se usa en C
« Última modificación: 12 de Julio de 2017, 12:26:11 por KILLERJC »

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1863
    • www.ingeniopic.com
Re:error #define del MPASM
« Respuesta #2 en: 12 de Julio de 2017, 16:28:42 »
gracias por responder KILLERJC.lo que yo hago es poner al final del codigo .asm las direcciones de las librerias.asi:

org      I2C_18F
include   "I2C_18F.inc"
org      retardos
include   "retardos.inc"
org      OV7670_18f87k22
include   "OV7670_18f87k22.inc"


y al principio los valores de las direcciones:

#define      I2C_18F                  0X1750   ;
#define      retardos                       0X2100   ;
#define      OV7670_18f87k22       0x2200   ;

no se si esto es correcto hacerlo asi.pero funciona.

el problema que tengo es que en el programa principal. .asm  no puedo usar un #define  de otro archivo .inc   y no se como hacer esas definiciones de forma global.
ya para el uso del codigo principal .asm como entre otros archivos  .inc
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6040
Re:error #define del MPASM
« Respuesta #3 en: 12 de Julio de 2017, 17:00:09 »
La biblia que voy a pasar consta de:
- Quejas mias :P
- Ejemplos para ver las diferencias, prueba y error es lo mejor
- Y tratar de explicar finalmente el porque. Asi si sabes como funciona vas a saber que tenes que hacer.

Esto es en general sobre la programacion ASM y para nada algo que afecte a tu problema:
Noto que los programas en ASM nunca se hacen como se deberian, en realidad no es un problema, es problema de como es que se enseña ASM buscandole lo mas simple para hacerlo funcionar. Y es por esto que usamos CBLOCK para lo que no es, usamos EQU para tambien cosas que no son, como en tu ejemplo te tomas mas trabajo poniendole ORG a cosas que no deberias proecuparte, nos olvidamos completamente del linker, y a esto me refiero a como se linkean los simbolos entre archivos, etc. Pero como ves esto se sigue haciendo porque simplemente funciona xD y nadie quiere meterse con mayores problemas.

Solo para recordar los pasos que sigue cualquier programador = Precompilar - > Compilar -> Linkear

Ahora si con tu problema
El problema que tenes es que cuando incluis un archivo de la forma en que lo estas incluyendo ocurre que el compilador agarra copia todo lo del otro archivo y lo pega en tu archivo principal ANTES de compilarlo (directiva de PREprocesamiento).

Voy a seguir con mi ejemplo anterior, el cual funcionaba:

Si tomamos en cuenta lo que dije, sabemos que el archivo final va a ser algo asi:

Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.    
  5.     #define TEST PORTA,0
  6.  
  7.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  8.    
  9.    
  10.     ORG 0
  11.     GOTO PRINCIPAL
  12.  
  13.     ORG 4
  14.     RETURN
  15.  
  16. PRINCIPAL:
  17.     BSF  TEST
  18.     GOTO PRINCIPAL
  19.    
  20.     END

Es decir donde esta el include es donde va a parar todo lo del otro archivo.
Probemos otro caso..
Esta ves vamos a poner el include abajo, Usemos esto ( test.inc no cambio ):

Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.    
  5.  
  6.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  7.    
  8.    
  9.     ORG 0
  10.     GOTO PRINCIPAL
  11.  
  12.     ORG 4
  13.     RETURN
  14.  
  15. PRINCIPAL:
  16.     BSF  TEST
  17.     GOTO PRINCIPAL
  18.    
  19.     INCLUDE "test.inc"
  20.    
  21.     END

Ocurre que si ahora intentamos compilar vamos a tener algo asi:


Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.    
  5.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  6.    
  7.    
  8.     ORG 0
  9.     GOTO PRINCIPAL
  10.  
  11.     ORG 4
  12.     RETURN
  13.  
  14. PRINCIPAL:
  15.     BSF  TEST          ;Aca linea 16
  16.     GOTO PRINCIPAL
  17.  
  18.     #define TEST PORTA,0
  19.    
  20.     END

Y tambien un hermoso error diciendo:

Citar
Error[113]   /home/fabian/workspace/MPLAB/PIC16asm.X/main.asm 16 : Symbol not previously defined (TEST)
Error[128]   /home/fabian/workspace/MPLAB/PIC16asm.X/main.asm 16 : Missing argument(s)

Por supuesto, si lo que estamos intentando usar todavia no fue definido. La definicion se encuentra ABAJO, y el compilador (ojo el compilador es) se queja de que cuando llego a BSF TEST eso no existe!

-------------------------------------------------------------------------------------------------------------------------------------------
Subrutinas
Esto para una subrutina no es problema, ¿ por que no ?
Cambiemos nuestros archivos para probarlo:

main.asm
Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.    
  5.  
  6.    
  7.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  8.    
  9.    
  10.     ORG 0
  11.     GOTO PRINCIPAL
  12.  
  13.     ORG 4
  14.     RETURN
  15.  
  16. PRINCIPAL:
  17.     CALL TEST
  18.     GOTO PRINCIPAL
  19.    
  20.     INCLUDE "test.inc"
  21.    
  22.     END

test.inc
Código: ASM
  1. TEST
  2.     BSF PORTA,0
  3.     RETURN

Rapidamente vemos que ya hay algo raro, como podemos usar PORTA en test.inc si nunca incluimos el .inc del microprocesador alli. Es decir no estaria definido, pero si pensamos que el include es copiar y pegar todo tiene sentido. Esto se realiza antes de la compilacion, entonces al momento de compilar se encuentra con este codigo

Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.    
  5.  
  6.    
  7.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  8.    
  9.    
  10.     ORG 0
  11.     GOTO PRINCIPAL
  12.  
  13.     ORG 4
  14.     RETURN
  15.  
  16. PRINCIPAL:
  17.     CALL TEST
  18.     GOTO PRINCIPAL
  19.    
  20. TEST
  21.     BSF PORTA,0
  22.     RETURN
  23.    
  24.     END

Lo cual es totalmente valido. Dejo el codigo como se ubica en la memoria:

Citar
       Line      Address       Opcode      Label            DisAssy         
       1     000           2805                    GOTO 0x5                 
       2     001           3400                    RETLW 0x0               
       3     002           3400                    RETLW 0x0               
       4     003           3FFF                    ADDLW 0xFF               
       5     004           0008                    RETURN                   
       6     005           2007                    CALL 0x7                 
       7     006           2805                    GOTO 0x5                 
       8     007           1405                    BSF PORTA, 0x0           
       9     008           0008                    RETURN   

¿ Que ocurre si lo pongo al principio ?
Tengo varios lados donde ponerlo obviamente. Uno es aca:

Código: ASM
  1. LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.      INCLUDE "test.inc"  
  5.    
  6.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  7.    
  8.     ORG 0
  9.     GOTO PRINCIPAL
  10.  

Tenemos los siguientes errores:

Citar
Error[150]   /home/fabian/workspace/MPLAB/PIC16asm.X/test.inc 4 : Labels must be defined in a code or data section when making an object file
Error[152]   /home/fabian/workspace/MPLAB/PIC16asm.X/test.inc 5 : Executable code and data must be defined in an appropriate section
Error[152]   /home/fabian/workspace/MPLAB/PIC16asm.X/test.inc 6 : Executable code and data must be defined in an appropriate section

Y es justamente el problema que tenemos, resulta que ahora estamos intentando poner codigo en un lugar que no esta definido como codigo ni datos. Antes era una directiva de preprocesamiento por lo cual no ocupa espacio y no necesita estar en esos lugares. Una solucion seria ponerlo luego de los vectores de Reset e Interrupcion,

Es decir aca:

Código: ASM
  1.     ORG 0
  2.     GOTO PRINCIPAL
  3.  
  4.     ORG 4
  5.     RETURN
  6.  
  7.     INCLUDE "test.inc"  
  8.    
  9. PRINCIPAL:
  10.     CALL TEST
  11.     GOTO PRINCIPAL

GENIAL! ahora si compilo correctamente, y si vemos como quedo en nuestra memoria, veremos que el codigo se encuentra donde pusimos nuestro include:

Citar
       Line      Address       Opcode      Label            DisAssy         
       1     000           2807                    GOTO 0x7                 
       2     001           3400                    RETLW 0x0               
       3     002           3400                    RETLW 0x0               
       4     003           3FFF                    ADDLW 0xFF               
       5     004           0008                    RETURN                   
       6     005           1405                    BSF PORTA, 0x0           
       7     006           0008                    RETURN                   
       8     007           2005                    CALL 0x5                 
       9     008           2807                    GOTO 0x7
« Última modificación: 12 de Julio de 2017, 18:15:30 por KILLERJC »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6040
Re:error #define del MPASM
« Respuesta #4 en: 12 de Julio de 2017, 17:52:29 »
Otra prueba de que el include utilizado de esta forma es un simple copy/paste es que si observamos la consola al momento de programar tenemos que:

Citar
make[2]: Entering directory '/home/fabian/workspace/MPLAB/PIC16asm.X'
"/opt/microchip/mplabx/v3.26/mpasmx/mpasmx" -q -p16f84a -u -l\"build/default/production/main.lst\" -e\"build/default/production/main.err\" -o\"build/default/production/main.o\" \"main.asm\"
"/opt/microchip/mplabx/v3.26/mpasmx/mplink"    -p16f84a  -w  -m"dist/default/production/PIC16asm.X.production.map"   -z__MPLAB_BUILD=1  -odist/default/production/PIC16asm.X.production.cof  build/default/production/main.o

Hay 2 lineas, primero el compilador y luego el linker, pero si observamos UNICAMENTE es el main.asm el cual se compila, el test.inc no. Si fueran realmente 2 archivos separados tendrias el compilado de ambos archivos y luego el link de ambos.

¿ A que quiero llegar con todo esto ?

Lo mas importante que nos estamos olvidando es el LINKER.

¿ Por que las subrutinas funcionan si las pongo antes o despues  de igual forma, pero no las directivas de preprocesamiento?

Pensemos un poco en el proceso que implica crear el .hex final.

- Primero el compilador va a resolver todas las directivas de "preprocesamiento", es decir va a incluir los archivos, reemplazar todos los define con el valor que le corresponde
- Luego va a compilar el archivo, compilar en este caso va a ser revisar que no exista ningun error. No va a asignar espacios de memoria, ni los CALL le va a poner el valor que debe, tambien va a generar los simbolos para que el linker luego haga su trabajo, su salida es masomenos esto:

Citar
                      00001     LIST P=16F84A , r=DEC
                      00002     ;RADIX DEC
                      00003     INCLUDE <p16f84a.inc>
                      00001         LIST
                      00002
                      00003 ;==========================================================================
                      00004 ; Build date : Feb 01 2016
                      00005 ;  MPASM PIC16F84A processor include
                      00006 ;
                      00007 ;  (c) Copyright 1999-2016 Microchip Technology, All rights reserved
                      00008 ;==========================================================================
                      00009
                      00209         LIST
                      00004     
2007   3FFD           00005     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
                      00006     
                      00007     
0000                  00008     ORG 0
0000   2807           00009     GOTO PRINCIPAL
                      00010
0004                  00011     ORG 4
0004   0008           00012     RETURN
                      00013
                      00014     INCLUDE "test.inc"   
                      00001
                      00002
                      00003
0005                  00004 TEST
0005   1405           00005     BSF PORTA,0
0006   0008           00006     RETURN
                      00015     
0007                  00016 PRINCIPAL:
0007   2005           00017     CALL TEST
0008   2807           00018     GOTO PRINCIPAL
                      00019     
                      00020     END

....................

SYMBOL TABLE
  LABEL                             VALUE

TEST                              00000005

Hay mucho mas simbolos pero solo muestro el de interes.
........................

- Y recien lo va a agarrar el linker quien es el encargado de tomar estos simbolos y darle ubicacion dentro del archivo, Aca es donde el TEST del CALL va a ser cambiado por el valor 0x0005.


Entonces retomando los ejemplos:

En el caso del define:
Es algo que realiza antes de compilarse, y debe estar definido al comienzo del archivo donde vayas a incluir todo ( tu main.asm), como son solo defines en tu .inc lo podes poner debajo del .inc del micro, ahora el compilador antes de compilar va a incluir esos archivos (copiar/pegar) y luego reemplazar lo que pongas en el #define

En el caso de la subrutina:
Como ves funciona si lo pongo atras o adelante, no hay problema siempre y cuando este es una zona donde sea codigo.
Esto es porque el compilador solo va a generar los simbolos, y el encargado de unir luego todo es el linker, por lo cual no se va a preocupar si esta adelante o detras.


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

Por ultimo te dejo un ejemplo mas y vamos a retomar el proceso desde 0

Archivos originales:

main.asm
Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.    
  5.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  6.    
  7.     #define TEST PORTA,0
  8.    
  9.     ORG 0
  10.     GOTO PRINCIPAL
  11.  
  12.     ORG 4
  13.     RETURN
  14.    
  15. PRINCIPAL:
  16.     INCLUDE "test.inc"      
  17.     GOTO PRINCIPAL
  18.    
  19.     END

test.inc
Código: ASM
  1.     BSF TEST

Paso 1 (includes):

Código: ASM
  1.     ; Aca todos los EQU del .inc
  2.    
  3.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  4.    
  5.     #define TEST PORTA,0
  6.    
  7.     ORG 0
  8.     GOTO PRINCIPAL
  9.  
  10.     ORG 4
  11.     RETURN
  12.    
  13. PRINCIPAL:
  14.     BSF TEST    
  15.     GOTO PRINCIPAL
  16.    
  17.     END

Paso 2 (define):

Código: ASM
  1.     ;Aca todos los EQU del .inc del micro
  2.    
  3.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  4.    
  5.     ORG 0
  6.     GOTO PRINCIPAL
  7.  
  8.     ORG 4
  9.     RETURN
  10.    
  11. PRINCIPAL:
  12.     BSF PORTA,0
  13.     GOTO PRINCIPAL
  14.    
  15.     END

Paso 3 (Compilar) y generar Simbolos
Se genera las direcciones gracias a los ORG, direcciones que todavia NO tienen un lugar en memoria, se crean las instrucciones, pero todo lo referente a donde va a ubicarse en la memoria del micro todavia NO esta dicho.

Paso 4 (Linkeo)
Aca finalmente es donde el GOTO toma la direccion de memoria del BSF, y procede a intentar acomodar esas funciones segun la memoria del micro ( dada por el archivo del linker ) y lo que le dio el compilador.


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

Resumen:

Hace algo asi:

main.asm
Código: ASM
  1.     LIST P=16F84A , r=DEC
  2.     ;RADIX DEC
  3.     INCLUDE <p16f84a.inc>
  4.     INCLUDE <placadef.inc>
  5.    
  6.     __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _XT_OSC
  7.    
  8.     ORG 0
  9.     GOTO PRINCIPAL
  10.  
  11.     ORG 4
  12.     RETURN
  13.    
  14. PRINCIPAL:
  15.    
  16.     GOTO PRINCIPAL
  17.    
  18.     ;Aca pone todas tus librerias
  19.    
  20.     END

Donde placadef.inc tendria unicamente todos los #define / EQU que te sirvan para todas las librerias.
Esto te va a permitir que puedas cambiar todo desde un solo punto.
« Última modificación: 12 de Julio de 2017, 18:05:44 por KILLERJC »

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1863
    • www.ingeniopic.com
Re:error #define del MPASM
« Respuesta #5 en: 13 de Julio de 2017, 11:06:33 »
gracias por tu extensa explicacion.yo lo que he aprendido de asm.ha sido de ejemplos en este foro y otros sitios
de intenet.no he hecho ningun curso y por eso igual cometo errores aunque finalmente funcione el programa.

le he hechado un buen vistazo a todo.y creo haber entendido lo que dices.

si en un archivo .inc ponemos  #define TEST PORTA,0 . cuando pongamos una linea en el codigo nombrando
TEST. esto es como poner PORTA,0

y podemos poner BSF   TEST.

aunque tambien podemos poner #define TEST BSF PORTA,0 y tambien funcionaria.

y solo tendriamos que poner TEST para que realizara la misma funcion.aunque claro,un poco mas restrisctiva respecto
a nuestras opciones con TEST.ya que solo podriapos poner a uno este bit.

esto de arriva habria que tratarlo como instrucciones del ensamblador.


otra cosa seria esto:

#define     WREN_REG  0x06

donde no se esta definiendo ningun registro ni es una instruccion.aqui asignamos un valor a una etiqueta.
y es gestionado directamente por el compilador.y deberia situarse debajo del INCLUDE <p16f84a.inc>
por ejemplo.

esta etiqueta podria usarse de la siguiente manera:

movlw   WREN_REG  para cargar el valor 0x06 en el acumulador o

movff   WREN_REG,PORTA   para cargar el valor 0x06 en PORTA. (instrucciones del 18Fxxxx)

el problema que yo veo en todo esto de situar los include en diversos sitios es que cuando cree una libreria
habria que realizar un .inc solo para este tipo de instrucciones.y si uso varias librerias tendria
que cojer datos de todas estas librerias para crear un archivo para el programa principal.

supongo que esto es asi.si hubiera una forma de entrelazar este tipo de definiciones de forma global.como se hace en C
y que la definicion no fuera exclusivo de cada archivo.nos ahorrariamos este tipo de inconpatibilidades y errores.


Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6040
Re:error #define del MPASM
« Respuesta #6 en: 13 de Julio de 2017, 14:12:15 »
Citar
gracias por tu extensa explicacion.yo lo que he aprendido de asm.ha sido de ejemplos en este foro y otros sitios
de intenet.no he hecho ningun curso y por eso igual cometo errores aunque finalmente funcione el programa.

Yo tambien aprendi asi, y a dodne vayas te enseñan asi. Fue cuando comence con C e intentar entender que es lo que hacia C cuando vi que en ASM se puede hacer todo por igual.
Nomas que nadie en ningun lado lo uso, tuve que aprender por mi mismo con el manual del MPASM/Linker al lado. Y jugando con el compilador.

Citar
el problema que yo veo en todo esto de situar los include en diversos sitios es que cuando cree una libreria
habria que realizar un .inc solo para este tipo de instrucciones.y si uso varias librerias tendria
que cojer datos de todas estas librerias para crear un archivo para el programa principal.

supongo que esto es asi.si hubiera una forma de entrelazar este tipo de definiciones de forma global.como se hace en C
y que la definicion no fuera exclusivo de cada archivo.nos ahorrariamos este tipo de inconpatibilidades y errores.

Todo lo que explicaste antes de este parrafo que quotee es correcto. Tu problema esta en que cosas debes poner en el .inc para que sea correcto. En realidad lo que pienso que falla es la forma de estructurar tu programa, algo que en C ocurre de forma mas normal y no lo vemos aplicado al ASM.
En C las definiciones se ubican generalmente en un .h ( equivalente a tu .inc ) en las cuales se incluyen en cada archivo que se necesiten esas definiciones. Es decir, estas definiciones NO son globales como decis, tenes la obligacion de usar el include de ese .h en cada archivo que quieras usar los defines que tenes en ese .h.

Si queres hago una analogia de lo que seria en C (si te manejas con C obviamente), y lo que seria en ASM, para que veas que realmente SI se puede usar lo que vos queres hacer y que es equivalente. Y si me das un ejemplo en el que estes trabajando seria aun mejor para hacerte lograr verlo de forma mas aplicada a lo que estes intentando hacer.
Sino explicame un poco mas cual es tu problema o como quisieras que fuera tu programa e intento realizarlo.

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1863
    • www.ingeniopic.com
Re:error #define del MPASM
« Respuesta #7 en: 14 de Julio de 2017, 11:27:52 »
pues tienes razon en lo de que asm puede ser estructurado como C.yo no se programar en C para pic.lo mas parecido a C es JAVA y lo uso para programar android.
aunque son lenguajes muy parecidos.y su estructuracion creo que es la misma.desde que programo en java.intento estructurar asm de casi la misma forma.
pero hay muchas cosas que desconozco del MPASM.

voy a intentar hacer lo que dices.no pongo el programa aqui porque esta muy sucio.en cuanto lo limpie lo subo aqui.

aunque quiero preguntarte algo.como te dije antes.yo les pongo a los archivos .inc  un ORG para indicar al compilador donde quiero poner el codigo en memoria.
pero si ese archivo .inc tiene dentro unas tablas que hay que especificar el inicio de estas.no seria un problema al darle al compilador la opcion de que
pongan nuestros archivos inc.sin especificar una direccion?

aunque supongo que lo que habria que hacer es poner las tablas lo mas alejadas posible del codigo principal para que hallan errores.

Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6040
Re:error #define del MPASM
« Respuesta #8 en: 14 de Julio de 2017, 11:56:10 »
voy a intentar hacer lo que dices.no pongo el programa aqui porque esta muy sucio.en cuanto lo limpie lo subo aqui.

No te pedia todo el programa, sino algun programa simple recortado, en que tengas variables, tablas y donde ocurra el problema que comentas.
Es decir un minimo, por mas que no haga nada, pero que te de el error.

aunque quiero preguntarte algo.como te dije antes.yo les pongo a los archivos .inc  un ORG para indicar al compilador donde quiero poner el codigo en memoria.
pero si ese archivo .inc tiene dentro unas tablas que hay que especificar el inicio de estas.no seria un problema al darle al compilador la opcion de que
pongan nuestros archivos inc.sin especificar una direccion?

aunque supongo que lo que habria que hacer es poner las tablas lo mas alejadas posible del codigo principal para que hallan errores.

Las tablas por comodidad siempre lo hacemos con un solo ADDWF, RETLW y listo. Lo cual nos obliga que si o si la tabla se encuentre en un inicio de direccion es decir xxx00, sino el comportamiento puede ser inadecuado. Este problema hace que debas usar esos ORG extras.
El RETLW se usa para crear tablas en aquellos micros que no pueden leer la FLASH. En micros que SI pueden leer la flash, es mejor poner directamente el dato y no la instruccion RETLW.

- Si usas PIC16 que NO permite lectura de la FLASH: el asunto es arreglar la tabla y empezar a usar el PCLATH como se debe, precalcular si con el offset se supera la pagina, si ocurre incrementar PCLATH del valor que posee la direccion de nuestro ADDWF, esto con pagesel.
- Si usas PIC16 que permite lectura de la FLASH: Empezar a guardar los datos en la FLASH y usar los registros correspondientes, que seguramente sean los de la EEPROM, o algunos ya posee el uso de los direccionamiento indirectos FSR para acceder a la flash.
- Si usas PIC18: Empezar a guardar los datos en la FLASH y usar los registros correspondientes ( TBLPTRx ), asi como sus instrucciones.


Voy a suponer que usas PIC18, debido a que tus librerias dicen "18F"
Para leer la direccion de una etiqueta se usa high/low/upper. Ejemplo si tenemos una tabla ubicada en FLASH (TABLA_1 ) y queremos acceder a esta, en un PIC18 deberiamos cargar los registros TBLPTRx con esos valores

Código: ASM
  1. TABLA_1 data "Este texto en flash", 0x00    ; El 0x00 para indicar el final
  2.  
  3.     MOVLW low TABLA_1
  4.     MOVWF TBLPTRL
  5.     MOVLW high TABLA_1
  6.     MOVWF TBLPTRH
  7.     MOVLW upper TABLA_1
  8.     MOVWF TBLPTRU
  9.  
  10.     TBLRD*+    ;Leo el primer valor e incremento los registros TBLPTRx ( solo llevan el carry)
  11.     MOVWF TABLAT    ; Resultado en TABLAT
(Este ejemplo no lo probe, solamente lo hice de memoria)

Y ahi accedemos a la tabla, o si tiene un offset operamos sobre los registros TBLPTRx.
Observa que al estar en la Flash, tengo 3 registros que me permiten direccionarla toda y no preocuparme para nada mas sobre donde se ubican las tablas.
« Última modificación: 14 de Julio de 2017, 12:07:35 por KILLERJC »

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1863
    • www.ingeniopic.com
Re:error #define del MPASM
« Respuesta #9 en: 15 de Julio de 2017, 06:54:33 »
hola KILLERJC.esta es la cabecera de mi programa.tengo que modificar algunas cosas.pero en principio comienzo asi.

Código: [Seleccionar]
;*************************************************www.ingeniopic.com*******************************************************
; PROGRAMA : CamaraOV7670
; Funcion :  Control de la camara OV7670 
;           
;   
;  Revision : 1.0        10/1/2015            Programa para : PIC18F87K22
; CPU Clock : 64 MHz                     Reloj instruccion :6.25ns
;       WDT : Deshabilitado                  Tipo de reloj : INTOSC
; Code Prot : OFF            Crystal:
;*****************************************************www.ingeniopic.com***************************************************


;FUNCIONAMIENTO:
;
;

;Pins utilizados:
;PORTC,3=pin44 SCL1 ;para I2C
;PORTC,4=pin45 SDA1 ;para I2C
;PORTC,5=pin46 ;reset de la OV7670
;PORTC,6=pin37 TX1 ;eusart1 (poner resistencia serie de 1k)
;PORTJ,7=pin42 ;conexion a WRST de la FIFO
;PORTJ,6=pin41 ;conexion a RRST de la FIFO
;PORTJ,5=pin40 ;conexion a Vsync de la camara
;PORTJ,4=pin39 ;conexion a WR = WE o WEN del AL422
;PORTJ,3=pin59 ;conexion a OE del AL422
;PORTJ,2=pin60 ;conexion a RCK del AL422
;PORT3,3=pin77 ;conexion a XCLK de la camara
;PORTH ;puerto de entrada para el bufer de la FIFO.

;PORTE,0=pin4 ;RS  de la TFT ILI9325
;PORTE,1=pin3 ;CS  de la TFT ILI9325
;PORTE,4=pin76 ;WR  de la TFT ILI9325
;PORTE,5=pin75 ;RD  de la TFT ILI9325
;PORTE,6=pin74 ;RST de la TFT ILI9325


LIST   P=PIC18F87K22   ;Se indica el modo de procesador


     #INCLUDE   <P18F87K22.inc>

     
     
     
     
     
     

      RADIX   HEX      ;Sistema de numeracion hexadecimal

       
CONFIG    RETEN=OFF ; VREG Sleep Disable bit:
            CONFIG    INTOSCSEL=LOW ; LF-INTOSC Low-power Enable bit:
CONFIG    SOSCSEL=DIG ; SOSC Power Selection and mode Configuration bits:
            CONFIG    XINST=OFF ; Extended Instruction Set:
          CONFIG    FOSC=INTIO2;INTIO1 ; Oscillator RC interno con funcion 1/4 Fosc en OSC2 (pin RA6)
            CONFIG    PLLCFG=ON ; PLL x4 Enable bit:
            CONFIG    FCMEN=OFF ; Fail-Safe Clock Monitor:
            CONFIG    IESO=OFF ; Internal External Oscillator Switch Over Mode:
            CONFIG    PWRTEN=OFF ; Power-up Timer:
            CONFIG    BOREN=OFF ; Brown-out Detect:
            CONFIG    BORV=1;3 ; Brown-out Reset Voltage bits:
            CONFIG    BORPWR=LOW ; BORMV Power level:
            CONFIG    WDTEN=OFF;ON ; Watchdog Timer:
            CONFIG    WDTPS=1024 ; Watchdog Postscaler:
            CONFIG    MSSPMSK=MSK7 ; MSSP address masking:
        CONFIG    MCLRE=ON ; Master Clear Enable:
            CONFIG    STVREN=ON ; Stack Overflow Reset:
            CONFIG    BBSIZ=BB1K ; Boot Block Size:
CONFIG   CCP2MX=PORTC
CONFIG   DEBUG = OFF

ERRORLEVEL      -302


CBLOCK    0x070A ;comienza el bloque de ram

CONT_FIFO1
CONT_FIFO2
CONT_FIFO3

IMPAR

ENDC


OV7670_VAR EQU 0x000
RETARDOS_VAR EQU 0X700 ;variables de la libreria "retardos.inc" hubicados en una zona de memoria accedida desde todos los bancos
;ILI9340_VAR EQU 0X750
ILI_TFT_VAR EQU 0X750
SPI_VAR EQU 0X760





;***************Bit Definitions****************************************
#define BANK0 movlb 0x00
#define BANK1 movlb 0x01
#define BANK2 movlb 0x02
#define BANK3 movlb 0x03
#define BANK4 movlb 0x04
#define BANK5 movlb 0x05
#define BANK6 movlb 0x06
#define BANK7 movlb 0x07
#define BANK8 movlb 0x08
#define BANK9 movlb 0x09
#define BANK10 movlb 0x0A
#define BANK11 movlb 0x0B
#define BANK12 movlb 0x0C
#define BANK13 movlb 0x0D
#define BANK14 movlb 0x0E
#define BANK15 movlb 0x0F

#define GENERAL_BANK movlb 0x07 ;banco de trabajo general

#define GIE_HI_ON bsf INTCON,GIE;;;;;;;;;;;;;;;;;;;;;bsf
#define GIE_HI_OFF bcf INTCON,GIE
#define GIE_LO_ON bsf INTCON,PEIE;;;;;;;;;;;;;;;;;;;;;bsf
#define GIE_LO_OFF bcf INTCON,PEIE

#define I2C_18F     0X1750 ;direccion donde hubicaremos las rutinas de temporizacion
#define retardos     0X2100 ;direccion donde hubicaremos las rutinas de temporizacion
#define OV7670_18f87k22     0x2200 ;rutinas de la camara OV7670
#define Eusart     0x2500 ;rutinas de la Usart
#define ILI9341     0x2600 ;rutinas de la TFT
#define SPI_18f     0x2900 ;


;#define ID_WRITE    movlw 0xD0 ;valor de direccion para escritura del DS1307
;#define ID_READ movlw 0xD1 ;valor de direccion para lectura del DS1307
;#define ID_WRITE    movlw 0x42 ;valor de direccion para escritura del OV7670
;#define ID_READ movlw 0x43 ;valor de direccion para lectura del OV7670
;#define ID_WRITE    movlw 0xA0 ;valor de direccion para escritura del 24c16
;#define ID_READ movlw 0xA1 ;valor de direccion para lectura del 24c16

#define CS_ON_OV7670 bsf LATC,5
#define CS_OFF_OV7670 bcf LATC,5

;referente a AL422
#define WRST_HI bsf LATJ,7
#define WRST_LO bcf LATJ,7
#define RRST_HI bsf LATJ,6
#define RRST_LO bcf LATJ,6
#define WEN_HI bsf LATJ,4
#define WEN_LO bcf LATJ,4
#define RCLK_HI bsf LATJ,2
#define RCLK_LO bcf LATJ,2
#define OE_HI bsf LATJ,3
#define OE_LO bcf LATJ,3



;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
          ORG    0x00      ;Inicio en el Vector de Reset
  goto   INICIO      ;ir a la primera instruccion del programa
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES ALTA PRIORIDAD ---------------->>>>>>>>>>
ORG 0X08
goto INTERRUP_HI
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES BAJA PRIORIDAD ---------------->>>>>>>>>>
ORG 0X18
goto INTERRUP_LO

ORG 0X0020

include "I2C_18F.inc"
include "retardos.inc"
include "OV7670_18f87k22.inc"
include "Eusart.inc"
include "ILI9341.inc"
include "SPI_18f.inc"
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO    BANK15 ;conmuta banco 15.por si se usan rgistros por debajo de 0x760.ya que no pueden accederse sin conmutacion.
;Configura oscilador interno
movlw b'01110000' ; 16 mhz clock,HF INTOSC
movwf OSCCON ; Oscon calibrado, ahora...
btfss OSCCON,HFIOFS ; El oscilador se ha estabilizado?
bra $-2 ; si no esta estabilizado,espera
nop ; NOP para terminar de estabilizar el reloj
btfss RCON,POR ; espera a que se estabilice la alimentacion.
bra $+2
movlw .27
call retardo_ms ; retardo de 10 ms para que se estabilize la fuente de alimentación...
movlw b'01000000' ; activa PLL para trabajar a 64Mhz
movwf OSCTUNE ;

;Configura PORTA
clrf PORTA ;inicializa PORTA
clrf LATA ;inicializa LATA
movlw b'00001111' ;PA0,PA1,PA2 y PA3 como entradas
movwf TRISA
movlw b'00001111' ;AN0,AN1,AN2 y AN3 como entradas analogicas
movwf ANCON0,ACCESS


;Configura PORTB
clrf PORTB ;inicializa PORTB
clrf LATB ;inicializa LATB
clrf TRISB ;PORTB como salidas

;Configura PORTC
clrf PORTC ;inicializa PORTC
clrf LATC ;inicializa LATC
setf TRISC ;PORTC como entradas

;Configura PORTD
clrf PORTD ;inicializa PORTD
clrf LATD ;inicializa LATD
setf TRISD ;PORTD como entradas
;movlw b'00000010' ;T5CKI como entrada.para señal de RPM
;movwf TRISD
;bsf PADCFG1,RDPU ;activa resistencias pull-up para el puerto D
;bsf PADCFG1,REPU ;activa resistencias pull-up para el puerto E

;Configura PORTH
clrf PORTH ;inicializa PORTH
clrf LATH ;inicializa LATH
movlw 0x0f
movwf ANCON2 ;I/O digitales
movlw 0x0f
movwf ANCON1 ;I/O digitales
setf TRISH ;PORTH como entradas



;Configura PORTJ
clrf PORTJ ;inicializa PORTJ
clrf LATJ ;inicializa LATJ
movlw b'11111110'
movwf TRISJ ;configura PORTJ

CLRF ADCON0
CLRF ADCON1
;tmr0
movlw b'11000000'
movwf T0CON




;asociado con las interrupciones
; movlw b'00100000'
; movwf INTCON ;habilita interrupciones por desbordamiento de TMR0
bsf RCON,IPEN ;activar interrupciones con prioridad
movlw b'01110000' ;activa pull-up del PORTB,TMR0 con interrupciones baja prioridad,
movwf INTCON2
clrf IPR1 ;prioridades de Interrupcion baja
clrf IPR2 ;prioridades de Interrupcion baja
clrf IPR3 ;prioridades de Interrupcion baja
clrf IPR4 ;prioridades de Interrupcion baja
clrf IPR5 ;prioridades de Interrupcion baja
; clrf IPR6 ;prioridades de Interrupcion baja




;inicializa modulos internos
call EUSART1_INI
;call I2C1_INI
;call OV7670_INI
call SPI1_INI
call ILI_TFT_INI


GIE_LO_OFF
GIE_HI_OFF



;BSF PADCFG1,RDPU
;BSF PADCFG1,RJPU
;<<<<<<<<-------------------------------ENVIO DE DATOS--------------------------->>>>>>>>>>>>>>
PRINCIPAL ;call ILI_TFT_INI
BANK7

he puesto los define donde dijistes y ya no me salen los errores que me salian.incluso me funcionan estas lineas que antes no funcionaban.

Código: [Seleccionar]
movlw UPPER(TFT_CONF_9341)
movwf TBLPTRU
movlw HIGH(TFT_CONF_9341)
movwf TBLPTRH
movlw LOW(TFT_CONF_9341)
movwf TBLPTRL

pero no me ha hecho falta poner los define que definian los valores al principio del programa antes del primer ORG 0x20

valores como estos:

#define      TFT_CONF_9341       0X00A000  ;direccion de hubicacion de tabla
#define      POS_PIXEL_DATA       0X00A100  ;direccion de hubicacion de tabla

#define     WREN_REG  0x06                 ;write enable latch
      #define     WRDI_REG  0x04                 ;reset the write enable latch
      #define     RDSR_REG  0x05                 ;read status register
      #define     WRSR_REG  0x01                 ;write status register
      #define     READ_REG  0x03                 ;read data from memory
      #define     WRITE_REG 0x02                 ;write data to memory
      #define     RDID_REG  0x85

que no son intrucciones.

si ves algo en mi forma de programar te agradeceria me lo comentaras.quiero llevar a buen puerto las artes del buen programador. :D
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6040
Re:error #define del MPASM
« Respuesta #10 en: 15 de Julio de 2017, 12:10:21 »
Pero esta genial groundman, no le veo ningun problema a tu codigo. Si quisieras dismuir la cabecera de tu codigo, podrias trasladar la definiciones por ejemplo de los pines a un .inc que sea especifico a la placa que estas haciendo, y lo pones debajo del .inc del pic,

Al menos yo cambiaria una sola cosa, por comodidad y rapidez. Y es la ubicacion de las memorias. Aunque tal ves lo estes haciendo, pero como no veo el codigo de las librerias te lo digo por las dudas.

Código: ASM
  1. OV7670_VAR              EQU     0x000          
  2. RETARDOS_VAR            EQU     0X700           ;variables de la libreria "retardos.inc"        hubicados en una zona de memoria accedida desde todos los bancos
  3. ;ILI9340_VAR            EQU     0X750
  4. ILI_TFT_VAR             EQU     0X750
  5. SPI_VAR                 EQU     0X760  

A algo mas asi:

Código: ASM
  1. RETARDOS_VAR            EQU     0X000           ;variables de la libreria "retardos.inc"        hubicados en una zona de memoria accedida desde todos los bancos
  2. ILI_TFT_VAR             EQU     0X020
  3. SPI_VAR                 EQU     0X030  
  4. OV7670_VAR              EQU     0x700

E intentar que RETARDOS, ILI y SPI VAR esten todos contenidos en las direcciones desde 0x00 a 0x5F. ( Los retardos no necesitan tantos lugares, ya que puede reutilizarse los registros

De esa forma no tenes que estar cambiando de bancos. Ya que de 0x00 a 0x5F funciona lo que es ACCESS RAM que al indicarle esto en esas direcciones accede al banco0 y superiores accede a los SFR, En el momento que quieras utilizar algo del OV7670, simplemente utilizas BANKED para os registros "generales", y si usas un buffer te vas por el uso de FSR en el cual no tenes que preocuparte por el banco que estas.
Omitir ACCESS o BANKED es lo mismo que sea ACCESS ( por eso podes hacer CLRF LATD ), la sentencia completa seria CLRF LATD, ACCESS

Ejemplo con la memoria como te dije supongamos que tenemos los siguientes registros definidos (1 de cada uno solo para mostrar):
RETARDOS_VAR -> RET0 (0x10)
ILI_TFT_VAR -> TFT_ORIENTATION (0x22)
SPI_VAR -> SPI_DATA (0x38)
OV7670_VAR -> OV_CONFIG0 (0x705)

Y quiero ponerle los valores 0x00, 0x20, 0x40 y 0x88 respectivamente, el codigo me quedaria asi:

Código: ASM
  1.     MOVLB 0x7                                        ; Banco 7 para cuando use BANKED
  2.     CLRF RET0, ACCESS                           ; Como esta en direcciones menores a 0x05F con ACCESS accedo directamente, al banco 0, por mas que seleccione el banco 7 antes
  3.     MOVLW 0x20
  4.     MOVWF TFT_ORIENTATION, ACCESS   ; El mismo caso que antes
  5.     MOVLW 0x40
  6.     MOVWF SPI_VAR, ACCESS                  ; El mismo caso que antes
  7.     MOVLW 0x88
  8.     MOVWF OV_CONFIG0, BANKED           ; Al usar BANKED le estoy diciendo que use el banco que le dije.

Se puede omitir los ACCESS, ya que por default se trata de esta forma para compatibilidad de codigo con los PIC16.
Podes estar direccionando a 3 lugares si usas un FSR y no moverte de bancos para nada. Todo depende obviamente de la aplicacion que estes realizando, pero seamos realistas, hay que tener 95 variables unicas en el espacio ACCESS + 256 unicas en un banco, y muchas que se pueden reutilizar. Sin tocar los bancos tenes al alcance 351 registros, Luego tenes el FSR para buffers.
Si ubicas los registros que usas "siempre" dentro del rango 0x00 a 0x5F, ubicas los registros del OV por ejemplo en algun banco solo y no varios bancos.
Y si usas el FSR para algun buffer ( que creo que algunos PIC18F poseen 2 FSR ) podrias direccionar hasta 4 lados sin siquiera moverte de bancos.

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

Una cosa mas donde tenés esto?
Código: ASM
  1. .   movlw       UPPER(TFT_CONF_9341)
  2.                         movwf   TBLPTRU
  3.                         movlw   HIGH(TFT_CONF_9341)
  4.                         movwf   TBLPTRH
  5.                         movlw   LOW(TFT_CONF_9341)
  6.                         movwf   TBLPTRL

Ya que lo único que deberías tener en tu main.asm son calls y nada correspondiente a como se maneje internamente la librería.
Por lo que las definiciones de las librerias serian unicamente de las librerias.
« Última modificación: 16 de Julio de 2017, 11:01:35 por KILLERJC »

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1863
    • www.ingeniopic.com
Re:error #define del MPASM
« Respuesta #11 en: 18 de Julio de 2017, 11:18:20 »
hola KILLERJC.

el asunto del accesss y banked hace tiempo que lo uso.es muy buena opcion para no estar cambiando de banco
constantemente.lo malo es que no quiero abusar de su uso por su limitada cantidad de registros que contiene.
para los retardos es la mejor opcion.sobretodo si usamos interrupciones.

pero si realizamos un codigo bien depurado.aveces podemos evitar el estar conmutando bancos.y ademas usar
cualquier zona de memoria sin estas conmutaciones.

y esto lo hago usando la intruccion movff REG,REG

en estos pic tienen la mejora de que el acumulador esta implementado en los registros de proposito general.

por ejemplo:

movf   REG1,w
movwf   REG2

es lo mismo que:

movff   REG1,REG2 o si queremos pasar el contenido del acumulador.  movff   WREG,REG2 o movff   REG2,WREG

y sin tener en cuenta en que banco estamos.

aunque no todas las rutinas nos dan esta posibilidad.todo depende de lo que queramos hacer.

Código: [Seleccionar]
movlw       UPPER(TFT_CONF_9341)
                        movwf   TBLPTRU
                        movlw   HIGH(TFT_CONF_9341)
                        movwf   TBLPTRH
                        movlw   LOW(TFT_CONF_9341)
                        movwf   TBLPTRL

esto lo pongo en el programa principal para indicar la hubicacion de una tabla a partir de la etiqueta
TFT_CONF_9341.

en la libreria solo esta la rutina para la gestion de los datos de esa tabla.
por ejemplo esta tabla configura una camara mediante el bus SCCB.

asi puedo enviar varias configuraciones con una sola rutina.


ya he creado el archivo .inc para la hubicacion de solamente tablas.y funciona bien.
ahora mirare lo de la hubicacion de las etiquetas.haber que tal queda.



Montando mi primera impresora 3D (Raprep Prusa i3)