PIC16F1XXX, microcontroladores PIC16 mejorados (parte 2: memoria de programa)

En esta entrada hablo de la memoria de programa en los PIC16F1XXX; de la forma de trabajar con ella usando las nuevas instrucciones: BRA, BRW, CALLW, MOVLP y RESET. En estas versiones mejoradas de los PIC16 puede haber capacidad para almacenar hasta 32768 instrucciones, lo que implica la existencia de hasta 16 páginas de 2048 localidades cada una, y un contador de programa de 15 bits. En el caso particular del PIC16F1938, figura 1, hay 16384 localidades en la memoria de programa y una pila de 16 niveles.

Figura 1. Memoria de programa y pila en un PIC16F1938.
Figura 1. Memoria de programa y pila en un PIC16F1938. La parte sombreada indica que si se intentara acceder a lo que serían las páginas 8 a 15 de otro PIC16F1, en un PIC16F1938 se accederá a las páginas 0 a 7 (sólo tiene 16384 de las 32768 localidades posibles). Esta figura pertenece a Microchip y está en la página 22 de la hoja de datos del PIC.

DIRECCIÓN CERO Y RESET. Recuerda que al energizar o reiniciar el microcontrolador, el contador de programa se pone a cero, y esto hace que la ejecución del código inicie con la instrucción que está almacenada en la dirección cero de la memoria de programa. Los PIC16 se reinician por algo que pasa en el circuito (un 0 en MCLR, se desborda el Watchdog, etc.); en los PIC16F1XXX esto puede ocurrir, además, por que se ejecuta la instrucción RESET.

Evidentemente sólo esperaríamos que el uC ejecutara una instrucción RESET si detecta un error grave. Además, no tendría sentido ejecutar exactamente el mismo código después del reinicio, porque es muy probable que esto nos lleve al mismo error. Así que usar la instrucción RESET implica:

  • Evaluar condiciones para decidir dar la orden de reinicio.
  • Averiguar si la ejecución del programa inicia por causa de esta instrucción.
  • Escribir un código que arregle el problema causante del reinicio.

En la figura 2 te muestro un código para verificación de “reinicio por programa” y, en su caso, llamada a subrutina para arreglar el error. Observa que la bandera que avisa del uso de RESET se llama RI y se encuentra en el registro PCON, que está en el banco 1.

Figura 2. Código mínimo para llamar a una subrutina en caso de reinicio por programa.
Figura 2. Código mínimo para llamar a una subrutina en caso de reinicio por programa. En este ejemplo se alcanza inevitablemente la instrucción RESET en la línea 14, pero en la primera ejecución no se llamará a la subrutina CORREGIR_ERROR. Después de arrancar la simulación, que se detiene inmediatamente por el punto de paro en la línea 9, oprimí 8 veces la tecla F7 para llegar a la situación que muestro.

Observa que como diseñador siempre tendrás la responsabilidad de evitar las fallas, la instrucción RESET sólo te proporciona otra modalidad de programar un código libre de situaciones descontroladas. En la página 82 de la hoja de datos del PIC16F1938 encontrarás más información referente a cómo determinar las causas de un reinicio del uC.

SALTOS RELATIVOS. La instrucción BRA ejecuta saltos a instrucciones que se encuentran cerca de ella. Es decir, la etiqueta que usamos después de BRA debe aparecer también al inicio de una línea que está, cuando muy lejos, 255 instrucciones antes o después de BRA. Para ejemplificar su funcionamiento ocuparé código que traspasa la frontera entre dos páginas de la memoria de programa (de otra forma, no se le vería ninguna ventaja al ser comparada con GOTO). Recuerda que GOTO tiene alcance dentro de una página; para saltar a otra página (aunque la instrucciones de origen y destino del salto estén muy cera) habría que poner atención al contenido del registro PCLATH (capítulo 4 del libro).

En la versión 8.53 del MPLAB (figura 3) no era necesario escribir código para hacer notar que se pasaba de una página a otra; en la versión 4.00 del MPLAB X, es necesario agregar directivas ORG (línea 15 del ejemplo siguiente – figura 4).

Figura 3. Figura 4.13 del libro que usé originalmente para hablar de la instrucción GOTO.
Figura 3. Figura 4.13 del libro que usé originalmente para hablar de la instrucción GOTO. Ahora nos sirve para observar que en versiones previas del MPLAB no era necesario escribir directivas cuando el código llenaba una página y continuaba en la siguiente – al trabajar en ensamblador, era responsabilidad exclusiva del programador darse cuenta que su código pasaba de una página a otra.
Figura 4. Código para ejemplificar el uso del salto relativo (instrucción BRA). Observa que usé la directiva ORG para simular un código que NO cabe en la página 0. Observa también que la versión 4.00 del MPLAB X, requiere que escribas de forma explícita (directiva ORG de la línea 15) en que página de la memoria de programa se acomodan los segmentos de código. Si reemplazas la instrucción BRA por GOTO, el programa fallará, es decir, el salto NO llegará a la línea con la etiqueta OTRA_PAG.

En lugar de escribir más, te sugiero que pruebes el código, que observes el paso de una página a otra sin usar PCLATH; y que después continúes las pruebas quitando las directivas ORG de las líneas 8 y 15. En este último caso, el programa funcionará exactamente igual con instrucciones BRA o GOTO; esto se debe a que todas las instrucciones quedarían en la página 0 y ninguna quedaría muy lejos de las ordenes de salto.

Por lo relacionado del tema, te comento en este punto que la instrucción MOVLP permite establecer el valor del registro PCLATH en un sólo paso (MOVLP k en lugar de MOVLW k y MOVWF PCLATH).

TABLAS. Puedes usar tablas, por ejemplo, para almacenar datos de calibración de sensores o resultados de cálculos “demasiado complejos”. En las sección 4.2.2 del libro abordé el diseño y uso de tablas, el programa mapa.asm (página 411) es un ejemplo de una tabla con 1024 elementos. Ahora ejemplificaré el uso de las nuevas instrucciones BRW, CALLW y MOVLP en el diseño de tablas.

Al igual que BRA, BRW ejecuta un salto relativo. En esta ocasión, es la posición de BRW y el contenido del registro de trabajo lo que se usa para determinar a que posición se debe saltar. El registro de trabajo puede contener números entre 0 y 255, así que la dirección de destino sólo puede estar hasta 256 posiciones adelante de la instrucción BRW. También al igual que en BRA, lo que se gana es poder saltar de una página a otra sin preocuparse por PCLATH.

Llamé TablaBRW.asm al programa de ejemplo. Éste consiste en un ciclo que extrae los 256 valores de la tabla. Ya que el valor del registro de trabajo será igual antes y después de leer la tabla, te recomiendo que simules paso por paso el código para observar su funcionamiento. La figura 5 muestra una captura de pantalla durante la sexta iteración del ciclo en el programa.

Figura 5. Captura de pantalla durante la simulación de TablaBRW.
Figura 5. Captura de pantalla durante la simulación de TablaBRW. Se muestra el momento en que se leerá el primer elemento de la tabla que está en la página 1. Observa que el registro de trabajo contiene un 5, y que la tabla devolverá también un 5. La intención de devolver el valor de contador es facilitar la verificación del código al simularlo paso por paso.

Podría decirse que la instrucción CALLW es una combinación de CALL y BRW. Con la ayuda de PCLATH, CALLW permite acceder a una tabla en cualquier posición de la memoria de programa, y el contenido del registro de trabajo indicará el elemento de la tabla que debe ser extraído. TablaCALLW.asm es el programa que te ofrezco como ejemplo. La captura de pantalla está en la figura 6. Observa que usé MOVLP para establecer el valor de PCLATH, que la tabla sólo consta de valores y, de una vez, que en los PIC16F1XXX el registro de trabajo está mapeado en la memoria de datos.

Figura 6. Captura de pantalla durante la simulación de TablaBRW.
Figura 6. Captura de pantalla durante la simulación de TablaBRW.

Muchas gracias y hasta la próxima.

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *