# Cambio de páginas en los PIC y uso del PCLATH



## OSSOMER (Dic 28, 2006)

Hola  y saludos de antemano.

La inquietud es la siguiente:
Estoy haciendo un programa en MPLAB con más de 2622 lineas ensambladas en lenguaje ensamblador con un PIC16F876A

Resulta que cuando lo ensamblo o lo corro, me sale el Mensaje[306]

Message[306] C:\MPLAB OSCAR\TESIS PRUEBA\CONCENTRADORP.ASM 1883 : Crossing page boundary -- ensure page bits are set.
Loaded C:\Mplab Oscar\Tesis prueba\ConcentradorP.COD
BUILD SUCCEEDED: Thu Dec 28 16:54:50 2006

Yo quisiera saber como solucionar ese mensaje.
Me han dicho que se corrige con el "PCLATH"  pero la verdad no sé como.



Te lo agradece tu amigo,  Oscar Somerson.


----------



## maunix (Dic 29, 2006)

Es un mensaje que te avisa que estás cruzando el límite de una página.
El código que ha generado el ensamblador en ese punto ha sobrepasado la posición 0x7FF de la primer página y ha pasado a la segunda página que comienza en 0x800.

El cuidado que debes tener, lo menciona el datasheet y es que el program counter HIGH no se carga automáticamente sino que lo debes hacer tú mismo a mano.  

Para eliminarlo prueba hacer *errorlevel -306*


----------



## OSSOMER (Dic 29, 2006)

Gracias maunix por la respuesta.
Vi el datasheet del PIC16F876A y encontré lo siguiente:

El PIC16F876A tiene las siguientes páginas y comprenden también las posiciones de memoria allí mencionadas:

Primera página direcciones de la 0000h hasta la 07FFh ....................2K
Segunda página direcciones de la 0800h hasta la 0FFFh ....................2K
Tercera página direcciones de la 1000h hasta la 17FFh ......................2K
Cuarta página direcciones de la 1800h hasta la 1FFFh .......................2K

Estas direcciones las puedes ver en MPLAB >> VIEW>>3 Program memory, ya compilado el programa.


Para ir a las paginas sólo tienes que cambiar los bit 3 y 4 del PCLAHT

primera página: bcf      PCLAHT,3
                        bcf      PCLAHT,4

sugunda página: bsf      PCLAHT,3
                         bcf      PCLAHT,4

Tercera página: bcf      PCLAHT,3
                        bsf      PCLAHT,4

Cuarta página:  bsf      PCLAHT,3
                        bsf      PCLAHT,4


EJEMPLO:::::

Si tu estas en la primera página y quieres acceder a una subrutina o un dato en el segunda página tienes que digitar el siguiente código..:

__________________________________________________________________
org 0X500

-------- "primer página"-------
          ....
          ....
          bsf   PCLATH,3   ; Configura al PCLAHT para ir a la segunda página
          bcf   PCLATH,4   ;  "    "
          call   puco
          clrf   PCLATH      ; Limpia al PCLAHT para estar en la primera página
          .....
          .....
          .....
          .....
          ..... 

Org 0X900

--------"Segunda página"--------
puco    movlw   ........
           ...
           ...
           ...
           return
____________________________________________________________

Tengan cuidado cuando se cambia de página por que si no haces lo correcto el programa se queda quieto y no funciona...

Espero que no le hallan quedado inquietudes.
Cualquier error, por favor moderadores, corregirlo.


----------



## pheidias (Abr 6, 2007)

Hola

resulta que tengo una tabla donde la mitad del codigo pertenece a una pagina y la mitad a otra, cuando hago un call a esa tabla para que me devuelva un valor resulta que me lo hace para valores menores a 18 si es mayor salta a la direccion 0x00 que puedo hacer?


----------



## Jairo (Abr 11, 2007)

Hola
Como sugerencia coloca toda la tabla en el comienzo de otra pagina o por el medio, pero no en el cambio de paginas, pero ten cuidado al llamar a la tabla tienes que guardar el valor de pclath

Saludos 
Jairo


----------



## nogueda (Ago 20, 2007)

mucho gusto, mi nombre es david, y estoy manejando un microcontrolador 16f877a, tengo mas de 2k de lineas de programa, y quiero pasar de paginacion con goto, desde pagina 0 a pagina 1; al usar el pclath para cambiar de pagina y compilar mi programa, este me marca todo correcto, ecepto que no reconoce el cambio de paginacion, al correr el programa y se cruza la pagina de cero a uno (banco0 a banco1) este se reinicia.....

no se, ya intente modificando el pclath (3,4) de muchas maneras; al mandar con el el goto desde pagina cero a la pagina uno no pasa de paginas, solo se reinicia...

NOTA: en la pagina cero, el pclath,(3,4) estan en ceros; para pasar a pagina 1 cambio el bit 3 del pclath a uno antes del goto, y asi debe de accesar a la etiqueta en la pagina 1; pero no me lo reconoce; he visto que si hace el goto, pero se reinicia por que no brinca de paginas.... no se si tenga que modificar algun otro registro del microcontrolador...aqui le muestro mi esquema.

pagina0(bank0)...
(programa de 0 hasta 2k de lineas)...
bcf pclath,4
bsf pclath,3
goto (etiqueta)

pagina1(bank1)
(programa de 2k hasta 4k de lineas)
(etiqueta)......

le agradeceria que me respondiaran...gracias......por su tiempo.


----------



## El nombre (Ago 21, 2007)

Evita problemas con:
PAgesel "etiqueta" 
 Al ensamblar te genera el código necesario sin tener que pensar en que banco la tienes (la etiqueta, naturalmente)

Saludos


----------



## SEBASTIAN_GRIMOLDI (Jun 19, 2009)

hola que tal amigos¡ no me queda muy claro como usar el PCLATH, Les cuento ,estoy haciendo un programa en un pic 16f84a y tiene una pequeña tabla que va del o al 9 pero cuando llego a la linea 255 de mi programa este se cuelga. puse la tabla al inicio pero igual no se por que me toma el programa como si fuera parte de una tabla como puedo hacer para programar despues de la linea 255 en adelante sin que se cuelgue el programa? bueno espero su respuesta muchas gracias.


----------



## mabauti (Jun 19, 2009)

postea el programa, asi ser mas sencillo auxiliarte


----------



## SEBASTIAN_GRIMOLDI (Jun 23, 2009)

Hola mabauti, muchas gracias por responder, bueno este es el programa que estoy haciendo es muy simple, pero tengo un problema y no es por pasar las 255 lines sino alguna otra cosa, si agrego lineas en algunas parte del programa este se cuelga en la parte de decremento, no importa lo que ponga asi sea un "nop" o algo mas complicado siempre se cuelga de igual manera, por ejemplo si agrego un nop en la interrupcion el programa ya no anda y si lo saco si. no se que es lo que me estoy comiendo, si tendra que ver con el pcl, el valor del acumulador o que....	bueno espero me puedas dar una mano con esto por que la verdad que me supero y por mucho¡¡¡¡¡ no se que pueda ser...... muchas gracias 

sebastian.....


```
LIST			 P=16F84A


 
PCL     		EQU			0X02				;************************
STATUS  		EQU     		0X03				;*						*	
TRISA   		EQU     		0X05				;* DECLARACION DE REG	*
PORTA   		EQU     		0X05				;*						*
TRISB   		EQU     		0X06				;*						*
PORTB   		EQU     		0X06				;************************
;-----------------------------------				;********************		
NUMERO1			EQU				0X0C				;VARIABLE PARA DIG1 *			
NUMERO2			EQU				0X10				;VARIABLE PARA DIG2	*
VISUAL1			EQU				0X0E				;VARIABLE PARA TIEMPO DE VISUALI1
VISUAL2			EQU				0X0F				;VARIABLE PARA TIEMPO DE VISUALI2
;-----------------------------------
INTCON			EQU				0X0B				;DIRECCION PARA LAS INTERRUPCIONES
ACUM    		EQU     		0X14				;VARIABLE PARA GUARDAR EL CONTENIDO DEL ACUMULADOR
STAT    		EQU     		0X15				;VARIABLE PARA LA INTERRUPCIO
OPTIONR			EQU				0X16				;DIRECCION PARA CONFIGURAR EL FLANCO DE RB0
;-----------------------------------
START			EQU				0X17				;VARIABLE PARA ENCENDIDO
TERMINO			EQU				0X17				;VARIABLE QUE USO PARA INCREMENTO DE UNI Y7 DEC
TITILO			EQU				0X17				;VARIABLE QUE USO PARA QUE TITILE EL PUNTO
PAUSA			EQU				0X17				;VARIABLE QUE USO PARA PAUSA
TVISUL			EQU				0X18				;VARIABLE PARA TIEMPO DE VISUALIZACION
CONTADOR		EQU				0X19				;VARIABLE PARA TIEMPO DE MUESTREO SEGUNDA PARTE
;-----------------------------------
REG1			EQU				0X20
REG2			EQU				0X21					
REG3			EQU				0X22
TIERES			EQU				0X23
;-----------------------------------
F       		EQU     		1
w		        EQU 	    	0
;-----------------------------------
				ORG     		0X00
				GOTO    		INICIO				;SALTO A INICIO  
				ORG     		0X04     			;DIRECCION DE SALTO EN UNA INTERRUPCION
           		MOVWF   		ACUM   				;COPIO EL ACUMULADOR EN EL REGISTRO ACUM
				MOVF    		STATUS,W 			;GUARDO ESTATUS EN EL ACUMULADOR
				BCF				STATUS,5         	;PASO AL BANCO CERO
				MOVWF   		STAT    			;COPIO EL ACUMULADOR AL REG STA		
;***************************************
; PROGRAMA DENTRO DE LA INTERRUPCION.***
;***************************************
				BCF     		INTCON,1			;PONGO A CERO LA BANDERA DE LA INTERRUPCION
;----------------------------------------				
				BTFSC			START,0				;PREGUNTO COMO ESTA ESTAR
				GOTO			INVIERTO			;SI ESTA EN UNO INVIERTO
				BSF				START,0				;PONGO A UNO START PARA PASAR A SEGUN PARTE
				BCF				PAUSA,4				;PONGO A CERO EL BIT PARA LA PAUSA
				GOTO			HECHO				;SALTO A HECHO
INVIERTO		BCF				START,0				;INVIERTO EL ESTADO DE ESTART
				BSF				PAUSA,4				;PONGO A UNO EL BIT PARA LA PAUSA
				BCF				PORTB,3				;APAGO EL LED PRINCIPAL	
				BCF				PORTB,7				;APAGO EL PUNTO SINO ME QUEDA PRENDIDO DURANTE PAUSA	
HECHO			MOVF    		STAT,W  			;CUARDO EL CONTENIDO DE ESTAT EN EL ACUMULADOR
       			MOVWF   		STATUS  			;RESTAURO EL ESTATUS
        		SWAPF   		ACUM,F  			;DA LA VUELTA EL REG ACUM
        		SWAPF   		ACUM,W  			;DOY VUELTA EL REG ACUM
			    RETFIE								;SALGO DE LA INTERRUPCION         

;---------------------------------------			;-----------------
;---------------------------------------			;SUBRRUTINA TABLA
;---------------------------------------			;-----------------
TABLA			ADDWF			PCL,F				;SUMA EL VALOR DEL ACUMULADOR A PCL
				RETLW			b'00000'; 0     	;NUMERO 0   #############################
				RETLW   		b'00001'; 1    		;NUMERO 1	#							#	
				RETLW   		b'00010'; 2  		;NUMERO 2  	#							#	
				RETLW   		b'00011'; 3   		;NUMERO 3  	#	TABLA DE NUMEROS DEL	#
				RETLW   		b'00100'; 4   		;NUMERO 4  	#	       0-9				#
				RETLW   		b'00101'; 5   		;NUMERO 5	#							#
				RETLW  			b'00110'; 6   		;NUMERO 6	#							#
				RETLW   		b'00111'; 7  		;NUMERO 7 	#							#
				RETLW   		b'01000'; 8 		;NUMERO 8 	#							#
				RETLW   		b'01001'; 9 		;NUMERO 9	#############################
;------------------------------------------

INICIO          BSF     		STATUS,5			;PASO AL BANCO 1
 	      		MOVLW			b'000000'			;CARGO EL ACUMULADOR
				MOVWF     		TRISA  				;CONFIGURO EL PUERTO A
        		MOVLW			b'00000111'			;CARGO EL ACU8MULADOR
				MOVWF	    	TRISB   			;CONFIGURO EL PUERTO B
				BCF				OPTIONR,6
				BCF     		STATUS,5        	;PASO AL BANCO 0
				CLRF			INTCON				;BORRA TODAS LAS INTERRUPCIONES
				BSF				INTCON,7			;ACTIVA LA INTERRUPCION GLOBALMENTE
				BSF				INTCON,4			;ACTIVA LA INTERRUPCION POR CAMBIO DE PORTB
;---------------------------------------
				CLRF			PORTB				;BORRO EL PUERTO B
				CLRF			PORTA				;BORRO EL PUERTO A		
				CLRF			NUMERO1
				CLRF			NUMERO2
				CLRF			START				;BORRO VARIABLE
				CLRF			TERMINO				;--------------------	
				CLRF 			TIERES				
;----------------------------------------			;TESTEO DE PULSADORES
													;--------------------
				MOVLW			d'9'	
				MOVWF			TIERES	

;--------------------------------------

TESTP			                BCF 			PORTB,4
				BTFSC			START,0				;TESTEA START SI ESTA EN 1 SALTA A LA SEGUNDA PARTE
				GOTO			SEGUPARTE			;SALTA A LA SGUNDA PARTE
				BTFSC			PORTB,1				;PREGUNTA COMO ESTA EL PULSADOR 2		
				GOTO			SIGO				;SI ESTA EN UNO SIGO
				INCF			NUMERO1,1			;SI ESTA EN CERO INCREMENTO LAS DECENAS
				BSF				PORTB,4
;----------------------------------------
				MOVF			NUMERO1,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				SUBLW			0X04				;ACA PONGO HASTA DONDE CUENTA MI CONTADOR (VALOR-1)
				BTFSC			STATUS,2			;STATUS SE PONE A UNO SI LA OP ANTERIOR ES IGUAL A CERO
				CLRF			NUMERO1				;PONGO A 0 RETARDO
;----------------------------------------
SIGO			MOVF			NUMERO1,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				SUBLW			0X03				;ACA PONGO HASTA DONDE CUENTA MI CONTADOR (VALOR-1)
				BTFSC			STATUS,2			;STATUS SE PONE A UNO SI LA OP ANTERIOR ES IGUAL A CERO
				CLRF 			NUMERO2
;---------------------------------------
				BTFSC			PORTB,2				;TESTEO DE PULSADOR 1
				GOTO			MUESTRADEC			;MUESTRA LOS VALORES
				INCF			NUMERO2,1			;INCREMENTA LAS UNIDADES
				BSF				PORTB,4
;----------------------------------------
				MOVF			NUMERO2,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				SUBLW			0X0A				;ACA PONGO HASTA DONDE CUENTA MI CONTADOR (VALOR-1)
				BTFSC			STATUS,2			;STATUS SE PONE A UNO SI LA OP ANTERIOR ES IGUAL A CERO
				CLRF			NUMERO2				;BORRO NUMERO 2

													;-------------------
;---------------------------------------			;MUESTRA LAS DECENAS 
													;--------------------
MUESTRADEC		MOVLW			d'55'
				MOVWF			TVISUL
MOSTRANDO		BSF				PORTB,5				;PRENDO EL PRIMER TRANSISTOR
				MOVF 			NUMERO1,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				CALL 			TABLA				;LLAMO  A MI TABLA
				MOVWF			PORTA				;MUESTRO EL NUMERO EN EL DISPLAY
;-----------------------------------------
DELAY			MOVLW			20					;########################
				MOVWF			VISUAL1				;#						#
UNN				MOVLW			10					;#	TIEMPO PARA			#
				MOVWF			VISUAL2				;#	VISUALIZAR			#	
TATA			DECFSZ			VISUAL2,1			;#	DISPLAY				#
				GOTO			TATA				;#						#	
				DECFSZ			VISUAL1,1			;#						#
				GOTO			UNN					;########################
				BCF				PORTB,5				;APAGO EL TRANSISTOR PARA LAS DECENAS
				CLRF			PORTA				;LIMPIO EL PUERTO A

													;--------------------
;---------------------------------------			;MUESTRA LAS UNIDADES
													;--------------------	

MUESTRAUNI		BSF				PORTB,6				;PRENDO EL SEGUNDO TRANSISTOR	
				MOVF 			NUMERO2,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				CALL 			TABLA				;LLAMO  A MI TABLA
				MOVWF			PORTA				;MUESTRO EL NUMERO EN EL DISPLAY
;----------------------------------------
DELAY1			MOVLW			20					;############################
				MOVWF			VISUAL1				;#							#
UNN1			MOVLW			10					;#	DELAY PARA				#
				MOVWF			VISUAL2				;#	VISUALIZAR				#
TATA1			DECFSZ			VISUAL2,1			;#	DISPLAY					#
				GOTO			TATA1				;#							#		
				DECFSZ			VISUAL1,1			;#							#
				GOTO			UNN1				;############################
;-----------------------------------------
				BCF				PORTB,6				;APAGO EL TRANSISTOR DE LAS UNIDADES
				CLRF			PORTA				;LIMPIO EL PUERTOA
				DECFSZ			TVISUL,1			;DECREMENTA LA VARIABLE P TIMPO DE VISUALIZAR
				GOTO			MOSTRANDO			;SALTA MIENTRAS TVIS NO SEA CERO						
;-----------------------------------------				
				BTFSS 			START,0				;SI STARY ESTA EN UNO SALTA
				GOTO			TESTP
;*****************************************
;*****************************************
;*****************************************														
													;---------------------------
;-------------------------------------				;SEGUDA PARTE DEL PROGRAMA
													;---------------------------
SEGUPARTE		CLRW
				MOVF			NUMERO1,W			;CARGO EL VALOR DE NUMERO1 EN EL ACUMULADOR
				SUBLW			0X00				;PREGUNTO SI ES IGUAL A CERO
				BTFSS			STATUS,2			;STATUS SE PONE A UNO SI LA OP ANTERIOR ES IGUAL A CERO
				GOTO			OK
				;----------
				MOVF			NUMERO2,W			;CARGO EL VALOR DE NUMERO2 EN EL ACUMULADOR
				SUBLW			0X00				;PREGUNTO SI ES IGUAL A CERO
				BTFSS			STATUS,2			;STATUS SE PONE A UNO SI LA OP ANTERIOR ES IGUAL A CERO
				GOTO			OK					;SI NO SE CARGO NADA EN NUM 1 Y 2 SE RESETEA TODO
				GOTO			INICIO
;-------------------------------------
OK													
MUESTRADEC2		MOVLW			d'255'				;CARGO ESTE VALOR EN MI
				MOVWF			CONTADOR			;VARIABLE PARA TIEMPO DE VISUALI

;--------------------------------------
MOSTRANDO2		BSF				PORTB,5				;PRENDO EL PRIMER TRANSISTOR
				MOVF 			NUMERO1,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				CALL 			TABLA				;LLAMO  A MI TABLA
				MOVWF			PORTA				;MUESTRO EL NUMERO EN EL DISPLAY
;-----------------------------------------
DELAY2			MOVLW			20					;########################
				MOVWF			VISUAL1				;#						#
UNN2			MOVLW			10					;#	TIEMPO PARA			#
				MOVWF			VISUAL2				;#	VISUALIZAR			#	
TATA2			DECFSZ			VISUAL2,1			;#	DISPLAY				#
				GOTO			TATA2				;#						#	
				DECFSZ			VISUAL1,1			;#						#
				GOTO			UNN2				;########################
				BCF				PORTB,5				;APAGO EL TRANSISTOR PARA LAS DECENAS
				CLRF			PORTA				;LIMPIO EL PUERTO A
;---------------------------------------			;--------------------
;---------------------------------------			;MUESTRA LAS UNIDADES
;---------------------------------------			;--------------------	

MUESTRAUNI2		BSF				PORTB,6				;PRENDO EL SEGUNDO TRANSISTOR	
				MOVF 			NUMERO2,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				CALL 			TABLA				;LLAMO  A MI TABLA
				MOVWF			PORTA				;MUESTRO EL NUMERO EN EL DISPLAY
;----------------------------------------
DELAY12			MOVLW			20					;############################
				MOVWF			VISUAL1				;#							#
UNN12			MOVLW			10					;#	DELAY PARA				#
				MOVWF			VISUAL2				;#	VISUALIZAR				#
TATA12			DECFSZ			VISUAL2,1			;#	DISPLAY					#
				GOTO			TATA12				;#							#		
DNN12			DECFSZ			VISUAL1,1			;#							#
				GOTO			UNN12				;############################
;-----------------------------------------
				BCF				PORTB,6				;APAGO EL TRANSISTOR DE LAS UNIDADES
				CLRF			PORTA				;LIMPIO EL PUERTOA
				DECFSZ			MOSTRANDO			;DECREMENTA LA VARIABLE P TIMPO DE VISUALIZAR
				GOTO			MOSTRANDO2			;SALTA MIENTRAS TVIS NO SEA CERO												
;-------------------------------------				;--------------------------------
;-------------------------------------				;PARTE PARA QUE EL DISPLAY TITILE
;-------------------------------------				;--------------------------------
				BTFSS			PAUSA,4
				GOTO			NADA
				MOVLW			255				;################################    
				MOVWF			REG1			;#    							#
TRES			MOVLW			55				;# TIEMPO DE TITILO DEL 		#
				MOVWF			REG2			;# DISPLAY ESTE DEPENDE DE SI   #
DOS				MOVLW			10				;#	TENGO EN UNO O NO LA		#
				MOVWF			REG3			;#	VARIABLE PAUSA.				#
UNO				DECFSZ			REG3,1			;#								#
				GOTO			UNO				;#								#
				DECFSZ			REG2,1			;#								#	
				GOTO			DOS				;#								#
				DECFSZ			REG1,1			;#								#
				GOTO			TRES			;################################
				GOTO			MUESTRADEC2
;-------------------------------------				;----------------------------
;-------------------------------------				;PARTE PARA QUE EL LED TITILE
;-------------------------------------				;----------------------------
NADA			BSF				PORTB,3
				BTFSS			TITILO,3			;PREGUNTO COMO ESTA LA VARIABLE
				GOTO 			PRENDE				;SI ESTA EN CERO SALTO A PRENDE
				GOTO			APAGA				;SI ESTA EN UNO SALTO A APAGA
PRENDE			BSF				PORTB,7				;PARTE DONDE PRENDE Y
				BSF				TITILO,3			;CAMBIA EL ESTADDO DE LA VARIABLE
				GOTO			TERMINTIT			;SALTO	
APAGA			BCF				PORTB,7				;PARTE DONDE APAGA  Y CAMBIA EL
				BCF				TITILO,3			;ESTADO DE LAS VARIABLES			
;---------------------------------------			;-----------------------------
;---------------------------------------			;DECREMENTO DE UNIDAD Y DECENA
;---------------------------------------			;------------------------------
TERMINTIT		DECF			NUMERO2,1			;TERMINI ES DONDE SALTO DE EL TITILE DEL PUNTO				
ULTIMO			MOVF			NUMERO2,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				SUBLW			0XFFFFFFFF			;ACA PONGO HASTA DONDE CUENTA MI CONTADOR (VALOR-1)
				BTFSS			STATUS,2			;STATUS SE PONE A UNO SI LA OP ANTERIOR ES IGUAL A CERO
				GOTO			MUESTRADEC2			;SALTO A CHATO
				MOVLW			d'9'				;CARGO MAX VALOR QUE PUEDE MOSTRAR DISP 2
				MOVWF			NUMERO2				;CARGO ESE VALOR EN NUMERO 2
;---------------------------------------		
SIGUEDEC		MOVF			NUMERO1,W			;CARGO EL VALOR DE NUMERO EN EL ACUMULADOR
				SUBLW			0X00				;ACA PONGO HASTA DONDE CUENTA MI CONTADOR (VALOR-1)
				BTFSC			STATUS,2			;STATUS SE PONE A UNO SI LA OP ANTERIOR ES IGUAL A CERO
				GOTO			FINALIZA			;SALTO A LA PARTE DE CHIRRIDO					
;----------------------------------------
				DECF			NUMERO1,1			;DECRENENTO NUMERO UNO	
				GOTO			MUESTRADEC2
;---------------------------------------
FINALIZA		BSF				TERMINO,1
				GOTO			CHIRRIDO					;SALTO A LA PARTE PARA EL ULTIMO DECREMENTO

				
;----------------------------------------			;--------------------------	
;----------------------------------------			;CHIRRIDO PARA FIN DE CICLO
;----------------------------------------			;---------------------------	

CHIRRIDO		CLRF            NUMERO1
				CLRF			NUMERO2
				BSF				PORTB,5
				BSF				PORTB,6	
				BSF				PORTB,4
				MOVLW			255				;#################################    
				MOVWF			REG1			;#    							#
TRE				MOVLW			55				;# PRENDO EL BUZZ ESPERO UN		#
				MOVWF			REG2			;# SEGUNDO, APAGO TODO Y RETORNO #
DO				MOVLW			5				;#	 							#
				MOVWF			REG3			;#								#
UN				DECFSZ			REG3,1			;#								#
				GOTO			UN				;#								#
				DECFSZ			REG2,1			;#								#	
				GOTO			DO				;#								#
				DECFSZ			REG1,1			;#								#
				GOTO			TRE				;################################
				BCF				PORTB,4
				GOTO			INICIO
END
```


----------



## bygelogelo (Nov 10, 2010)

Hola, tengo un problema, mi programa en ensamblador sobrepasó la primer pagina (mas de 2048 instrucciones) y quiero ver si me pueden ayudar, ya revisé en internet pero no entiendo bien, es la primera ocasion que escuho esto.

la pregunta es como cambiar a la segunda pagina y llamar rutinas de la primer pagina o viceversa? en internet hablan de tablas pero yo no estoy manejando tablas.

gracias.


----------



## fdesergio (Nov 13, 2010)

Mira esto, el paginado es importante en el uso de tablas, por lod emas no veo que se complique, chauuuuuuuuuuuuu


----------



## bygelogelo (Nov 13, 2010)

Ok muchas gracias ya lo he comprendido, ademas ya lo solucioné haciendo esto:

SEND ;inicio en pagina 0
BSF PCLATH,3 ;cambia a pagina 1
CALL SEND_PAG ;llamando a rutina contenida en pagina 1
RETURN ;retornar
ORG 0X800 ;de aqui en adelante programa contenido en pagina 1
SEND_PAG ; rutina que mandamos llamar desde pagina 0
BANKSEL TXREG ;esta rutina envia datos por el serial (uart)
MOVWF TXREG 
BANKSEL TXSTA
BTFSS TXSTA,TRMT ;comprueba si acabo de enviar.
GOTO $-1
BANKSEL PORTA
BCF PCLATH,3 ;cambio a pagina 0
RETURN ;retorno de rutina


----------



## chekolieneas (Jul 16, 2011)

saludos 

soy nuevo en el foro, y pregunta es que tengo un problema con un programa que estoy realizando de una matriz de led, el cual sobrepasa los 2k de memoria alcanza el limite de la pagina0 y ala hora que lo simulo en isis proteus, solo me toma la simulacion hasta la pagina0 lo que tengo escrito en la paguina 1 no me lo toma en cuanta. solo tengo una subrutina de restardo la cual utilizo para todo.

e intentado hacerlo con PAGESEL, o intercambiendo los bits de pclath, tambien cuando termina la primer pagina o pagina cero. pongo org 0x800 para que todo lo que esta escrito despues de eso lo ponga en la pagina1.
pero de todas maneras me sigue sin tomar lo de esa pagina ala hora de simular..

espero me puedan auxiliar con este problema...GRACIAS.


----------



## mcpiebot (Jul 16, 2011)

Tienes que usar el pagesel en conjunto con las variantes de call y goto que son lcall y lgoto, estas se encargan de hacer el cambio de pagina correspondiente cuando es necesario.

Aun así debes revisar que de preferencia todas las subrutinas queden en una sola pagina para que alguna subrutina no quede entre paginas y tengas problemas.

Ademas debes considerar que lgoto se convierte en 2 instrucciones, por lo que no debes usarlo después de una instrucción de decisión.

Saludos!


----------



## chekolieneas (Jul 17, 2011)

mcpiebot dijo:
			
		

> Tienes que usar el pagesel en conjunto con las variantes de call y goto que son lcall y lgoto, estas se encargan de hacer el cambio de pagina correspondiente cuando es necesario.
> 
> Aun así debes revisar que de preferencia todas las subrutinas queden en una sola pagina para que alguna subrutina no quede entre paginas y tengas problemas.
> 
> ...



saludos amigo gracias por responder....e intentado hacer eso que me comentas pero el programa ala ora de la simulacion sigue sin tomar todo el programa toma hasta las pagina0. pongo una parte del codigo para poder verlo mejor.
inicio del programa

```
LIST P=16F887
    INCLUDE <P16F887.INC>
    
    __CONFIG _CONFIG1, _INTOSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_ON & _FCMEN_ON & _LVP_ON 
    __CONFIG _CONFIG2, _WRT_OFF & _BOR40V    

    ;ERRORLEVEL -306 ; esto te elimina todos los warnings generados del tipo 306 
    ERRORLEVEL -302 ; 

TRISC       equ   0x87 
TRISD       equ   0x88
PORTC       equ   0x07
PORTD       equ   0x08
STATUS      equ   0x03
PCLATH        equ    0x0A
F           equ       1
W           equ       0
CONT1       equ       0x21
CONT2       equ       0x22
CUENTA1     equ       0x23
CUENTA2     equ       0x24
VUELTA1     equ       0x25
CUENTA11     equ       0x26
CUENTA22     equ       0x27


 
            ORG       0x00
            GOTO      INICIO
            ORG       0x05


RETARDO     MOVLW   0xDF
            MOVWF   CUENTA1
ACA1        MOVLW   0x02
               MOVWF   CUENTA2
ACA            DECFSZ  CUENTA2,F 
            GOTO    ACA
            DECFSZ  CUENTA1,F
            GOTO    ACA1
            RETURN   

RETA2       MOVLW   0xFF
            MOVWF   CONT1
AJA1        MOVLW   0xFF
            MOVWF   CONT2
AJA         DECFSZ  CONT2,F 
            GOTO    AJA
            DECFSZ  CONT1,F
            GOTO    AJA1
            RETURN   


INICIO      BSF       STATUS,5
            CLRF      TRISD
           CLRF      TRISC
           BCF       STATUS,5
           MOVLW     0x1F
           MOVWF     VUELTA1  

INICIO2    CLRF      PORTC        
           CLRF      PORTD
           CALL      RETA2
           CALL      RETA2
           MOVLW     b'11111110'  ;PONER TIERRA EN ULTIMA COLUMNA...prende primer punto
           MOVWF     PORTD
           MOVLW     b'0000001'      ;prende la primera fila de arriba hacia abajo
           MOVWF     PORTC
           CALL      RETA2
           CALL      RETA2

T1      MOVLW     b'11111110' 
        MOVWF     PORTD
        MOVLW     b'0000001'  ; PRIMER punto
        MOVWF     PORTC
        CALL      RETARDO
         CALL      RETARDO 
        MOVLW     b'11111101'  ; ACTIVAR LA COLUMna 2
        MOVWF     PORTD
        MOVLW     b'0000001'  ;  PRENDE EL segundo punto
        MOVWF     PORTC
       CALL      RETARDO 
         CALL      RETARDO 
        DECFSZ    VUELTA1,F
        GOTO      T1
        MOVLW     0X1F
        MOVWF     VUELTA1
```
parte donde ya cruzo la pagina 0

```
R2  MOVLW     b'10111111'  ; ACTIVA EL PALO DE R
    MOVWF     PORTD
    MOVLW    b'1111111'  ;LO ACTIVA
    MOVWF     PORTC
    PAGESEL RETARDO 
    CALL    RETARDO
    MOVLW     b'11011111'  ; ACTIVA DOS PUNTOS DE R
    MOVWF     PORTD
    MOVLW    b'0001001'  ;LOS ACTIVA
    MOVWF     PORTC
    PAGESEL RETARDO 
    CALL    RETARDO
    MOVLW     b'11101111'  ; ACTIVA OTROS DOS PUNTOS DE R
    MOVWF     PORTD
    MOVLW     b'0011001'    ;LOS ACTIVA
    MOVWF     PORTC
    PAGESEL RETARDO 
    CALL    RETARDO
    MOVLW     b'11110111'  ; ACTIVA TRES PUNTOS DE LA R
    MOVWF     PORTD
    MOVLW     b'0100110'    ;LOS ACTIVA
    MOVWF     PORTC
    PAGESEL RETARDO 
    CALL    RETARDO
    MOVLW     b'11111011'  ; ACTIVA EL ULTIMO PUNTO DE LA R
    MOVWF     PORTD
    MOVLW     b'1000000'    ;LOS ACTIVA
    MOVWF     PORTC
    PAGESEL RETARDO 
    CALL    RETARDO
    MOVLW     b'11111110'  ; ACTIVA EL PALO DE LA SEGUNDA E
    MOVWF     PORTD
    MOVLW     b'1111110'    ;LOS ACTIVA
    MOVWF     PORTC
   PAGESEL RETARDO 
    CALL    RETARDO
     DECFSZ    VUELTA1,F
     GOTO      R2
     MOVLW     0X1F
     MOVWF     VUELTA1
```

en esta parte solo utilizo el CALL sin el LCALL por que me marca un Message[307] K:\MATRIZ_LEDS\MATRIZ887_PRUE.ASM 2029 : Setting page bits. por esa razon no se si este correcto.

de antemano gracias.


----------



## Edwardjusto (May 30, 2012)

Y sabes como se puede hacer ese salto de pagina pero en el Mikro C, nesecito esa instruccion, te lo agradeceria mucho


----------



## teguoc (Nov 12, 2012)

buenos dias chekolieneas

debes usar el LCALL en tu programa y colocar ERRORLEVEL -307 (que es el que elimina los errores del LCALL) a continuación de la palabra de configuración.

espero sea de ayuda

saludos


----------



## kenoby (Ene 21, 2015)

Hola amigos, tengo una duda y estoy cansado de buscar sin encontrar respuesta, asi que pregunto a ustedes. 
hace bastante que hago varias cosas con pics básicos (16f628 12f629 16f84 etc..) pero hubo algo que siempre me quedo colgado y es el uso de las paginas de memoria de programa.
Compilo mi codigo assembler con MPLAB v8.56. y siempre pregunta si va a ser absolute o relocatable code y tengo entendido que es respecto a la disposicion que va a tener el programa respecto a las páginas pero no entiendo muy bien la diferencia. y sobre todo* ¿cuales son las direcciones de las 4 paginas que tiene un pic 16f628a?* eh mirado del datasheet y no encuentro nada. 
tengo entendido también que si no se administran bien, puede causar imprevistos.

por favor, acudo a ustedes como ultima opción. saludos y gracias.
por cierto, si alguien me puede recomendar un buen tutorial de pics (16f628) no básico pero entendible se lo agradecería. gracias.


----------



## papirrin (Ene 21, 2015)

> ¿cuales son las direcciones de las 4 paginas que tiene un pic 16f628a?


Supongo que te refieres a los bancos, fijate en el capitulo de memory organization, si no te refieres a eso haz caso omiso de mi comentario porque yo nunca he escuchado eso de paginas.


----------



## kenoby (Ene 21, 2015)

no, no son los bancos de memoria, gracias igual.

cito algo que es de otro foro:


> Estás confundiendo los bancos de memoria RAM con las páginas de la memoria de programa. Los cambios de bancos son para la memoria RAM y escribir datos en la memoria RAM o ver los estados de los diferentes registros ubicado en la RAM.
> 
> Lo que tu quieres hacer es con las páginas de la memoria de programa y se hace con la directiva org. Tienes que dirigirte al datasheet del microcontrolador y ver hasta que direccionamiento cambia de página.


extraido de
http://www.ucontrol.com.ar/forosmf/programacion-en-asm/como-hago-para-escribir-codigo-en-otro-banco-del-pic16f628a/?wap2


----------



## papirrin (Ene 21, 2015)

aahhh supongo que se refiere a esto:
Ver el archivo adjunto 124026



busca informacion de pcl pclath

Ver el archivo adjunto 124027

en teoria si la memoria del 16f628A es 1K, son 1024/256=4paginas y las cambias con el PCLATH.


----------



## kenoby (Ene 21, 2015)

si, es eso. entonces primero tengo que estudiar bien el tema de pcl. muchas gracias


----------



## MrAlphonse (Ene 21, 2015)

El contador del programa, para los microcontroladores de Rango Medio esta formado por dos registros: 

PCL = contiene los primeros 8 bits del contador del programa, por lo tanto maneja hasta un máximo de 256 líneas de código. 

PCLATH = contiene los últimos 5 bits del contador de programa, por lo tanto maneja, en conjunto con el PCL, hasta 8192 líneas de código. 

¿Cómo influye el contador del programa en el desarrollo de mi programa? 

Dependiendo de la memoria flash que tenga tu microcontrolador, 2048 líneas para el 16F628A, y de como coloques tu programa dentro de la memoria, el correcto funcionamiento de tu programa puede verse afectado por una mala paginación. 

¿Como se realiza la paginación del código? 

Para los microcontroladores de medio rango los primeros 11 bits del contador del programa (los 8 del PCL y los tres primeros de PCLATH (PCLATH<2:0>)) se cambian automáticamente, es decir, no es necesario manejarlos de manera manual, puedes realizar instrucciones como CALL y GOTO entre las 2048 líneas de una pagina sin ningún problema de paginación dentro de ella. 

El problema viene cuando necesitas llamar una rutina que se encuentra fuera de la página que estas trabajando, es decir, cuando necesitas manejar los últimos dos bits del contador (PCLATH <4:3>) pues estos es necesario que se manejen de manera manual. 

Ejemplo:


```
;----------------------------------------------------------------------------------------
	ORG		0x0000					;PAGINA 0 DEL PIC
CICLO_PAG_0
	;AQUI LLAMAREMOS UNA FUNCION QUE SE ENCUENTRA EN LA PAGINA 0
	
	CALL	FUNCION_0_PAGINA_0		;AQUI NO HAY PROBLEMA DE PAGINACION PUES ESTAS LLAMANDO 
									;UNA FUNCION QUE SE ENCUENTRA ENTRE LAS 2048 LINEAS
									;QUE COMPRENDE ESTA PAGINA, LA PAGINA 0
									
	;AQUI LLAMAREMOS UNA FUNCION QUE SE ENCUENTRA EN LA PAGINA 1, ES DECIR UNA FUNCION QUE ESTA
	;EN LAS SEGUNDAS 2048 LINEAS
									
	BSF		PCLATH,3				;ACCEDEMOS A LA PAGINA 1 DEL PROGRAMA DEL PIC
	CALL	FUNCION_0_PAGINA_1		;LLAMAMOS A UNA FUNCION DE LA PAGINA 1
	BCF		PCLATH,3				;VOLVEMOS A REGRESAR EL CONTANDOR DEL PROGRAMA A LA PAGINA 0
	
;NOTA:		SE MENCIONA EN EL DATASHEET QUE: PUEDES O NO REESTABLECER EL VALOR CORRECTO DEL PCLATH
;			CUANDO REGRESAS DE UNA FUNCION, PERO TE RECOMIENDO QUE LO HAGAS, PUES SI LO OLVIDAS, 
;			CUANDO REALICES EL LLAMADO DE OTRA FUNCION, YA SEA QUE SE ENCUENTRE EN LA PAGINA QUE 
;			QUIERES O EN OTRA, PUEDES TENER PROBLEMAS CON EL HILO DE COMO SE LLEVA A CABO TU PROGRAMA	
	
	;AQUI LLAMAREMOS OTRA FUNCION QUE SE ENCUENTRA EN LA PAGINA 0
	
	CALL	FUNCION_1_PAGINA_0
		
FUNCION_0_PAGINA_0
	;CODIGO DE LA FUNCION
	;
	;
	RETURN
	
	
FUNCION_1_PAGINA_0
	;CODIGO DE LA FUNCION
	
	;DENTRO DE ESTA FUNCIÓN, LLAMAMOS A OTRA FUNCION QUE SE ENCUENTRA EN LA PAGINA 1	
	BSF		PCLATH,3
	CALL	FUNCION_1_PAGINA_1
	BCF		PCLATH,3		
	;
	RETURN
	GOTO		CICLO_PAG_0

;----------------------------------------------------------------------------------------
ORG		0x0800						;PAGINA 1 DEL PIC
	
FUNCION_0_PAGINA_1
	;CODIGO DE LA FUNCION			;TODO ESTE CODIGO SE ENCUENTRA EN LA PAGINA 1 DEL PIC
	;
	;
	RETURN
		
FUNCION_1_PAGINA_1
	;CODIGO DE LA FUNCION

	;AQUI LLAMAMOS A UNA FUNCION QUE SE ENCUENTRA DENTRO DE LA PAGINA 0				
	BCF		PCLATH,3
	CALL	FUNCION_0_PAGINA_0
	BSF		PCLATH,3
	
	;CODIGO DE LA FUNCION
	;
	RETURN
	
	
	END
```
 
Esto también puede afectar cuando haces los "INCLUDE" de las librerías, pues si las librerías se encuentran entre paginas, debes de saber en que paginas se encuentran estas para no causar problemas. 
En tu caso, no debes de tener ningún problema de paginación manual, pues tu microcontrolador solo maneja 2048 líneas de código, es decir, no es necesario manejar PCLATH<4:3>, esas líneas se manejan de manera automática con los 11 bits del contador del programa. Pero no esta de mas saberlo para cuando migres a microcontroladores de mayor memoria flash.


----------



## papirrin (Ene 21, 2015)

> En tu caso, no debes de tener ningún problema de paginación manual, pues tu microcontrolador solo maneja 2048 líneas de código



Con razon yo nunca habia oido hablar de las paginas, nada mas el 628 he programado en ASM XD.

muy clara tu explicacion...


----------



## dragon33 (Ene 22, 2015)

El nombre dijo:


> Evita problemas con:
> PAgesel "etiqueta"
> Al ensamblar te genera el código necesario sin tener que pensar en que banco la tienes (la etiqueta, naturalmente)
> 
> Saludos




¿Podría poner un pequeño ejemplo en ensamblador?


----------



## MrAlphonse (Ene 22, 2015)

Al igual que BANKSEL, PAGESEL es tomado por el compilador como un comando a ser convertido a ensamblador, solo que PAGESEL es utilizado para hacer cambios de pagina del programa (memoria flash) y BANKSEL se utiliza para hacer cambios en los bancos de memoria RAM y registros especiales del micro controlador. 

Cuando utilizas BANKSEL tienes que especificar el registro al que te quieres dirigir, por ejemplo:



CMCON se encuentra en el banco 1 de la memoria RAM de PIC16F873A,874A,876A y 877A; por lo tanto es necesario realizar el cambio de los bits STATUS <RP1:RP0>. Y es lo que hace la comando BANKSEL, cambia esos bits para asegurarte de que estés en el Banco adecuado. 

Ahora, te muestro la misma rutina, pero en ensamblador:



NOTA: Te preguntaras por que en el "Program Memory" aparece MOVWF CCPR2H en lugar de aparecer MOVWF CMCON como la instrucción lo pide. Bueno, pues es un "error" que tiene IDE, en realidad lo que sucede es que, si vas al Datasheet, CCPR2H y CMCON están a la misma "altura" de bancos: 



Y los toma como si se tratase del mismo registro, pero no, el puntero se dirige al registro CMCON, de ahí se origina el famoso mensaje: 

Message[302]C: ...  Register in operand not in bank 0.  Ensure that bank bits are correct. 

El cual eliminas con: errorlevel      -302





Ahora, y disculpa que te haya tirado el choro acá arriba pero es mejor demostrar con ejemplos, te muestro lo de PAGESEL. 

Funciona de la misma manera que BANKSEL. Es un comando que toma MPLAB para convertir a ensamblador. Solo que aquí, en lugar de darle como referencia un Banco de trabajo, le das como referencia una etiqueta, es decir:



Y la instrucción es cambiar los bits de PCLATH. Como podrás darte cuenta, lo que se hace es poner el comando PAGESEL seguido de la etiqueta, esto te dirigirá a la pagina en la que se encuentra esa etiqueta y después puedes llamar a esa etiqueta y a cualquier otra que se encuentre dentro de esa misma página, solo recuerda que cuando ya no vayas a trabajar con funciones o etiquetas de esa pagina debes de regresar a la página en la que estabas trabajando, puedes volver a utilizar PAGESEL y poner la etiqueta de una función que se encuentre en esa pagina, por que, cabe aclarar, PAGESEL no te dirige a funciones, te dirige a paginas donde se encuentran esas funciones, yo puedo venir y poner: 


```
PAGESEL    FUNCION_0_PAG_1 
	;PERO DESPUES VENIR Y LLAMAR A 
	CALL        FUNCION_1_PAG_1
```

Ahora, te muestro como se hace en ensamblador:



Si te das cuenta, aquí me ahorre una línea de código al poner solo BSF    PCLATH,4; puesto que yo sabia que me encontraba trabajando en la pagina 0 (unas cuantas líneas arriba estaba el código ORG 0x0000), solo hice el cambio de PCLATH,4 para dirigirme a la pagina 2. 

Como te darás cuenta son exactamente lo mismo, solo que PAGESEL y BANKSEL siempre tomaran 2 líneas de código de ensamblador puesto que no sabe en que página o banco se encuentran trabajando. Tú como programador sabes en que banco y pagina trabajas y puedes ahorrarte unas cuantas líneas de código al saber eso, líneas que te ahorran tiempo de procesamiento. 

Esos cambios de banco y de pagina son en los que muchas veces los compiladores, no dedicados a ensamblador, abusan y generan "código basura" y te consumen memoria flash.


----------



## kenoby (Ene 26, 2015)

MrAlphonse dijo:


> En tu caso, no debes de tener ningún problema de paginación manual, pues tu microcontrolador solo maneja 2048 líneas de código, es decir, no es necesario manejar PCLATH<4:3>, esas líneas se manejan de manera automática con los 11 bits del contador del programa. Pero no esta de mas saberlo para cuando migres a microcontroladores de mayor memoria flash.



o sea que no puedo tener mas de una tabla en mi programa con un pic 16f628?
segun entiendo cada tabla se relaciona con una pagina. y entonces a que se refieren en http://www.puntoflotante.net/tablas.htm cuando hablan de las 8 paginas del pic 16f628???

muchas gracias, saludos


----------



## papirrin (Ene 26, 2015)

> o sea que no puedo tener mas de una tabla en mi programa con un pic 16f628?



No, nada tienen que ver las tablas con las paginas. excepto que una table se coloca dentro de una pagina, o varias paginas. y puedes tener tantas tablas como quepan en la memoria de programa.

por ejemplo aqui dice



> Finalmente se ofrece un ejemplo de manejo de tablas y arreglos de datos: en este archivo se muestra un programa de ejemplo que accesa y transfiere a RAM *los elementos de una tabla de 16 datos en la página 0 de la memoria de código*:



el compañero a lo que se refiere es que en el 16f628 el cambio de esas paginas *es automatico* y no es necesario utilizar el PCLATH, en pic mas grandes o de mas de 8 paginas hay que hacerlo manual, sin descartar que en el 628 puedes hacerlo manual.



> y entonces a que se refieren en http://www.puntoflotante.net/tablas.htm cuando hablan de las 8 paginas del pic 16f628???



la memoria del 16f628 es de 2048 lo divides entre 256 de cada pagina te da 8 paginas


----------

