Curso Basico de Pic16f877 PDF
Curso Basico de Pic16f877 PDF
Curso Basico de Pic16f877 PDF
BÁSICO
DE
PIC16F877
Anexos
Tabla de códigos ASCII
Juego de instrucciones PIC16F877
Relación de ejercios
Generalidades
Historia e importancia de los microcontroladores
Con la aparición de los microprocesadores, se varió el esquema de diseño de tal forma que
un problema era descompuesto en una serie de tareas mas simples, el microprocesador
ejecutaba una serie de pasos o instrucciones para llevar a efecto cada una de las tareas, en
ocasiones no era necesario volver a armar un circuito para solucionar otro problema sino
que se cambiaba las instrucciones (programa) para obtener otra aplicación
Metodología de estudio
Como podemos apreciar todo principia en una idea la cual se ha de plasmar en diagramas
de flujo o automatas o alguna otra metodologia que ayude al modelamiento, una vez
superado este punto procedemos a usar un editor de texto para codificar el diagrama de
flujo a través de las instrucciones con que cuenta el microcontrolador.
Una vez que superamos esa etapa procedemos a usar un software, para simular el
programa verificando que la solución es válida. En caso que la simulación indique errores
procedemos a replantear la solución retomando el punto inicial. Si la solución es la que
deseamos procedemos a grabar el programa (debidamente compilado) en el
microcontrolador haciendo uso de una herramienta (grabador de microcontroladores). En
este punto es posible aplicar un emulador o un ICD a fin de verificar que los resultados
elaborados por el simulador son apropiados, el emulador o ICD a diferencia del simulador
trabaja sobre hardware real. En caso que falle en este punto retomamos el diseño original.
Superada ambas fases procedemos a colocarlo sobre el hardware final que ha de operar.
Microcontroladores Microchip 16F87X
Casi todos los fabricantes de microprocesadores lo son también de microcontroladores, en el
mercado existen una serie de marcas bastante conocidas y reconocidas como es el caso de
Microchip, Motorola, Hitachi, etc. Hemos seleccionado a Microchip y en particular la serie
16F87X, motivos para usar este dispositivo sobran, el principal de ellos es la abundante
información y herramientas de diseño existente en el mercado (tanto local como
internacional). También salta a la vista el hecho que es sencillo en el manejo y contiene un
buen promedio elevado en los parámetros (velocidad, consumo, tamaño, alimentación).
•
•
Procesador de arquitectura RISC avanzada
Juego de 35 instrucciones con 14 bits de longitud. Todas ellas se ejecutan en un ciclo
•
de instrucción menos las de salto que tardan 2.
•
Frecuencia de 20 Mhz
•
Hasta 8K palabras de 14 bits para la memoria de codigo, tipo flash.
•
Hasta 368 bytes de memoria de datos RAM
•
Hasta 256 bytes de memoria de datos EEPROM
•
Hasta 14 fuentes de interrupción internas y externas
•
Pila con 8 niveles
•
Modos de direccionamiento directo, indirecto y relativo
•
Perro guardian (WDT)
•
Código de protección programable
•
Modo Sleep de bajo consumo
•
Programación serie en circuito con 2 patitas
•
Voltaje de alimentación comprendido entre 2 y 5.5 voltios
Bajo consumo (menos de 2 mA a 5 V y 5 Mhz)
Donde:
PIN DESCRIPCION
OSC1/CLKIN(9) Entrada para el oscilador o cristal externo.
OSC2/CLKOUT Salida del oscilador. Este pin debe conectarse al cristal o resonador. En caso de
(10) usar una red RC este pin se puede usar como tren de pulsos o reloj cuya frecuencia
es 1/4 de OSC1
PIN DESCRIPCION
MCLR/VPP/ Este pin es el reset del microcontrolador, también se usa como entrada o pulso de
THV(1) grabación al momento de programar el dispositivo.
RA0/AN0(2) Puede actuar como línea digital de E/S o como entrada analógica del conversor AD
(canal 0)
RA1/AN1(3) Similar a RA0/AN0
RA2/AN2/VREF-(4) Puede actuar como línea dígital de E/S o como entrada analógica del conversor AD
(canal 2) o entrada negativa de voltaje de referencia
RA3/AN3/VREF+(5) Puede actuar como línea digital de E/S o como entrada analógica del conversor AD
(canal 3) o entrada positiva de voltaje de referencia
RA4/T0CKI (6) Línea digital de E/S o entrada del reloj del timer 0. Salida con colector abierto
RA5/SS#/AN4(7) Línea digital de E/S, entrada analógica o selección como esclavo de la puerta serie
síncrona.
RB0/INT(21) Puerto B pin 0, bidireccional. Este pin puede ser la entrada para solicitar una
interrupción.
RB1(22) Puerto B pin 1, bidireccional.
RB2(23) Puerto B pin 2, bidireccional.
RB3/PGM(24) Puerto B pin 3, bidireccional o entrada del voltaje bajo para programación
RB4(25) Puerto B pin 4, bidireccional. Puede programarse como petición de interrupción
cuando el pin cambia de estado.
RB5(26) Puerto B pin 5, bidireccional. Puede programarse como petición de interrupción
cuando el pin cambia de estado.
RB6/PGC(27) Puerto B pin 6, bidireccional. Puede programarse como petición de interrupción
cuando el pin cambia de estado. En la programación serie recibe las señales de
reloj.
RB7/PGD(28) Puerto B pin 7, bidireccional. Puede programarse como petición de interrupción
cuando el pin cambia de estado. En la programación serie actua como entrada de
datos
RC0/T1OSO/ Línea digital de E/S o salida del oscilador del timer 1 o como entrada de reloj del
T1CKI(11) timer 1
RC1/T1OSI/ Línea digital de E/S o entrada al oscilador del timer 1 o entrada al módulo captura
CCP2(12) 2/salida comparación 2/ salida del PWM 2
RC2/CCP1(13) E/S digital. También puede actuar como entrada captura 1,/salida comparación 1/
salida de PWM 1
RC3/SCK/SCL E/S digital o entrada de reloj serie síncrona /salida de los módulos SP1 e I2C.
(14)
RC4/SDI/SDA E/S digital o entrada de datos en modo SPI o I/O datos en modo I2C
(15)
RC5/SDO(16) E/S digital o salida digital en modo SPI
RC6/TX/CK(17) E/S digital o patita de transmisión de USART asíncrono o como reloj del síncrono
RC7/RX/DT(18) E/S digital o receptor del USART asíncrono o como datos en el síncrono
RD0/PSP0- Las ocho paptitas de esta puerta pueden actuar como E/S digitales o como líneas
RD7/PSP7 para la transferencia de información en la comunicación de la puerta paralela
(19-22, 27-30) esclava. Solo están disponibles en los PIC 16F874/7.
RE0/RD#/AN5 E/S digital o señal de lectura para la puerta paralela esclava o entrada analógica
(8) canal 5.
RE1/WR#/AN6 E/S digital o señal de escritura para la puerta paralela esclava o entrada analógica
(9) canal 6.
RE2/CS#/AN7 E/S digital o señal de activación/desactivacion de la puerta paralela esclava o
entrada analógica canal 7.
PIN DESCRIPCION
VSS(8,19) Tierra.
VDD(20,32) Fuente (5V).
Arquitectura 16F87X
En el caso de la arquitectura Von Neuman podemos apreciar que existe un único bus de
direcciones y de datos. Podemos apreciar como cada posición de memoria tiene una
dirección, a su vez la memoria se divide en memoria de programa (conocida como ROM) y
memoria de datos (conocida como RAM).
La arquitectura Harvard mejora el ancho de banda por que el bus de datos es de 14 bits
frente a los de 8 de un bus tradicional Von Neumann por tanto en una sola lectura puede
llevar mayor cantidad de datos.
Arquitectura interna 16F87x
Ciclo de instrucción
También debemos notar que los procedimientos de búsqueda y ejecución de una misma
instrucción son secuenciales mas son paralelos para diferentes instrucciones, es decir que
mientras se ejecuta una instrucción la ALU ya esta buscando la siguiente por tanto se
asume que el tiempo de ejecución de una instrucción es un ciclo de instrucción salvo que sea
una instrucción de salto o bifurcación en cuyo caso el tiempo es de dos ciclos de instrucción
dado que el procesador no sabe hacia donde va a saltar lo normal es introducir un ciclo
muerto a fin que evalue la condición necesaria y recién proceda a saltar.
Organización de la memoria
• SFR (Special Function Register) Registros de propósito especial, son registros que
ayudan a configurar el hardware interno asi como sirven para escribir o leer valores
de los diferentes componente que constituyen el microcontrolador. Por ejemplo el
registro “trisa” que nos permite configurar el modo de trabajo de las líneas del
puerto A
Debe señalarse también que la memoria de datos se divide en cuatro bancos (esto para el
caso específico del 16F87X). Las posiciones bajas siempre estan reservadas para los SFR en
tanto que las altas para los GFR.
También tenemos una memoria EEPROM, con 256 posiciones, para acceder a la memoria
no podemos leer o escribir directamente es decir colocar la dirección y obtener o dejer el
valor. Para trabajarla debemos apoyarnos en registros adicionales de tal forma que la
usamos indirectamente
El contador de programa tiene 13 bits con los cuales se pueden direcionar 8K posiciones.
Cuando levantamos el microcontrolador el contador de programa siempre apunta a una
dirección conocida como el VECTOR DE RESET, la dirección es la posición de memoria
0000h. También existe otro vector llamado de VECTOR DE INTERRUPCIONES que ocupa
la posición 0004h. Cuando se lleva a cabo una petición de interrupción el contador de
programa va automáticamente a esa posición en busca de las instrucción que atiendan la
petición de interrupción. Como se ha mencionado la pila trabaja con el contador de
programa cada vez que hay una instrucción de llamada a procedimiento o función (call) el
contador de programa se almacena allí y va en busca de la rutina, cuando acaba la rutina
(con la ejecución de una instrucción return retfie o retlw) se restituye el valor del contador
de programa, la capacidad de la pila es de 8 posiciones en caso tengamos un desborde (ej 9
llamadas anidadas) la pila se dice que se desborda y vuelve a 0. Por tanto hemos de pensar
que la pila tambien cuenta con un contador que indica cual es la siguiente dirección vacia.
Herramientas
• MPLAB
El MPLAB es un entorno de desarrollo es decir es un recipiente que incluye varias
herramientas:
contiene un editor de textos que no permite ingresar el programa expresado en
códigos nemónico (o simplemente llamado ensamblador), normalmente este se
guarda en una archivo con extensión ASM. Una vez que hemos ingresado el
programa dentro de un archivo creamos un proyecto dentro del MPLAB el proyecto
puede contener a su vez varios archivos ASM que se relacionen a través de
llamadas a rutinas o compartan y/o variables, adicionalmente el proyecto tiene un
grupo de variables que debemos configurar como es el tipo de microcontrolador que
vamos a usar ya que el MPLAB soporta todas las familias de microcontroladores
Microchip (MPLAB es producido por Microchip). A continuación procedemos a
llamar al programa ensamblador que lleva el MPLAB capaz de transformar los
código nemónicos (instrucciones) a los correspondientes valores binarios que a su
vez grabaremos en el microcontrolador. El ensamblador (MPASMWIN) también
genera otros archivos de salida que ayudan en el diseño de aplicaciones. Dentro del
MPLAB encontramos también al MPSIM que es un potente simulador que nos
permitirá observar el comportamento del programa antes de proceder grabar el
programa. El archivo .HEX es el que contine los códigos binarios a grabar en el
microcontrolador. (El MPLAB es un software de libre distribución que se encuentra
•
disponible en el homepage de microchip www.microchip.com)
ICD
El ICD (In circuit debugger) es una herramienta que tiene componentes en
hardware y en software. El software viene incluido en el MPLAB es de facil uso y
configuración. ICD es una característica incluída en algunos microcontroladores de
Microchip. Se habilita mediante un bit al momento de grabar el microcontrolador de
tal forma que el microcontrolador ejecuta el programa hasta una determinada
instrucción, en ese momento el microcontrolador se detiene y procese a transmitir
via puerta serial todos los datos que tiene en los bancos de memoria (SFR y los
GFR). De esta forma podemos ver en la pantalla del ordenador lo que pasa
internamente en el microcontrolador cuando ejecutamos un programa. El hardware
es otro componente del ICD consiste en una serie de circuitos que ejecutan la
grabación (transistores que trabajan como interruptores en corte y saturacion) asi
como un microcontrolador (PIC16F876) que recibe los datos y los transmite a la
computadora. Finalmente el ICD se conecta a una tarjeta básica pero efectiva
llamada DEMOBOARD. El ICD es una herramienta potente en el sentido que
permite corregir rápidamente los errores lógicos que siempre se presentan en la
•
programación.
GRABADORES
Los grabadores de microcontroladores, toman como entrada un archivo HEX para
grabarlo en un microcontrolador. Generalmente los grabadores son herramientas
que trabaja con un circuito conectado al puerto paralelo, la idea es tomar el
contenido del archivo HEX y depositarlo en la memoria de programa del PIC. Uno
de los mas populares es el NOPPP, en internet esta disponible el programa
ejecutable, el programa fuente y el circuito. Es un excelente punto de partida para
entender como se lleva a cabo el proceso de grabacion de un PIC.
El PIC16F877 contine 5 puertos que pueden ser configurados como entrada o salida
digitales (A, B, C, D, E). El puerto A contiene 6 bists (RA0-5). El puerto B (RB0-7), el puerto
C (RC0-7) y el puerto D (RD0-7) tiene cada uno 8 líneas. El puerto E solo cuenta con 3
líneas (RE0-2)
•
•
Ingresar al banco 1
•
Configurar los puertos (registros TRISA, TRISB, TRISC, TRISD y TRISE)
•
Regresar al banco 0
Escribir o leer datos desde los puertos. (registros PORTA, PORTB, PORTC, PORTD
y PORTE )
Hemos indicado que la memoria de datos del PIC16F877 se divide en cuatro bancos: 0, 1, 2
y 3. En las posiciones inferiores de ambos bancos se encuentran los registros especiales de
función (SFR). En la posición 0x05, 0x06, 0x07, 0x08 y 0x09 respectivamente se encuentran
los registros PORTA, PORTB, PORTC, PORTD y PORTE que se usan para leer o escribir
datos en tanto que en las posiciones 0x85, 0x86, 087, 0x88 y 0x89 se encuentran los
registros TRISA, TRISB, TRISC, TRISD y TRISE respectivamente, es allí donde se
configuran los puertos. Cabe señalar que el PORTB también aparece en el banco 2 en la
posición de memoria 0x106 y el TRISB en la posición de memoria 0x186.
ADCON1 0x1F
Cada una de las líneas de los puertos puede ser configurado como entrada o como salida. En
el registros TRIS determinamos la configuración de los puertos. Los registros son una
suerte de mascara. Por ejemplo si escribimos un 0 en el bit 0 del TRISA la línea RA0 se
comportará como una línea de salida. Si colocamos a 1 el bit 0 del TRISA a la línea RA0 se
comportará como entrada.
A través de los valores que escribamos en los registros TRIS determinamos el
comportamiento de los puertos.
La escritura y lectura de valores desde los puertos se hace a través de los registros PORT
que se encuentran en el Banco 0 (y banco 2 para el puerto B). Desde luego si configuramos
un puerto como entrada (lectura) los valores que escribamos en el no tendrán efecto porque
fue configurado como entrada y no como salida. A través de las instrucciones MOV podemos
leer o escribir valores.
NOTA.- El puerto A es un puerto multifunción que se puede configurar como digital o como
analógico este modo de funcionamiento dependerá del registro ADCON1 (banco 1 posicion
0x1F). Por el momento no profundizaremos en el tema sino cuando llegemos al módulo
ADC. Solo nos bastará saber que el debemos configurar los bits de la siguiente manera:
Descripción general de las instrucciones
•
hacemos referencia, por ende cada instrucción tiene un código en particular.
Operadores, cada instrucción es aplicada sobre determinados operadores, parte de
los 14 bits están destinados a especificar quienes son los registros o valores que se
veran afectados como resultado de la aplicación de la instrucción.
Las instrucciones orientadas a byte reservan los 7 bits de menor peso para
indicar la dirección del registro que será operado. Una vez que se lleva a
efecto la operación usamos el bit d para indicar donde será almacenado el
resultado. Si d es 0 el resultado se almacena en el registro de trabajo W, si d
es 1 el resultado será guardado en el mismo registro (o file) que se opero.
Las instrucciones de control son las que ayudan a formar bucles dentro de los programas
asi como sirven para llamar a rutinas o procedimientos (instrucciones CALL o GOTO). En
este caso en particular se emplea los 11 bits inferiores para enviar la dirección a la cual el
contador de programa (PC) saltará. Los bits superiores de la instrucción sirven para
identificar a la instrucción.
14-Bit
Opcode
Mnemonic, Status
Description Cycles Notes
Operands Affected
MSb LSb
BYTE-ORIENTED FILE REGISTER
OPERATIONS
ADDWF f, d Add W and f 1 00 0111 dfff ffff C,DC,Z 1,2
ANDWF f, d AND W with f 1 00 0101 dfff ffff Z 1,2
CLRF f Clear f 1 00 0001 lfff ffff Z 2
CLRW - Clear W 1 00 0001 0xxx xxxx Z
COMF f, d Complement f 1 00 1001 dfff ffff Z 1,2
DECF f, d Decrement f 1 00 0011 dfff ffff Z 1,2
DECFSZ f, d Decrement f, Skip if 0 1(2) 00 1011 dfff ffff 1,2,3
INCF f, d Increment f 1 00 1010 dfff ffff Z 1,2
INCFSZ f, d Increment f, Skip if 0 1(2) 00 1111 dfff ffff 1,2,3
IORWF f, d Inclusive OR W with f 1 00 0100 dfff ffff Z 1,2
MOVF f, d Move f 1 00 1000 dfff ffff Z 1,2
MOVWF f Move W to f 1 00 0000 lfff ffff
NOP - No Operation 1 00 0000 0xx0 0000
RLF f, d Rotate Left f through Carry 1 00 1101 dfff ffff C 1,2
RRF f, d Rotate Right f through Carry 1 00 1100 dfff ffff C 1,2
SUBWF f, d Subtract W from f 1 00 0010 dfff ffff C,DC,Z 1,2
SWAPF f, d Swap nibbles in f 1 00 1110 dfff ffff 1,2
XORWF f, d Exclusive OR W with f 1 00 0110 dfff ffff Z 1,2
BIT-ORIENTED FILE REGISTER
OPERATIONS
BCF f, b Bit Clear f 1 01 00bb bfff ffff 1,2
BSF f, b Bit Set f 1 01 01bb bfff ffff 1,2
BTFSC f, b Bit Test f, Skip if Clear 1 (2) 01 10bb bfff ffff 3
BTFSS f, b Bit Test f, Skip if Set 1 (2) 01 11bb bfff ffff 3
LITERAL AND CONTROL OPERATIONS
ADDLW k Add literal and W 1 11 111x kkkk kkkk C,DC,Z
ANDLW k AND literal with W 1 11 1001 kkkk kkkk Z
CALL k Call subroutine 2 10 0kkk kkkk kkkk
CLRWDT - Clear Watchdog Timer 1 00 0000 0110 0100 TO,PD
GOTO k Go to address 2 10 1kkk kkkk kkkk
IORLW k Inclusive OR literal with W 1 11 1000 kkkk kkkk Z
MOVLW k Move literal to W 1 11 00xx kkkk kkkk
RETFIE - Return from interrupt 2 00 0000 0000 1001
RETLW k Return with literal in W 2 11 01xx kkkk kkkk
RETURN - Return from Subroutine 2 00 0000 0000 1000
SLEEP - Go into Standby mode 1 00 0000 0110 0011 TO,PD
SUBLW k Subtract W from literal 1 11 110x kkkk kkkk C,DC,Z
XORLW k Exclusive OR literal with W 1 11 1010 kkkk kkkk Z
Lectura y escritura en puertos
a) Desarrollar un programa que configure las líneas del puerto A como entrada y las líneas
del puerto B como salida. Y que muestre en forma permamente la entrada del puerto A en
el puerto B.
DIRECTIVAS
• Directiva ORG
Sirve para indicar la direccion de memoria en la cual será colocada el código generado a
continuación . Si el ORG no es indicado se empieza en la dirección 0. Ejemplo
ORG 0x04
nop
• DIRECTIVA EQU
• DIRECTIVA END
END
Es de uso obligatorio y siempre se coloca al final del programa sirve para marcar el final del
programa. El MPLAB solo reconoce las líneas que esten escritas previas a la aparición de la
direcitiva END.
• DIRECTIVA LIST
Sirve para indicarle al MPLAB cual es el formato del archivo *.list dentro de los parámetros
esta el tipo de procesador que se va a emplear. Ejemplo:
list p=16F877
• DIRECTIVA INCLUDE
include <file>
Sirve para incluir en el ensamblado el archivo indicado por el parametro “file”. Es como si el
“file” fuera parte del archivo, como si se hubiera situado en la posición en la cual la
directiva aparece. El parámetro “file” puede incluir el path o camino en el cual se encuentra
el fichero a incluir. En caso se omita asumirá los directorios del MPLAB y del archivo
fuente. Ejemplo
include <p16f877.inc>
Incluye el archivo “p16F877.inc” que contiene las etiquetas genéricas del PIC16F877
• PRIMERAS INSTRUCCIONES
CLRF Clear f
Sintaxis: [ label ] CLRF f
Operandos: 0 f 127
Operación: 00h (f)
1 Z
Afecta Status : Z
Descripción: El contenido del registro ’f’ es puesto a 0-lógicos y el bit Z del STATUS es puesto a 1-
lógico.
MOVWF Move W to f
Sintaxis: [ label ] MOVWF f
Operandos: 0 f 127
Operación: (W) (f)
Afecta Status: No
Descripción: Mueve el dato del registro W al registro 'f'.
Con las directivas y las instrucciones mostradas procedemos a elaborar el código del primer
programa.
Primer programa en ensamblador:
list p=16F877
include "p16f877.inc"
BUCLE
movf PORTA,W ; W=PORTA
movwf PORTB ; PORTB=W
goto BUCLE ; Ir bucle
Uso del MPLAB
a) Nociones previas
MPLAB. Es un entorno de desarrollo que incluye varias herramientas que ayudan a desarrollar
aplicaciones en torno a microcontroladores de la familia Microchip. Incluye un editor, un
ensamblador (MPASMWIN), un simulador (MPSIM), el software del PICSTART (programador),
software para el ICD (in circuit debugger).
Cada vez que usamos el MPLAB para programar apliaciones debemos ejecutar la siguiente
secuencia de pasos:
1. Ingresar al MPLAB:
Inicio-> Programas-> Microchip MPLAB-> MPLAB
o haga doble click sobre el icono del programa en el escritorio:
2. Cree un proyecto:
c:\Archivos de Programa\MPLAB\CURSO
•
microcontrolador
•
File Register. Nos muestra la zona de memoria de datos (GFR+SFR)
•
Stopwatch: Muestra un clock para la evolución del programa paso a paso
Stack:Muestra la pila
Una vez abiertas las ventanas ordenelas en la pantalla (workspace) a fin que se vean a la vez:
6.Simulación
Otra forma de ver como es la evolución del programa sin necesidad de apretar la secuencia paso
a paso es através de la opción ANIMATE. Ejecutela y observe que es lo que pasa.
Para salir del estado de animación es necesario usar la opción HALT (F5) del submenú run o
presione el icono del semáforo rojo.
También contamos con una opción que hace que el microcontrolador corra el programa
libremente esa es la opción RUN (F9) o presione el icono del semáforo verde, cuando ejecute
esta acción note como la barra de estado (parte baja de la pantalla) cambia de color a amarillo.
Para salir elija nuevamente la opción HALT.
•
•
Pulse, equivale a ingresar un pulso en el pin
•
Low, equivale a colocar 0 en el pin
•
High, equivale a colocar 1 en el pin
Toggle, es un interruptor que oscila entre 1 y 0. Si lo
presiona una vez ira a 0 si lo presiona de nuevo irá a 1 y
asi sucesivamente.
Observaciones
Las instrucciones de escritura en puertos siempre son precedidas de una
operación de lectura. Es decir ponemos el valor del registro PORTA o
PORTB en el registro de trabajo W. Allí modificamos su valor (podemos
variar uno o más bits) y luego llevamos el valor de W al registro del puerto.
Esto se hace por ejemplo en la ejecución de las instrucciones BCF y BSF.
Por tanto debemos tener cuidado con aquellos puertos cuyas líneas son configuradas como
entrada y salida a la vez. Por ejemplo: una instrucción bsf PORTB,5 hace que W =PORTB
luego en bit 5 de W se pone a 1 y finalmente W es llevado a PORTB. Si otro bit del PORTB
es definido al inicio del programa como entrada y en el desarrollo del programa es
reconfiguardo como salida, la línea no necesariamente coincidirá con el valor que habia
antes, por tanto se pierde.
Ejemplo:
La introducción de las instrucciones de “no operación” (nop) no hacen mas que crear un
espacio de tiempo para leer el dato después que el transitorio ha finalizado. Si la frecuencia
de funcionamiento del clock es muy alta conviene ubicar mas instrucciones nop a fin de
evitar la pérdida de data.
Principales registros del PIC16F877 (STATUS)
Hemos indicado que la memoria del datos del microcontrolador se divide en bancos de
memoria, las posiciones inferiores estan destinadas a los registros especiales de función
(SPECIAL FUNCTION REGISTER). En esta sección profundizaremos un poco mas acerca
de los principales registros y observaremos el uso que se les puede dar en el desarrollo del
programa.
El STATUS es un archivo o registro que ocupa la posición la posición 0x03 de los bancos de
memoria:
•
•
La última operación aritmética lógica realizada en la ALU
•
El estado de reset del microcontrolador
El banco de memoria que actualmente se tiene en uso
7 6 5 4 3 2 1 0
IRP RP1 RP0 - - Z DC C
T0 PD
Bit 7: IRP Register Bank Select Bit (es un bit que se usa para las operaciones de
direccionamiento indirecto
0 = Si se trabaja sobre el banco 0 ó 1 ( posiciones de memoria que van desde 00h hasta
FFh)
1 = Si trabajamos con el banco 2 ó 3 (posiciones de memoria que van desde 100h hasta
1FFh)
Bit 6-5: RP1, RP0 Register Bank Select (bits usando en el direccionamiento directo)
Bit 1: DC Digit carry/borrow bit usado como acarreo en las instrucciones de suma ( ej:
ADDWF y ADDWL) en caso se lleve a cabo una operación de resta se procede a tomarlo
como bit de préstamo). Este bit trabaja con los 4 bits inferiores o nible bajo.
Los tres bits que se encuentran en la parte inferior son bits que reportan el estado de la
ALU tras la ejecución de una instrucción. Estos bits son de lectura. Los bits pueden ser de
escritura si y solo si la instrucción no afecta el estado de los bits Z, DC y C. Las
instrucciones que no afetan al STATUS son BCF, BSF, SWAP y MOVWF. Si quisieramos
colocar todos los bits del STATUS a 0 lógico la aplicación de la instrucción CLRF STATUS
fallaría por que la instrucción afecta a los bis Z, DC y C. De hecho los bits C y DC
conservarían el valor previo a la aplicación de la instrucción CRLF STATUS en tanto que el
bit Z se colocaría a 1 por que el resultado de la última operación fue un 0.
Los bits que se encuentran en medio (-T0 y -PD) son usados para registrar si el
microcontrolador esta trabajando y cual es el modo de operación. El microcontrolador puede
estar encendido y a su vez tiene dos modos de operación: activo y reposo (o bajo consumo).
Los bits también reportan el estado del WATCHDOG, cuando el periodo de tiempo del
WATCHDOG se ha vencido el bit -T0 se coloca a 1. Es necesario indicar que ambos bits son
solo de lectura y se modifican en función al modo de operación de microcontrolador (visto
desde el punto de vista de la alimentación o consumo de energía). En consecuencia la
aplicación de la instrucción CLRF STATUS fallaría también por que no es posible modificar
el estado de los bits.
Los bits localizados en la parte superior del registro STATUS son relacionados al uso de los
bancos la combinación de los mismo determina cual es el banco actual con el que estamos
trabajando. Las instrucciones recomendables para manipular los bits son BSF y BCF. Los
bits superiores son de lectura y escritura.
Observaciones
Cuando se aplican las instrucciones de rotación de bits a la izquierda o derecha (RLF ó
RRF) el bit de C es el valor que se emplea para llenar el agujero producido por la
instrucción, motivo por el cual es necesario colocar el bit C a cero o uno lógico dependiendo
si deseamos que la posición libre sea cubierta por uno de los dos valores.
La instrucción SWAPF no modifica el estado de los bits Z, DC y C pero eso no implica que la
aplicación de la instrucción sobre el STATUS vaya a lograr el intercambio de los nibles. Al
aplicar las instrucciones seguramente los bits IRP, RP1, RP0, Z, DC y C se intercambiarán
uno a uno pero los bits -T0 y -PD no seran intercambiados ya que son de lectura.
Cuando una instrucción es ejecutada puede afectar el estado del STATUS, este hecho
resulta aparentemente irrelevante mas la ayuda que presta es valiosa en la elaboración de
soluciones por ejemplo:
Considere la instruccion:
Ejercicios
Ejercicio 1: Suponga una lampara que debe ser prendida o apagada desde tres
puntos. Diseñe un programa que la encienda si y solo si hay dos interruptores
activados.
Supongamos que tenemos los tres interruptores dispuestos en el PORTB (RB0,RB1 y RB2)
y definimos la línea RB3 como salida tendríamos la siguiente tabla de verdad:
OUT IN
RB3 RB2 RB1 RB0
0 0 0 0
0 0 0 1
0 0 1 0
1 0 1 1
0 1 0 0
1 1 0 1
1 1 1 0
0 1 1 1
a) Definiciones previas.
SUBWF Substrae W de f
Pese a que el manejo es correcto este no resulta el mas apropiado sobre todo si el programa es
extenso. Para hacerlo simple nos apoyamos en la directiva de compilación EQU que permite
definir equivalencias:
Diagrama de
flujo:
c) Trabajo en el MPLAB
1. Ingrese al MPLAB:
Cree un projecto en la carpeta de trabajo c:\archivos de programa\curso\
Asigne como nombre lamparin.pjt.
Abra un nuevo archivo e ingrese el siguiente código:
list p=16F877
include "p16f877.inc"
BUCLE
movfw PORTB ; W=PORTB
movwf M_PORTB ; M_PORTB=W
bcf M_PORTB,3 ; Limpia el tercer bit
2. Simulación
Empiece la simulación.
Con ayuda del Asynchronous Stimulus asigne al PORTB el valor 0x05 luego 0x03 y 0x06. La
salida RB3=1
Nota.- No olvide revisar el bit Z del STATUS el bit 2
Ejercicio 2 : Diseñar un programa que simule a un comparador de 4 líneas.
Dato B Dato A
RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
B3 B2 B1 B0 A3 A2 A1 A0
a) Definiciones previas.
Para solucionar el problema nos apoyaremos en el uso de la instrucción SUBWF. La definición
de la instrucción es la siguiente:
SUBWF Substrae W de f
Descripción: El nible superior e inferior del registro 'f' son intercambiados. Si 'd' es 0 el resultado
es almacenado en el registro W . Si 'd' es 1 el resultado es almacenado en el registro 'f'.
Descripción: Y-lógica del registro W con el registro 'f'. Si 'd' es 0 el resultado es almacenado en
W. Si 'd' es 1 el resultado es almacenado en el registro 'f'.
c) Trabajo en el MPLAB
1. Ingrese al MPLAB:
Cree un projecto en la carpeta de trabajo c:\archivos de
programa\curso\
Asigne como nombre compara4.pjt.
Abra un nuevo archivo e ingrese el siguiente código:
list p=16F877
include "p16f877.inc"
CONF_ADCON1 EQU b'00000110' ; PA como puerto digital
DATO_A EQU 0x20 ; Dato A
DATO_B EQU 0x21 ; Dato B
org 0x000 ; Origen del codigo
nop ; No operacion
nop ; No operacion
END
2. Simulación
Si desea eliminar algún valor de los incluidos en la ventana puede usar la opción Edit. Si
desea guardar la ventana que ha creado elegirá la opción Save y para cargarla posteriormente
empleará la opción Load.
También habilite la ventana del estimulo asíncrono. Asigne los botones a los pines del puerto
B (RB0-7). Configure los botones para que trabajen en modo TOGGLE.
Empiece la simulación.
Con ayuda del Asynchronous Stimulus asigne al PORTB el valor 0x55. La salida del
PORTA debería ser A=B. Luego cambie el PORTB a 0x72 la salida debería ser A<B.
Finalmente 0x5A la salida debería ser A>B También usar la animación para verificar el
funcionamiento del programa. Elija Ud. los valores. Nota.- No olvide Z es el bit 2 y C es
el bit 0 del STATUS
Ejercicio3:
Se tiene tres válvulas (A,B y C) que alimentan un tanque, el tanque a su vez tiene
una salida. Existen 3 sensores de nivel (X,Y y Z). Cuando el tanque está vacio los 3
sensores estan a 0-lógico y es necesario activar el trabajo de las tres bombas.
Cuando se llena 1/3 del tanque el sensor X pasa a 1-lógico y la bomba C deja de
funcionar. Cuando se llenan 2/3 del tanque el sensor Y esta activado y la bomba B
deja de funcionar. Cuando esta lleno el tanque el sensor Z se activa y la bomba A
deja de funcionar. Una vez que el tanque esta lleno este empieza a expulsar el
líquido acumulado. Cuando los 3 sensores pasan a 0-lógico la secuencia antes
descrita se repite ANTES NO.
Salidas Entradas
C B A Z Y X
RC2 RC1 RC0 RB2 RB1 RB0
1 1 1 0 0 0
1 1 0 0 0 1
No permitido 0 1 0
1 0 0 0 1 1
No permitido 1 0 0
No permitido 1 0 1
No permitido 1 1 0
0 0 0 1 1 1
Algoritmo
1. Configurar PORTB como entrada y PORTC como salida
2. Si PORTB != 0 entonces Ir paso2
3. Abrir las 3 válvulas (PORTC=0x07)
4. Si PORTB != 0x01 entonces Ir paso4
5. Abrir 2 válvulas (PORTC= 0x06)
6. Si PORTB != 0x03 entonces Ir paso6
7. Abrir 1 válvulas (PORTC= 0x04)
8. Si PORTB != 0x07 entonces Ir paso8
9. Cerrar todas las válvulas (PORTC= 0x00)
10. Ir paso 2
Elabore el diagrama de flujo, el código del programa y pruebe la simulación en el MPLAB
Módulo : Manejo de Temporizadores
Módulo Timer 0
El módulo Timer0 puede ser usado para generar periodos de tiempo ( si funciona como
temporizador) o puede ser usado para registrar el paso de eventos (si trabaja como contador
de eventos). Al igual que en el módulo anterior existen registros que controlan el
funcionamiento del módulo timer 0:
•
•
Ingresar al banco 1
•
Configurar el modulo timer 0 (como contador de eventos o timer)
•
Regresar al banco 0
Cargar el valor del TMR0 (inicializar la cuenta )
• Puede ejecutar hasta 256 cuentas (0-255) debido a que el registro TMR0 es de 8
•
bits.
El registro TMR0 puede ser leído para saber cual es valor actual de las cuentas o
•
puede ser escrito para colocar un valor inicial.
•
Posee un bloque de preescalamiento que permite ampliar el rango de las cuentas.
Selector interno para definir si trabaja como temporizador o como contador de
•
eventos
Genera una señal de interrupción cuando se produce un desborde en el registro
•
TMR0 (cuando pasa de 0xFF a 00). Bit T0IF del registro INTCON
Selector para indicar si detecta flanco de subida o bajada cuando opera como
contador de eventos. Bit T0SE del registro OPTION_REG (OPTION para fines
prácticos lo llamaremos OPTION_REG en adelante).
Diagrama de Bloques del TMR0
Como se aprecia en la parte superior derecha esta presente un MUX. El MUX es controlado
por el bit T0CS, si es 0 el módulo opera como temporizador; si es 1 como contador de
eventos. El bit TOCS pertenece al registro OPTION_REG y es el bit 5.
Cuando el módulo funciona como timer el registro TMR0 se incrementa en cada ciclo de
instrucción (siempre y cuando el Preescalamiento este deshabilitado). Cuando el registro
TMR0 es escrito el microcontrolador debe esperar 2 ciclos de instrucción para que comenzar
la cuenta.
Cuando el módulo trabaja como contador de eventos el registro TMR0 incrementa su valor
cada vez que aparece un flanco en el pin RA4/TOCKI. La selección del tipo de flanco (subida
o bajada) dependerá de la programación del bit TOSE (registro OPTION_REG bit 4). Si
TOSE es 0-lógico trabaja con flanco de subida si es 1-lógico con flanco de bajada.
bit 7 bit 0
bit 7 RBPU
bit 6 INTEDG
0 =Clock interno(CLKOUT)
011 1 : 16 1:8
100 1 : 32 1 : 16
101 1 : 64 1 : 32
110 1 : 128 1 : 64
Ejercicio 9
a) Definiciones previas.
MODULO TMR0
Es un módulo que se encuentra en el PIC que se puede usar como temporizador o como contador
de eventos. Cuando se emplea como contador de eventos se aplican los pulsos al pin
RA4/TOCKI. En este tipo de programación se dice que trabaja como TOCK. Cuando se emplea
como temporizador (timer) la entrada de valores la hace el oscilador (en nuestro caso un XTAL).
Como es necesario mostrar el número de eventos usaremos una tabla en el manejo de los
display.
Car PORT B
Rb6 Rb5 Rb4 Rb3 Rb2 Rb1 Rb0
G F E D C B A
0 0 1 1 1 1 1 1
1 0 0 0 0 1 1 0
2 1 0 1 1 0 1 1
3 1 0 0 1 1 1 1
4 1 1 0 0 1 1 0
5 1 1 0 1 1 0 1
6 1 1 1 1 1 0 1
7 0 0 0 0 1 1 1
8 1 1 1 1 1 1 1
9 1 1 0 1 1 1 1
Recordando el diagrama de bloques del Timer 0 vemos el detalle del módulo. Definimos la ruta
como contador de eventos por eso será necesario colocar el bit TOCS a 1. No será necesario usar
preescalamiento, por tanto el bit PSA estará a 1. El bit TOSE define si trabajamos con flanco de
subida o bajada: si TOSE=1, detecta flanco de bajada. Si TOSE =0, detecta el flanco de subida.
Según el planteamiento del programa será necesario usar el flaco de bajada (TOSE=1).
Diagrama de flujo:
c) Trabajo en el MPLAB
1. Ingrese al MPLAB:
Cree un projecto en la carpeta de trabajo c:\archivos de programa\mplab\curso
Asigne como nombre evento.pjt.
Abra un nuevo archivo e ingrese el siguiente código:
; REGISTRO OPTION
; ----------------------------------------------
; X X TOCS TOSE PSA PS2 PS1 PS0
; ----------------------------------------------
; 1 1 1 1 1 0 0 0 = 0xF8
; ----------------------------------------------
; C.EVEN. F.BAJ TMR0 Escalamiento
_inicio
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP1
BUCLE
movf TMR0,W ;W=TMR0
movwf TEMP ;TEMP=W
movlw LIMITE ;W=10
xorwf TEMP,W ;W XOR TEMP
btfss STATUS,Z ;EL resultado de la anterior instruccion es 0?
goto SIGUE ;Z=0, NO es diferente de 0, TMRO = 0,1,2,3,4,5,6,7,8,9
clrf TMR0 ;Z=1, SI vale 10, TMRO > 9, TMR0=0
clrf TEMP ;Temp=0
DISPLAY
addwf PCL,f
retlw b'01000000' ;0
retlw b'01111001' ;1
retlw b'00100100' ;2
retlw b'00110000' ;3
retlw b'00011001' ;4
retlw b'00010010' ;5
retlw b'00000010' ;6
retlw b'01111000' ;7
retlw b'00000000' ;8
retlw b'00010000' ;9
END
2. Simulación
Habilite la ventana del ASINCHONUS STIMULUS, SPECIAL FUNTION REGISTER,
organice las ventanas. A continuación asigne al botón 1 el valor TOCKI y al botón 2 el valor
RA4. Asegúrece que ambos botones estén definidos como señales de pulso. A continuación
simule el programa con ayuda del STEP (F7). No olvide presionar entre paso y paso (STEPS)
cualquiera de los botones recientemente asignados. Notará como es que el pulso toma efecto 3
ciclos de instrucción después debido a que hemos elegido el flanco de bajada es decir el pulso
demora 3 ciclos de instrucción. Si hubiéramos elegido el de subida la acción hubiera sido
inmediata. Use la opción de animación para probar el incremento y como se resetea a 0 una
vez que alcanzo el valor de 10
Ejercicio 10
Programar el TMR0 para generar un retardo de un segundo. A partir del cual se
a) Definiciones previas.
Para generar retardos es necesario usar el modulo timer 0 como temporizador por lo tanto es
necesario colocar el bit T0CS a 0. Ahora debemos encontrar una expresión que nos ayude a
calcular cuantos ciclos de instrucción necesitamos para generar un retardo de un segundo.
Un ciclo de instruccion = 4*Tosc ( donde Tosc es el inverso de la frecuencia del clock que usa el
PIC)
Si lo multiplicamos por un numero 'X'; tendremos un retardo de
Retardo= Un ciclo de instruccion * X; (como el modulo Timer 0 lleva la cuenta en el registro
TMR0)
Ademas sabemos que el modulo timer 0 posee un preescaler que sirviria para amplia el retardo.
Si lo usamos debemos configurar el bit PSA a 0 . Si seteamos el bit PS2, PS1 y PS0 a 1 el
preescaler tendria un valor de 256.
Retardo_T0_Pre= 4*Tosc*TMR0*Preescaler.
Retardo=Bucle*Retardo_T0_Pre
Retardo=Bucle*65,536ms
1000ms =Bucle*65,536
Bucle=15.25
Como vemos el generar el retardo no es tan dificil si consideramos este procedimiento desde
luego que nos faltaría definir una función que de nos indique cuando el TMRO ha generado las
256 cuentas.
Existe un bit T0IF (Timer 0 interrup flag) que se pone a 1 siempre que hay un desborde en el
Registro TMR0 es decir cuando pasa de 255 a 0. Esta característica nos puede ayudar mucho ya
que una vez producido el desborde el bit T0IF permanece en 1. Es necesario resetear el bit T0IF.
Y lo mas importante es que debemos cargar el TMR0 con el valor apropiado para conseguir el
retardo deseado.
1. T0IF=0
2. Colocar TMR0 a 246
3. Esperar a que T0IF sea 1.
TMR0 246 247 248 249 250 251 252 253 254 255 0
Cuenta: 0 1 12 23 34 45 56 67 78 89 9 10 10
T0IF=1
Como se puede apreciar si cargamos el TMRO con 246 10 ciclos de instruccion (10 us) mas tarde
obtendremos el retardo necesario si revisamos el valor de T0IF. Para fines prácticos equivale a
restar el retardo de 256.
Por tanto no existe una sino múltiples soluciones considerando este último punto y la fórmula :
Retardo= 4*Tosc*TMR0*Preescaler*Bucle.
Observe el siguiente cuadro (considere que los valores siempre deben ser enteros):
Opcion Ciclo de TMR0 Preescaler Bucle Retardo
instrucción
Algoritmo
De acuerdo a las consideraciones expuestas el registro OPTION_REG debería configurarse así:
Programa Principal
1. Ir banco 1
2. TRISC=0
3. OPTION_REG=b'11001110'
4. Ir banco 0
5. PORTC=0
6. Call RETARDO
7. PORTC=PORTC+1
8. Ir paso 6
Rutina Retardo
1. CONTA=64
2. T0IF=0
3. TMR0=134 (122 cuentas)
4. Si T0IF es 1. Ir paso 6
5. sino ir paso 4
6. CONTA=CONTA -1
7. Si CONTAes 0 ir paso 9
8. sino Ir paso 4
9. Retorno
iagrama de flujo:
CONTA EQU 0x20 ;Variable CONTA en dirección 0x20 hexadecimal de ;memoria RAM
_inicio
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP1
c) Trabajo en el MPLAB
Ingrese al MPLAB:
Cree un projecto en la carpeta de trabajo c:\archivos de programa\mplab\curso
Asigne como nombre m2p1.pjt.
Abra un nuevo archivo e ingrese el código.
Proceda a enlazar el ICD debugger al la tarjeta demoboard y grabe el programa
Ejecute el programa y verifique si es que aumenta la cuenta que se muestra en el
PORTC cada segundo
Proceda a correr el programa paso a paso.
Estructura Interna y Funcionamiento del TMR1
El valor contenido en TMR1H : TMR1L puede ser leído o escrito y los impulsos de reloj que
originan el contaje ascendente pueden provenir del exterior o de la frecuencia de
funcionamiento del microcontrolador (Fosc/4)
El Timer1 tiene tres formas de funcionamiento:
a) Temporizador
b) Contador Síncrono
c) Contador Asíncrono
Como Temporizador el valor concatenado TMR1H : TMR1L se incrementa con cada ciclo de
instrucción (Fosc/4). En el modo contador, el incremento se puede producir con los flancos
ascendentes de un reloj externo, cuya entrada se aplica a las líneas RC0 y RC1 de la puerta
C, o por impulsos aplicados en la línea RC0.
bit 7 bit 0
bit 7-6 Bits no implementados. Leído como 0
bit 5-4 T1CKPS1:T1CKPS0: El Preescaler es un divisor de la frecuencia de los impulsos que se
aplican al TIMER1
11 = 1:8 Valor de Preescaler
10 = 1:4 Valor de Preescaler
01 = 1:2 Valor de Preescaler
00 = 1:1 Valor de Preescaler
bit 3 T1OSCEN: Control de habilitación para el oscilador del Timer1
1 = El Oscilador es habilitado (RC0 y RC1 = entradas del oscilador externo)
0 = El oscilador trabaja en otro modo(RC0 = entrada del oscilador externo)
bit 2 T1SYNC: Determina la posible sincronización o no de los impulsos del reloj externo con los del
reloj interno.
TMR1CS = 1
1 = No sincronización con un reloj externo
0 = Sincronización con un reloj externo TMR1CS = 0
Este bit es ignorado cuando el Timer1 usa el reloj interno
bit 1 TMR1CS: Selecciona la fuente de los impulsos de contaje
1 = Reloj externo desde el pin RC0/T1OSO/T1CKI (en el flanco de subida)
0 = Reloj interno (FOSC/4)
bit 0 TMR1ON: gobierna el permiso o la prohibición de funcionamiento del Timer1.
1 = Habilitar el Timer1
0 = Detener el Timer1
Este modo es seleccionado limpiando el bit TMR1CS (T1CON<1>). En este modo la entrada
de reloj al timer es Fosc/4. El bit T1SYNC (T1CON<2>) no tiene efecto desde el reloj
interno; es siempre síncrono.
Este modo es seleccionado seteando el bit TMR1CS. En este modo el timer incrementa cada
flanco de subida de una entrada de reloj externo en el pin RC1, cuando el bit T1OSCEN es
seteado. O cuando una entrada de reloj ingresa por el pin RC0, cuando el bit T1OSCEN es
limpiado. Si el T1SYNC es limpiado, entonces el reloj externo es sincronizado con la fase del
reloj interno.
c.- Timer1 en modo Contador Asíncrono
Leer los registros TMR1H TMR1L mientras el timer esta corriendo desde un reloj asíncrono
externo garantizará una lectura válida (tener cuidado con el hardware). Sin embargo el
usuario tendrá en mente que leer 16 bits del timer en 2 registros de 8 bits puede causar
molestia si el timer desborda mientras se produce la lectura.
Para escribir es recomendable que el usuario detenga el timer y escriba recién los valores
deseados.
Un oscilador de cristal puede ser construido entre los pines T1OSI (entrada) y T1OSO
(salida amplificada). Esto es habilitado seteando el bit de control T1OSCEN (T1CON<3>).
El oscilador puede ser hasta de 200 Khz. Este continuará oscilando durante el modo
SLEEP.
Ejercicios
Ejercicio 11
Programar el TMR1 para generar un retardo de 524.2 ms. Cada vez que concluya
el tiempo se activará el PORTC de forma escalonada
a) Definiciones previas.
El modulo timer 1 cuenta con dos registros TMR1H y TMR1L que sumados nos pueden proveer
de 2^16 cuentas esto es 65536 cuentas. Si tenemos un ciclo de instrucción de demanda 1 us
(XTAL de 4MHZ). El retraso sera de 65.536 ms. Para alcanzar el valor que deseamos
emplearemos el preescaler. Si lo colocamos a 1:8 obtendremos el valor deseado:
Retardo=4*Tosc*TMR1*Preescaler
Retardo=4*0.25us * 65636*8
Retardo=524,288 ms
Al igual que en el caso anterior nos apoyaremos en el bit de desborde del modulo timer 1
TMR1F. Como el valor lo vamos a mostrar en el PORTC como una escalera que se incrementa
cada 524,2 ms usaremos una tabla para decodificar el valor a mostrar en el PORTC.
Algoritmo
Deshabilitamos el modulo timer 0 (OPTION_REG=0x80) y habilitamos el modulo timer 1(
preescaler 1:8, deshabilitamos oscilador, no hay sincronismo, el clock es interno, el modulo timer
1 esta apagado ).
Programa Principal
1. Ir banco 1
2. TRISC=0
3. OPTION_REG=b'10000000'
4. Ir banco 0
5. T1CON=b'00110000'
6. CONTA=0, PORTC =0;
7. W=CONTA (indice)
8. CALL DISPLAY
9. PORTC=W
10 CALL RETARDO
11. CONTA=CONTA +1
12. Si CONTA es 8, entonces CONTA =0, Ir paso 7
13. Sino CONTA =CONTA+1, Ir paso 7
Retardo
1.TMR1IF=0
2. TMR1=0
3. TMR1ON=1
4. Si TMR1IF es 1, entonces TMR1ON=1, return
5. Ir paso 4
Display
1. PCL=PCL+W
2. Return con el valor literal indicado por el indice W
iagrama de flujo:
_inicio
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP1
_bucle
movf CONTA,W ;Cargar el valor de CONTA en W
call _display ;Llama a la tabla _display
movwf PORTC ;Al retornar de la subrutina el valor de W se saca
;por el PORTC
call _retardo ;Llama a la subrutina retardo
incf CONTA,F ;incrementa el valor de CONTA
movlw d'8' ;Verifica si ha llegado a 8
subwf CONTA,W
btfss STATUS,Z
goto _bucle ;Si no es 8: ir _bucle
clrf CONTA ;Si es 8: CONTA = 0
goto _bucle ;Ir _bucle
_retardo
bcf PIR1,TMR1IF ;Borrar la bandera de desborde
clrf TMR1L ;Limpiar los registros de conteo
clrf TMR1H
bsf T1CON,TMR1ON ;Habilita el TMR1
_espera
btfss PIR1,TMR1IF ;Verificar el desborde
goto _espera ;Si no ir _espera
bcf T1CON,TMR1ON ;Si desborda: limpiar bandera de desborde
return ;Retorno
_display
addwf PCL,F ;pcl + W >>>> W
;El PCL se incrementa con el valor de W
;proporcionando un salto
retlw b'10000000' ;retorna con valores para PORTC
retlw b'11000000'
retlw b'11100000'
retlw b'11110000'
retlw b'11111000'
retlw b'11111100'
retlw b'11111110'
retlw b'11111111'
end
c) Trabajo en el MPLAB
Ingrese al MPLAB:
Cree un projecto en la carpeta de trabajo c:\archivos de programa\mplab\curso
Asigne como nombre m2p2.pjt.
Abra un nuevo archivo e ingrese el código.
Proceda a enlazar el ICD debugger al la tarjeta demoboard y grabe el programa
Corra el programa y verifique si cada 524,2 ms el valor en el PORTC crece como una
escalera
Proceda a correr el programa paso a paso.
Ejercicio 12
Modificar el programa anterior para que lea el pin RB0, cuando se pulse
deshabilitara el TMR1 y si se deja de pulsar reanudara el timer.
El ejercicio es similar al anterior. Configuramos el pin RB0 como entrada (en TRISB). El
valor por defecto en el RB0 es 1-lógico en la tarjeta demoboard. Si la cuenta esta subiendo
(con intervalos de 524 ms) y presionamos el pulsador conectado a RB0 ( pasa a 0-lógico)
deshabilitamos el TMR1 con la ayuda del bit TMR1ON (deshabilitado). En consecuencia la
cuenta seguirá siendo visualizada e incrementada por el resto del programa pero como es
muy rápida no podremos verla a simple vista por que el TMR1 ahora no genera el tiempo de
524 ms. Para solucionar el problema adicionaremos código a la rutina de retardo.
Revisaremos el valor del RB0 dependiendo si es 0 detenemos la cuenta caso contrario el
módulo seguirá generando los retardos. Observe el diagrama de flujo y el código.
Diagrama de Flujo
_inicio
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP1
_bucle
movf CONTA,W ;Cargar el valor de CONTA en W
call _display ;Llama a la tabla _display
movwf PORTC ;Al retornar de la subrutina el valor de W se saca ;por el PORTC
call _retardo ;Llama a la subrutina retardo
incf CONTA,F ;Incrementa el valor de CONTA
movlw d'8' ;Verifica si ha llegado a 8
subwf CONTA,W
btfss STATUS,Z
goto _bucle ;Si no es 8: ir _bucle
clrf CONTA ;Si es 8: CONTA = 0
goto _bucle ;Ir _bucle
_retardo
bcf PIR1,TMR1IF ;Borrar la bandera de desborde
clrf TMR1L ;Limpiar los registros de conteo
clrf TMR1H
btfss PORTB,0
goto _deshabilitar ;Ir _deshabilitar
bsf T1CON,TMR1ON ;Habilita el TMR1
_espera
btfss PIR1,TMR1IF ;Verificar el desborde
goto _espera ;Si no ir _espera
_deshabilitar
bcf T1CON,TMR1ON ;Si desborda: limpiar bandera de desborde
return ;Retorno
_display
addwf PCL,F ;pcl + W >>>> W
;El PCL se incrementa con el valor de W
;proporcionando un salto
retlw b'10000000' ;retorna con valores para PORTC
retlw b'11000000'
retlw b'11100000'
retlw b'11110000'
retlw b'11111000'
retlw b'11111100'
retlw b'11111110'
retlw b'11111111'
end
Módulo : Convertidor Análogo Digital
Introduccion
Un convertidor análogo digital tiene como entrada un nivel de voltaje (valor analógico) y
produce en su salida un número binario de n bits proporcional al nivel de la entrada (valor
digital). Los convertidores de señal análogo a digital abrevian ADC o A/D.
Uno de los parámetros que definen al A/D es la resolución como la mínima variación de
voltaje en la entrada que produce cambio del valor digital en la salida. Por ejemplo un
convertidor de 10 bits tiene un total de 210 valores (1024 valores de 0 a 1023).
Descripción General
El módulo convertidor Análogo Digital (A/D) del PIC 16F877 tiene 8 canales de entrada. La
conversión de la señal analógica aplicada (a uno de los canales) se plasma en número
binario de 10 dígitos. El módulo A/D posee voltajes de referencia que pueden ser
seleccionados para emplear las tensiones VDD, VSS del microcontrolador o puede emplear
tensiones aplicadas a los pines RA2 o RA3 (incluso es posible establecer combinaciones de
los anteriores valores).
Una vez que el periodo de adquisición ha terminado la conversión A/D puede empezar. Los
siguientes pasos muestran la secuencia de uso:
•
voltajes de referencia. (en el registro ADCON1)
•
Seleccione el canal de entrada al módulo A/D (en el registro ADCON0)
•
Seleccione el clock de conversión A/D (en el registro ADCON0)
Ponga a funcionar el módulo A/D (en el registro ADCON0)
1.
•
Configure la interrupción del A/D si lo desea:
•
ADIF=0 -lógico (bit que indica si se produjo una conversión)
•
ADIE=1-lógico (habilitador de interrupción del modulo analógico)
•
PEIE=1 lógico (habilitador de interrupción de periféricos)
GIE=1-lógico (Habilitador general de interrupciones)
1. Espere por el tiempo de adquisición (es el tiempo que se demora en trabajar el
bloque de sampling and hold)
2. Comienzo de la conversión
GO/-DONE=1-lógico (en el registro ADCON0)
3. Esperar a que la conversión se complete. Para saber si la conversión termino
•
podemos:
•
Revisar el bit GO/-DONE esperando que sea de nuevo 0 -lógico
O esperar al flag de ADIF sea 1-lógico (puede emplearse como interrupción)
4. Leer el resultado del A/D en el par de registros (ADRESH:ADRESL). No debemos
olvidar colocar el bit ADIF a 0-lógico (si se requiere)
5. Para la siguiente conversión, regrese al paso 1 o paso 2 dependiendo si solo se usa
uno o mas canales.
Requerimientos para la adquisición A/D
Para que el modulo convertido A/D trabaje apropiadamente la carga del capacitor que
muestrea la señal análoga debe ser la máxima .
Selección del clock de conversión Analógica Digital
•
•
2Tosc
•
4Tosc
•
8Tosc
•
16Tosc
•
32Tosc
•
64Tosc
Oscilador RC interno que tiene el modulo A/D (crea un retardo de 2us a 6 us).
Para el correcto funcionamiento del módulo el clock de conversión debe ser seleccionado
para asegurar un TAD de 1.6 us como mínimo.
La siguiente tabla muestra el resultado de varios TAD calculados para diferentes clock
aplicados al microcontrolador.
Configuración de los pines de los puertos para que trabajen de forma
analógica
Los registros ADCON1 y TRIS controlan la operación de los pines de los canales A/D. Los
pines que se empleen como entradas deben ser configurados en los registros TRIS como 1-
lógico. Si en el registro TRIS se coloca a 0-lógico (como línea de salida) el módulo A/D
convertirá el voltaje presente a la salida del pin. La operación de conversión del A/D es
independiente del estado de los bits CHS2:CHS0 y de los bits de los registros TRIS
Nota
Conversiones A/D
Nota. EL bit GO/-DONE y el bit ADON están en el registro ADCON0 pero no debe ser
activados a la vez, esto es en la misma instrucción.
Registros que almacenan el resultado de la conversión
Los bits extras (6 bits) son llenados con 0-lógicos. Si en un programa no se emplea el módulo
A/D es posible usar los registros ADREH :ADRESL como si fueran registros de propósito
general (registros de 8 bits).
Operación del módulo A/D durante la operación SLEEP
El módulo A/D puede seguir operando durante el modo SLEEP, esto requiere que el clock
A/D sea la red RC (ADCS1:ADCS0=111). Cuando el clock RC es seleccionado, el módulo A/D
espera un cliclo de instrucción antes de empezar la conversión. Esto le permite a la
instrucción SLEEP ser ejecutada eliminando todos los ruidos digitales producidos por el
swticheo en la conversión.
Si las interrupciones del módulo A/D no están habilitadas, el módulo A/D será apagado pese
a que el bit ADCON sigue aun en 1-lógico. Cuando se apaga el modulo A/D se tiene el
mínimo consumo de corriente.
Nota. Para que el módulo A/D opere durante el modo SLEEP la fuente del clock A/D debe
ser siempre el RC (ADCS1:ADCS0=11). Para permitir que la conversión ocurra durante el
modo SLEEP asegurece de colocar la instrucción SLEEP inmediatamente después de
colocar el bit GO/-DONE a 1-lógico.
Efectos en el RESET
Después de un RESET el módulo A/D esta apagado y si había una conversión en curso ésta
es abortada. Todos los pines que entran al modulo A/D son configurados como entradas
analógicas. El valor presente en ADRESH:ADRESL no se modifica después de un RESET.
Luego de encender el microcontrolador el valor presente en ADRESH:ADRESL es aleatorio
(basura).
Ejercicios
Ejercicio 13
Diseñar un programa que permita leer el voltaje aplicado al canal 0 del módulo
ADC, convertirlo a un valor digital de 10 bits y mostrar los ocho bits mas
significativos en el PORTC
a)Definiciones previas
El módulo del ADC cuenta con dos registros ADRESH y ADRESL donde se almacena
automaticamente la conversión digital de 10bits.
Sin embargo es posible seleccionar a cual de los dos registros se va a leer como ceros los 6
bits que restan.
Con ayuda del bit ADFM del registro ADCON1 podemos seleccionar la distribución de los
10 bits. Por ejemplo si ADFM=1 los bits estaran asignados entre los 8 bits de ADRESL y los
2 menos significativos de ADRESH.
Por otro lado si ADFM=0 los bits estarán asignados a los 8 bits de ADRESH y los 2 mas
significativos de ADRESL. Para el programa a diseñar vamos a asignar el valor de 0 a
ADFM.
_inicio
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
movlw b'00000111'
movwf OPTION_REG ;TMR0 preescaler, 1:156
_bucle
btfss INTCON,T0IF
goto _bucle ;Esperar que el timer0 desborde
bcf INTCON,T0IF ;Limpiar el indicador de desborde
bsf ADCON0,GO ;Empezar la conversion A/D
_espera
btfsc ADCON0,GO ;ADCON0 es 0? (la conversion esta completa?)
goto _espera ;No, ir _espera
movf ADRESH,W ;Si, W=ADRESH
movwf PORTC ;Muestra el resultado en PORTC
Ejercicio 14
Elaborar un programa que lea el canal 0 del modulo ADC y que muestre el
resultado en los 6 bits menos significativos del PORTC (RC0-RC5) adicionalmente
active un pin del Pic (RC7) cuando el valor adquirido por el ADC sea mayor a 512
y desactive cuando sea menor a ese valor.
a) Definiciones previas:
Para el desarrollo del presente ejercicio es importante recordar la instrucción “rrf f,d” que
permite rotar los bits de un registro hacia la derecha, de manera que el dato que
obtengamos del ADC se rote a la derecha y podamos obtener la data en los 6 bits menos
significativos del PuertoC.
Diagrama de Flujo:
_inicio
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
movlw b'01000001' ;A/D conversion Fosc/8
movwf ADCON0
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP1
movlw b'00000111'
movwf OPTION_REG ;TMR0 preescaler, 1:156
movlw b'00001110' ;A/D Port AN0/RA0
movwf ADCON1
bsf TRISA,0 ;RA0 linea de entrada para el ADC
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
clrf PORTC ;Limpiar PORTC
_bucle
btfss INTCON,T0IF
goto _bucle ;Esperar que el timer0 desborde
bcf INTCON,T0IF ;Limpiar el indicador de desborde
bsf ADCON0,GO ;Comenzar conversion A/D
_espera
btfsc ADCON0,GO ;ADCON0 es 0? (la conversion esta completa?)
goto _espera ;No, ir _espera
movf ADRESH,W ;Si, W=ADRESH
movwf ADC ;ADC=W
rrf ADC,F ;ADC /4
rrf ADC,F
bcf ADC,7
bcf ADC,6
movfw ADC ;W = ADC
movwf PORTC ;PORTC = W
movlw D'32' ;Comparamos el valor del ADC para saber si es menor
que 128
subwf ADC,W
btfss STATUS,C ;Es mayor a 128?
goto _desactivar ;No, desactivar RC7
bsf PORTC,7 ;Si, RC7 = 1 logico
goto _bucle ;Ir bucle
_desactivar
bcf PORTC,7 ;RC7 = 0 logico
goto _bucle ;Ir bucle
end
Ejercicio 15
Un tanque es empleado para almacenar agua y se ha conectado un sensor para
saber el nivel de agua. El sensor se ha conectado al canal 0 del Pic 16F877 y un
indicador es accionado por el pin RC7. Desarrollar un programa que informe si el
nivel de agua esta en el rango de 64 a 128 unidades del ADC RC7=0 (RC7=1 fuera
del rango)
Diagrama de flujo
Código del programa
Entre las herramientas que disponen los PIC16F8x se encuentra el USART, llamado SCI
(Serial Comunications Interface), puede funcionar como un sistema de comunicación
bidireccional, adaptándose a multitud de periféricos y dispositivos que transfieren
información de forma serial, tales como un ordenador. También puede trabajar en modo
unidireccional para soportar periféricos como memorias, conversores, etc.
El USART (Transmisor/Receptor Síncrono/Asíncrono Serie) puede trabajar de dos formas:
o Asíncrono (Bidireccional)
o Síncrono (Unidireccional)
En el modo asíncrono, la comunicación serie del USART en los PIC16F8x esta soportada
por las líneas RC6/TX/CK y RC7/RX/DT por las que se mueven los bits a la frecuencia
interna de reloj. En el modo síncrono, los bits de información circulan en ambos sentidos por
la línea DT a la frecuencia de los impulsos que genere el maestro por la linea CK.
En esta forma de comunicación serie, se usa la norma RS-232-C, donde cada palabra de
información o dato se envía independientemente de los demás. Suele constatar de 8 o 9 bits
y van precedidos por un bit de START (inicio) y detrás de ellos se coloca un bit de STOP
(parada), de acuerdo con las normas del formato estandar NRZ (Non Return-to-Zero) Los
bits se transfieren a una frecuencia fija y normalizada. La USART transmite y recibe
primero el bit menos significativo.
o Generador de Baudios
o Circuito de Muestreo
o Transmisor Asíncrono
o Receptor Asíncrono
Generador de Baudios
Para el protocolo asíncrono RS-232-C, la frecuencia en baudios (bits por segundo) a la que
se realiza la transferencia se debe efectuar a un valor normalizado: 330, 600, 1200, 2400,
4800, 9600, 19200, 38400, etc. Para generar esta frecuencia, el USART dispone de un
generador de frecuencia en Baudios, BRG, cuyo valor es controlado por el contenido grabado
en el registro SPBRG.
Aparte del valor X cargado en el registro SPBRG, la frecuencia en baudios del generador
depende del bit BRGH del registro TXSTA <2>. En el caso de que BRGH = 0 se trabaja en
baja velocidad y si BRGH = 1 se trabaja en alta velocidad. Según este bit se obtendrá el
valor de una constante K necesaria en la determinación de la frecuencia de funcionamiento.
Modo asíncrono:
1 = Alta velocidad
0 = Baja velocidad
Modo Sincrono:
No se usa en este modo
bit 0 TX9D: Bit 9 del dato a transmitir (puede ser el bit de paridad)
Receptor Asíncrono
Una vez que el modo asíncronoha sido seleccionado, la recepción es habilitada colocando a
1-lógico el bit CREN (RCSTA<4>). El corazón de la recepción serial es el registro de
corrimiento de recepción (RSR). Después de detectar el bit de parada la data presente en
RSR es transferida al registro RCREG( si es que está vacío). Si la transferencia ha sido
completada con éxito el RCIF (PIR1<5>) es puesto a 1-lógico. Si lo deseamos podemos usar
esta característica para trabajar interrupciones. Para ello deberemos habilitar el bit RCIE
(PIE1<5>). El bit RCIF solo es de lectura y colocado a 0-lógico por hardware ; es decir
cuando el registro RCREG esta vacío. Al parecer el registro RCREG es un solo registro pero
no es asi; el registro RCREG es una suerte de pila de dos posiciones. Por tanto es capaz de
almacenar 2 datos (bytes) y mantener un tercer dato en RSR. Si la pila está llena y se llena
el RSR (tercer dato) es decir llega el bit de stop de ese tercer dato el microcontrolador
procede a colocar a 1-lógico el bit OERR (over run error bit) y el valor presente en RSR se
pierde. De darse esta situación lo que debemos hacer es rescatar los dos datos que estan en
la pila de RCREG. Luego resetear el OERR, para eso es necesario resetear el bit CREN
(ponerlo a 0-lógico y luego a 1-lógico). Cuando se activa el bit OERR las transferencias de
RSR a RCREG son deshabilitadas por lo tanto debemos cumplir con hacer el reset del bit
CREN para normalizar la recepción. Hay otro bit que también es importante señalar y es el
bit FERR (RCSTA<2>) error de frame o trama o marco. El bit FERR se coloca a 1-lógico si
detecta un 0-lógico como bit de parada. Por lo tanto antes de leer lo que contiene el registro
RCREG es necesario revisar el valor de los bits FERR y OERR.
1. Inicializar el registro SPBRG con el valor apropiado que genere los baudios
necesarios. No olvide colocar un valor al bit BRGH en función a si va o no a
transmitir en alta velocidad.
2. Habilite la puerta serial asíncrona colocando a 0-lógico el bit SYNC y a 1-lógico el
bit SPEN.
3. Si se va a trabajar con interrupción, asignar RCIE=1, además de habilitar las
interrupciones.
4. Habilite la recepción colocando a 1-lógico el bit CREN.
5. El bit RCIF se colocará a 1-lógico cuando un dato llegue completo al
microcontrolador y una interrupción se generará si es que se ha seteado el bit RCIE.
6. Lea el registro RCSTA para obtener el valor del noveno bit (si es que esta trabajndo
con 9 bits de datos) y determine si hubo error en la comunicación (revise los bits
OERR y FERR).
7. Si no hubo error lea los 8 bits de datos del registro RCREG.
8. Si no hubo algun error resetee el bit CREN.
bit 0 RX9D: Bit 9 del dato recibido (Puede ser el bit de paridad)
Ejercicios
Ejercicio 16
Transmitir muestras analógicas provenientes del canal AN= del ADC del PIC
hasta la computadora y visualizar el dato por el hyper terminal de Windows.
a) Definiciones previas
- Para el desarrollo de este programa es recomendable contar con un resonador por que nos
brinda una frecuencia mas exacta que la nos da una red RC. En los ejercicios que se
muestran a continuación asumimos que estamos trabajando con un cristal de 4MHz.
- Necesitamos de un programa que nos permita recibir o transmitir datos al
microcontrolador por eso emplearemos el Hyper terminal que es un accesorio de
comunicaciones que encontramos en Windows. La configuración es bastante sencilla y la
configuración debe coincidir con la que hemos seleccionado para en el PIC.
- Este programa lee un dato del canal AN0 del A/D y lo transmite a la PC a (2400 baudios:8
bits de datos:ninguna paridad:1 bit de parada y ningún control de flujo). El manejo del A/D
es similar a los programas anteriores con la diferencia que no usamos el timer 0 para
generar el retardo (mínimo 19,2 us) para el tiempo de adquisición sino que las instrucciones
que empleamos en el programa nos permiten asegurar el tiempo apropiado.
b) Diseño del programa
Algoritmo
1. Ir banco 0.
2. ADCON0: ADCS1 ADCS0 CH2 CH1 CH0 GO/-DONE ----- ADON
0 1 0 0 0 0 --- 1
Seleccionamos el canal 0 del A/D (CH2-0), encendemos el modulo (ADCON=1) y
elegimos el TAD Fosc/8 (ADS1:0)
3. Ir banco 1.
4. TRISA=TRISB=TRISC=TRISD=TRISE=Salidas
5. ADCON1: ADMF ADCS2 ------ ------ PCFG3 PCFG2 PCFG1 PCFG0
00001110
Justificamos el resultado de los registros ADRES a la izquierda (ADMF=0). Solo el
pin RA0 será canal analógico y las tensiones de referencia para el ADC serán
VREF+=VDD y VREF-= VSS
6. TRISA<0>=0, configurar el pin RA0 como entrada.
7. TRISC<6>=1, configurar el pin RC6 como salida para la Tx serial.
8. SPBRG =25 (si y solo si el Cristal es de 4MHz )para lograr una frecuencia de 2400
baudios (referirse a la tabla).
9. TXSTA<BRGH>=0 para baja velocidad de acuerdo a la tabla del registro SPBRG
10. TXSTA<SYNC>=0 configuramos en modo asíncrono
11. Ir banco 0
12. RCSTA<SPEN>=1 habilitamos la puerta serial.
13. Ir banco 1
14. TXSTA<TX9>=0 , elegimos 8 bits de datos para la transmisión.
15. TXSTA<TXEN>=1, habilita la transmisión, automáticamente el bit TXIF se va a 1-
lógico
16. GO/-DONE=1. Iniciar la conversión A/D.
17. Si GO/-DONE es 1 ir paso 17
18. Si GO/-DONE es 0 ir paso 19
19. TXREG=PORTC=ADRESH
20. Si TXIF=0 Ir paso 20
21. Si TXIF=1 Ir paso 16
Diagrama de Flujo
include "p16f877.inc"
end
Inicio->Accesorios->Comunicaciones->Hyper terminal
Ingrese a:
Inicio-> Configuración panel de control -> Agregar quitar programas
Elija la pestaña Instalación de Windows. Ahora seleccione Comunicaciones y habilite el Hyper
terminal.
Una vez que abra el hyper terminal
observará una ventana como la que se
muestra.
Elija el ícono para crear una conexión.
A continuación le aparecerá una
ventana de mensajes:
Necesita instalar un modem antes
de poder hacer una conexión
Desea hacerlo hora?
Elija el botón “No”
Si todo ha terminado
sin novedad
aparecerá una
ventana como la que
se muestra en este
momento podrá
usted conectarse con
algún dispositivo que
tenga conectado al
COM2 y que
transmita bajos
parámetros
establecidos
(2400:8:0:1:Ninguna)
Trabajo en el MPLAB
Ejercicio 17
Recibir datos provenientes de la computadora de forma serial y mostrarlos en el
PORTC
a) Definiciones previas
Para el desarrollo del programa es importante conocer la frecuencia del XTAL con el que
funcionará el microcontrolador. En nuestro caso es de 4MHz. Ahora a partir de eso definimos la
velocidad de transmisión que será de 2400 bits por segundo. Por tanto Ese valor esta tipificado
como de baja velocidad y el bit BRGH ha de ser 0. En base a las tablas mostradas en el apartado
teórico elegimos 25 para el registro SPBRG. Colocamos el bit SYNC a 0 para una transmisión
asíncrona. Este programa solo recepciona datos por tanto configuramos el pin RC7 como entrada.
El diagrama de bloques del USART nos musetra que hay 2 bits que controlan el trabajo de
recepción; SPEN es una suerte de compuerta que debemos habilitar y el bit CREN también ya
que indica que se llevará una recepción continua de datos. En el diagrama de bloque observamos
la aparición de otros bits como es el caso del OERR y el FERR que sirve para la detección de
errores. También figura el bit TX9 que define si la transmisión se realiza con 8 ó 9 bits de datos,
es este caso optaremos por 8 bits de datos. Finalmente existe un bit el RCIF que se pone a 1
cuando un byte ha llegado exitosamente, usaremos esta característica para recoger el valor del
USART y lo pasaremos al PORTC. El proceso se realiza en forma continua.
b) Diseño del programa
Algoritmo
1. Ir banco 1.
2. Configurar TRISA=TRISB=TRISC=TRISD=TRISE como salidas
3. Colocar el pin RC7 como entrada
4. Configurar la frecuencia de recepción. Considerando un XTAL de 4MHz tenemos
SPBRG=25
5. Configurar para que trabaje a baja velocidad, BRGH=0
6. Configurar el modo asíncrono, SYNC=0
7. Ir banco 0
8. Habilitar la compuerta serie de entrada, SPEN=1
9. Configurar 8 bits de datos, RX9=0
10. Configurar recepción continua, CREN=1
11. Si PIR<RCIF>=0 Ir paso 11
12. Si PIR<RCIF>=1 Ir paso 13
13. PORTC=RCREG
14. Ir paso 11
Diagrama de Flujo
org 0x00
nop
nop
end
Trabajo en el MPLAB
c:\Archivos de programa\MPLAB\m4e2.pjt
Ejercicio 18
Diseñe un programa en el PIC 16F877 que reciba datos de la computadora, los
muestre por el PORTC y devuelva el mismo dato a la computadora para poder
visualizar los datos por el hyper terminal de Windows
a) Definiciones previas
El programa lo que pretende es crear una suerte de “echo“ de tal forma que el valor enviado al
presionar una tecla sea visualizado en el PORTC del microcontrolador. A continuación ese mismo
valor que fue recibido será devuelto a la PC (es como si rebotará), es decir es un “echo”. En este
programa debemos conjuncionar tanto la transmisión como la recepción serial.
b) Diseño del programa
Algoritmo
1. Ir banco 1.
2. Configurar TRISA=TRISB=TRISC=TRISD=TRISE como salidas
3. Colocar el pin RC6 como salida
4. Colocar el pin RC7 como entrada
5. Configurar la frecuencia de recepción. Considerando un XTAL de 4MHz tenemos
SPBRG=25
6. Configurar para que trabaje a baja velocidad, BRGH=0
7. Configurar el modo asíncrono, SYNC=0
8. Ir banco 0
9. Habilitar la compuerta serie de entrada y la compuerta serie de salida, SPEN=1
10. Ir banco 1
11. Configurar 8 bits de datos en transmisión , TX9=0
12. Habilitar transmisión serie, TXEN=1
13. Ir banco 0
14. Configurar 8 bits de datos en recepción , RX9=0
15. Configurar recepción continua, CREN=1
16. Si PIR<RCIF>=0 Ir paso 11
17. Si PIR<RCIF>=1 Ir paso 13
18. PORTC=RCREG
19. TXREG=RCREG
20. Si PIR<TXIF>=0 Ir paso 20
21. Si PIR<TXIF>=1 Ir paso 16
Diagrama de Flujo
_esperatx
btfss PIR1,TXIF ;Espera hasta que transmisión culminó
goto _esperatx ;No, ir _esperatx
Trabajo en el MPLAB
Conecte el demoboard a la PC (COM2) y revise el funcionamiento del programa con ayuda del
Hyper terminal. Si todo marcha bien notara como el carácter que digita aparece en el PORTC
y ademas es puesto en la ventana del Hyper terminal.
Módulo : Manejo de interrupciones
Interrupciones
Registro de Control de Interrupciones (INTCON)
Registro de permiso de interrupciones 1 (PIE1)
Contiene los bits que permiten (1) o prohiben (0) las interrupciones provocadas por los
periféricos internos del microcontrolador y que no estaban contempladas en INTCON.
Ocupa la dirección 8Ch y para que cumplan su función los bits de PIE1 es necesario que
PEIE=1 en INTCON <6>. El bit PSPIE solo es valido en los modelos de 40 pines,
manteniéndose a 0 en los que tienen 28 pines.
Note 1: PSPIE is reserved on PIC16F873A/876A devices; always maintain this bit clear.
Registro de permiso de interrupciones 2 (PIE2)
Contiene los bits de permiso de interrupción de las tres causas que no figuran en PIE1. La
de fin de escritura en la EEPROM, colisión de bus en el modo SSP y producción de una
captura o una comparación en el módulo CCP2.
Registros de los señalizadores de interrupciones 1 y 2 (PIR1 y PIR2)
Lógica de Interrupciones:
Ejercicios
Ejercicio 20
Diseñar y simular un programa que trabaja la interrupción RB0/INT para ir
acumulando los flancos de subida que vayan ingresando por el pin RB0. En este
primer ejemplo el bucle principal del programa no “tareas”.
• Debe existir una variable “contador” que acumule los pulsos que llegan al RB0/INT. Al
Condiciones:
list p=16f877
include "p16f877.inc"
BUCLE
nop ;No operacion
nop
goto BUCLE ;Ir a BUCLE
END
b) Simulación MPLAB
•
Para hacer esta tarea:
Ingresar al menú -> DEBUG -> STIMULUS SIMULATOR -> ASYNCHRONUS
•
STIMULUS
Para asociar Stim 1(P) a RBO haga clic derecho sobre el botón Stim 1 (P). Elija la
•
opción Assing PIN. Seleccione RB0
Asegurece que el tipo de estimulo a ser aplicado sea tipo PULSE.
• Stack Window
• Special Funcion Register
• File Register
omode las en la ventana a fin que pueda tener una visión de todas ellas a la vez.
• Proceda a simular el programa ingrese al modo STEP (F7, avance paso a paso ).
•
Avance hasta ingresar a la etiquta “BUCLE”.
Con ayuda del mouse simule un pulso en RB0/INT (haga un click en: RBO (P), ventana
ASYNCHRONUS STIMULUS). Observara como es que simulador salta a la rutina de
•
interrupción e incrementa el valor de la cuenta CONTADOR (registro 0x0C).
Observe el lo que sucede en la ventana STACK WINDOWS.
TRACE POINT
•
•
Resetee el programa (DEBUG->RUN->RESET)
Coloque el mouse sobre la línea “bcf INTCON,INTF” , click izquierdo, BREAK
•
POINT
•
Cree un punto de revisión (TRACE POINT)
Coloque el mouse sobre la instrucción “incf CONTADOR,1”, click izquierdo,
TRACE POINT
•
•
Abra la ventana TRACE WINDOWS (menú Windows -> Trace Memory)
Ahora corra el programa (click sobre el semáforo verde). Ingrese 5 pulsos en el pin
•
RB0/INT del microcontrolador.
•
Detenga el programa (click en el SEMAFORO ROJO).
Observe que aparece en la ventana TRACE MEMORY.
NOTA.- Los TRACE POINTS siempre se muestran en COLOR VERDE. Es posible usar el
TRACE POINT en combinación con el BREAK POINT. Desde luego que solo visualizara los
datos acumulados hasta encontrar el BREAK POINT.
OBSERVACIONES.-La ventana TRACE MEMORY reporta los cambios operados sobre la
linea que ha sido marcada con el TRACE POINTS. Como nuestro objetivo era examinar el
valor de CONTADOR pusimos el TRACE POINTS sobre la instrucción “incf
CONTADOR,1”.
c) ¿Qué es lo que pasa con el bit GIE del registro INTCON cuando entramos a la rutina de
interrupción?
Explique que utilidad tiene esto.
d) Si reemplazamos la instrucción:
ORG 4
incf CONTADOR,1
bcf INTCON,INTF
bsf INTCON,GIE
goto BUCLE
Ejercicio 21
Configurar el TMR1 para generar espacios de tiempo de 500ms. Cada vez que se
cumpla el tiempo invertir el valor del RC7 (similar a un led intermitente).
Emplear la interrupción RB0 para incrementar el valor del PORTC cada vez que
llegue una petición.
Definiciones Previas
El PIC16F877 cuenta con 14 causas que pueden originar una interrupción; el uso de
interrupciones es importante porque permite realizar varias tareas a la vez. Cuando se
produce una interrupción se salva el valor del contador de programa y se carga con el valor
0x04 donde debe estar la rutina de interrupción. Una vez concluída la rutina de
interrupción restablece el valor del contador del programa.
list p=16f877 ;Comando que indica el Pic usado
include "p16f877.inc" ;Etiquetas genéricas para el Pic16F877
org 0x00 ;Inicio del programa en la posición cero de memoria
nop ;Libre (uso del debugger)
goto _inicio ;Ir _inicio
org 0x04 ;Vector de interrupcion
goto _interrupción ;Ir rutina de interrupcion
_inicio
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP1
_retardo
bcf PIR1,TMR1IF ;Borrar la bandera de desborde
clrf TMR1H ;TMR1H = 0
movlw 0xa ;TMR1L = 10
movwf TMR1L
bsf T1CON,TMR1ON ;Habilita el TMR1
_espera
btfss PIR1,TMR1IF ;Verificar el desborde
goto _espera ;Si no ir _espera
bcf T1CON,TMR1ON ;Si desborda: limpiar bandera de desborde
return ;Retorno
_compara
movlw 0Xff ;PORTC = 0xff?
subwf PORTC,W
btfss STATUS,Z
goto _salida ;No, ir _salida
clrf PORTC ;Si, PORTC = 0
bsf PORTC,7 ;RC7 = 1
retfie ;Fin interrupcion
_salida
incf PORTC,F ;PORTC = PORTC + 1
retfie ;Fin interrupcion
END
Ejercicio 22
Configurar el canal AN0 del ADC para mostrar en forma permanente el valor de
conversión en el puerto C. Cada vez que llegue una interrupción provocada por el
hiperterminal el microcontrolador enviará a la PC el valor actual del ADC.
_inicio
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
_bucle
bsf ADCON0,GO ;Start A/D conversion
_espera
btfsc ADCON0,GO ;ADCON0 es 0? (la conversion esta completa?)
goto _espera ;No, ir _espera
_esperatx
btfss PIR1,TXIF ;Espera hasta que transmisión culminó
goto _esperatx ;No, ir _esperatx
_inicio
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP 1
clrf TRISA ;PORTA salida
clrf TRISB ;PORTB salida
clrf TRISC ;PORTC salida
clrf TRISD ;PORTD salida
clrf TRISE ;PORTE salida
_esperatx
btfss PIR1,TXIF ;Espera hasta que transmisión culminó
goto _esperatx ;No, ir _esperatx
_retorno
bsf INTCON,PEIE ;Habilita INTR perifericos
swapf _int_save_OPTION_REG,W ;Restaurar valor de OPTIO_REG
movwf OPTION_REG
swapf _int_save_PCLATH,W ;Restaurar valor de PCLATH
movwf PCLATH
swapf _int_save_FSR,W ;Restaurar valor de FSR
movwf FSR
swapf _int_save_STATUS,W ;Restaurar valor de STATUS
movwf STATUS
swapf _int_save_W,W
retfie
_teclas
addwf PCL,F ;pcl + W >>>> W
;El PCL se incrementa con el valor
;de W proporcionando
;un salto
retlw A'A' ;retorna con valores para PORTC
retlw A'B'
retlw A'C'
retlw A'a'
retlw A'b'
retlw A'c'
_salidas
addwf PCL,F ;pcl + W >>>> W
;El PCL se incrementa con el valor
;de W proporcionando
;un salto
goto _on_RC0
goto _on_RC1
goto _on_RC2
goto _off_RC0
goto _off_RC1
goto _off_RC2
END
Módulo : Memoria EEPROM
Memoria de Datos EEPROM y Memoria FLASH de Programa
EECON1
EECON2
EEDATA
EEDATH
EEADR
EEADRH
La memoria de datos (EEPROM) tiene una palabra de 8 bits. Cuando accedemos a este
bloque de memoria el registro EEDATA contiene los 8 bits de datos y el registro EEADR
contiene la dirección que deseamos trabajar. El PIC16F877 tiene 256 posiciones de
memoria de datos (EEPROM) numeradas de 0x00 a 0xFF (de 0 a 255). La memoria de datos
(EEPROM) es una memoria no volátil que se graba eléctricamente, es útil por que nos
permite almacenar valores o parámetros que sean persistentes en la ejecución de la
aplicación. Esto es, que no se borren frente a la pérdida de energía o reset.
Los valores escritos en la memoria de programa no tiene que ser necesariamente valores
correspondientes a instrucciones. Por tanto los 14 bits almacenados pueden servir como
parámetros, números seriales, paquetes de 7 bits ASCII , etc. La ejecución de una posición
de la memoria de programa que contenga datos resulta en un código NOP.
El registro EEADR
Sirve para direccionar (apuntar) a una posición de las 256 disponibles para la memoria
EEPROM o para las 8192 de la memoria de programa (FLASH). El registro EEADRH
contiene los valores mas significativos, la EEADR los 8 menos significativos.
Los registros EECON1 y EECON2
El registro EECON1 es el registro que contiene los bits de control del proceso de lectura o
escritura en la memoria EEPROM. El registro EECON2 es un registro que se usa en la
secuencia de escritura y que físicamente no existe, si se lee se encuentra que esta lleno de
ceros.
En el registro EECON1 esta el bit EEPGD (posición 7) que indica si el trabajo a realizar se
lleva a efecto sobre la memoria de datos o sobre la memoria de programa. Cuando es
colocado a cero las operaciones serán sobre la EEPROM (memoria de datos) y si es colocado
a 1 las operaciones son sobre la memoria de programa (FLASH)
Los bits WR y RD del registro EECON1 sirven para controlar y revisar el estado de la
operaciones de escritura y lectura respectivamente. Para iniciar cualquier de esas
operaciones se coloca a 1-lógico el bit de la operación. Cuando se ha completado un ciclo de
lectura o escritura los bits se colocan a 0-lógico nuevamente. Por software solo se puede
colocar a 1-lógico.
El bit WREN (write enable) se coloca a 1 para habilitar la operación de escritura esto para
evitar escrituras espurías en el EEPROM. Cuando el microcontrolador es energizado el bit
WEN permanece a 0-lógico.
El bit EEIF es una bandera que se coloca a 1-lógico cuando la operación de escritura ha
terminado, debe ser colocada a 0 por software. La bandera se puede usar cuando deseamos
trabajar interrupciones. A continuación se presenta el detalle del registro EECON1:
EECON1
REGISTER
(ADDRESS
18Ch)
Operación de lectura de la memoria de datos EEPROM
• Colocar a 0-lógico el bit EEPGD del registro EECON1 para indicar que vamos a
Operación de escritura en la memoria de datos EEPROM
Al igual que en el caso anterior antes de realizar una operación debemos cargar la dirección
de la memoria en el registro EEADR y el dato debe ser cargado en el registro EEDATA. El
siguiente segmento de código muestra la secuencia de grabación a ser operada:
Protección contra escrituras espurias
Hay condiciones en las cuales se desea proteger el dispositivo contra posibles grabaciones
indeseadas para ello existen mecanismos. Cuando se energiza el microcontrolador (Power-
Up) el bit WREN es puesto a 0-lógico, ademas hay un temporizador Power-Up timer que
demora 72 us antes de que se efectúe cualquier instrucción en el microcontrolador. El bit
PWRTE de la palabra de configuración debe ser puesto a 1-lógico al momento de grabar el
PIC para que el temporizador Power-Up funcione. Finalmente existe la secuencia de
grabación y el bit WREN que controla el ciclo de escritura.
Ejercicios
Ejercicio 24
a) Algoritmo
Para la implementación de programa usaremos dos rutinas: una que graba
(ESCRIBIR_EEPROM) y una que lee (LEER_EEPROM). En ambos casos definimos dos
variables ADDR_L (0x20) y DATA_L(0x21). El proceso de lectura o grabación se realiza
conforme lo establecido por el fabricante. Antes de llamar a la rutina ESCRIBIR_EEPROM
es necesario cargar la dirección ADDR_L y el dato que deseamos grabar. Antes de invocar a
la rutina LEER_EEPROM debemos cargar la dirección a leer, al terminar la rutina
almacenamos el valor en DATA_L para que sea usado desde el programa principal.
a) Diagrama de Flujo
b) Código del programa
ESCRIBIR_EEPROM
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
movf ADDR_L,W ;EEADR = ADDR_L
bcf STATUS,RP0 ;Ir banco 2
bsf STATUS,RP1
movwf EEADR
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
movf DATA_L,W ;EEDATA = DATA_L
bcf STATUS,RP0 ;Ir banco 2
bsf STATUS,RP1
movwf EEDATA
bsf STATUS,RP0 ;Ir banco 3
bsf STATUS,RP1
bcf EECON1,EEPGD ;Apuntar a la memoria EEPROM
bsf EECON1,WREN ;Habilitar escritura
bcf INTCON,GIE ;Deshabilita interrupciones
movlw 55h
movwf EECON2 ;Escribe 55 hexadecimal
movlw 0xAA
movwf EECON2 ;Escribe AA hexadecimal
bsf EECON1,WR ;Habilita el bit de escritura
; bsf INTCON,GIE ;Habilita interrupciones
_bucle1
btfsc EECON1,WR ;Espera el final de grabación
goto _bucle1 ;Si no termina la grabación: Ir _bucle
bcf PIR2,EEIF ;Si termina Borra bandera de interrupción
bcf EECON1,WREN ;Deshabilitar escritura
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
return ;Retorno
LEER_EEPROM
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
movf ADDR_L,W ;Cargar dirección a leer
bcf STATUS,RP0 ;Ir banco 2
bsf STATUS,RP1
movwf EEADR
bsf STATUS,RP0 ;Ir banco 3
bsf STATUS,RP1
bcf EECON1,EEPGD ;Apunta a la memoria EEPROM
bsf EECON1,RD ;Habilita ciclo de lectura
bcf STATUS,RP0 ;Ir banco 2
bsf STATUS,RP1
movf EEDATA,W ;W = EEDATA (leer dato de EEPROM)
bcf STATUS,RP0 ;Ir banco 0
bcf STATUS,RP1
movwf DATA_L ;DATA_L = W (almacena dato de EEPROM)
return ;Retorno
end
a) Diagrama de Flujo
Nota. -Los diagramas de flujo de las rutinas ESCRIBIR_EEPROM y LEER_EEPROM son
los mismos que los que se mostraron en el programa anterior
ESCRIBIR_EEPROM
LEER_EEPROM
Ejercicio 26
• El segundo programa lee el canal AN0 del ADC y según esa lectura obtiene
posición 0x01, y asi sucesivamente hasta 0 en la posición 0xFF.
PRIMER PROGRAMA
SEGUNDO PROGRAMA
end
Módulo : Manejo de Páginas de
Memoria y Watch Dog
PCL Y PCLATCH
El contador de programa (PC) es un registro que tiene 13 bits para direccionar las 8K
posiciones de memoria que tiene el microcontrolador. Los bits menos significativos se
almaceman en el registro PCL, que es un registro que se puede leer o escribir. Los bits mas
significativos PC<12:8> no se pueden leer pero pueden ser ESCRITOS
INDIRECTAMENTE a traves del registro PCLATCH. Como lo muestra la figura:
La Pila
El PIC16F877 tiene una pila de 8 niveles en hardware y es exclusiva para el PC. Existe un
puntero de pila que apunta a la última posición disponible (en un reset apunta a la posición
0). El puntero de pila no se puede leer ni escribir. Generalmente cuando usamos una pila
empleamos las instrucciones PUSH (colocar en pila) y POP (extraer de la pila). En el caso
del PIC no hay tales instrucciones . La colocación de valores dentro de la pila se hacen a
través de la instrucción CALL. La extracción se hace por medio de las instrucciones
RETURN, RETLW y RETFIE. El PCLATH no se ve afectado por la extracción o
colocación de valores en la pila condición que debemos tener presente al
momento de hacer uso de varias páginas de memoria.
La pila opera como un buffer circular, es decir que si se hacen 9 operaciones PUSH
estaremos sobreescribiendo la primera posición de la pila. Si fueran 10 perderiamos los dos
primeros valores.
Paginación de la memoria de programa
La combinación de los bits 4 y 3 del PCLATCH nos permite seleccionar una página de
memoria como se muestra:
Siempre que deseamos hacer un salto de página debemos cargar el PCLATCH con la
combinación apropiada. Y cuando regresamos de la llamada es necesario “liberar la página”.
Esto es restituir los valores para que el PCLATCH este en la página previa a la llamada:
; Supongamos que estamos en la página 0 y vamos a llamar a una rutina que esta en la
página 3
; PCLATCH<4:3> = <0:0>
•
•
Retardo de mas de 1 segundo Led conectado a RC0=ON
•
Retardo de mas de 1 segundo Led conectado a RC1=ON
•
Retardo de mas de 1 segundo Led conectado a RC0=OFF
Retardo de mas de 1 segundo Led conectado a RC1=OFF
Definiciones previas
Las condiciones seran las siguiente: Debe existir la rutina de retardo en base al TMR0 y el
código debe estar en la página 0. La rutina que controla RC0 debe estar en la página 0. La
rutina que controla RC1 debe estar en la página 1 y debe llamar a la rutina retardo de la
página 0. Si hacemos un resumen de las rutinas y las asociamos a las páginas de memoria
tendriamos:
Pagina 0 Pagina 1
org 0x00 org 0x800
configurar rc1{.......
bucle call Retardo
call retardo .......
call rc0 }
call rc1
goto bucle
retardo{ .....}
rc0{......}
a) Diagrama de flujo
Como se observa el manejo de páginas es sencillo, basta con cargar en el PCLATCH los
valores correspondientes a la página hacer la llamada a la función y desde luego LIBERAR
LA PAGINA para evitar la pérdida del contador de programa. Si no liberamos la página y
hacemos una instrucción goto o una instrucción call el contador de programa cargará los
valores del PCLATH. En este caso en particular iría de nuevo a la página 1.
b) Código de programa
list p=16f877
include "p16f877.inc" ;Etiquetas genericas para el Pic16F877
TEMP EQU 0x20 ;Variable para temporizacion
;=====================================================================
==
org 0x0 ;PAGINA 0
;=====================================================================
==
nop
nop
clrf TRISA
clrf TRISB
clrf TRISC
clrf TRISD
clrf TRISE
;---------------------------------;
; Llamada a rutina en pagina 1 ;
;---------------------------------;
bcf PCLATH,4 ;PCLATH=Pagina 1
bsf PCLATH,3
call _pagina_1 ;Enciendo o apaga el bit 1 del PORTC
bcf PCLATH,4 ;PCLATH=Pagina 0, LIBERAR PCLATH
bcf PCLATH,3
;=====================================================================
==
_retardo
movlw d'25'
movwf TEMP ;TEMP=25
_retardo_0
bcf INTCON,T0IF
_retardo_1
btfss INTCON,T0IF
goto _retardo_1
decfsz TEMP
goto _retardo_0
return
;=====================================================================
==
_pagina_0 ;PAGINA 0
btfss PORTC,0 ;Es el valor de PORTC<0>=1
goto _on_0 ;PORTC<0>=1
bcf PORTC,0
return
_on_0 bsf PORTC,0 ;PORTC<0>=0
return
;=====================================================================
==
org 0x800 ;PAGINA 1
;=====================================================================
==
_pagina_1
;----------------------------------------;
; Llamada a rutina _retardo en pagina 0 ;
;----------------------------------------;
bcf PCLATH,4 ;PCLATH=Pagina 0
bcf PCLATH,3
call _retardo
bcf PCLATH,4 ;PCLATH=Pagina 1, LIBERAR PCLATH
bsf PCLATH,3
end
Metodología de acceso a funciones por medio de una solo página
Como hemos visto el acceso a funciones o rutinas que se encuentran en otras páginas es
relativamente sencillo. Ahora suponga que tiene una rutina llamada 'A' que se encuentra
en la página 0, esa rutina es llamada desde varias varias páginas como lo muestra la
siguiente figura:
org 0x800
.......
bcf PCLATH,4 ;Pagina 0
bcf PCLATH,3
call A
bcf PCLATH,4 ;Liberar pagina
bsf PCLATH,3
........
Entonces cuando queremos llamar a la rutina A lo que hacemos es cargar el PCLATH para
ir a la página 0 y, luego hacemos el CALL. El CALL almacenará la siguiente dirección.
Entramos al página 0 y volvemos a cargar el PCLATH con la página donde esta el código
propiamente dicho de la rutina A (página 0) que es _A_code. Saltamos a esa dirección con
ayuda de la instrucción GOTO (no coloca nada en la pila del PC). Cuando termina _A_code
con la instrucción return extrae de la pila el PC que le permite regresar a la página original
de la llamada (no regresa a la página 0).
Note como ahora el resto del código de programa no sufre modificación alguna solo hemos
cambiado la dirección en el indice que esta en la página 0.
Ejercicios
Ejercicio 28
•
•
Retardo de mas de 1 segundo Led conectado a RC0=ON
•
Retardo de mas de 1 segundo Led conectado a RC1=ON
•
Retardo de mas de 1 segundo Led conectado a RC2=ON
•
Retardo de mas de 1 segundo Led conectado a RC3=ON
•
Retardo de mas de 1 segundo Led conectado a RC0=OFF
•
Retardo de mas de 1 segundo Led conectado a RC1=OFF
•
Retardo de mas de 1 segundo Led conectado a RC2=OFF
Retardo de mas de 1 segundo Led conectado a RC3=OFF
Definiciones previas
En el programa usaremos un indice de páginas. Las llamadas seran hechas desde la página
0 a las rutinas que controlan el RC0(_pagina_0) , RC1(_pagina_1), RC2(_pagina_2), RC3
(_pagina_3). La rutina de RC2 (_pagina_2) llama a la función de retardo de la página 0.
a)Diagrama de flujo
b)Código del programa
list p=16f877
include "p16f877.inc" ;Etiquetas genericas para el Pic16F877
TEMP EQU 0x20 ;Variable para temporizacion
;=====================================================================
==
org 0x0 ;PAGINA 0
;=====================================================================
==
nop
nop
clrf TRISA
clrf TRISB
clrf TRISC
clrf TRISD
clrf TRISE
;---------------------------------;
; Llamada a rutina en pagina 1 ;
;---------------------------------;
call _retardo ;Llama a retardo (pagina 0 de memoria)
bcf PCLATH,4 ;PCLATH=Pagina 0, LIBERAR PCLATH
bcf PCLATH,3
call _pagina_1 ;Enciendo o apaga el bit 1 del PORTC
bcf PCLATH,4 ;PCLATH=Pagina 0, LIBERAR PCLATH
bcf PCLATH,3
;----------------------------------;
; Llamada a rutina en pagina 2 ;
;----------------------------------;
;El RETARDO esta dentro de la rutina _pagina_2
call _pagina_2 ;Enciendo o apaga el bit 2 del PORTC
bcf PCLATH,4 ;PCLATH=Pagina 0, liberar PCLATH
bcf PCLATH,3
;----------------------------------;
; Llamada a rutina en pagina 3 ;
;----------------------------------;
call _retardo
bcf PCLATH,4 ;PCLATH=Pagina 0, LIBERAR PCLATH
bcf PCLATH,3
call _pagina_3 ;Enciendo o apaga el bit 2 del PORTC
bcf PCLATH,4 ;PCLATH=Pagina 0, liberar PCLATH
bcf PCLATH,3
;=====================================================================
==
_pagina_0_code ;PAGINA 0
btfss PORTC,0 ;Es el valor de PORTC<0>=1
goto _on_0 ;PORTC<0>=1
bcf PORTC,0
return
_on_0 bsf PORTC,0 ;PORTC<0>=0
return
;=====================================================================
==
; DEFINICIONES DE SALTOS. Similar a declarar funciones
;=====================================================================
==
_pagina_0
bcf PCLATH,4 ;Pagina 0
bcf PCLATH,3
goto _pagina_0_code
_pagina_1
bcf PCLATH,4 ;Pagina 1
bsf PCLATH,3
goto _pagina_1_code
_pagina_2
bsf PCLATH,4 ;Pagina 2
bcf PCLATH,3
goto _pagina_2_code
_pagina_3
bsf PCLATH,4 ;Pagina 3
bsf PCLATH,3
goto _pagina_3_code
_retardo
bsf PCLATH,4 ;Pagina 3
bsf PCLATH,3
goto _retardo_code
;=====================================================================
==
org 0x800 ;PAGINA 1
;=====================================================================
==
_pagina_1_code
btfss PORTC,1 ;Es el valor de PORTC<1>=1
goto _on_1 ;PORTC<1>=1
bcf PORTC,1 ;PORTC<1>=0
return
_on_1 bsf PORTC,1
return
;=====================================================================
==
org 0x1000 ;PAGINA 2
;=====================================================================
==
_pagina_2_code
;----------------------------------;
; Llamada a rutina _retardo ;
;----------------------------------;
bcf PCLATH,4 ;PCLATH=Pagina 0
bcf PCLATH,3
call _retardo
bsf PCLATH,4 ;PCLATH=Pagina 2, LIBERAR PCLATH
bcf PCLATH,3
;=====================================================================
==
org 0x1800 ;PAGINA 3
;=====================================================================
==
_pagina_3_code
btfss PORTC,3 ;Es el valor de PORTC<2>=1
goto _on_3 ;PORTC<3>=1
bcf PORTC,3 ;PORTC<3>=0
return
_on_3 bsf PORTC,3
return
;=====================================================================
==
_retardo_code
movlw d'25'
movwf TEMP ;TEMP=25
_retardo_0
bcf INTCON,T0IF
_retardo_1
btfss INTCON,T0IF
goto _retardo_1
decfsz TEMP
goto _retardo_0
return
end
PERRO GUARDIAN (WDR: WATCHDOG TIMER)
El WDT de los PIC16F87x es un contador que funciona con los impulsos de su propio
oscilador y que provoca un reset cuando se desborda en funcionamiento normal. Si el
desbordamiento se produce cuando en microcontrolador se halla en estado de reposo, se
despierta y sigue su comportamiento normal. En la figura se muestra un esquema con los
bloques principales que constituyen el perro guardian.
Las instrucciones CLRWDT y SLEEP borran o ponen a cero el valor del contaje del WDT y
el postdivisor. Si se ejecuta la instrucción CLRWDT y el predivisor de frecuencia esta
asignado al perro guardian, se borra, pero no cambia su configuración.
MODO DE REPOSO O DE BAJO CONSUMO
Ejercicio
Ejercicio 29
Según el valor del interruptor RB0, se encenderán o apagarán los leds del
puertoC pero, antes de volver a mirar el valor de dichos interruptores, se
introducirá al microcontrolador en estado de reposo, del cual despertara al
desbordarse el perro guardian, iniciandose de nuevo el proceso.
list p=16f877 ;Comando que indica el Pic usado
include "p16f877.inc" ;Etiquetas genéricas para el Pic16F877
goto _inicio
org 0x005
_inicio
bsf STATUS,RP0 ;Ir banco 1
bcf STATUS,RP1
Ejercicio 0: Desarrollar un programa que configure las líneas del puerto A como entrada y
las líneas del puerto B como salida. Y que muestre en forma permamente la entrada del
puerto A en el puerto B.
Ejercicio 1: Suponga una lampara que debe ser prendida o apagada desde tres puntos.
Diseñe un programa que la encienda si y solo si hay dos interruptores activados.
Ejercicio 3: Se tiene tres válvulas (A,B y C) que alimentan un tanque, el tanque a su vez
tiene una salida. Existen 3 sensores de nivel (X,Y y Z). Cuando el tanque está vacio los 3
sensores estan a 0-lógico y es necesario activar el trabajo de las tres bombas. Cuando se
llena 1/3 del tanque el sensor X pasa a 1-lógico y la bomba C deja de funcionar. Cuando se
llenan 2/3 del tanque el sensor Y esta activado y la bomba B deja de funcionar. Cuando esta
lleno el tanque el sensor Z se activa y la bomba A deja de funcionar. Una vez que el tanque
esta lleno este empieza a expulsar el líquido acumulado. Cuando los 3 sensores pasan a 0-
lógico la secuencia antes descrita se repite ANTES NO.
Ejercicio 4: Diseñar un programa que configure el RB0 como entrada y el RC0 como salida
y probarlo en el demoboard.
Ejercicio 5: Diseñar un programa que muestre en el puerto C los cuatro bits mas
significativos activados si RB0 es 0 y los bits menos significativos activados si RB0 es 1.
Ejercicio 7: Diseñar un programa que lea los 4 bits inferiores del puerto A y muestre el
dato en un display de 7 segmentos que se encuentra conectado en el puerto C.
Ejercicio 10: Programar el TMR0 para generar un retardo de un segundo. A partir del cual
se incrementa un contador cuyo valor se muestra por el PORTC
Ejercicio 11: Programar el TMR1 para generar un retardo de 524.2 ms. Cada vez que
concluya el tiempo se activará el PORTC de forma escalonada
Ejercicio 12 : Modificar el programa anterior para que lea el pin RB0, cuando se pulse
deshabilitara el TMR1 y si se deja de pulsar reanudara el timer.
Ejercicio 13: Diseñar un programa que permita leer el voltaje aplicado al canal 0 del
módulo ADC, convertirlo a un valor digital de 10 bits y mostrar los ocho bits mas
significativos en el PORTC
Ejercicio 14: Elaborar un programa que lea el canal 0 del modulo ADC y que muestre el
resultado en los 6 bits menos significativos del PORTC (RC0-RC5) adicionalmente active un
pin del Pic (RC7) cuando el valor adquirido por el ADC sea mayor a 512 y desactive cuando
sea menor a ese valor.
Ejercicio 16: Transmitir muestras analógicas provenientes del canal AN0 del ADC del PIC
hasta la computadora y visualizar el dato por el hyper terminal de Windows.
Ejercicio 18: Diseñe un programa en el PIC 16F877 que reciba datos de la computadora,
los muestre por el PORTC y devuelva el mismo dato a la computadora para poder visualizar
los datos por el hyper terminal de Windows
Ejercicio 20: Diseñar y simular un programa que trabaja la interrupción RB0/INT para ir
acumulando los flancos de subida que vayan ingresando por el pin RB0. En este primer
ejemplo el bucle principal del programa no “tareas”.
Ejercicio 21: Configurar el TMR1 para generar espacios de tiempo de 500ms. Cada vez que
se cumpla el tiempo invertir el valor del RC7 (similar a un led intermitente). Emplear la
interrupción RB0 para incrementar el valor del PORTC cada vez que llegue una petición.
Ejercicio 22: Configurar el canal AN0 del ADC para mostrar en forma permanente el valor
de conversión en el puerto C. Cada vez que llegue una interrupción provocada por el
hiperterminal el microcontrolador enviará a la PC el valor actual del ADC.
Ejercicio 23: Diseñe un programa en el Pic16F877 que funcione con la interrupción del
USART. Si desde el hiperterminal se presiona la tecla ‘A’ RC0 = 1, ‘a’ RC0 = 0, ‘B’ RC1 = 1,
‘b’ RC1 = 0, ‘C’ RC2 = 1, ‘c’ RC2 = 0.
Ejercicio 24: Diseñe un programa que permita escribir y leer un byte en la posición 0x00
de la memoria EEPROM
•
•
Retardo de mas de 1 segundo Led conectado a RC0=ON
•
Retardo de mas de 1 segundo Led conectado a RC1=ON
•
Retardo de mas de 1 segundo Led conectado a RC0=OFF
Retardo de mas de 1 segundo Led conectado a RC1=OFF
•
•
Retardo de mas de 1 segundo Led conectado a RC0=ON
•
Retardo de mas de 1 segundo Led conectado a RC1=ON
•
Retardo de mas de 1 segundo Led conectado a RC2=ON
•
Retardo de mas de 1 segundo Led conectado a RC3=ON
•
Retardo de mas de 1 segundo Led conectado a RC0=OFF
•
Retardo de mas de 1 segundo Led conectado a RC1=OFF
•
Retardo de mas de 1 segundo Led conectado a RC2=OFF
Retardo de mas de 1 segundo Led conectado a RC3=OFF
Ejercicio 29: Según el valor del interruptor RB0, se encenderán o apagarán los leds del
puertoC pero, antes de volver a mirar el valor de dichos interruptores, se introducirá al
microcontrolador en estado de reposo, del cual despertara al desbordarse el perro guardian,
iniciandose de nuevo el proceso.