; º º ; º _\\|//_ º ; º (` o-o ') º ; º------ooO-(_)-Ooo----------------------------------------------------º ; º º ; º www.todopic.com.ar º ; º .oooO Oooo. º ; º ( ) ( ) obtenga su email gratis º ; º_____\ (_______) /___________________________________________________º ; º \_) (_/ º ; ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; ; Si quiere convertir este archivo a formato Unix, escriba ; el siguiente lo siguiente en el interprete de comandos: ; prompt$ dos2unix OSPIC1xx.ASM ; ; Si contribuye en el desarrollo, ponga sus datos en "autores". ; ;*********************************************************************** ;* * ;* nombre de archivo : OSPIC104.ASM * ;* fecha de inicio : Sabado 27 de abril del 2002 * ;* version : 1.04 * ;* autores ; Néstor A. Marchesini * ;* ; nestorm@xinet.com.ar * ;* * ;*********************************************************************** ;* * ;* Descripción: * ;* * ;* Kernel con tres niveles de prioridad y 8 tareas por nivel de * ;* prioridad, es decir 24 tareas en total. * ;* * ;* Notas: * ;* * ;* El kernel tiene tres niveles de prioridad y 8 tareas en * ;* prioridad por cada nivel, las tareas de mayor prioridad son las * ;* del nivel Prioridad_0, estas son testedas secuencialmente desde * ;* la tarea 0 hasta la 7, ejecutando laa tareas asignadas. * ;* Solo cuando no hay tareas pendientes de ejecutarse en la * ;* Prioridad_0, se actualizará el registro de sombra de la * ;* Prioridad_1 y será ejecutada una sola tarea de Prioridad_1, * ;* luego volverá a comenzar con la Prioridad_0, pero se * ;* incrementará un contador de Prioridad_1 para la próxima vez que * ;* toque ejecutar una tarea de Prioridad_1, de manera que se * ;* ejecute la tarea numero 1 del nivel de Prioridad_1 y no la * ;* tarea 0 del nivel de Prioridad_1. * ;* Solo cuando no hay tareas pendientes de ejecutarse en la * ;* Prioridad_0 y la Prioridad_1, se actulizará el registro de * ;* sombra de la Prioridad_2 y será ejecutada una sola tarea de * ;* Prioridad_2, luego volverá a comenzar con la Prioridad_0, pero * ;* se incrementará un contador de Prioridad_2 para la próxima vez * ;* que toque ejecutar una tarea de Prioridad_2, de manera que se * ;* ejecute la tarea numero 1 del nivel de Prioridad_2 y no la * ;* tarea 0 del nuvel de Prioridad_2. * ;* La tareas deberán ser lo mas pequeñas posible e cuanto al tiempo * ;* utilizado. * ;* Las tareas serán asignadas por otras tareas poniendo a 1 el bit * ;* correspondiente en el registro de demanda de tareas (DPx,x) pero * ;* antes deberá cargarse el identificador de la subrutina asignada * ;* al nivel de prioridad y tarea requerida. * ;* * ;* Ejemplo * ;* * ;* Aqui se asigna "dentro de una tarea" la subrutina 11 al nivel 1 * ;* de prioridad y tarea 5. * ;* * ;* movlw D'11' * ;* movwf P1T5 * ;* bsf DP1,5 * ;* * ;*********************************************************************** ; TITLE "Poner aqui el titulo de la aplicación" SUBTITLE "Revision Nø " LIST F = INHX8M, MM = ON, T = ON, ST = OFF; X = OFF RADIX HEX ERRORLEVEL 0, -302, -306, -226 PROCESSOR 16F84 #INCLUDE __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC __IDLOCS H'0000' ; ; B'00111111' B'11110001' ; 3F F1 ; 3FF1 ; ; Configuration Bits 16F84A ; ; SCRAMBLER CP PWRTE WDT OSC ; ; 00 = SI 0 = SI 0 = SI 0 = NO 00 = LP ; 3F = NO 1 = NO 1 = NO 1 = SI 01 = XT ; 10 = HS ; 11 = RC ; ;*********************************************************************** ;* Cristal utilizado * ;*********************************************************************** ; ; 04Mhz en modo XT con 1useg por instrucción ; ;*********************************************************************** ;* Descripcion del uso de cada pin. * ;*********************************************************************** ; ; LIBRE ( ) RA2 pin 1 ; LIBRE ( ) RA3 pin 2 ; LIBRE ( ) RA4/TOCK1 pin 3 ; MCLR/VPP ( reset y voltage Vpp ) MCLR/VPP pin 4 ; VSS ( negativo 0V ) VSS pin 5 ; LIBRE ( ) RB0/INT pin 6 ; LIBRE ( ) RB1 pin 7 ; LIBRE ( ) RB2 pin 8 ; LIBRE ( ) RB3 pin 9 ; LIBRE ( ) RB4 pin 10 ; LIBRE ( ) RB5 pin 11 ; LIBRE ( ) RB6 pin 12 ; LIBRE ( ) RB7 pin 13 ; VDD ( positivo 5V ) VDD pin 14 ; OSC ( salida 4Mhz XT ) OSC2/CLKOUT pin 15 ; OSC ( entrada 4Mhz XT ) OSC1/CLKIN pin 16 ; LIBRE ( ) RA0 pin 17 ; LIBRE ( ) RA1 pin 18 ; ;*********************************************************************** ;* Definicion de puertos * ;*********************************************************************** ; ;#define PORTA,0 ;#define PORTA,1 ;#define PORTA,2 ;#define PORTA,3 ;#define PORTA,4 ; ;#define PORTB,0 ;#define PORTB,1 ;#define PORTB,2 ;#define PORTB,3 ;#define PORTB,4 ;#define PORTB,5 ;#define PORTB,6 ;#define PORTB,7 ; ;*********************************************************************** ;* Asignación de ID de tarea a cada subrutina del usuario * ;*********************************************************************** ; ; Esta es la tabla de asignación de equivalencias de los Id de tarea ; a las subrutinas del usuario (tareas que serán asignadas al sistema ; operativo). En este caso de ejemplo se repiten las asignaciones de ; los Id a solo 3 subrutinas. ; Tarea_00 = Temp_1000 Tarea_01 = Temp_100 Tarea_02 = Temp_Disparo Tarea_03 = Temp_1000 Tarea_04 = Temp_100 Tarea_05 = Temp_Disparo Tarea_06 = Temp_1000 Tarea_07 = Temp_100 Tarea_08 = Temp_Disparo Tarea_09 = Temp_1000 Tarea_10 = Temp_100 Tarea_11 = Temp_Disparo Tarea_12 = Temp_1000 Tarea_13 = Temp_100 Tarea_14 = Temp_Disparo Tarea_15 = Temp_1000 Tarea_16 = Temp_100 Tarea_17 = Temp_Disparo Tarea_18 = Temp_1000 Tarea_19 = Temp_100 Tarea_20 = Temp_Disparo Tarea_21 = Temp_1000 Tarea_22 = Temp_100 Tarea_23 = Temp_Disparo Tarea_24 = Temp_1000 Tarea_25 = Temp_100 Tarea_26 = Temp_Disparo Tarea_27 = Temp_1000 Tarea_28 = Temp_100 Tarea_29 = Temp_Disparo Tarea_30 = Temp_1000 Tarea_31 = Temp_100 ; ;*********************************************************************** ;* Definicion de RAM.para el sistema operativo * ;*********************************************************************** ; CBLOCK H'0C' ; ;Registros de demanda de tareas DP0 DP1 DP2 ;Registros de sombra de tareas SP0 SP1 SP2 ;Asignación de tareas para la prioridad 0 P0T0 P0T1 P0T2 P0T3 P0T4 P0T5 P0T6 P0T7 ;Asignación de tareas para la prioridad 1 P1T0 P1T1 P1T2 P1T3 P1T4 P1T5 P1T6 P1T7 ;Asignación de tareas para la prioridad 2 P2T0 P2T1 P2T2 P2T3 P2T4 P2T5 P2T6 P2T7 ;Registros indicadores de próxima tarea a realizarse para los niveles ;de Prioridad_1 y Prioridad_2 Contador_Prioridad_1 Contador_Prioridad_2 ;Registros puntero de dirección a la subrutina a ejecutarse y de tarea ;a ejecutarse Tarea_H Tarea_L Tarea ;Registros para salvar W y Status durante las interrupciones SalvaW SalvaStatus ; ;*********************************************************************** ;* Definicion de RAM.para las subrrutinas del usuario * ;*********************************************************************** ; Contador_A ; ENDC ; ;*********************************************************************** ;* Macros del sistema operativo * ;*********************************************************************** ; Asignar_Tarea macro Id_Tarea, PxTx expand movlw Id_Tarea movwf PxTx ; noexpand if PxTx == P0T0 expand bsf DP0,0 noexpand endif ; if PxTx == P0T1 expand bsf DP0,1 noexpand endif ; if PxTx == P0T2 expand bsf DP0,2 noexpand endif ; if PxTx == P0T3 expand bsf DP0,3 noexpand endif ; if PxTx == P0T4 expand bsf DP0,4 noexpand endif ; if PxTx == P0T5 expand bsf DP0,5 noexpand endif ; if PxTx == P0T6 expand bsf DP0,6 noexpand endif ; if PxTx == P0T7 bsf DP0,7 endif ; if PxTx == P1T0 expand bsf DP1,0 noexpand endif ; if PxTx == P1T1 expand bsf DP1,1 noexpand endif ; if PxTx == P1T2 expand bsf DP1,2 noexpand endif ; if PxTx == P1T3 expand bsf DP1,3 noexpand endif ; if PxTx == P1T4 expand bsf DP1,4 noexpand endif ; if PxTx == P1T5 expand bsf DP1,5 noexpand endif ; if PxTx == P1T6 expand bsf DP1,6 noexpand endif ; if PxTx == P1T7 expand bsf DP1,7 noexpand endif ; if PxTx == P2T0 expand bsf DP2,0 noexpand endif ; if PxTx == P2T1 expand bsf DP2,1 noexpand endif ; if PxTx == P2T2 expand bsf DP2,2 noexpand endif ; if PxTx == P2T3 expand bsf DP2,3 noexpand endif ; if PxTx == P2T4 expand bsf DP2,4 noexpand endif ; if PxTx == P2T5 expand bsf DP2,5 noexpand endif ; if PxTx == P2T6 expand bsf DP2,6 noexpand endif ; if PxTx == P2T7 expand bsf DP2,7 noexpand endif ; endm ; ;*********************************************************************** ;* Vector de inicio del PIC * ;*********************************************************************** ; ORG H'000' goto Inicio ; ;*********************************************************************** ;* ISR * ;*********************************************************************** ; ORG H'004' ; Interrupciones ; ;Salva registros ; movwf SalvaW ;Salva W swapf STATUS,W ;Invierte STATUS --> W movwf SalvaStatus ;Salva STATUS ; ;Selector y asingnacion de prioridades de atención a las interrupciónes ; btfsc INTCON,RBIF ;? Hubo algun cambio de RB4-RB7 ? goto Rb ;Si btfsc INTCON,T0IF ;? Hubo sobrefujo en TMR0 ? goto T0 ;Si btfsc INTCON,INTF ;? Hubo interrupcion en RB0 ? goto In ;Si ; Ee bsf STATUS,RP0 ;Banco 1 bcf EECON1,EEIF ;Pone a cero el indicador para poder salir de la ISR bcf INTCON,EEIE ;Sacar si se quiere seguir capturando interrupciones bcf STATUS,RP0 ;Banco 0 goto RestaurarRegistros ;Retorna habilitando todas las interrupciones ; Rb bcf INTCON,RBIF ;Pone a cero el indicador para poder salir de la ISR bcf INTCON,RBIE ;Sacar si se quiere seguir capturando interrupciones goto RestaurarRegistros ;Retorna habilitando todas las interrupciones ; T0 bcf INTCON,T0IF ;Pone a cero el indicador para poder salir de la ISR bcf INTCON,T0IE ;Sacar si se quiere seguir capturando interrupciones goto RestaurarRegistros ;Retorna habilitando todas las interrupciones ; In bcf INTCON,INTF ;Pone a cero el indicador para poder salir de la ISR bcf INTCON,INTE ;Sacar si se quiere seguir capturando interrupciones ; RestaurarRegistros swapf SalvaStatus,W ;Invierte STATUS --> W movwf STATUS ;Restaura STATUS swapf SalvaW,F ;Invierte --> F swapf SalvaW,W ;Restaura W retfie ;Retorna habilitando todas las interrupciones ; ;*********************************************************************** ;* Subrutinas de las tareas del usuario * ;*********************************************************************** ; ; Temp_1000 = ((D'249' * 4) + 5) = 1001 ; ; Temp_1000 ; movlw D'249' movwf Contador_A nop decfsz Contador_A,F goto $ - 2 return ; ;*********************************************************************** ; ; Temp_100 = ((D'24' * 4) + 5) = 101 ; ; Temp_100 ; movlw D'24' movwf Contador_A nop decfsz Contador_A,F goto $ - 2 return ; ; ;*********************************************************************** ; ; Temp_Disparo = ((D'24' * 4) + 5) = 101 ; ; Temp_Disparo ; movwf Contador_A nop decfsz Contador_A,F goto $ - 2 return ; ;*********************************************************************** ;* Sistema Operativo * ;*********************************************************************** ; Inicio ; clrf Contador_Prioridad_1 clrf Contador_Prioridad_2 ; ; Las primeras tareas del sistema operativo deberian ser por ejemplo el borrado ; de la memoria RAM y la configuración de los puertos, estas deberian ; estar asignadas a un nivel de prioridad alto, por ejemplo el mas alto "P0T0" ; ; Supongamos que la subrutina D'25' configura los puertos, entonces la asignamos ; para la ejecución mas rapida que tenemos. ; Asignar_Tarea D'25', P0T0 ; ; Supongamos ahora que la subrutina D'19' es para borrar toda la memoria RAM, ; entonces la asignamos a la tarea 1 de nivel de prioridad 0, justo despúes ; de que terminamos de configurar los puertos con la subrutina D'25'. ; Asignar_Tarea D'19', P0T1 ; Asignar_Tarea D'31', P2T3 Asignar_Tarea D'07', P1T6 ; ;*********************************************************************** ;* Testea la asignación de tareas de Prioridad_0 * ;*********************************************************************** ; Prioridad_0 movf DP0,W movwf SP0 clrf DP0 ; ;Si no hay tareas de Prioridad_0 asignadas, se pasa a testear las tareas de Prioridad_1. ; tstf SP0 skpnz goto Prioridad_1 ; Testear_Demanda_P0T0 btfss SP0,0 goto Testear_Demanda_P0T1 movf P0T0,W call Ejecutar_Tarea bcf SP0,0 ; Testear_Demanda_P0T1 btfss SP0,1 goto Testear_Demanda_P0T2 movf P0T1,W call Ejecutar_Tarea bcf SP0,1 ; Testear_Demanda_P0T2 btfss SP0,2 goto Testear_Demanda_P0T3 movf P0T2,W call Ejecutar_Tarea bcf SP0,2 ; Testear_Demanda_P0T3 btfss SP0,3 goto Testear_Demanda_P0T4 movf P0T3,W call Ejecutar_Tarea bcf SP0,3 ; Testear_Demanda_P0T4 btfss SP0,4 goto Testear_Demanda_P0T5 movf P0T4,W call Ejecutar_Tarea bcf SP0,4 ; Testear_Demanda_P0T5 btfss SP0,5 goto Testear_Demanda_P0T6 movf P0T5,W call Ejecutar_Tarea bcf SP0,5 ; Testear_Demanda_P0T6 btfss SP0,6 goto Testear_Demanda_P0T7 movf P0T6,W call Ejecutar_Tarea bcf SP0,6 ; Testear_Demanda_P0T7 btfss SP0,7 goto Prioridad_1 movf P0T7,W call Ejecutar_Tarea bcf SP0,7 ; ;*********************************************************************** ;* Testea la asignación de tareas de Prioridad_1 * ;*********************************************************************** ; Prioridad_1 ; ;Precarga y testea las tareas de Prioridad_1 solo si se ha terminado ;de ejecurse las tareas de Prioridad_1 ya cargadas. ; tstf SP1 skpz goto Testear_Demanda_SP1 movf DP1,W movwf SP1 clrf DP1 clrf Contador_Prioridad_1 ; ;Si no hay tareas de Prioridad_1 asignadas, se pasa a testear las tareas de Prioridad_2. ; tstf SP1 skpnz goto Prioridad_2 ; Testear_Demanda_SP1 movf Contador_Prioridad_1,W andlw B'00000111' addwf PCL,F goto Testear_Demanda_P1T0 goto Testear_Demanda_P1T1 goto Testear_Demanda_P1T2 goto Testear_Demanda_P1T3 goto Testear_Demanda_P1T4 goto Testear_Demanda_P1T5 goto Testear_Demanda_P1T6 goto Testear_Demanda_P1T7 ; Testear_Demanda_P1T0 btfss SP1,0 goto Testear_Demanda_P1T1 movf P1T0,W call Ejecutar_Tarea bcf SP1,0 incf Contador_Prioridad_1,F goto Prioridad_0 ; Testear_Demanda_P1T1 btfss SP1,1 goto Testear_Demanda_P1T2 movf P1T1,W call Ejecutar_Tarea bcf SP1,1 incf Contador_Prioridad_1,F goto Prioridad_0 ; Testear_Demanda_P1T2 btfss SP1,2 goto Testear_Demanda_P1T3 movf P1T2,W call Ejecutar_Tarea bcf SP1,2 incf Contador_Prioridad_1,F goto Prioridad_0 ; Testear_Demanda_P1T3 btfss SP1,3 goto Testear_Demanda_P1T4 movf P1T3,W call Ejecutar_Tarea bcf SP1,3 incf Contador_Prioridad_1,F goto Prioridad_0 ; Testear_Demanda_P1T4 btfss SP1,4 goto Testear_Demanda_P1T5 movf P1T4,W call Ejecutar_Tarea bcf SP1,4 incf Contador_Prioridad_1,F goto Prioridad_0 ; Testear_Demanda_P1T5 btfss SP1,5 goto Testear_Demanda_P1T6 movf P1T5,W call Ejecutar_Tarea bcf SP1,5 incf Contador_Prioridad_1,F goto Prioridad_0 ; Testear_Demanda_P1T6 btfss SP1,6 goto Testear_Demanda_P1T7 movf P1T6,W call Ejecutar_Tarea bcf SP1,6 incf Contador_Prioridad_1,F goto Prioridad_0 ; Testear_Demanda_P1T7 btfss SP1,7 goto Prioridad_2 movf P1T7,W call Ejecutar_Tarea clrf Contador_Prioridad_1 bcf SP1,7 ; ;*********************************************************************** ;* Testea la asignación de tareas de Prioridad_2 * ;*********************************************************************** ; Prioridad_2 ; ;Precarga y testea las tareas de Prioridad_2 solo si se ha terminado ;de ejecurse las tareas de Prioridad_2 ya cargadas. ; tstf SP2 skpz goto Testear_Demanda_SP2 movf DP2,W movwf SP2 clrf DP2 clrf Contador_Prioridad_2 ; ;Si no hay tareas de Prioridad_2 asignadas, se pasa a testear las tareas de Prioridad_0. ; tstf SP2 skpnz goto Prioridad_0 ; Testear_Demanda_SP2 movf Contador_Prioridad_2,W andlw B'00000111' addwf PCL,F goto Testear_Demanda_P2T0 goto Testear_Demanda_P2T1 goto Testear_Demanda_P2T2 goto Testear_Demanda_P2T3 goto Testear_Demanda_P2T4 goto Testear_Demanda_P2T5 goto Testear_Demanda_P2T6 goto Testear_Demanda_P2T7 ; Testear_Demanda_P2T0 btfss SP2,0 goto Testear_Demanda_P2T1 movf P2T0,W call Ejecutar_Tarea bcf SP2,0 incf Contador_Prioridad_2,F goto Prioridad_0 ; Testear_Demanda_P2T1 btfss SP2,1 goto Testear_Demanda_P2T2 movf P2T1,W call Ejecutar_Tarea bcf SP2,1 incf Contador_Prioridad_2,F goto Prioridad_0 ; Testear_Demanda_P2T2 btfss SP2,2 goto Testear_Demanda_P2T3 movf P2T2,W call Ejecutar_Tarea bcf SP2,2 incf Contador_Prioridad_2,F goto Prioridad_0 ; Testear_Demanda_P2T3 btfss SP2,3 goto Testear_Demanda_P2T4 movf P2T3,W call Ejecutar_Tarea bcf SP2,3 incf Contador_Prioridad_2,F goto Prioridad_0 ; Testear_Demanda_P2T4 btfss SP2,4 goto Testear_Demanda_P2T5 movf P2T4,W call Ejecutar_Tarea bcf SP2,4 incf Contador_Prioridad_2,F goto Prioridad_0 ; Testear_Demanda_P2T5 btfss SP2,5 goto Testear_Demanda_P2T6 movf P2T5,W call Ejecutar_Tarea bcf SP2,5 incf Contador_Prioridad_2,F goto Prioridad_0 ; Testear_Demanda_P2T6 btfss SP2,6 goto Testear_Demanda_P2T7 movf P2T6,W call Ejecutar_Tarea bcf SP2,6 incf Contador_Prioridad_2,F goto Prioridad_0 ; Testear_Demanda_P2T7 btfss SP2,7 goto Prioridad_0 movf P2T7,W call Ejecutar_Tarea bcf SP2,7 clrf Contador_Prioridad_2 goto Prioridad_0 ; ;*********************************************************************** ;* Cargador de tareas * ;*********************************************************************** ; ; Esta subrutina es la entrada comúu a todas las subrutinas del usuario. ; Los pasos de asignación, carga y ejecución son los siguientes: ; ; Ejemplo ; ; movlw D'11' ;Asigna la subrutina D'11' ; movwf P1T5 ;a la tarea 5 del nivel ; bsf DP1,5 ;de prioridad 1 ; ; Cuando el sistema operativo detecta el bit SP1,5 del registro de sombra ; de demanda de ejecución, hace un call a esta rutina, es decir, consume ; un nivel de la pila, luego esta rutina, el paso siguiente es obtener la parte ; alta y baja de la dirección de memoria de programa en donde está localizada ; la subrutina a ejecutar, una vez hecho esto, carga los registros PCLATH:PCL ; haciendo un salto directo a la entrada de la subrutina, el ultimo paso lo ; hace la subrutina después de ejecutar su codigo, es decir, retlw-return-retfie ; que saca de la pila y devuelve en call Ejecutar_Tarea + 1, para que el ; sistema operativo siga procesando las tareas y sus niveles de prioridad. ; Ejecutar_Tarea movwf Tarea call Get_Add_H movwf Tarea_H call Get_Add_L movwf Tarea_L ; ;Ejecuta la subrutina asignada, recordar que las subrutinas deben terminar con RETLW, RETURN o RETFIE. ; movf Tarea_H,W movwf PCLATH movf Tarea_L,W movwf PCL ; ;Obtiene la parte alta de la dirección de la subrutina asignada. ; Get_Add_H movlw HIGH Tareas_H movwf PCLATH movlw LOW Tareas_H movwf PCL ; ;Obtiene la parte baja de la dirección de la subrutina asignada. ; Get_Add_L movlw HIGH Tareas_L movwf PCLATH movlw LOW Tareas_L movwf PCL ; ;*********************************************************************** ;* Tablas de tareas * ;*********************************************************************** ; ; Estas tablas devuelven la dirección completa de memoria de programa ; en donde estan localizadas la subrutinas que fueron asignadas a los ; identificadores de tareas Id en la tabla de asignación de equivalencias. ; Es necesario utilizar las dos tablas Tareas_H:Tareas:L para obtener ; las direcciones de las subrutinas, puesto que se accede a la entrada ; de las mismas cargando el PCL, esta forma de goto nos obliga también ; a cargar la parte alta PCLATH del contador de programa. ; Asegurese de asignar debidamente las equivalencias Id de tareas versus subrutinas. ; ; Se pueden asignar hasta 127 subrutinas, para mas habrá que cambiar el ORG H'xxx' ; ORG H'300' Tareas_H ; ;Limita y salva el numero de subrutinas a 32 como máximo (00-31) ; movf Tarea,W andlw B'00011111' movwf Tarea addwf PCL,F retlw HIGH Tarea_00 retlw HIGH Tarea_01 retlw HIGH Tarea_02 retlw HIGH Tarea_03 retlw HIGH Tarea_04 retlw HIGH Tarea_05 retlw HIGH Tarea_06 retlw HIGH Tarea_07 retlw HIGH Tarea_08 retlw HIGH Tarea_09 retlw HIGH Tarea_10 retlw HIGH Tarea_11 retlw HIGH Tarea_12 retlw HIGH Tarea_13 retlw HIGH Tarea_14 retlw HIGH Tarea_15 retlw HIGH Tarea_16 retlw HIGH Tarea_17 retlw HIGH Tarea_18 retlw HIGH Tarea_19 retlw HIGH Tarea_20 retlw HIGH Tarea_21 retlw HIGH Tarea_22 retlw HIGH Tarea_23 retlw HIGH Tarea_24 retlw HIGH Tarea_25 retlw HIGH Tarea_26 retlw HIGH Tarea_27 retlw HIGH Tarea_28 retlw HIGH Tarea_29 retlw HIGH Tarea_30 retlw HIGH Tarea_31 ; Tareas_L ; ;Limita y salva el numero de subrutinas a 32 como máximo (00-31) ; movf Tarea,W andlw B'00011111' movwf Tarea addwf PCL,F retlw LOW Tarea_00 retlw LOW Tarea_01 retlw LOW Tarea_02 retlw LOW Tarea_03 retlw LOW Tarea_04 retlw LOW Tarea_05 retlw LOW Tarea_06 retlw LOW Tarea_07 retlw LOW Tarea_08 retlw LOW Tarea_09 retlw LOW Tarea_10 retlw LOW Tarea_11 retlw LOW Tarea_12 retlw LOW Tarea_13 retlw LOW Tarea_14 retlw LOW Tarea_15 retlw LOW Tarea_16 retlw LOW Tarea_17 retlw LOW Tarea_18 retlw LOW Tarea_19 retlw LOW Tarea_20 retlw LOW Tarea_21 retlw LOW Tarea_22 retlw LOW Tarea_23 retlw LOW Tarea_24 retlw LOW Tarea_25 retlw LOW Tarea_26 retlw LOW Tarea_27 retlw LOW Tarea_28 retlw LOW Tarea_29 retlw LOW Tarea_30 retlw LOW Tarea_31 ; END