El problema es que no sabes como funcionan las instrucciones y el micro sobre el direccionamiento.
Es el caso del GOTO/CALL. Que puede que te sirva, pero te lo digo igual.
La direccion de memoria flash del PIC16 es de 13bits.. Ocurre en cambio que para un GOTO/CALL la direccion va en el OPCODE
GOTO - 10 1kkk kkkk kkkk
CALL - 10 0kkk kkkk kkkkEs decir puede direccionar hasta 11bits. Como ejemplo si quisieras hacer un GOTO/CALL a las direcciones FLASH 0x0 y 0x800 el OPCODE quedaria:
GOTO 0x0 - 10 1000 0000 0000
CALL 0x0 - 10 0000 0000 0000
GOTO 0x800 - 10 1000 0000 0000
CALL 0x800 - 10 0000 0000 0000Como podras ver no hay ninguna diferencia entre uno u otro y estarias saltando a 0x0. Entonces tenes que asegurar que si la direccion a la que estas apuntando con tu tabla SUPERA los 11bits 0x3FF, vas a tener que modificar el registro PCLATH antes! del salto. Que para el caso del GOTO/CALL los bits que afectan a los mismos son el 4 y 3 del registro PCLATH.
Volviendo al ejemplo anterior si veo que mi funcion debe saltar a 0x800 tendria hacer:
MOVLW 0x8
MOVWF PCLATH
CALL 0x800
Entonces ahora el CALL y el PCLATH esta formado de la siguiente forma:
CALL 0x800 - 10 0
000 0000 0000PCLATH - 000
0 1000
Lo cual forma la direccion:
0 1000 0000 0000 = 0x800
Esto es rescpecto a los CALL/GOTO. Lo mismo ocurre cuando usas cualquier otra instruccion para modificar el PCL. Ejemplo
ADDWF PCL,F
RETLW ----
..
..
..
RETLW ..
El problema aca es que PCL es un registro de solo 8 bits, y por lo tanto puede direccionar 256, Pero de donde saca los 5 bits restantes? Del PCLATH
Esta ves el PCLATH aporta su 5 bits.. Un ejemplo muy simple.
;PCLATH = 0
ORG 0x0FC
MOVLW 0x3 ; 0xFD
ADDWF PCL,F ; 0xFE
RETLW 0 ; 0xFF
RETLW 1 ; 0x100
RETLW 2 ; 0x101
RETLW 3 ; 0x102
Si usas eso en ves de saltar a 0x102 y que use el RETLW, vas a saltar a la posicion 0x02. Como lo solucionas? Es simple
Llamar_Tabla1:
pageselw Tabla1 ; Esto genera un MOVLW y MOVWF a PCLATH con el valor Tabla1, PCLATH = 0x01
MOVLW Tabla1 ; Cargo el comienzo de la tabla ( 0xFE ) solo 8 bits permite el OPCODE
ADDWF Indice,W ; Se lo sumo al indice del elemento a acceder
BTFSC STATUS, C ; Esta en 1 el Carry?, es decir supero los 255 ?
INCF PCLATH, F ; Si es 1 el carry, quiere decir que tengo que incrementar el PCLATH
MOVWF PCL ; El resultado de la suma lo pongo el PCL, esta instruccion carga el PCLATH al PCH
ORG 0x1FE
Tabla1:
RETLW 0 ; 0x1FE
RETLW 1 ; 0x1FF
RETLW 2 ; 0x200
RETLW 3 ; 0x201
En este caso vamos a ir por parte, vamos a suponer que el indice es 0x3, el pageselw van a generar un MOVLW y un MOVWF al PCLATH con el valor 0x01, ya que ese valor es el que posee Tabla1.
Luego se suma el Indice al comienzo de la tabla, 0xFE + 0x3 = 0x01, y queda en W. Luego observamos el valor del carry y vemos que ocurrio un carry entonces incrementamos PCLATH dejandolo en 0x2. Y luego procedemos a mover el valor de W ( 0x01 ) a PCL, al hacer esto la direccion queda:
PCH | PCL
0 0010 0000 0001 = 0x201
La direccion de retorno no influye el PCLATH; ya que cuando se ejecuta el CALL se guardan los 13 bits en el stack
Y ahora por mas que cruce el borde de 256 bytes podes usar la tabla. Por lo del comienzo solo debes asegurarte que lo que llama a esta tabla este dentro de los 11 bits de direccionamiento. Asi no tenes que cambiar el PCLATH