Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Alexis Sanchez
Figura 38 Principio de determinación de los bits de mayor peso del PC por PCLATCH
Bit 5 y 6: RP0 y RP1 o bits de selección de página. Sirven para escoger si se quiere
trabajar en el banco 0 o en el 1. En la figura 39 se detallan sus posibles condiciones, y a
continuación las que se usan comúnmente.
RP0 RP1
- 0 0: Banco de memoria 0 (00h-7Fh)
- 0 1: Banco de memoria 1 (80h-FFh)
Figura 39. Posibles configuraciones de los bits de selección de página. El bit RP1 deberá
ser puesto a cero, ya que si no nos saldríamos del rango de memoria.
Bit 7: bit IRP. Este bit está previsto para un futuro direccionamiento de paginado indirecto,
pero no se utiliza en el 16C84. Tan solo se usa para compatibilidad con las futuras
versiones, por lo que se debe poner a cero.
El contenido del FSR se utiliza para el direccionamiento indirecto. Este registro contiene 8
bits, tamaño suficiente para las versiones actuales del PIC 16CXX; no obstante, es
preciso saber que en direccionamiento indirecto, puede construirse una dirección de 9 bits
utilizando el contenido de este registro y el bit IRP del registro de estado. Esta función no
se utiliza en el 16C84, sino que está prevista para extensiones futuras, de ahí que se
aconseje no usar el bit IRP. Como no es usado en estas versiones, pasaremos este
registro por alto hsata que veamos el direccionamiento indirecto.
bit 7 6 5 4 3 2 1 bit 0
RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
bit 7 6 5 4 3 2 1 bit 0
RA4 RA3 RA2 RA1 RA0
Aquí todos los bits pueden ser leídos y escritos, excepto los 3 bits más significativos del
puerto A.
Bit 3: RBIE o bit de habilitación de las interrupciones del puerto B (RB Interrupt Enable).
- 1: Si se pone a uno este bit, autoriza las interrupciones provocadas por un
cambio de estado de las líneas RB4 a RB7 del puerto B.
- 0: Si se pone a cero, estas interrupciones están deshabilitadas.
PS2 PS1 PS0 División del PS2 PS1 PS0 División del WDT
TMR0
0 0 0 1/2 0 0 0 1/1
0 0 1 1/4 0 0 1 1/2
0 1 0 1/8 0 1 0 1/4
0 1 1 1/ 16 0 1 1 1/8
1 0 0 1 / 32 1 0 0 1 / 16
1 0 1 1 / 64 1 0 1 1 / 32
1 1 0 1 / 128 1 1 0 1 / 64
1 1 1 1 / 256 1 1 1 1 / 128
Bit 7: RBPU o bit de conexión de resistencias Pull-Up para el Puerto B (RB Pull Up
enable)
- 1: Si está a uno las resistencias permanecen desconectadas
- 0: Si se pone a cero las resistencias se activarán
Como podemos observar, lo normal es que las resistencias se activen ante un 1. Esto es
por que este bit del registro OPTION está negada. Debido a esto, su etiqueta en el
compilador será NOT_RBPU.
El registro TMR0 se incrementa en una unidad con cada impulso de reloj seleccionado
mediante el registro OPTION. Cada vez que llega al valor FF, vuelve a 00 generando una
interrupción, si se ha autorizado, y continúa su ciclo indefinidamente.
El registro TMR0 se puede leer o escribir directamente con cualquier instrucción, con el fin
de conocer su posición actual, o para inicializarlo en un estado determinado. Es
importante saber que después de cualquier escritura en este registro, es necesario un
retardo de dos ciclos de instrucción para que se retome la incrementación. Este retraso es
independiente de la fuente de reloj usada. Las instrucciones concernidas son MOVF
TMR0 o CLRF TMR0.
Para comprobar el paso por cero sin inferir en el desarrollo regular del recuento, es
aconsejable utilizar, por ejemplo, una instrucción MOVF TMR0,W, que no hace mas que
una lectura.
El reloj interno deja de funcionar en el modo SLEEP, por lo que no se puede contar con
sus interrupciones en este modo ni por consiguiente, que salga de este modo de
funcionamiento por medio de dicha interrupción.
Obsérvese que todas las instrucciones que escriben en el TMR0 ponen a cero al
prescaler (divisor), cuando éste está asignado al temporizador.
Después del registro anterior vienen algunos registros del banco 0, que también están
disponibles en el banco 1, pero para mantener la compatibilidad, accederemos a ellos
desde el primero.
Los registros TRISA y TRISB los vimos bastante a fondo cuando estudiamos los puertos,
pero para evitar retroceder hasta entonces, explicaré de nuevo cual y cómo es su
funcionamiento.
Registro EECON1
Este registro contiene configuraciones importantes acerca de la escritura y la lectura de la
EEPROM de datos. En concreto tiene 5 bits de control, cuya distribución y significado es
el siguiente.
7 6 5 4 3 2 1 0
EEIF WRERR WREN WR RD
Registro EECON2
Este registro no está implementado físicamente, por lo cual no se puede leer. Tan sólo
sirve para un proceso de protección de escritura que consiste en copiar en él unos datos
específicos, con el fin de evitar que un programa que tenga un despiste pueda programar
la EEPROM por accidente, manipulando simplemente los bits del EECON1.
Veremos sus aplicaciones cuando lleguemos a la parte de algoritmos sobre la EEPROM.
Como ya dije al principio este lenguaje es complejo por su sencillez. Esto quiere decir
que, a diferencia de los lenguajes de alto nivel, aquí no hay funciones que nos solucionen
y simplifiquen el algoritmo, si no que hay que implementar hasta los pasos más
elementales.
Para los PIC se han creado unas instrucciones y una estructura de programa que lo
hacen más sencillo y atractivo todavía. En este apartado veremos la síntesis que tiene
este lenguaje y los elementos que la componen. D
- f (file register)
Este carácter se usa para definir registros de cualquier tipo. Cualquier instrucción
que contenga este campo, contendrá la dirección de un registro, no su contenido.
Un registro puede variar entre las direcciones 00h y 7Fh. En el caso de los
registros especiales en vez de la dirección podremos poner directamente el
nombre del registro.
Ej: (ya voy a empezar a poner algunos ejemplos con instrucciones para q nos
vayamos familiarizando)
en vez de:
BSF 03,5
podemos poner:
- w (working register)
BSF STATUS,5
ponemos:
BSF STATUS,RP0
- l o k (literal)
- d (destiny bit)
- label o etiquetas
Las instrucciones más importantes que podemos manejar son las que proporciona el
fabricante de un microprocesador para su producto. Pero existen otras genéricas para
gran cantidad de microcontroladores, que no son para el manejo del PIC, si no del
ensamblador. Estos comandos generalmente se usan para simplificar la tarea de
programar, y reciben el nombre de directrices.
A continuación expongo las más relevantes.
- Directriz EQU
Esto es lo que se ha hecho para crear las abreviaturas de los registros antes
expuestas. Estas están contenidas en un fichero que se incluye al principio de
código y del cual hablaremos más tarde (véase apartado Instrucción INCLUDE).
Además de esto, podremos igualar a las etiquetas cualquier otro tipo de valores
que usemos, como, por ejemplo, el cero y el 1 en el bit de destino:
W EQU 0
F EQU 1
- Directriz ORG
Ej:
Inicia el programa en la posición cero
ORG 0x00
- Directriz INCLUDE
include "P16F84.INC"
En ciertas ocasiones gran cantidad errores son debidos a que el nombre del
archivo puesto entre comillas no coincide con el que tiene el ensamblador en sus
registros internos. Para suprimirlos basta con poner en la cabecera el nombre de
este archivo.
- Directriz LIST
Este comando sirve para que el compilador tenga en cuenta sobre qué procesador
se está trabajando. Este comando debe estar en todo proyecto, situado debajo del
“include”, con la siguiente sintaxis.
LIST P=16F84
- Directriz END
Al igual que las dos anteriores, esta debe ir incluida una sola vez en todo el
programa. En concreto, esta debe situarse al final, para indicar al ensamblador
que el programa ha finalizado. Esta siempre debe estar presente, aunque el flujo
de nuestro programa acabe en un bucle.
- Directriz #DEFINE
Define se usa para crear pequeñas macros. Con estas macros podremos poner
nombres a pequeños fragmentos de código que nos facilitarán la realización y
comprensión del algoritmo.
Por ejemplo, podremos poner nombres a bits.
Así, en vez de tener que llamar al bit por un numero y un registro, podremos usar
directamente la palabra CERO. Hemos de tener en cuenta que la definición del
ejemplo ya está hecha en el archivo P16F84.inc.
Otro ejemplo muy práctico es el de poner nombre a un fragmento de código usado
frecuentemente. Este fragmento de código, puede ser por ejemplo, el que conmuta
entre los dos bancos.
BSF OPTION,RP0
BCF OPTION,RP0
- Directriz TITLE
Esta directriz no sirve de mucho, pero será útil para aquellos que quieran que el
compilador tenga en cuenta el título que le ha puesto a su código. Tiene la
siguiente sintaxis:
Este nombre aparecerá en los archivos .lst (listados) que cree el compilador.
- Directriz MACRO
; ahora lo invocamos
Ya hemos estudiado algunas partes del programa en lenguaje ensamblador. Sólo nos
falta conocer la parte más importante: las instrucciones. Pero antes de eso, veremos cual
es la estructura básica de un algoritmo en código ensambladora con la finalidad de ener
claro cual es la estructura de todos los elemento que acabamos de ver. Esto lo veremos
más a fondo cuando veamos todo lo concerniente a la programación.
Esta estructura contiene los siguientes elementos o partes que deben ser codificadas:
- Comentario descriptivo del programa (opcional, pero recomendable)
- Definir el microcontrolador que se usará (con las directrices LIST e INCLUDE).
- Introducir las opciones de compilación (que serán vistas más
adelante)(opcional)
- Establecer las constantes que se usarán (con la directriz EQU).
Y su estructura es:
Hemos visto la estructura general. Ahora veremos la posición de los elementos del código
por columnas. Estas se dividen en cuatro:
Normalmente las columnas son separadas por una tabulación. El espacio mínimo entre
dos columnas es de un carácter, que puede ser un espacio en vez de una tabulación
Aparte de estas instrucciones, hay otro tipo de instrucciones usadas para simplificar la
tarea de programar, y q generalmente están formadas por dos instrucciones básicas.
Estas no las trataremos a fondo, pero las veremos en un resumen después de
comprender el funcionamiento de las 35 instrucciones básicas.
En los tres apartados siguientes veremos todos los datos que se pueden dar acerca de
una función. Algunos de ellos son irrelevantes y no son nuestro objetivo. En cambio otros,
como la acción, la sintaxis, el funcionamiento, la operación, el comportamiento del registro
STATUS y los ejemplos, son imprescindibles para comprender su funcionamiento.
ADDWF
ANDWF
ENTRADA SALIDA
f W S
0 0 0
0 1 0
1 0 0
1 1 1
CLRF
CLRW
COMF
DECF
DECFSZ
INCF
INCFSZ
IORWF
ENTRADA RESULTADO
W f W+f
Bit 7 0 1 1
Bit 6 0 1 1
Bit 5 0 1 1
Bit 4 0 1 1
Bit 3 1 0 1
Bit 2 1 0 1
Bit 1 1 0 1
Bit 0 1 0 1
Ejemplo 2 En este segundo ejemplo tenemos que W = 01110011 y f =
ENTRADA RESULTADO
MOVF
MOVWF
NOP
Acción No opera
Sintaxis NOP
Funcionamiento No Operation
Operación Ninguna
Descripción Esta instrucción no reliza ninguna ejecución, pero sirve para
gastar un ciclo de máquina, equivalente a 4 de reloj
Registro No modifica ningún bit de estado.
STATUS
Ejemplo Si usamos un cristal de cuarzo de 4 Mhz. en el oscilador,
podremos obtener un retardo igual a un microsegundo por cada
instrucción NOP que insertemos en el código del programa:
RETARDO NOP
NOP
NOP
RETURN
Cada vez que llamemos a la subrutina RETARDO, obtendremos 3
microsegundos de demora.
RLF
RLF VALOR
RLF VALOR
RRF
RRF VALOR
RRF VALOR
SUBWF
SWAPF
XORWF
ENTRADA SALIDA
f W S
0 0 0
0 1 1
1 0 1
1 1 0
S=f+W
BCF
BTFSC
BTFSS
ADDLW
ANDLW
CALL
CLRWDT
GOTO
ENTRADA SALIDA
f W S
0 0 0
0 1 1
1 0 1
1 1 1
ENTRADA RESULTADO
W l W+l
Bit 7 0 1 1
Bit 6 0 1 1
Bit 5 0 1 1
Bit 4 0 1 1
Bit 3 1 0 1
Bit 2 1 0 1
Bit 1 1 0 1
Bit 0 1 0 1
MOVLW
RETFIE
RETURN
SLEEP
SUBLW
ENTRADA SALIDA
f W S
0 0 0
0 1 1
1 0 1
1 1 0
S=f+W
Registro Modifica el bit Z.
STATUS • Z vale 1 si el resultado de la operación es 0.
Ejemplo W = 01110011 y k = 00101001 antes de ejecutar la instrucción
XORWF k
ENTRADA RESULTADO
W k W+k
Bit 7 0 0 0
Bit 6 1 0 1
Bit 5 1 1 1
Bit 4 1 0 1
Bit 3 0 1 1
Bit 2 0 0 0
Bit 1 1 0 1
Bit 0 1 1 0
OPTION
TRIS