Microchip assembly language - Page 1
Forum section: electronics / general

author: jcaser1948
author_rank: Contributor
timestamp: July 27, 2016, 02:54:41 pm
content: This code snippet worked perfectly with an older verssion of MPlab, but the new microchip assambler compiler does not accept it anymore.The offending part is equ $ what can I do to substitute this statement with an equivalent one whitout rewriting everything?Tabla_Mensajes movwf PCL ;Calcula el desplazamiento sobre la tablaMens_0 equ $ ;equ Mens_0 apunta al primer carácter del mensaje 0retlw 'H'retlw 'o'retlw 'l'retlw 'a'retlw 0x00 ;Ultimo carácter del mensaje 0Mens_1 equ $ ;equ Mens_1 apunta al primer carácter del mensaje 1retlw 'A'retlw 'd'retlw 'i'retlw 'o'retlw 's'retlw 0x00 ;Ultimo carácter del mensaje 1Help would be appreciated, since I an new to the PICS

author: Andy Watson
author_rank: Super Contributor
timestamp: July 27, 2016, 03:20:08 pm
content: Why do you need the equ $ statement? Mens_0 and Mens_1 should be sufficient labels to identify the start address of the tables.

author: StillTrying
author_rank: Super Contributor
timestamp: July 27, 2016, 03:21:20 pm
content: Bit of a guess;Mens_0 equ $% .256;equ Mens_0

author: mikerj
author_rank: Super Contributor
timestamp: July 27, 2016, 03:26:01 pm
content: Quote from: Andy Watson on July 27, 2016, 03:20:08 pm^^^ This. The assembler knows this is a label for an address, you don't need to add the equ $.

author: StillTrying
author_rank: Super Contributor
timestamp: July 27, 2016, 03:33:57 pm
content: Quote from: mikerj on July 27, 2016, 03:26:01 pmI'm thinking you need to force it to just have the lower byte of the address.

author: Andy Watson
author_rank: Super Contributor
timestamp: July 27, 2016, 04:01:04 pm
content: Quote from: StillTrying on July 27, 2016, 03:33:57 pmIn that case it should be resolved with the LOW() or HIGH() macros when mens_0 is used:e.g. movlw LOW(mens_0)

author: jcaser1948
author_rank: Contributor
timestamp: July 27, 2016, 06:17:08 pm
content: Quote from: Andy Watson on July 27, 2016, 03:20:08 pmIt compiles I have to test if it works as intended. Thanks

author: jcaser1948
author_rank: Contributor
timestamp: July 27, 2016, 06:20:04 pm
content: Quote from: mikerj on July 27, 2016, 03:26:01 pmIt does not compile Operand is too complexThanks nevertheless

author: jcaser1948
author_rank: Contributor
timestamp: July 27, 2016, 06:22:35 pm
content: Quote from: Andy Watson on July 27, 2016, 04:01:04 pmYes, Ithink this is the caseThaks

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: July 27, 2016, 07:07:24 pm
content: Just use normal address labels, like this:-Code:Tabla_Mensajes:movwf PCL ;Calcula el desplazamiento sobre la tablaMens_0: ;equ Mens_0 apunta al primer carácter del mensaje 0retlw 'H'retlw 'o'retlw 'l'retlw 'a'retlw 0x00 ;Ultimo carácter del mensaje 0Mens_1: ;equ Mens_1 apunta al primer carácter del mensaje 1retlw 'A'retlw 'd'retlw 'i'retlw 'o'retlw 's'retlw 0x00 ;Ultimo carácter del mensaje 1..movlw Mens_0call Tabla_Mensajes.

author: mikerj
author_rank: Super Contributor
timestamp: July 28, 2016, 08:08:35 am
content: Quote from: jcaser1948 on July 27, 2016, 06:20:04 pmYou just said it did compile in your previous post?

author: jcaser1948
author_rank: Contributor
timestamp: July 29, 2016, 11:01:26 am
content: Here is the complete program; EJERCICIO 18 : LCD con varios mensajes; -----------------------------------;List p=16F870 ;Tipo de procesadorinclude "P16F870.INC" ;Definiciones de registros internosLcd_var equ 0x20 ;Variables (2) de las rutinas de manejo del LCDDelay_Cont equ 0x21 ;Variable para la temporizaciónTemporal_1 equ 0x22 ;Variable temporalTemporal_2 equ 0x23 ;Variable temporalorg 0x00 ;Vector de Resetgoto Inicioorg 0x05 ;Salva vector de interrupcióninclude "lcd_cxx.inc" ;Incluye las rutinas de manejo del LCD;******************************************************************************************;Según el valor contenido en el registro W, se devuelve el carácter a visualizarTabla_Mensajes movwf PCL ;Calcula el desplazamiento sobre la tablaMens_0 equ $ ;equ Mens_0 apunta al primer carácter del mensaje 0retlw 'H'retlw 'o'retlw 'l'retlw 'a'retlw 0x00 ;Ultimo carácter del mensaje 0Mens_1 equ $ ; Mens_1 apunta al primer carácter del mensaje 1retlw 'A'retlw 'd'retlw 'i'retlw 'o'retlw 's'retlw 0x00 ;Ultimo carácter del mensaje 1;*********************************************************************************;Delay_var: Esta rutina de propósito general realiza una temporización variable;entre 50 mS y 12.8". Se emplea un preescaler de 256 y al TMR0 se le carga con 195.;La velocidad de trabajo es de 4Mhz y por tanto el TMR0 se incrementa cada uS. De;esta forma, el TMR0 debe contar 195 eventos que, con un preescaler de 256 hace una;intervalo total de 50000 uS/50 mS (195 * 256). El valor 195 hay que expresarlo;en Hex. (c3) y como el TMR0 es ascendente habrá que cargar su complemento (3C hex.);Dicho intervalo de 50 mS se repite tantes veces como indique la variable "Delay_cont",;es por ello que el delay mínimo es de 50 mS ("Delay_cont=1) y el máxima de 12.8";(Delay_cont=255).Delay_var: bcf INTCON,T0IF ;Desconecta el flag de rebosamientomovlw 0x3c ;Complemento hex. de 195movwf TMR0 ;carga el TMR0Intervalo clrwdt ;Refrescar el WDTbtfss INTCON,T0IF ;Rebasamiento del TMR0 ??goto Intervalo ;Todavía nodecfsz Delay_Cont,F ;Decrementa contador de intervalosgoto Delay_var ;Repite el intervalo de 50 mSreturn;*************************************************************************************;Mensaje: Esta rutina visualiza en el LCD el mensaje cuyo inicio está indicado en;el acumulador. El fin de un mensaje se determina mediante el código 0x00Mensaje movwf Temporal_1 ;Salva posición de la tablaMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Tabla_Mensajes ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfss STATUS,Z ;Mira si es el últimogoto No_es_ultimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1;**********************************************************************************;Inicio clrf PORTB ;Borra los latch de salidabsf STATUS,RP0 ;Selecciona banco 1clrf TRISB ;Puerta B se configura como salidamovlw b'00011000'movwf TRISA ;RA0-RA2 salidas, RA3-RA4 entradasmovlw b'00000110'movwf ADCON1 ;Configuramos como salidas digitalesmovlw b'00000111'movwf OPTION_REG ;Preescaler de 256 para el TMR0bcf STATUS,RP0 ;Selecciona banco 0call LCD_INI ;Secuencia de inicio del LCDmovlw b'00001100'call LCD_REG ;Envía instrucción: LCD ON, Cursor OFF y blink OFFLoop movlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw Mens_0call Mensaje ;Visualiza el mensaje 0movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosmovlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw Mens_1call Mensaje ;Visualiza el mensaje 1movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosgoto LoopEND ;Fin del programa fuenteAnd here the include; LCD_CXX.INC;;;El conjunto de rutinas que se presentan a continuación permiten realizar las tareas básicas;de control del módulo de visualización LCD. Este fichero se debe incluir en los futuros;programas fuente mediante la directiva INCLUDE#define ENABLE bsf PORTA,2 ;Activa señal E#define DISABLE bcf PORTA,2 ;Desactiva señal E#define LEER bsf PORTA,1 ;Pone LCD en Modo RD#define ESCRIBIR bcf PORTA,1 ;Pone LCD en Modo WR#define OFF_COMANDO bcf PORTA,0 ;Desactiva RS (modo comando)#define ON_COMANDO bsf PORTA,0 ;Activa RS (modo datoCBLOCK Lcd_var ;Inicio de las variables. Será la primeraLcd_Temp_1 ;direccón libre disponibleLcd_Temp_2ENDC;*************************************************************************;UP_LCD: Configuración PIC para el LCD.;UP_LCD bsf STATUS,RP0 ;Banco 1clrf PORTB ;RB <0-7> salidas digitalesmovlw b'00011000'movwf PORTA ;RA0-RA2 salidas, RA3-RA4 entradasbcf STATUS,RP0 ;Banco 0OFF_COMANDO ;RS=0DISABLE ;E=0return;;**************************************************************************;LCD_BUSY: Lectura del Flag Busy y la dirección.;LCD_BUSY LEER ;Pone el LCD en Modo RDbsf STATUS,RP0movlw H'FF'movwf PORTB ;Puerta B como entradabcf STATUS,RP0 ;Selecciona el banco 0ENABLE ;Activa el LCDnopLCD_BUSY_1 btfsc PORTB,7 ;Chequea bit de Busygoto LCD_BUSY_1 ;DISABLE ;Desactiva LCDbsf STATUS,RP0clrf PORTB ;Puerta B salidabcf STATUS,RP0ESCRIBIR ;Pone LCD en modo WRreturn;**************************************************************************;LCD_E: Pulso de Enable;LCD_E ENABLE ;Activa EnopDISABLE ;Desactiva Ereturn;;**************************************************************************;LCD_DATO: Escritura de datos en DDRAM o CGRAM. Envía el dato presente en el W;LCD_DATO OFF_COMANDO ;Desactiva RS (modo comando)movwf PORTB ;Valor ASCII a sacar por portbcall LCD_BUSY ;Espera a que se libere el LCDON_COMANDO ;Activa RS (modo dato).goto LCD_E ;Genera pulso de E;**************************************************************************;LCD_REG: Escritura de comandos en el LCD. Envía el comando presente en el WLCD_REG OFF_COMANDO ;Desactiva RS (modo comando)movwf PORTB ;Código de comando.call LCD_BUSY ;LCD libre?.goto LCD_E ;SI.Genera pulso de E.;***************************************************************************;LCD_INI: inicialización del LCD enviando el comando "Function Set" 3 veces consecutivas;con un intervalo de unos 5 mS. El LCD queda borrado y el cursor en la primera posiciónLCD_INI movlw b'00111000'call LCD_REG ;Código de instruccióncall LCD_DELAY ;Temporizamovlw b'00111000'call LCD_REG ;Código de instruccióncall LCD_DELAY ;Temporizamovlw b'00111000'call LCD_REG ;Código de instruccióncall LCD_DELAY ;Temporizamovlw b'00000001' ;Borra LCD y Home.call LCD_REGreturn;*****************************************************************************;LCD_DELAY: Rutina de temporización de unos 5 mS. Se emplean las variables Lcd_Temp_1;y LCD_Temp_2 en lugar del TMR0. Este queda libre para las aplicaciones del usuarioLCD_DELAY: clrwdtmovlw .10movwf Lcd_Temp_1clrf Lcd_Temp_2LCD_DELAY_1: decfsz Lcd_Temp_2,Fgoto LCD_DELAY_1decfsz Lcd_Temp_1,Fgoto LCD_DELAY_1returnWe need the statement " Mens_0 equ $ (programcounter) ;Mens_0 apunta al primer carácter del mensaje 0" in order to adress the lower byte of the list .Try co compile the program and make (when possible; any suggestios how I couls access the first caracter of the list "Hola"Thanks

author: Andy Watson
author_rank: Super Contributor
timestamp: July 29, 2016, 11:46:03 am
content: Quote from: jcaser1948 on July 29, 2016, 11:01:26 amThe example that I gave earlier is apparently the gputil version. The mplab version of the assembler directive is simply "low", e.g.call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlwlowMens_1call Mensaje ;Visualiza el mensaje 1See page 40:http://ww1.microchip.com/downloads/en/DeviceDoc/33014K.pdf

author: Ata
author_rank: Contributor
timestamp: July 29, 2016, 11:59:21 am
content: Hi Jcaser..All you need is to add the following upper case code in your Routine: Mensaje.And it will work ok.Mensaje movwf Temporal_1 ;Salva posición de la tablaMOVLW LOW(Tabla_mensajes)+1SUBWF Temporal_1,FMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Tabla_Mensajes ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfss STATUS,Z ;Mira si es el últimogoto No_es_ultimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1

author: Ata
author_rank: Contributor
timestamp: July 29, 2016, 12:27:34 pm
content: JcaserI forgot .... Remove the equ $ from Mens_0 and Mens_1 ... Leave them as labelsTabla_Mensajes movwf PCL ;Calcula el desplazamiento sobre la tablaMens_0 retlw 'H'retlw 'o'retlw 'l'retlw 'a'retlw 0x00 ;Ultimo carácter del mensaje 0Mens_1 retlw 'A'retlw 'd'retlw 'i'retlw 'o'retlw 's'retlw 0x00 ;Ultimo carácter del mensaje 1

author: Ata
author_rank: Contributor
timestamp: July 29, 2016, 12:38:10 pm
content: Jcaser..Another omission... Please correct your Tabla_mensajes as follows:Tabla_mensajes ADDWF PCLMens_0 DT "Hola",00Mens_1 DT "Adios",00Now all will work ok

author: Ata
author_rank: Contributor
timestamp: July 29, 2016, 01:16:54 pm
content: JcaserEvery time you write to PCL ( movwf PCL, addwf PCL, subwf PCL, andwf PCL, etc) you will change PCL's contents but also PCH will take the actual PCLATH value.....This means that your data-table: Tabla_mensajes Must be within any 256 boundary program area pointed by the contents of PCLATH.So you need to include in your start area (INICIO) the following code:MOVLW HIGH Tabla_mensajesMOVWF PCLATHThis way, when the code ADDWF PCL or MOVWF PCL are executed... PCH will have the corresponding 256 address bank where your Table_mensajes is located.At power-on-reset PCLATH=00, If your Tabla_mensajes is not placed on the first 256 byte-address.. It will explain why it did not work at the beginning.

author: jcaser1948
author_rank: Contributor
timestamp: July 29, 2016, 02:48:54 pm
content: Dear AltaI have tried your solution.The code is like this; EJERCICIO 18 : LCD con varios mensajes; -----------------------------------;List p=16F870 ;Tipo de procesadorinclude "P16F870.INC" ;Definiciones de registros internosLcd_var equ 0x20 ;Variables (2) de las rutinas de manejo del LCDDelay_Cont equ 0x21 ;Variable para la temporizaciónTemporal_1 equ 0x22 ;Variable temporalTemporal_2 equ 0x23 ;Variable temporalorg 0x00 ;Vector de Resetgoto Inicioorg 0x05 ;Salva vector de interrupcióninclude "lcd_cxx.inc" ;Incluye las rutinas de manejo del LCD;******************************************************************************************;Según el valor contenido en el registro W, se devuelve el carácter a visualizarTabla_Mensajes movwf PCL ;Calcula el desplazamiento sobre la tablaTabla_mensajes ADDWF PCLMens_0 DT "Hola",00Mens_1 DT "Adios",00;*********************************************************************************;Delay_var: Esta rutina de propósito general realiza una temporización variable;entre 50 mS y 12.8". Se emplea un preescaler de 256 y al TMR0 se le carga con 195.;La velocidad de trabajo es de 4Mhz y por tanto el TMR0 se incrementa cada uS. De;esta forma, el TMR0 debe contar 195 eventos que, con un preescaler de 256 hace una;intervalo total de 50000 uS/50 mS (195 * 256). El valor 195 hay que expresarlo;en Hex. (c3) y como el TMR0 es ascendente habrá que cargar su complemento (3C hex.);Dicho intervalo de 50 mS se repite tantes veces como indique la variable "Delay_cont",;es por ello que el delay mínimo es de 50 mS ("Delay_cont=1) y el máxima de 12.8";(Delay_cont=255).Delay_var: bcf INTCON,T0IF ;Desconecta el flag de rebosamientomovlw 0x3c ;Complemento hex. de 195movwf TMR0 ;carga el TMR0Intervalo clrwdt ;Refrescar el WDTbtfss INTCON,T0IF ;Rebasamiento del TMR0 ??goto Intervalo ;Todavía nodecfsz Delay_Cont,F ;Decrementa contador de intervalosgoto Delay_var ;Repite el intervalo de 50 mSreturn;*************************************************************************************;Mensaje: Esta rutina visualiza en el LCD el mensaje cuyo inicio está indicado en;el acumulador. El fin de un mensaje se determina mediante el código 0x00Mensaje movwf Temporal_1 ;Salva posición de la tablaMOVLW LOW(Tabla_mensajes)+1SUBWF Temporal_1,FMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Tabla_Mensajes ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfss STATUS,Z ;Mira si es el últimogoto No_es_ultimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1;**********************************************************************************;InicioMOVLW HIGH Tabla_mensajesMOVWF PCLATHclrf PORTB ;Borra los latch de salidabsf STATUS,RP0 ;Selecciona banco 1clrf TRISB ;Puerta B se configura como salidamovlw b'00011000'movwf TRISA ;RA0-RA2 salidas, RA3-RA4 entradasmovlw b'00000110'movwf ADCON1 ;Configuramos como salidas digitalesmovlw b'00000111'movwf OPTION_REG ;Preescaler de 256 para el TMR0bcf STATUS,RP0 ;Selecciona banco 0call LCD_INI ;Secuencia de inicio del LCDmovlw b'00001100'call LCD_REG ;Envía instrucción: LCD ON, Cursor OFF y blink OFFLoop movlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw Mens_0call Mensaje ;Visualiza el mensaje 0movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosmovlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw Mens_1call Mensaje ;Visualiza el mensaje 1movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosgoto LoopEND ;Fin del programa fuenteIt still does not compile, probaly because I undertood something wrong in your kindly explanatios. Please check if this code is like what you intended to convey Gracias

author: jcaser1948
author_rank: Contributor
timestamp: July 29, 2016, 03:07:47 pm
content: Quote from: Andy Watson on July 29, 2016, 11:46:03 amThaks Andy, with your solution it compiles and works fineGracias

author: Ata
author_rank: Contributor
timestamp: July 29, 2016, 04:24:39 pm
content: Jcaser..It doesn't compile because you had duplicated the label: Tabla_mensajesYou have to ways to do it... Both needs to set PCLATH at the beginnig (Inicio)If you don't set PCLATH.. I will only work if Table_mensajes is located on the first 256 address of Prog-memory.MOVLW HIGH Tabla_mensajesMOVWf PCLATH So you can place your Tabla_mensajes wherever you wantAnd you don't need: Mens_0 equ $... Also, doing MOVLW LOW Mens_0 is the same like MOVLW Mens_0 Because the MPASM will only take the label's (Mens_0) low byte address by default.Andy's way: (Better)Tabla_Mensajes MOVWF PCL ;Calcula el desplazamiento sobre la tablaMens_0 DT "Hola",00Mens_1 DT "Adios",00Mensaje movwf Temporal_1 ;Salva posición de la tablaMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Tabla_Mensajes ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfss STATUS,Z ;Mira si es el últimogoto No_es_ultimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1.....call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw low Mens_0call Mensaje ;Visualiza el mensaje 0.....My Way:Tabla_Mensajes ADDWF PCL ;Calcula el desplazamiento sobre la tablaMens_0 DT "Hola",00Mens_1 DT "Adios",00Mensaje movwf Temporal_1 ;Salva posición de la tablaMOVLW LOW(Tabla_mensajes)+1SUBWF Temporal_1,FMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Tabla_Mensajes ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfss STATUS,Z ;Mira si es el últimogoto No_es_ultimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1........call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw low Mens_0call Mensaje ;Visualiza el mensaje 0........

author: jcaser1948
author_rank: Contributor
timestamp: July 29, 2016, 05:41:20 pm
content: ATA,Thanks for your prompt answer .With your solutio it does not compile. It says "Symbol not previously defined (Tabla_mensajes)"here is the program again as I understood your way; EJERCICIO 18 : LCD con varios mensajes; -----------------------------------;List p=16F870 ;Tipo de procesadorinclude "P16F870.INC" ;Definiciones de registros internosLcd_var equ 0x20 ;Variables (2) de las rutinas de manejo del LCDDelay_Cont equ 0x21 ;Variable para la temporizaciónTemporal_1 equ 0x22 ;Variable temporalTemporal_2 equ 0x23 ;Variable temporalorg 0x00 ;Vector de Resetgoto Inicioorg 0x05 ;Salva vector de interrupcióninclude "lcd_cxx.inc" ;Incluye las rutinas de manejo del LCD;******************************************************************************************;Según el valor contenido en el registro W, se devuelve el carácter a visualizarTabla_Mensajes ADDWF PCL ;Calcula el desplazamiento sobre la tablaMens_0 DT "Hola",00Mens_1 DT "Adios",00;*********************************************************************************;Delay_var: Esta rutina de propósito general realiza una temporización variable;entre 50 mS y 12.8". Se emplea un preescaler de 256 y al TMR0 se le carga con 195.;La velocidad de trabajo es de 4Mhz y por tanto el TMR0 se incrementa cada uS. De;esta forma, el TMR0 debe contar 195 eventos que, con un preescaler de 256 hace una;intervalo total de 50000 uS/50 mS (195 * 256). El valor 195 hay que expresarlo;en Hex. (c3) y como el TMR0 es ascendente habrá que cargar su complemento (3C hex.);Dicho intervalo de 50 mS se repite tantes veces como indique la variable "Delay_cont",;es por ello que el delay mínimo es de 50 mS ("Delay_cont=1) y el máxima de 12.8";(Delay_cont=255).Delay_var: bcf INTCON,T0IF ;Desconecta el flag de rebosamientomovlw 0x3c ;Complemento hex. de 195movwf TMR0 ;carga el TMR0Intervalo clrwdt ;Refrescar el WDTbtfss INTCON,T0IF ;Rebasamiento del TMR0 ??goto Intervalo ;Todavía nodecfsz Delay_Cont,F ;Decrementa contador de intervalosgoto Delay_var ;Repite el intervalo de 50 mSreturn;*************************************************************************************;Mensaje: Esta rutina visualiza en el LCD el mensaje cuyo inicio está indicado en;el acumulador. El fin de un mensaje se determina mediante el código 0x00Mensaje movwf Temporal_1 ;Salva posición de la tablaMOVLW LOW(Tabla_mensajes)+1SUBWF Temporal_1,FMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Tabla_Mensajes ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfss STATUS,Z ;Mira si es el últimogoto No_es_ultimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1;**********************************************************************************;InicioMOVLW HIGH Tabla_mensajesMOVWF PCLATHclrf PORTB ;Borra los latch de salidabsf STATUS,RP0 ;Selecciona banco 1clrf TRISB ;Puerta B se configura como salidamovlw b'00011000'movwf TRISA ;RA0-RA2 salidas, RA3-RA4 entradasmovlw b'00000110'movwf ADCON1 ;Configuramos como salidas digitalesmovlw b'00000111'movwf OPTION_REG ;Preescaler de 256 para el TMR0bcf STATUS,RP0 ;Selecciona banco 0call LCD_INI ;Secuencia de inicio del LCDmovlw b'00001100'call LCD_REG ;Envía instrucción: LCD ON, Cursor OFF y blink OFFLoop movlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw low Mens_0call Mensaje ;Visualiza el mensaje 0movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosmovlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw low Mens_1call Mensaje ;Visualiza el mensaje 1movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosgoto LoopEND ;Fin del programa fuenteYou may compile it, if you like;the Include is in my previous post .Y gracias por todo

author: Ata
author_rank: Contributor
timestamp: July 29, 2016, 10:37:17 pm
content: Jcaser .. Please read the compiler errors...Tabla_mensajes was misspelled as Tabla_Mensajes... That's the error.Change all to Tabla_mensajes and all errors are gone..Now its ok..; EJERCICIO 18 : LCD con varios mensajes; -----------------------------------;List p=16F870 ;Tipo de procesadorinclude "P16F870.INC" ;Definiciones de registros internosLcd_var equ 0x20 ;Variables (2) de las rutinas de manejo del LCDDelay_Cont equ 0x21 ;Variable para la temporizaciónTemporal_1 equ 0x22 ;Variable temporalTemporal_2 equ 0x23 ;Variable temporalorg 0x00 ;Vector de Resetgoto Inicioorg 0x05 ;Salva vector de interrupcióninclude "lcd_cxx.inc" ;Incluye las rutinas de manejo del LCD;******************************************************************************************;Según el valor contenido en el registro W, se devuelve el carácter a visualizarTabla_mensajes ADDWF PCL,F ;Calcula el desplazamiento sobre la tablaMens_0 DT "Hola",00Mens_1 DT "Adios",00;*********************************************************************************Delay_var: bcf INTCON,T0IF ;Desconecta el flag de rebosamientomovlw 0x3c ;Complemento hex. de 195movwf TMR0 ;carga el TMR0Intervalo clrwdt ;Refrescar el WDTbtfss INTCON,T0IF ;Rebasamiento del TMR0 ??goto Intervalo ;Todavía nodecfsz Delay_Cont,F ;Decrementa contador de intervalosgoto Delay_var ;Repite el intervalo de 50 mSreturn;*************************************************************************************;Mensaje: Esta rutina visualiza en el LCD el mensaje cuyo inicio está indicado en;el acumulador. El fin de un mensaje se determina mediante el código 0x00Mensaje movwf Temporal_1 ;Salva posición de la tablaMOVLW LOW(Tabla_mensajes)+1SUBWF Temporal_1,FMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Tabla_mensajes ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfss STATUS,Z ;Mira si es el últimogoto No_es_ultimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1;**********************************************************************************;InicioMOVLW HIGH Tabla_mensajesMOVWF PCLATHclrf PORTB ;Borra los latch de salidabsf STATUS,RP0 ;Selecciona banco 1clrf TRISB ;Puerta B se configura como salidamovlw b'00011000'movwf TRISA ;RA0-RA2 salidas, RA3-RA4 entradasmovlw b'00000110'movwf ADCON1 ;Configuramos como salidas digitalesmovlw b'00000111'movwf OPTION_REG ;Preescaler de 256 para el TMR0bcf STATUS,RP0 ;Selecciona banco 0call LCD_INI ;Secuencia de inicio del LCDmovlw b'00001100'call LCD_REG ;Envía instrucción: LCD ON, Cursor OFF y blink OFFLoop movlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw low Mens_0call Mensaje ;Visualiza el mensaje 0movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosmovlw b'00000001'call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)movlw low Mens_1call Mensaje ;Visualiza el mensaje 1movlw .20movwf Delay_Contcall Delay_var ;Temporiza 2 segundosgoto LoopEND ;Fin del programa fuente

author: jcaser1948
author_rank: Contributor
timestamp: July 30, 2016, 12:19:06 pm
content: Dear AltaI have changed Tabla_mensajes as you suggested. I still get the ErrorC:\USERS\JCASE\MPLABXPROJECTS\LABORA_EJER_18_PIC16F870_ALTA.X\LABORA_EJER_18_PIC16F870.ASM 45 : Operand contains unresolvable labels or is too complexThe offending line is MOVLW LOW(Tabla_mensajes)+1 (at pos 45)sorry for the bothering, but this error nags me. It should compile, but it does not, and de distinctionbetween lower and upper case does not seem to be the problemThanks

author: StillTrying
author_rank: Super Contributor
timestamp: July 30, 2016, 03:38:41 pm
content: Here's 2 variations thatshouldwork.Mensaje movwf Temporal_1 ;Salva posición de la tablaMOVLW LOW(Tabla_mensajes+ 1)SUBWF Temporal_1,FMensaje_1 movf Temporal_1,W ;Recupera posición de la tablaMensaje movwf Temporal_1 ;Salva posición de la tablaMOVLW LOW(Tabla_mensajes)ADDLW 1SUBWF Temporal_1,FMensaje_1 movf Temporal_1,W ;Recupera posición de la tabla

author: jcaser1948
author_rank: Contributor
timestamp: July 30, 2016, 04:11:27 pm
content: This compiles (both solutions). Thank everyone for the help

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: July 31, 2016, 06:42:53 am
content: I have one suggestion before you go. Using 'ADDWF PCL' is making your code more complicated than it needs to be. If you replace it with 'MOVWF PCL' then you don't need to calculate the offset between this instruction and the message address. You can also place itanywherein your code (not necessarily in the table) like this:-Code:Tabla_Mensajes:Mens_0 DT "Hola",00Mens_1 DT "Adios",00..MOVLW Tabla_MensajesMOVWF PCLATH.movlw Mens_0call Mensaje..Mensaje movwf Temporal_1 ;Salva posición de la tablaMensaje_1 movf Temporal_1,W ;Recupera posición de la tablacall Table_Read ;Busca caracter de salidamovwf Temporal_2 ;Guarda el caractermovf Temporal_2,Fbtfsc STATUS,Z ;Mira si es el últimoreturnNo_es_ultimo call LCD_DATO ;Visualiza en el LCDincf Temporal_1,F ;Siguiente caractergoto Mensaje_1Table_Read MOVWF PCL ; jump to table *** page address in PCLATH ***

author: Ata
author_rank: Contributor
timestamp: July 31, 2016, 12:02:48 pm
content: JcaserStrange.... It compiles (no errors) using MPASM 5.64 from MPLABX IDE 3.15All cases compile the same:MOVLW LOW(Tabla_mensajes)+1MOVLW LOW(Tabla_mensajes+1)MOVLW LOW Tabla_mensajes +1movlw low Tabla_mensajes+1A portion of the LST generated:MPASM 5.64 TEST.ASM 7-31-2016 7:27:31 PAGE 2LOC OBJECT CODE LINE SOURCE TEXTVALUE00042 ;el acumulador. El fin de un mensaje se determina mediante el código 0x0000043001A 00A2 00044 Mensaje movwf Temporal_1 ;Salva posición de la tabla00045001B 3006 00046 MOVLW LOW(Tabla_mensajes)+1001C 3006 00047 MOVLW LOW (Tabla_mensajes)+1001D 3006 00048 MOVLW LOW(Tabla_mensajes +1)001E 3006 00049 MOVLW LOW (Tabla_mensajes +1)001F 3006 00050 MOVLW LOW Tabla_mensajes + 10020 3006 00051 movlw low Tabla_mensajes+1000520021 02A2 00053 SUBWF Temporal_1,F000540022 0822 00055 Mensaje_1 movf Temporal_1,W ;Recupera posición de la tabla00056000570023 2005 00058 call Tabla_mensajes ;Busca caracter de salida0024 00A3 00059 movwf Temporal_2 ;Guarda el caracter0025 08A3 00060 movf Temporal_2,F0026 1D03 00061 btfss STATUS,Z ;Mira si es el último0027 2829 00062 goto No_es_ultimo0028 0008 00063 return0029 0000 00064 No_es_ultimo nop ;call LCD_DATO ;Visualiza en el LCD002A 0AA2 00065 incf Temporal_1,F ;Siguiente caracter002B 2822 00066 goto Mensaje_1.............. Same result always.Which MPASM are you using?