0% encontró este documento útil (0 votos)
262 vistas222 páginas

Programación de Microcontroladores

El documento es un manual sobre la programación de microcontroladores PIC en lenguaje C, escrito por Cándido Bariáin, Jesús María Corres y Carlos Ruiz. Incluye una introducción a la programación en C, el uso de puertos de entrada y salida, temporizadores, módulos de captura y comparación, así como módulos analógicos y de comunicación. También se abordan aspectos prácticos como la creación de proyectos en MPLAB-IDE y ejemplos de simulación.

Cargado por

bilydekit123
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
262 vistas222 páginas

Programación de Microcontroladores

El documento es un manual sobre la programación de microcontroladores PIC en lenguaje C, escrito por Cándido Bariáin, Jesús María Corres y Carlos Ruiz. Incluye una introducción a la programación en C, el uso de puertos de entrada y salida, temporizadores, módulos de captura y comparación, así como módulos analógicos y de comunicación. También se abordan aspectos prácticos como la creación de proyectos en MPLAB-IDE y ejemplos de simulación.

Cargado por

bilydekit123
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

MICROCONTROLADORES

Programación de microcontroladores
P1C en lenguaje C
Programación de microcontroladores
PIC en lenguaje C
Cándido Bariáin
Jesús María Corres
Carlos Ruiz

Marcombo
Programación de microcontroladores PIC en lenguaje C

Primera edición, 2017

© 2017 Cándido Bariáin Aisa, Jesús María Corres Sanz y Carlos Ruiz Zamarreño

© 2017 MARCOMBO, S.A.


[Link]

Diseño de la cubierta: NDENU DISSENY GRÁFIC

«Cualquier forma de reproducción, distribución, comunicación pública o transformación de


esta obra solo puede ser realizada con la autorización de sus titulares, salvo excepción pre­
vista por la ley. Diríjase a CEDRO (Centro Español de Derechos Reprográficos,
[Link]) si necesita fotocopiar o escanear algún fragmento de esta obra».

ISBN: 978-84-267-2427-4
DL: B-25226-2016

Impreso en Ulzama Digital


Printed in Spain
PROGRAMACIÓN DE MICROCONTROLADORES PIC EN 'C

ÍNDICE
In tr o d u cció n ........................................................ ...9
B ib lio g r a fía ........................................................... 10
1. Introducción a la programación en C ........... 11
1.1 Introducción............................................... .11
1.1.1 Estructura de un programa en C ...... .12
1.1.2 Directivas del preprocesador........... .13
1.1.3. Función Printf.................................... .14
1.1.4. Variables y tipos de datos................. .15
1.1.5 Definiciones de constantes................ .17
1.1.6 Macros y compilación condicional .... 18
1.2. Uso de las variables................................. .18
1.2.1 Declaraciones..................................... .18
1.2.2 Conversiones de tipo s....................... .20
1.2.3 Clases de almacenamiento................ .21
1.3. Funciones.................................................. .22
1.3.1. Paso de argumentos a las funciones 22

1.3.2 Retorno de resultados.......................


1.3.3 Interrupciones.................................... .24
1.4. Operadores............................................... .25
1.5. Estructuras de control en C ..................... ,27
1.5.1 Condicionales...................................... .27
1.5.2 Bucles de tipo FOR............................. .27
1.5.3 Bucles de tipo WHILE......................... .28
1.5.4 Bucles de tipo DO-WHILE................. .2S
1.5.5 Break.................................................... .29
1.5.6 Continué............................................. .29
1.5.7 Condicionales switch - case.............. .29
.30
1.6. Vectores....................................................
1.6.1 Vectores unidimensionales.............. .30
.30
1.6.2. Cadenas de caracteres.....................
.31
1.6.3 Vectores multidimensionales..........
.32
1.7. Punteros...................................................
.33
1.8. Estructuras y Uniones.............................

Página | 1
1.8.1. Estructuras..............................................................................................................................33
1.8.2. Uniones................................................................................................................................... 34
2. Puertos de entrada y salida digitales............................................................................................... 37
2.1 LED y Pulsadores............................................................................................................................38
2.1.1 Secuencias de encendido de LED........................................................................................... 38
2.1.2 Generación de la señal de auxilio internacional y su visualización mediante un LED........40
2.1.3 Visualización de una cadena de caracteres en código morse mediante un LED ................ 42
2.1.4 Generación de la señal acústica SOS mediante un Zumbador Piezoeléctrico.....................45
2.2 Visualizadores numéricos de 7 segmentos.................................................................................. 47
2.2.1 Control de 1 display............................................................................................................... 48
2.2.2 Control de un visualizador con 4 displays.............................................................................49
2.3. Exploración de teclado matricial.............................................................................................. 52
2.4 Control de Pantallas LCD.......................................................................................................... 54
2.4.1 Envío de cadenas de caracteres al LCD................................................................................ 56
2.4.2 Creación de nuevos caracteres.............................................................................................. 57
2.4.3 Cronómetro segundero en la pantalla LCD.......................................................................... 58
3. Temporizadores................................................................................................................................... 61
3.1. Temporizador 0 ........................................................................................................................... 62
3.1.1 Utilización del Temporizador 0 sin interrupción................................................................... 63
3.1.2 Utilización del Temporizador 0 con interrupción..................................................................64
3.1.3 Utilización del Temporizador 0 como contador de pulsos....................................................66
3.2. Temporizador 1 ........................................................................................................................... 68
3.2.1 Utilización del Temporizador 1 sin interrupción................................................................... 69
3.2.2 Utilización del Temporizador 1 con interrupción..................................................................71
3.2.3 Utilización del Temporizador 1 como contador de pulsos....................................................74
3.2.4 Utilización del Temporizador 1 con un oscilador externo.....................................................79
3.3. Temporizador 2 ........................................................................................................................... 78
3.3.1 Utilización del Temporizador 2 sin interrupción................................................................... 79
3.3.2 Utilización del Temporizador 2 con interrupción..................................................................81
3.4. WATCHDOG................................................................................................................................. 84
3.4.1 Uso de TIMER 0, TIM E R ly WATCHDOG.......................................................................... 85
4. Módulos de Captura, Comparación y Modulación de A nchura de Pulsos (PW M )............................ 89
4.1. Módulo Captura..........................................................................................................................
4.1.1. Cálculo del periodo de una señal......................................................................................... 99
4.1.2. Medidor de distancias...........................................................................................................9¿*
4.1.3. Medidor de anchura de pulsos..............................................................................................97
4.1.4. Calculo de la velocidad de un motor................................................................................. 163
4.2. Módulo Comparación................................................................................................................ 166
4.2.1. Temporizador automático de 16 bits.............................................................................107

Página | 2
4.2.2. Contador de cajas en cinta transportadora
4.3. Módulo PWM............................................ ...................................... ....109
4 . 3 . 1. Generación de tonos............................ ......................................... ....112
4.3.2. Señal periódica con ciclo de trabajo variable ........................................... ....113
4.3.3. Control motor D C ................................... ......................................... ...115
4.3.4. Creación de melodías.............................. ......................................... ...118
5. Módulos analógicos.............................................. .................................. ...122

5.1. Módulo generador de tensión de referencia (CVref) .................................... ...127


5.1.1. Generación de señal analógica................ ...127
... 128
5.2. Módulos Comparadores de Tensión Analógica
...129
5.2.1. Comparar dos señales analógicas................
...130
5.2.2. Comparación de una señal analógica con una señal de referen^......................
...132
5.2.3. Sensor de luminosidad TSL251RD...............
..134
5.3. Módulo Conversor Analógico Digital (CAD)............
..136
5.3.1. Configuración del módulo CAD....................
..137
5.3.2. Conversión analógica digital en un canal.........
..139
5.3.3. Conversión analógica digital de varios canales..
..141
5.3.4. Sensor de Temperatura TC1047A.....................
..142
6. Módulos de comunicaciones..........................................
..145
6.1. Módulo USART...........................................................
..145
6.1.1. Crear una macro que permita configurar del módulo USART en modo asincrono ..147
6.1.2. Envió de datos utilizando el módulo USART........
.149
6.1.3. Recepción de datos utilizando el módulo USART .152
6.1.4. Adivina el número.................................................. .154
6.2. Módulo MSSP (Master Synchronous Serial Port).............. .156
6.2.1. Configuración del módulo MSSP en modo l2C maestro .157
6.2.2. Sensor de temperatura TC74........................................... .159
6.2.3. Memoria EEPROM 24LC256...................................................... .162
7. Módulos periféricos........................................................................... .165
7.1. Memoria interna EEPROM......................................................................................... .165
7.1.1. Almacenamiento de datos no volátiles en memoria interna EEPROM.................. .166
7.2. Circuito de Reset....................................................................................................... .167
7.2.1. Comprobación del origen de reset al inicio del programa.................................... 168
A l. Librerías en C .................................................................................................................. .171
A l.l. ports......................................................................................................................... .171
A l.2. interrupts................................................................................................................. 171
A l.3. timers....................................................................................................................... 172
A1.4. ccp............................................................................................................................ 173
A l.5. analog....................................................................................................................... 173

Página | 3
A1.6. usart.h / usart.c................................................
..176
A1.7. ¡2c.h/¡2c.c.......................................................
..177
Al.S. Icd.h/lcd.c.......................................................
..178
A2. Registros de Funciones Especiales (SFR s) .....................
..181
A2.1. STATUS............................................................
..181
A2.2. Registro OPTION_REG.......................................
..182
A2.3.T1CON.............................................................
..182
A2.4.T2CON.............................................................
,.183
A2.5. Registro INTCON...............................................
..183
A2.6. Registro PIE1....................................................
.184
A2.7. Registro PIR1....................................................
.184
A2.8. Registro PIE2 y PIR2..........................................
,.185
A2.9. CCPxCON..........................................................
.185
A2.10. ADCONO.........................................................
.186
[Link]. ADCON1.........................................................
.186
A2.12. CVRCON.........................................................
.187
A2.13. CMCON..........................................................
.187
[Link]............................................................
.188
A2.15. RCSTA............................................................ .188
A2.16. PCON............................................................. .188
A2.17. SSPSTAT......................................................... .189
A2.18. SSPCON......................................................... .190
A2.19. SSPCON2....................................................... .191
A2.20. PALABRA DE CONFIGURACIÓN........................ .191
A3. Introducción a MPLAB-IDE/MPLAB-SIM con Hi-T ech . .193
A3.0. Instalación....................................................... .193
A3.1. Configuración................................................... .194
A3.2. Creación del proyecto...................................... .194
A3.3. Creación del fichero fuente.............................. .198
A3.4. Compilación del proyecto................................. .200
A3.5. Simulación del proyecto................................... .203
A3.6. Observando el funcionamiento......................... .207
A3.7. Generador de Estímulos................................... .210
A3.7. Interfaz de control........................................... .213
A4. T abla de códigos ASCII................................................ ,215

Página | 4
INDICE DE FIGURAS
Figura 1.1: Simulación Ejemplo 1.1.1....................................................................................... .13
Figura 1.2: Simulación Ejemplo 1.1.4a..................................................................................... .15
Figura 1.3: Simulación Ejemplo 1.1.4b..................................................................................... .16
Figura 1.4: Simulación Ejemplo 1.1.4b, valor de las variables.................................................... .16
Figura 1.5: Simulación Ejemplo 1.1.4c....................................................................................... -16
Figura 1.6: Simulación Ejemplo 1.1.4c, valor de las variables..................................................... .17
Figura 1.7: Simulación Ejemplo 1.1.4b....................................................................................... .17
Figura 1.8: Simulación Ejemplo 1.1.4b, valor de las variables..................................................... .17
Figura 1.9: Simulación Ejemplo 1.1.5......................................................................................... 18
Figura 1.10: Simulación Ejemplo 1.2.1....................................................................................... 19
Figura l . l i : Simulación Ejemplo 1.2.I B ..................................................................................... .20
Figura 1.12: Simulación Ejemplo 1.2.2....................................................................................... .21
Figura 1.13: Simulación Ejemplo 1.3.1....................................................................................... 22
Figura 1.13: Simulación Ejemplo 1.3.I B .....................................................................................
Figura 1.14: Simulación Ejemplo 1.3.3....................................................................................... .25
Figura 1.15: Simulación Ejemplo 1.5.2........................................................................................ .28
Figura 1.16: Simulación Ejemplo 1.5.3........................................................................................ ,28
Figura 1.17: Simulación Ejemplo 1.5.4........................................................................................ 29
Figura 1.18: Simulación Ejemplo 1.5.6........................................................................................ .29
Figura 1.19: Simulación Ejemplo 1.6.2........................................................................................ .30
Figura 1.20: Simulación Ejemplo 1.6.3........................................................................................ .31
Figura 1.21: Simulación Ejemplo 1.7a.........................................................................................
Figura 1.22: Simulación Ejemplo 1.7b.........................................................................................
Figura 2.1: Los puertos de E/S del microcontrolador PIC16F877A................................................ .37
Figura 2.2: Conexiones con el PIC16F877A .................................................................................. .3S
Figura 2.3: Diagrama de funcionamiento de la secuencia de encendido/apagado de los LED...... .39
Figura 2.4: Simulación del ejercicio 2.1.1..................................................................................... .40
Figura 2.5: Conexiones con el PIC16F877A .................................................................................. .40
Figura 2.6: Simulación del ejercicio 2.1.2...................................................................................... .42
Figura 2.7: Simulación del ejercicio 2.1.3...................................................................................... .45
Figura 2.8: Conexiones con el PIC16F877A.................................................................................. .45
Figura 2.9: Simulación del ejercido 2.1.4..................................................................................... .47
Figura 2.10: Diagrama interno de un display 7 segmentos........................................................... .48
Figura 2.11: Conexión de un display de 7 segmentos con el PIC16F877A. Codigo 7 segmentos y
complementado de las cifras hexadecimales (0-F)........................................................................ .48

Página | 5
Figura 5.9: Esquema de conexiones con el microcontrolador para utilizar el sensor
de temperatura analógico TC1047 propuesto en el ejercicio 5.3.4............................... 142
Figura 6.1: Esquema de bloques del módulo transmisor USART................................... .146
Figura 6.2: Esquema de bloques del módulo receptor USART..................................... .147
Figura 6.3: Simulación de la configuración el módulo USART (Watch)......................... .149
Figura 6.4: Esquema de conexiones con el microcontrolador para utilizar el módulo
de comunicaciones USART propuesto en el ejercicio 6.1.2.......................................... .149
Figura 6.5: Configuración de MPLAB SIM para utilizar el módulo USART y simulación
del ejercicio 6.1.2...................................................................................................... ,.151
Figura 6.6: Simulación del ejercicio 6.1.2 utilizando el progrma HERCULES................ ..152
Figura 6.7: Simulación el ejericio 6.1.3 utilizando el programa HERCULES................. ..154
Figura 6.8: Simulación del ejercicio 6.1.4 utilizando el programa HERCULES.............. ..156
Figura 6.9: Esquema de bloques del módulo MSSP................................................... ..157
Figura 6.10: Esquema de conexiones con el microcontrolador para utilizar el sensor
de temperatura digital TC74 propuesto en el ejercicio 6.2.2.........................................................160
Figura 6.11: Esquema para la lectura de datos utilizando el sensor de temperatura digital TC74. .160
Figura 6.12: Esquema de conexiones con el microcontrolador para utilizar la memoria EEPROM
24LC256 propuesto en el ejercicio 6.2.3.......................................................................................162
Figura 6.13: Esquema para la lectura y escritura de datos en la memoria EEPROM 24LC256........ 163
Figura 7.1: Simulación de la escritura en la memoria EEPROM interna propuesto
en el ejercicio 7.1.1...................................................................................................................... 167
Figura 7.2: Esquema de bloques del circuito de reset...................................................................162
Figura 7.3: Simulación del sistema para la detección del origen de RESET propuesto
en el ejercicio 7.2.1 (Watch)......................................................................................................... 169
Figura 7.4: Configuración de MPLAB SIM para la simulación del ejercicio 7.2.1............................ 1®®
Figura 7.5: Simulación del programa de detección de origen de RESET propuesto
en el ejercicio 7.2.1......................................................................................................................120

Página | 8
Introducción
Este es un libro que guía en el aprendizaje de la programación en C de sistemas embebidos.
C es un lenguaje de nivel medio, muy bien estructurado, que soporta el uso de fundones y
módulos, pero que permite el uso de todas las características de bajo nivel, propias del
ensamblador. Como el lenguaje C es eficiente y está muy probado en la programación de
sistemas embebidos, es el más usado, por delante del ensamblador y de lenguajes de alto
nivel orientados a objetos como C++ o Java. Los campos de aplicación son muchos: audio,
automoción, comunicaciones, periféricos de ordenadores, equipos de consumo,
instrumentación industrial, procesamiento de imagen, control de motores, robótica, etc. En
este libro se usa el compilador de C de microchip y el microprocesador PIC16F877A, pero los
conceptos y ejercicios son válidos para otras plataformas y compiladores mediante ligeras
modificaciones.
El libro se ha estructurado para que el aprendizaje sea gradual: primero se introducen los
esquemas de programación en C y después se aplican a los proyectos de diseño con ei
microcontrolador PIC. A lo largo de los distintos temas se han creado funciones que
permiten un uso sencillo de los periféricos de los que dispone el microcontrolador. De esta
manera la programación del microcontrolador para lograr que realice las tareas deseadas es
más directa y el código, más fácil de interpretar.
El uso del simulador permite desarrollar programas sin necesidad de disponer de
equipamiento hardware. Muchos de los ejercicios se pueden simular para comprobar su
funcionamiento, lo que ahorra mucho tiempo en el proceso de diseño.

Página | 9
Bibliografía
• Hoja de Especificaciones del PIC16F877A. PIC16F87xA DataSheet. Microchip
DS39582b ([Link]).
• Guía de usuario HI-TECH C® for PIC10/12/16. DS51865A ([Link]).
• Guía de usuario de los microcontroladores PIC de gama media. PICmicro Mid-Range
MCU Family Reference Manual. DS33023a ([Link]).
• Compiled Tips 'N Tricks Guide. DS01146B ([Link]).
• Sensor de luminosidad TSL251RD. ([Link]).
• Sensor de temperatura digital TC74. DS21462D. ([Link]).
• Memoria EEPROM 24LC256. DS21203M. ([Link]).
• Sensor de temperatura TC1047A. DS21498D ([Link]).
• Hoja de especificaciones del MAX232. ([Link]).
• Hoja de especificaciones de la pantalla LCD Hitachi HD44780
[Link]
• The C Programming Language, second edition, de Brian W. Kernighan y Dennis M.
Ritchie. Ed. Prentice Hall.
• Ejercicios de programación con microcontroladores PIC de Jesús M. Corres, Carlos
Ruiz y, Cándido Bariáin. Ed. Marcombo.

Página | 10
1. ¡nixoducción a la programación en C
1.1. Introducción
1.1.1. Estructura de un programa en C
1.1.2. Directivas del preprocesador
1.1.3. Función Printf
1.1.4. Variables y tipos de datos
1.1.5. Definiciones de constantes
1.1.6. Macros y compilación condicional
1.2. Uso de las variables
1.2.1. Declaraciones
1.2.2. Conversiones de tipos
1.2.3. Clases de almacenamiento
1.3. Funciones
1.3.1. Paso de argumentos a las funciones
1.3.2. Retorno de resultados
1.3.3. interrupciones
1.4. Operadores
1.5. Estructuras de control
1.5.1. Condicionales
1.5.2. Bucles de tipo FOR
1.5.3. Bucles de tipo WHILE
1.5.4. Bucles de tipo DO-WHILE 1.5.5 Break
1.5.6. Continué
1.5.7. Condicionales switch - case
1.6. Vectores
1.6.1. Vectores unidimensionales
1.6.2. Cadenas de caracteres
1.6.3. Vectores multidimensionales
1.7. Punteros
1.8. Estructuras y Uniones
1.8.1. Estructuras
1.8.2. Uniones

1.1 Introducción
La programación en C de microcontroladores tiene importantes ventajas respecto al
lenguaje ensamblador. C es un lenguaje de programación de propósito general, mientras
que el lenguaje ensamblador está ligado a un microprocesador especifico. Una vez se
aprende a programar en C con un microcontrolador es muy sencillo cambiar a otra familia y,
además, los códigos son mucho más fáciles de entender y modificar.

Página | 11
Programación de microcontroladores PIC en lenguaje C

En este libro se emplean ejemplos cuya dificultad aumenta de forma progresiva para
facilitar la comprensión de las estructuras de datos y de programación. Para profundizar
más en el conocimiento de la programación en C es recomendable consultar libros de
referencia como The C Programming Language, second edition, de Kernighan y Ritchie.

1.1.1 Estructura de un programa en C


Un programa en C contiene los siguientes elementos:
• Directivas: Las directivas del procesador le indican al compilador, por ejemplo, las
definiciones de las etiquetas creadas por el programador, o los archivos externos que
debe incluir.
• Declaraciones: En C se deben declarar las variables y las funciones antes de usarse
por primera vez. En la declaración se indica el tipo de dato que almacenará la
variable. Las variables globales se declaran fuera de las funciones y son visibles a
partir del punto donde se realiza la declaración, mientras que las variables locales,
que se declaran dentro de las funciones, solo son visibles dentro de la función.
• Definiciones: Establece el contenido de la variable o de la función.
• Sentencias: Todas las sentencias se terminan con
• Funciones: Subprogramas que realizan una tarea concreta. Se delimitan mediante
llaves {}. La función "main" es la primera en ejecutarse, indicando el principio y el fin
del programa.

En el siguiente ejemplo de un programa en C se pueden observar sus distintos


componentes:

Código fuente

/ / D ir e c t iv a s d e l p r e p r o c e s a d o r
# in c lu d e < h tc .h >
# in c lu d e < s t d io .h >
# in c lu d e <m ath.h>
__ CONFIG(FOSC HS & WDTE_OFF & LVP_OFF & PWRTE_ON) ; / / B it s de c o n f i g u r a c i ó n p a r a
/ / e l P IC
# d e fin e _XTAL_FREQ 20000000 / / F r e c u e n c ia de t r a b a j o a 20MHz

/ / D e c la r a c ió n y d e f i n i c i ó n de v a r i a b l e s g l o b a l e s
v o l a t i l e s ig n e d c h a r v e c t o r [ 9 0 ] ;

v o id m a in (v o id ){ / / Fu n ción m a i n ( ) , que se e j e c u t a t r a s un RESET

/ / D e c la ra c ió n de v a r i a b l e s l o c a l e s
f l o a t x?
in t x l= - 1 0 ;
u n s ign ed i n t x2=123;
s ig n e d ch a r x 3 = -1 0 ;
ch a r x4=200;
f l o a t y = 1 .2 5 ;
ch ar z [ 2 0 ] = " Cadena de c a r a c t e r e s " ;

Página | 12
1. Introducción a la programación en C

ch ar i ;

p r i n t f p ' E s t o e s una p r u e b a \ n " ) ;


p r i n t f ( " x l= % d \ n ",x l);
p r i n t f ( " x 2 = % d \ n ",x 2 ) ;
p r i n t f ( " x 3 = % d \ n " ,x 3 );
p r i n t f ( " x 4 = % u \ n " ,x 4 );
p r i n t f ( "z = % s \ n " , z ) ;
x = 0 .0 0 3 4 ;
p r i n t f ( " x = % f\ n " ,x );

w h ile (1 );
}
v o i d p u t c h (u n s ig n e d c h a r b y t e ) { / / F u n c ió n p u t c h ( ) , qu e s e e j e c u t a al
/ / e m p le a r p r i n t f
TXSTA=0x26;
RCSTA|= 0 x 8 0 ;
TXR EG =byte;
w h i l e ( ! T X I F )c o n t in u é ;
T X IF = 0 ;
}
Resultado:

Figura 1.1: S imulación Ejem plo 1.1.1.

Al realizar un programa en C es necesario tener en cuenta que existe una serie de palabras
reservadas que no se pueden utilizar para definir variables o nombres de funciones. A
continuación, se muestra la lista de palabras reservadas de ANSI C:
a u to d o u b le in t s tru c t
b rea k e ls e lo n g s w itc h
case enum r e g is t e r typ e d ef
char e x te rn re tu rn u n ió n
const f lo a t sh ort u n s ig n e d
c o n t in u é fo r s ig n e d v o id
d e fa u lt g o to s iz e o f v o la tile
do if s ta tic w h ile

1.1.2 Directivas del preprocesador


Las directivas aportan al compilador la información necesaria sobre el sistema (tipo de
microcontrolador, oscilador, etc.).

Página | 13
Programación de microcontroladores PIC en lenguaje C

La directiva #include permite insertar archivos completos. Estos archivos incluyen


normalmente las definiciones de los registros del microcontrolador y las estructuras
necesarias para acceder a cada uno de los bits de los mismos. Cuando el archivo se
especifica con < > indica al compilador que lo busque en los directorios especificados,
mientras que si se especifica"" le indica que lo haga primero en el directorio actual.

Ejemplo: #¡nclude <htc.h>

En la siguiente tabla se muestran las directivas de tipo "pragma", las cuales modifican el
comportamiento del compilador.

D ir e c t iv c M e a n in g E x a m p le

in lin e S p e c i f y fu n c tio n as in lin e # p ra gm a in lin e (fa b s )


3is E n a b le J IS c h a ra c te r h a n d lin g in # p ra gm a jis
strin gs

no j i s D is a b le J IS c h a ra c te r h a n d lin g (d e - # p ra gm a n o jis
fa u lt)
pack S p e c i f y stru ctu re p a c k in g # p ra gm a pack 1
p r in tf_ c h e c k E n a b le p r in if- s t y le fo r m a l s irin g # p ra gm a
c h e c k in g p r in tf_ c h e c k (p r in tf)
con st
regsu sed S p e c i f y r eg is te rs u sed b y fu n c lio n # p ra gm a regsu sed
w r e g ,fs r
s w itc h S p e c if y c o d e g e n e ra tio n f o r s w itc h ü p ragm a s w itc h d ir e c t
s ta tem en ls
w a r n in g C o n tro l m e s s a g in g p a ra m eters tfp ra g m a w a r n in g d is a b le
2 9 9 ,4 0 7

1.1.3. Función Printf


La función printf está definida en el archivo "stdio.h" (Standard Input Output). En un PC, la
salida por defecto es la pantalla, pero en un microcontrolador es necesario especificar el
tipo de dispositivo a emplear (pantalla LCD, RS232, etc.). La función putch permite
especificar el tipo de salida. En el ejemplo de la sección 1.1.1 se usa el puerto serie (UART)
del microcontrolador cuyo funcionamiento se detalla en el capítulo 6.

La entrada de la función printf consta de una cadena de control y una lista de argumentos:
p r in tf ( " c a d e n a _ d e _ c o n t r o l" , a rg u m e n to s );

Dentro de la cadena de control se pueden incluir caracteres constantes y códigos especiales. Los códigos
especiales van precedidos por % y están vinculados a la siguiente lista de argumentos:

%c C a r á c te r
%d e n t e r o d ec im a l con s ig n o
%f coma f l o t a n t e n o t a c ió n d e c im a l
%e coma f l o t a n t e n o t a c ió n e x p o n e n c ia l
%u e n t e r o d ec im a l s in s ig n o
%x e n t e r o s in s ig n o h e x a d e cim a l m in ú scu la s
%X e n t e r o s in s ig n o h e x a d e cim a l m ayúscu las
1 p r e f i j o usado ju n t o a %d, %u, %x p a ra e s p e c i f i c a r e n t e r o l a r g o

Página | 14
1. Introducción a la programación en C

%0 [w id th ] Se im prim en lo o c e r o s a l a i z q u i e r d a , [w id t h ] i n d i c a e l número t o t a l de
d íg ito s .
%[w id t h ] . [ p r e c i s i ó n ] La p r e c i s i ó n i n d i c a e l núm ero d e d e c i m a l e s .

Códigos de escape:

\n n u e va l í n e a
\ t t a b u la d o r h o r i z o n t a l
\ r r e to r n o de c a rr o
\ f fo r m fe e d
V C o m illa s im p le
\ " C o m illa d o b le
\\ C o n tr a b a r r a
%% S ím b o lo de p o r c e n t a j e
\? I n t e r r o g a n t e
\b b a c k s p a c e
\0 C a r á c t e r n u lo
\ v T a b u la d o r v e r t i c a l
\xhhh C ó d ig o h e x a d e c im a l hhh

1.1.4. Variables y tipos de datos


Una variable especifica una posición de memoria. Las posiciones de memoria pueden
albergar distintos tipos de datos, dependiendo de cómo sea declarada. Como regla general
se estudiará el tipo de dato que albergará la variable para asignarle el tipo de variable que
mejor se ajuste economizando así la utilización de la memoria de datos, un recurso muy
valioso y limitado cuando se trabaja con microcontroladores. A continuación, se detallan los
diferentes tipos de datos y se muestran ejemplos de utilización de los mismos.

Bit
Un bit tiene dos posibles estados: "0" o "1". Cada uno de los LED o interruptores conectados
a un puerto se pueden controlar mediante este tipo de dato.

Ejemplo 1.1.4A:
s t a t ic b it b l;
b l =0 ;
p r i n t f ( " % d - %d \ n " , b l , ~ b l);

Resultado:

O u tp u t

Build VersiónControl FindinFiles MPLAB SIM SIMUaiU


0 -1

Figura 1.2: S imulación Ejemplo 1.1.4A.


Char
Los datos en la memoria del PIC se manejan como conjuntos de S bits. Si se considera que el
número binario no tiene signo, el rango es de 0 a 255, mientras que si tiene signo es -128 a

Página | 15
Programación de microcontroladores PIC en lenguaje C

127. Para indicarlo existen en C los modificadores signed y unsigned. Por ejemplo, para
declarar las variables x e y como char con signo y sin signo respectivamente:

s ig n e d ch a r x ;
u n s ig n e d ch a r y ;

Int
Los datos enteros (integer) son tipos de datos de 16 bits. También pueden ser con signo o
sin signo.

Ejemplo 1.1.4B:
in t x l = -10000;
u n s ig n ed i n t x2=12300;
p r i n t f ( ux l= % d \ n ", x l ) ;
p r i n t f ( nx 2 =% d\n ",x 2 ) ;

Resultado:

Figura 1.3: S imulación Ejemplo 1.1.4b.

Íj Watch i a c o É s
AddSFR ADCONO v Add Symbol -
üpdate j Addreaa j Symbol Ñame Valué | Decimal Binary
Q2E mam gxl OxDSFO -10000 11011000 11120000
030 main@x2 0x300C 12300 00110000 0000110Q
1 ; -
Watch 1 Watch 2 V/atch 3 Watch 4

Figura 1.4: S imulación Ejemplo 1.1.4b, valor de las variables .

Long
Son datos enteros de 32 bits.

Ejemplo: 1.1.4C
lo n g u n sign ed i n t x2=123045;
p r i n t f ( " x 2 = % ld \ n ",x 2 ) ;

Resultado:

Figura 1.5: S imulación Ejemplo 1.1.4c.

Página | 16
1. Introducción a la programación en C

•j Watch
AddSFR ADCONO v AddSymbol .

U p d a te j A d d re a a | S y m b o l lla m e j V a lu é j D e c im a l | 3 l= .ry
03D m a ln @ x2

Walch 1 Watch2 Walch 3 Walch 4

F igura 1.6: S imulación Ejem plo 1.1.4 c , valor de las variables .

Float, Double
Son números reales de 24 bits por defecto en formato IEEE754. Se pueden cambiar a 32
bits (Project/Build options/Project/Global).

F o rm at N um ber b ia s e d expo- l.m a n tis s a d e c im a l


nent
___________________
3 2 -b it 7D A6B69B11 11111011b 1 .0 1 0 0 1 1 0 1 0 1 1 0 1 1 0 1 0 0 1 1 0 1 Ib 2 .7 7 0 0 0 e + 3 ~
(2 5 1 ) (1 .3 0 2 4 4 7 6 7 6 6 5 9 )
2 4 -b it 42123Ah 1 0 0 0 0 100b 1 .0 0 1 0 0 1 0 0 0 1 1 1 0 1 0 b 3 6 .5 5 7
(1 3 2 ) (1 .1 4 2 3 9 5 0 1 9 5 3 1 )

Ejemplo 1.1.4D:
f l o a t y = 1 .2 5 , x = 0 .0 0 3 4 ;
p r i n t f ( " x = % f\ n " ,x );

Resultado:

*3 Output o ' j. -gpj


Build VersiónConUol Findin Files MPLAB SIM SIMUartl
y=1 250000
x=0 0034

F igura 1.7: S imulación Ejem plo 1.1.4D.

H Watch a 3* 3
AddSFR ADCONO v Add Symbol main@y V

Update j Addreas j Symbol llame Valué j Decimal j B in ary


03C mainGx .
0B9 mainGy

Walch 1 Walch 2 ' Watch 3 Walch 4

F igura 1.8: S imulación Ejemplo 1.1.4D, valor de las variables .

1.1.5 Definiciones de constantes


Las definiciones de constantes no se almacenan en memoria, se resuelven en el momento
de la compilación y para ello se usa la directiva define.

^ d e f i n e < l a b e l > v a lu é

Página | 17
C
Programación de microcontroladores PIC en lenguaje

Por ejemplo:
« d e f i n e p i 3.14159265359

Para almacenar constantes en memoria ROM, se debe usar el modificador const

ch ar co n s t i d [ 5 ] = {" 1 2 3 4 " };
p r i n t f ( "%s\n“ , i d ) ;

Resultado:

AddSR 6DCOIIO
" p í a t e ! A d ir e s a ¡ S y c io l ¡
p 3009 5 c a l = 3l á
00110001
P 0039 10] 00110010
P 00SA I» !
P 0003 - 12] 00110011
00110100
P 300C
_________ P 000D -
13]
[«]
00000000
Watchl v/aich 2 W¿ch3 W¿ch4

Figura 1.9: S imulación Ejemplo 1.1.5.

1.1.6 Macros y compilación condicional


Usando la directiva tidefine también se pueden implementar macros:

« d e f i n e MAX(A,B) (A > B )? A :B
z = M A X (x ,y ); // z c o n t ie n e e l v a l o r m ayor de x e y

Para la compilación condicional de secciones del programa se emplean las siguientes


directivas del preprocesador: #define, #if, #endif, #else

Ejemplo:
# d e f in e o u t p u t _ h ig h (A ) A=1
# d e f in e HW_VERSION 5
# i f HW_VERSION>3
o u tp u t_h igh (R B O ) ;
# e ls e
o u t p u t _ h ig h (R B 1 );
# e n d if

1.2. Uso de las variables


1.2.1 Declaraciones
Las variables se pueden declarar dentro o fuera de las funciones, según sean locales o
globales respectivamente.

Las variables locales definidas en distintas funciones pueden compartir el mismo nombre y solo
existirán durante la ejecución de la función y se liberarán posteriormente para su reutilización
por otras funciones excepto en el caso de ser de tipo static (véase apartado 1.2.3).

Página | 18
1. Introducción a la programación en C

v o id f 2 (v o id ){
i n t c o u n t;
f o r (c o u n t = 0 ; c o u n t < 10 ; c o u n t+ + )
p r in t f(" % d "/ c o u n t);
}
fio {
i n t c o u n t;
f o r (c o u n t = 0 ; c o u n t c lO ; c o u n t + + ) {
f 2 () ;
p r i n t f ( " - %d \ n " , c o u n t ) ;
}
}
v o id m a in (v o id ){
fl() ;
w h ile ( 1) ;
}

Resultado:
Output
Bu'ld ’ Versión Control [Link] m Res MPL¿£ SIM SIM Uartl
0123456 7 89 -0
01 23456 7 89 -1
0 1 2 3456 789 -2
01 23456 789 -3
01 23456 789 -4
0 1 2 3 456 789 -5
01 23 456 789 -6
0 1 2 3456 789 -7
0 123456 789 -8
0123456789-9

F igura 1.10: S imulación Ejem plo 1.2.1.

Las variables globales se pueden usar en distintas funciones, y deben declararse antes de
usarse por primera vez.

i n t max;
fl(){
in t i ;
f o r ( i = 0 ; i< m a x ;i+ + )
p r i n t f ( "%d " , i ) ;
}
v o id m a in (v o id ){
max= 1 0 ;
fio ;
w h ile ( 1) ;
}

Mediante typedef se pueden definir nuevos tipos en función de tipos ya existentes:

t y p e d e f s ig n e d c h a r i n t 8 ;
in t 8 i= 1 2 ;

La palabra reservada enum permite enumerar automáticamente cualquier lista de


identificadores que se le pase, asignándoles valores de 0, 1, 2, etc. Un tipo de datos

Página | 19
Programación de microcontroladores PIC en lenguaje C

enumerado es una manera de asociar nombres a números y, por consiguiente, de ofrecer


más significado a alguien que lea el código. Se pueden definir así nuevos tipos de variables
mediante enum (que se representan siempre como valores enteros). La declaración de un
tipo de datos enumerado se parece a la declaración de un struct (apartado 1.8.1)
enum n o m b r e _ tip o {
N o a b r e l,
N o a b re 2 ,

NombreN
};

Ejemplo 1.2.1B:

enum sem an a{Lu n es, M a r te s , M i é r c o l e s , J u eves, V ie r n e s , S ab ad o, D o m in g o };


v o i d m a in (v o id ) {
enum semana a c t u a l= J u e v e s ;
sw i t c h ( ac t u a l ) {
case Lu n es: p r i n t f ( "L u n e s " ) ; b r e a k ;
case M a rtes : p r i n t f ( "M a rte s ") ; b rea k ;
case M ié r c o le s : p r i n t f ( "M ié r c o le s " ) ; b rea k ;
case Ju eves: p r i n t f ( "J u e v e s ") ; b rea k ;
case V ie r n e s : p r i n t f ( "V ie r n e s " ) ; break;
case S ab ad o: p r i n t f ( " S a b a d o ") ; b r e a k ;
case D om ingo: p r i n t f ( "D om in g o") ; b r e a k ;
1

Resultado:

¡ _____ ° utPui______ c s in n r e a
Bu-d Versión Control : Fnd m File: . MPLAB SIM SIM Uatll
jJuevesj — “

Figura 1.11: Simulación Ejemplo 1.2.1B.

1.2.2 Conversiones de tipos


Como C permite mezclar distintos tipos de datos en la misma expresión, tiene unas reglas
de promoción de tipos para convertir las variables al tipo de la variable de mayor tamaño.
En el siguiente ejemplo:
c h a r ch = ' 0 #;
in t i = 1 5 .
f l ° a t f = 2 5 .6 ;
d o u b le r e s u l t ;
r e s u lt = c h * i / f ;

- Primero la variable ch de tipo char


- Se multiplica ch * i (8 bits) se convierte a entero (16 bits).
1. Introducción a la programación en C

- Se convierte ch*¡ a float (24/32 bits)


- Se divide entre f
- El float se convierte a double (24/32 bits) y se almacena en result (24/32 bits).

También se puede forzar la conversión de tipos usando el siguiente formato: (tipo) valor
En el siguiente ejemplo se convierte el float en int:

flo a t f;
f = 100.2 ;
p r in tf("% d \ n " , ( i n t ) f ) ;
p r in tf("% d \ n " , f ) ;

Obsérvese que el resultado del segundo printf no es correcto, mientras que el primero si.

Resultado:

O u tp u t — - —

B u ld • V e rsió n Control F in d in F ie : M P L A E S!M S iM U s r t l

100
-1 4 2 3 4

Figura 1.12: S imulación Ejemplo 1.2.2.

1.2.3 Clases de almacenamiento


Hay cuatro clases de almacenamiento en C: auto, extern, static y register. Este último no se
usa en el PIC.

auto: Las variables definidas dentro de una función son auto por defecto. El compilador
asigna un bloque de RAM a esas variables y las posiciones de memoria que ocupan se
pueden reutilizar cuando se sale de la función.

extern: La variable declarada como extern se define en otro fichero.

static: Las variables definidas como static son globalmente activas y solo se inicializan una
vez, aunque se definan dentro de una función.

En el siguiente ejemplo:

v o id te s t(){
ch ar x , y , z ;
s t a t i c i n t c o u n t = 4;
p r i n t f ( " c o u n t = % d \ n " ,+ + c o u n t );
>

La variable count se incrementa con cada llamada de la función test: 4, 5, 6...

No es una variable global, porque no se puede acceder a ella desde otras funciones.

Página | 21
Programación de microcontroladores PIC en lenguaje C

1.3. Funciones
Las fundones son los bloques con los que se construyen los programas en C. Encapsulan
partes del código, ayudando a que se puedan reutilizar en otros programas.

1.3.1. Paso de argumentos a las fundones


Es posible pasar hasta 31 argumentos a una función. Si la función no se ha definido
previamente a su uso por primera vez, al menos es necesario declararla. Cuando no hay
argumentos o no se devuelve ningún resultado se usa void.

Ejemplo:
v o i d s u m a (in t a , i n t b ) ; / / D e c la r a c ió n d e l p r o t o t i p o de l a fu n c ió n
v o id r e s t a ( i n t a , in t b) ; / / D e c la r a c ió n d e l p r o t o t i p o de l a fu n c ió n

v o id m a in (v o id ){
i n t a = 1 0 / b = l;
suma (a , b ) ;
r e s t a (a ,b );
p r i n t f ( "O p e r a n d o s : % d,% d\n" , a , b ) ;
}
v o i d s u m a (in t a , i n t b ) {
a =a +b;
p r i n t f ( "Suma: % d\n"/a ) ;
}
v o id r e s t a ( i n t a, in t b ) {
b = a -b ;
p r i n t f ( " R e s t a : % d\n"/b ) ;
}

En el ejemplo anterior se han pasado los argumentos por valor. Cualquier cambio realizado
en la variable no modifica el valor original pasado como argumento como se muestra a
continuación.

Resultado:

Figura 1.13: S imulación Ejemplo 1.3.1.

También se puede pasar el argumento utilizando el "paso por referencia". En este caso, se
pasa la dirección de la variable, con lo que es posible modificar el valor de la variable
original dentro de la función.

Página | 22
1. Introducción a la programación en C

En el siguiente ejemplo se pasa la dirección de la variable "inputl" a la fundón neg, es decir, su


puntero. Esta función calcula el opuesto y modifica el valor de la variable cuyo puntero se ha
pasado.
v o id n e g (in t * in p u t ); / / D e c la r a c ió n d e l p r o t o t i p o de la fu n c ió n

v o id m a in (v o id ){
in t in p u tl= 1 0 ;
n e g (fc in p u tl);
p r i n t f ( " V a r i a b l e : % d\n ", i n p u t l ) ;
w h ile (1 );

v o i d n e g ( i n t * in p u t ) {
* in p u t= - * in p u t;
}
Resultado:

13 Output <=¡ 'j j k&»|


Build Versión Contiol Findin Files MPLAB SIM SIM Uartl
Variable -10

FIGURA 1.13: SIMULACIÓN EJEMPLO 1.3.1E.

1.3.2 Retorno de resultados


Para hacer que una función devuelva un resultado se usa return.

in t fu ñ e ( ) ; / / D e c la r a c ió n d e l p r o t o t i p o de la fu n c ió n
i n t s u m (in t a , in t b) ; / / D e c la r a c ió n d e l p r o t o t i p o de l a fu n c ió n

v o id m a in (v o id ){
i n t num;
num = fu ñ e ( ) ;
p r i n t f ( "% d \ n ", n u m );
num = s u m (5 ,1 2 7 );
p r i n t f ( "% d\nM, n u m );
w h ile ( 1) ;
}
in t fu ñ e ( ) {
re tu r n 6;

i n t s u m (in t a , i n t b ) {
in t r e s u lt;
r e s u lt = a + b;
re tu r n r e s u lt ;
}

En cuanto una función llega a la línea en que está el comando return. termina su ejecución.
Todas las sentencias que se encuentren después no se ejecutarán.

Página | 23
Programación de microcontroladores PIC en lenguaje C

1.3.3 Interrupciones
Son funciones especiales que se activan por un evento hardware. Se declaran mediante el
modificador interrupt.

Las interrupciones deben ser habilitadas en el programa principal.

En el siguiente ejemplo la interrupción ISR se ejecuta cada vez que el temporizador TMRO se
desborda (el funcionamiento de los temporizadores se describirá en el Capítulo 3),
incrementando el contador xl.
S in e lu d e < h tc .h >
S in e lu d e < s t d io .h >
S in e lu d e “ i n t e r r u p t s . h M
S in e lu d e nt i m e r s , h n
__ CONFIG(FOSC_HS & WDTE_OFF & L V P O F F & PW R TE O N );
« d e f i n e _XTAL_FREQ 20000000

v o id in te r r u p t I S R (v o id ); / / D e c la r a c ió n d e l p r o t o t i p o d e l a fu n c ió n

in t x l= 0 ; / / D e c la r a c ió n de v a r i a b l e g l o b a l

v o id m a in (v o id ){
e i () ; / / H a b ilita in te r r u p c io n e s g lo b a le s
e n a b le _ in te r r u p t s (IN T T 0) ; / / H a b i l i t a i n t e r r u p c i ó n d e l T im e r 0
setu p_tim erO (R TC C _IN TE R N A L|R TC C _D IV 2); / / C o n fig u ra e l T im e r 0
w h ile (1 ) ;
}
v o id in te r r u p t I S R (v o id ){
if([Link] == 1 && [Link] == 1){
s e t _ t im e r O (0 x 0 0 ); / / A ju s ta e l c o n t a d o r d e l TIMER
IN TCO N [Link] R O IF = 0;
p r i n t f ( " % d \ n ",x l);
x l+ + ;
}
}
v o i d p u tc h (u n s ig n e d c h a r b y t e ) {
TXSTA=0x26;
RCSTA|=0x80;
TXREG=byte;
w h i l e ( ! T X I F )c o n t in u é ;
T X IF = 0 ;
}

Resultado:

Página | 24
1. Introducción a la programación en C

1.4. Operadores
En la siguiente tabla se muestran los operadores C en orden de precedencia, de m ayor a
menor. Su asociatividad indica cómo se aplican en una expresión los operadores de la
misma precedencia.

En la cuarta columna se muestra el resultado de la operación para una variable A = 10 y otra


variable B = 20.

Operador Descripción Ejemplo Resultado Asociatividad


0 Paso de parámetros a funciones
[] índices en arrays
Selección de elemento mediante objeto
-> Selección de elemento mediante puntero
++ Postincremento A++ 11 Izquierda a
-- Postdecremento A- 9 derecha
++ Preincremento ++A 11 Derecha a
- Predecremento -A 9 izquierda
+- + / - unitario
!~ Negación lógica / complement bit a bit
(type) Conversión de tipos de datos
* Referencia al valor
& Operador de dirección de memoria
sizeof Valor en bytes de la variable
A*B
<oN

f, . ,
O

* / % Multiplicación/división/módulo A/B 2 Izquierda a


A%B derecha
. 0

Página | 25
Programación de microcontroladores PIC en lenguaje C

Operador Descripción Ejemplo Resultado Asociatívidad


A+B 30 Izquierda a
+ - Suma/Resta A-B -10 derecha
1-----------------------------------------------------------------------------------------
A«2 Izquierda a
i « » Rotación de bits a izquierda/derecha derecha
A»2
A<2 0 Izquierda a
Relacional menor/menoro igual A<=2 0 derecha
i
<<=
> >= Relacional mayor/mayoro igual A>2 1
A>=2 1
A==10 1 Izquierda a
= != Relacional es igual/no es igual derecha
A 1=10 0
A&B 0 Izquierda a
& AND bit a bit
derecha
AAB 30 Izquierda a
A
XOR bit a bit
derecha
A|B 30 Izquierda a
1 OR bit a bit
derecha
A&&B 0 Izquierda a
& & AND lógico
derecha
A11B 1 Izquierda a
11 OR lógico
derecha
Derecha a
? :
Condicional ternaria
izquierda
= Asignación Derecha a
Suma/resta y asignación izquierda
* = /= Vlultiplicación/división y asignación
% = & = Vlódulo / And y asignación
A= |=
Xor/ Or y asignación
« = » =
desplazamiento izquierda/derecha v asig.
Izquierda a
-orna (separa expresiones)
derecha

Notas:

dtferentel's^evaWande dentro hada afuera eX*5reS'° neS f° rZand° PreCedenC¡a


S 'mportante no in fu n d ir la asignación "=" con el operador relacional
• Los operadores ++ y — c¡p
preceden a la vari bl mpre lncrementan 0 decrementan una unidad. Cuando
expresión. Cuando'si ^ S6 incrementa/decrementa y después se usa en la
¡ncrementa/decrementa611 3 ^ Var'able' esta se usa en la expresión y después se

¿agina | 26
1. Introducción a la programación en C

Ejemplos:
sum = a+b+ + -> sum = a+b b = b +1
sum = a+b- - -> sum = a+b b = b -1
sum = a+ ++b -> b = b +1 sum = a+b
sum = a+ - -b -> b = b - 1 sum = a+b

1.5. Estructuras de control en C


1.5.1 Condicionales
La estructura condicional en C se implementa del siguiente modo:

if ( e x p r e s ió n ) s e n te n c ia ; e ls e s e n t e n c ia _ a lte r n a tiv a ;

Cuando los bloques condicionales constan de varias sentencias, estas se agrupan entre
llaves:
if ( e x p r e s ió n ) (s e n t e n c ia !.; s e n te n c ia 2 ; ...} e ls e (s e n t e n c ia _ a lt e r n a t iv a l;

Ejemplo:
i f (c o u n t <0) p r i n t f ( " N e g a t i v o \ n " ) ;
e l s e i f (c o u n t ==0) p r i n t f ( " C e r o \ n " ) ;
e ls e p r i n t f ( "P o s itiv o \ n ") ;

También se puede expresar del siguiente modo:


e x p r e s i ó n l ? e x p r e s ió n 2 : e x p r e s ió n 3

Primero se evalúa la expresiónl. Si es verdadera, entonces se evalúa la expresiónl, y si es


falsa, la expresión3.

Ejemplo:

i ? j=o : j= l;

1.5.2 Bucles de tipo FOR


La estructura FOR se implementa en C de la siguiente manera:

fo r (s e n t e n c ia _ in ic ia liz a c ió n ; s e n te n c ia c o n d ic ió n ; in c r e m e n t o )
{ s e n t e n c i a l ; s e n t e n c ia 2 ; . . . }

La sentencia de iniciaüzación da el valor inicial a las variables que se usan en el bucle y se


ejecuta una vez.
La sentencia de condición se evalúa antes de cada iteración y determina si se ejecuta o no el
bucle.
Con cada iteración se ejecuta el incremento de la variable de control.

Página | 27
Programación de microcontroladores PIC en lenguaje C

v o id m a in (v o id ){
in t i ;
f o r ( i = 0 ; i < 1 0 ; i+ + ) p r i n t f ( “ %d " , i ) ;

Resultado:
Output ! <=> II S ll
BuJd Versión Centre) Frndin Files MPLAB SIM SIM Uaitl
|01 23456789

Figura 1.15: Simulación Ejemplo 1.5.2.

1.5.3 Bucles de tipo WHILE


w h ile (e x p r e s ió n ) {s e n te n c ia !.; ...}

Primero se evalúa la expresión y si es verdadera se ejecuta una iteración del bucle.

Ejemplo:
v o id m a in (v o id ){
in t i= 0 ;
w h ile (i< 10) p r in t f(" % d " ,i+ + );
}
Resultado:
*_| Output o 'E
Buid ' Vefiion Control Findr Res WPLAB SIW SIM Uarll
|0123456789

Figura 1.16: Simulación Ejemplo 1.5.3.

1.5.4 Bucles de tipo DO-WHILE


do { s e n t e n c i a l ; s e n t e n c ia 2 ; ...} w h ile ( e x p r e s ió n )

Primero se ejecutan las sentencias y después se evalúa la expresión. Si es falsa se termina el


bucle.

v o id m a in (v o id ){
in t i= 0 ;
^ Pr in tf("% d " , i + + ) ; w h ile (i< 1 0 );

Resultado:

Página | 28
1. Introducción a la programación en C

O u tp u r

Buíd VeriionCont/d F ndm Fie; MPIABSIM SIMUa»’ "


0 1 2 3 4 5 6 7 9 9

F ig u r a 1.17: S imulación Ej e m p l o 1.5.4.

1.5.5 Break
Cuando un bucle encuentra una sentencia break se finaliza el bucle en el que se encuentre
(if, for, while, etc.)

1.5.5 Continué
Cuando un bucle encuentra una sentencia continué se salta las sentencias que le siguen
hasta la siguiente condición de test.
v o id m a in (v o id ){
in t i ;
fo r (i= 0;i< 10;i+ + ){
i f (i< 5 ){
p r in tf( " x " );
c o n t in u é ;
}
p r i n t f ( "%d " , i ) ;
}
>
Resultado:
i)J Output - -L

BuOd Versión Control Find m Fi'es • MFLAB SIM SIM Uartl

xxxaS 6 7 8 91

F ig u r a 1.18: S im u l a c ió n Ejemplo 1.5.6.

1.5.7 Condicionales switch - case


s w it c h (v a r ia b le )
{
ca se c o n s ta n t l:
s ta te m e n t( s ) ;
b reak ;
ca se c o n s ta n t2 :
s ta te m e n t(s );
b reak ;
c a s e c o n s ta n t N :
s ta te m e n t(s );
b reak ;
d e fa u lt :
s ta te m e n t(b ) ;
}

Página | 29
programación de microcontroladores P1C en lenguaje C

Se va comprobando la variable con cada una de las constantes. Break y default son
opcionales.
Ejemplo:

b i t b=0;
s v itc h ( b ) {
c a s e 0: p r in tf("b is fa ls e " ) ;
break;
case 1: p r in tf("b is tr u e ");
brea k ;
}

1.6. Vectores
1.6.1 Vectores unidimensionales
La forma general de un vector unidimensional es:
t y p e v a r name [s iz e ] ;

El índice de los elementos va desde 0 hasta size-1.


Por ejemplo i n t h e i g h t [ 5 0 ] ; declara un vector de 50 enteros.
Para asignar el valor 10 al primer elemento y al último usamos h e ig h t [o] =io,- h e i g h t [49] =10;
C asigna los elementos de un vector en posiciones contiguas de la memoria.
Para inicializar el vector se usan las llaves i n t h e i g h t [5 0 ] = { 1 , 2 , 3 , 4 , 5 , . .

1.6.2. Cadenas de caracteres


Una cadena es un vector de tipos char que termina con el carácter nulo \0. La librería
string.h incluye funciones que permiten trabajar con este tipo de estructuras de forma
sencilla como se muestra en el siguiente ejemplo que crea una cadena de caracteres.

Código fuente

# in c lu d e < s t r in g . h >
v o id m a in (v o id ){
ch a r s t r [ 1 0 ] ;
s t r c p y ( s t r , " E s t o es una p r u e b a " ) ;
p r i n t f ( "% s" , s t r ) ;
}

Resultado:

?_______________________ Q u tp u t o ¡ b ¡| ^ a » |

Buiid Vemc-n Conhol Find in Files MPLAB SIM SIM Uartl


jEsto es una prueba

F ig u r a 1.19: S imulación Ejemplo 1.6.2.

Página | 30
1. Introducción a la programación en C

Funciones para manejo de cadenas en la librería string.h:


s t r c a t C o n c a te n a d o s ca d e n a s
s t r c h r Bu sca e l p r im e r c a r á c t e r d e n t r o d e una ca d en a
s t r r c h r Busca e l ú lt im o c a r á c t e r d e n t r o de una ca d en a
s trc m p Compara d o s c a d en a s
strn cm p Compara un núm ero de c a r a c t e r e s d e n t r o d e una c a d en a
s t r ic m p Compara dos ca d en a s ig n o ra n d o l a d i f e r e n c i a e n t r e m a y ú scu las y m in ú scu la s
s t r n c p y C o p ia un número d e c a r a c t e r e s d e una c a d e n a en o t r a
s t r l e n C a lc u la l a l o n g i t u d d e una c a d en a
s t r l w r R ee m p la za m a y ú s cu la s co n m in ú s c u la s
s t r p b r k L o c a l i z a e l p r im e r c a r á c t e r qu e c o i n c i d e en d o s ca d e n a s
s t r s t r L o c a l i z a l a p r im e r a o c u r r e n c i a d e una s u b ca d e n a d e c a r a c t e r e s d e n t r o d e
una ca d en a

Realizar programas que permitan comprobar el funcionamiento de las fanclcns: as


librería para el manejo de cadenas de caracteres "string.h".

1.6.3 Vectores mulíidimensionales


La forma general de un vector multidimensional es:
t y p e va r_n a m e [ s i z e l ] [ s i z e 2 ] [...] [ s i z e N ] ;

El índice de los elementos va desde 0 hasta sizeX-1.


Por ejemplo i n t h e i g h t [2] [2] ,• declara una matriz de 2 filas por 2 columnas (4 enteros).
Para asignar el valor 10 al elemento de la fila 2 columna 1 utilizamos height m [0] =io,-
C asigna los elementos de un vector en posiciones contiguas de la memoria.
Para inicializar el vector se usan las llaves in t h e ig h t [2] [2] = {i, 2, 3, 4}

Ejemplo:
v o id m a in (v o id }{
in t a r r a y [5 ][4 ];
in t i / j ;
f o r ( i =0 ;i< 5 ;i+ + ) f o r ( j = 0 ;j < 4 ;j ++) a r r a y [i] [j ] = i * j ;

f o r ( i = 0 ; i < 5 ; i ++ ) {
f o r (j= 0 ;j< 4 ;j+ + ) p r i n t f ( "%02d " #a r r a y [ i ] [ j ] ) ;
p r i n t f ( "\ n ") ;
}
}
Resultado:
Output •' |-»r^|
Build Veiiion Contra) Fmd in File; MPLABSIM SIM Uartl
ÍOO00 00 00
CIO01 02 03
00 02 04 0G
00 03 0G09
00 04 0812

F ig u r a 1.20: S im ulación Ejem plo 1.6.3.

Página | 31
Programación de microcontroladores PIC en lenguaje C

1.7. Punteros
Un puntero es una variable que contiene la dirección de memoria de otra variable.

La forma de declarar un puntero es mediante el asterisco:

tipo ‘variable

donde tipo especifica el tipo de variables a las que la variable apunta.

Por ejemplo, para declarar un puntero de nombre ptr a variables de tipo entero se usa ínt
*ptr;

Una vez declarado, para acceder a la dirección de una variable usamos el símbolo &,
mientras que el operador * devuelve el valor almacenado en la dirección apuntada por la
variable.

Ejemplo: Se declara un puntero entero o, y un entero b. Se asigna al entero b el valor 6 y al


puntero a la dirección del entero b. Al imprimir el valor apuntado por a, nos estamos
dirigiendo al valor de la variable entera b, que es 6.

Código fuente A

void main(void){
int *a,b;
b=6 ;
a=&b;
printf("%d",* a ) ;
}

Resultado:

OutpUt | cu 1; S ||—£?—|

Build Versión Control Fmd in Files i MPLAB SIM SIM Uartl


|¡T

Figura 1.21: S imulación Ejemplo 1.7?.

Los punteros se pueden incrementar y decrementar, lo que es muy útil para acceder a
elementos dentro de vectores o tablas.
Por ejemplo, al escribir o++, dependiendo del tipo de dato al que apunta, al incrementarse
se suma 1 si es char, 2 si es entero, etc.
También se puede incrementar el valor al que apunta el puntero: (*a)++. En este caso se
incrementa en una unidad, independientemente del tipo de dato.

Página | 32
1. Introducción a la programación en C

En el caso de datos de tipo vector, el nombre del vector es un puntero al primer elemento
del mismo.
En el siguiente ejemplo, ambas instrucciones printf muestran el mismo resultado.

Código fuente B

v o id m a in (v o id ){
in t a [5 ]= {l, 2 , 3 , 4 , 5 };
in t *p ;
p=a;
p r i n t f ( " % d \ n " , * (p + 3 ) ) ; p r i n t f ( "%d \ n " /a [ 3 ] ) ;

Resultado:

13 Output - _ i_
Build Versión Control Find in Files MPLAB SÍM SIM Uaitl
4
4

Figura 1.22: S imulación Ejemplo 1.7 b .

i.o . Estructuras y Uniones

1.8.1. Estructuras
Las estructuras sirven para agrupar distintos datos dentro de un mismo contenedor, para
poder acceder a ellos de forma más sencilla, mediante un nombre de objeto común. Dentro
de la estructura, cada elemento puede tener su propio tipo de dato.

atruct etiqueta{
type elemento!.;
type elemento2;

type elementon;
} lista de variables;

etiqueta es el nombre de la estructura mientras que lista de variables es la lista con los
nombres de las variables declaradas de ese tipo de estructura.

En el siguiente ejemplo se declara una estructura llamada card de tipo catalog. que agrupa
5 campos de datos.

Ejemplo:
struct catalogf
char author[40];

Página | 33
Programación de microcontroladores PIC en lenguaje C

char title [40];


char p u b [40];
unsigned int data;
unsigned char rev;
} card;

Para acceder a los campos de la variable card se utiliza el punto, que separa el nombre de la
variable de los elementos que la componen:

[Link]='w';
[Link]=12;
printf(n%s",[Link]);

Una vez definida la estructura se pueden declarar más variables del mismo tipo, incluso
vectores de estructuras como en el caso de la variable bigcat que se muestra a
continuación:
struct catalog card2,card3,bigcat[3];
bigcat[2] .data=12;

1.8.2. Uniones
Una unión es una única posición de memoria que se comparte entre dos o más variables.
Las uniones son útiles para ahorrar espacio de memoria y para acceder a la posición de
memoria con diferentes formatos.
Para declarar una unión se procede de forma similar a una estructura:

unión etiqueta{
type elementol;
type elemento2;

type elementon;
} lista de variables;

En el siguiente ejemplo se declara una variable temp que está formada por la unión
de un vector de tres caracteres, un entero de 16 bits y un real de 32 bits.
unión u_type{
int i ;
char c [3];
double d;
} temp;

El entero usa dos bytes, el vector de char usa 3 y el double usa los 4.

Página | 34
1. Introducción a la programación en C

En el siguiente ejemplo se crea una variable s i formada por la unión de un vector de 2


caracteres y un entero con signo.

unión sample{
unsigned char bytes[2];
signed short word;
} si

Utilizando la unión podemos acceder a los 16 bytes: [Link]; o a cada uno de los bytes
independientemente: si.b yte s [o] ,• si.b y te s [i] ;

Página | 35
2. Puertos de entrada y salida digitales
2.1. LED y Pulsadores
2.2. Visualizadores numéricos de 7 segmentos
2.3. Exploración de teclado matricial
2.4. Control de Pantallas LCD

FIGURA 2.1: LOS PUERTOS DE E/S DEL MICROCONTROIADOR PIC16F877A.

Los puertos digitales de entrada y salida son los periféricos más sencillos de que dispone el
microcontrolador, y mediante los cuales es posible controlar otros dispositivos y
monitorizar su estado.
El PIC16F877A tiene los terminales de entrada/salida divididos en 5 puertos (desde el
PORTA hasta el PORTE), algunos disponen de hasta 8 terminales. Los terminales se pueden

Página | 37
Programación de microcontroladores PIC en lenguaje C

configurar como entrada o salida mediante el correspondiente registro de dirección de


datos (TRIA, TRISB, etc). Los bits del registro TRIS que se escriben con "1" indican que los
terminales correspondientes del PORT son entradas (Input), mientras que los se escriben
con "0" indican que los terminales son de salida (Output). Es fácil de recordar ya que el "1"
es similar a la "I" de "Input" y el "0" a la "O" de "Output".

Para aumentar la flexibilidad del PIC la mayoría de los pines están multiplexados con
funciones alternativas, de modo que cuando un periférico como, por ejemplo, la USART
(Transmisión Serie) está funcionando sus pines no podrán ser utilizados como l/O de
propósito general. En el caso de los puertos multiplexados con el convertidor A/D, la
configuración como analógicos o digitales se realiza mediante el registro ADCON1. Cuando
se selecciona como analógico, estos bits se leen como "0".

El registro PORT está formado por los biestables que almacenan los datos que se van a
mostrar en la salida. Sin embargo, cuando se lee el registro PORT, el resultado no son los
datos almacenados en los biestables, sino los niveles presentes en los pines de
entrada/salida.

2.1 LED y Pulsadores


2.1.1 Secuencias de encendido de LED
Realiza un programa que ilumine los LED de la figura 2.2 según dos secuencias diferentes. Cada
vez que se accione el pulsador conectado a RA4 se cambiará la secuencia. Los LED cambiarán
con una cadencia de 0.5 segundos. El funcionamiento será el mostrado en la figura 2.3.

+5V

Figura 2.2: Conexiones con el PIC16F877A.

Página | 38
2. Puertos de entrada y salida digitales

Tras pulsación
Comienzo
SECUENCIA 1 SECUENCIA 2
RB3 RB2 RB1 RBO RB3 RB2 RB1RB0
+0.5 seg. o o o -O O O • *
+0.5 seg. ¿c
o o 0 +0.5 seg. C° ° • ] ♦0 5 seg.
o o o o o • I
+0.5 seg. KT
'♦ o o o o +0.5 seg.
5o e • oy

F igura 2.3: D iagrama de funcionamiento de la secuencia de encendido / apagado de los LED.

Solución:

Código fuente
//ARCHIVOS d e d e f i n i c i o n e s
#include <htc.h> //Incluimos librería del micro a usar
#include "ports.h"
ttdefine _XTAL_FREQ 4000000 //Oscilador Interno de 4MHZ
__CONFIG(WRTOFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & LVP_OFF); //Configuración
//del PIC
//Variables
bit CAMBIAR=0; //Flag para cambiar la secuencia de los LED
/ / (SECUENCIA1 si CAMBIAR=0) y (SECUENCIA2 si CAMBIAR=1) - Empieza con la
//SECUENCIA1
unsigned char SECUENCIAl=0xll; //Secuencia 1 empieza con LED DO
//encendido
unsigned char SECUENCIA2=0x09; //Secuencia 2 empieza con LEDs D3-D0
//encendidos

//PROGRAMA PRINCIPAL
void main()
{ //INICIALIZACIONES PARA EL PIC
set_all_digital(); //Desactivamos PORTA como entradas analógicas

TRISA=0xl0; //PORTA con RA4 como entrada y resto como salidas


TRISB=0x00; //PORTB con todos los terminales de salida.

wh ile(1)
{ if (RA4 == 0) { //Se ha presionado el pulsador
CAMBIAR=~CAMBIAR; //Cambiar secuencia
}
if(CAMBIAR==0){
P0RTB=SECUENCIA1;
__d e l a y m s (500); //Esperar 500 ms
r°l_8 (SECUENCIA1,1); //Rotar un bit a la izquierda en SECUKNCIA1

else{
PORTB=SECUENCIA2;
__delay ms(500); //Esperar 500 ms
SECUENCIA2 = ~SECUENCIA2; //Cambiar LED encendidos en SECUENCIA2

}
}

Página | 39
Programación de microcontroladores PIC en lenguaje C

//PROGRAMA FRINCIPAL
v o id n a in (
/ / D e s a c t iv a r PORTA como e n t r a d a s a n a l ó g i c a s
set a l l d i g i t a l O ;
TR IS A =0 x l0 ; / / C o n fig u r a r RA4 como e n t r a d a
TRISB=0x00; / / C o n fig u r a r RBO como s a l i d a
FORTB=0; //Todos l o s l e d a p agados
ESTAD0=1; //Em pieza con l a s e ñ a l a c t i v a d a

w h ile (1 ) {
if(E S T A D 0 = = 1 ){ / / S i s e ñ a l a c t iv a d a
p u n to ( ) ;
p u n to ( ) ;
p u n to () ;
ra ya ();
ra ya ();
ra ya ();
p u n to () ;
p u n to ( ) ;
p u n to ( ) ;
pau sa O ; }
e l s e {PORTB=0? } / / S i s e ñ a l d e s a c t iv a d a to d o s l o s l e d a p a ga d o s
}
}

Comprueba el funcionamiento mediante la utilización del simulador MPLAB SIM y


el visualizador de señales digitales (menú View=> Simulator Logic Analyzer)
observando la salida RBO y el generador de estímulos en modo asincrono (menú
Debugger=> Stimulus) asociado al terminal RA4.

Logic Anacer I •=> 3


TnjgerPoríion Ti^gerPC» TmsBa:e Mode
Sia.1 o Certíi End j Now |[ Oeai [ Cyc - Sirrpie | Channeli |

l+'ftl :~l»i.| [faiBlalBl ¡

RA4

RBO
m ¥ 1 TJUi n
0.0 1000000 0 2000000.0 30000000 4000000.0 5000000.0

Figura 2.6: Simulación del ejercicio 2.1.2.

2.1.3 Visualización de una cadena de caracteres en código morse


mediante un LED
Escribe un programa para la tarjeta PICDEM2PLUS que genere el código morse de una
cadena de caracteres y lo visualice en un LED conectado a la salida RBO (Figura 2.5).

La duración de cada punto será de 10 ms y cada raya de 30 ms. El silencio entre símbolos
(punto/raya) serán 10 ms, mientras que la separación entre caracteres serán 30 ms y entre
palabras de 70 ms.

Página | 42
2. Puertos de entrada y salida digitales

Solución:

La función morse() recorre la cadena de caracteres que se le pasa como parámetro de


entrada, detectando el tipo de carácter y llamando a la función flashLEDQ con el código de
puntos y barras que le corresponde. Esta función decodifica el código, el cual consiste en
dos campos diferentes: el primero (los tres bits más significativos) indica el número de
elementos (puntos y rayas) y el segundo el tipo de símbolo en cada posición, empezando
por el bit menos significativo.

Código fuente
//ARCHIVOS DE DEFINICIONES
# in c lu d e < h t c .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
ft in c lu d e " p o r t s . h "
t fd e f in e _XTAL_FREQ 4000000 / / O s c i l a d o r I n t e r n o d e 4MHZ
CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & L V P _ O F F );
v o i d m o rse (c h a r t x t S t r i n g [ ] ) ;
// PROGRAMA PRIN C IPA L
/ / D u ra c ió n d e 1 e le m e n t o : 10 ms
/ / P u n to = 1 e le m e n to
//R aya = 3 e le m e n to s
/ / E s p a c io e n t r e s ím b o lo s = 1 e le m e n to
/ / E s p a c io e n t r e c a r a c t e r e s = 3 e le m e n t o s
/ / E s p a c io e n t r e p a l a b r a s = 7 e le m e n t o s
v o i d m a in ( ) {
s e t_ a ll_ d ig ita l(); / / D e s a c t i v a r PORTA como e n t r a d a s a n a l ó g i c a s
TR IS B = 0 x 0 0 ; / / C o n fig u r a r RB0 como s a l i d a
RB0=0; //Todos lo s le d apagados
m o r s e ( " H o la M u n d o ");
w h ile ( 1) ;
}
/ / D e f i n i c i ó n de p u n to s y r a y a s
//Para c a r a c t e r e s a lfa n u m é r ic o s , 3 MSB b i t s d e f in e n e l número de s ím b o lo s (1 a 5'
/ / P a ra c a r a c t e r e s de p u n tu a c ió n ( ' , ' y 2 MSB b i t s i n d i c a n 6 s ím b o lo s
/ / P u n to :0, r a y a : 1;
//LSB b i t s a lm a cen a d o s en o rd e n i n v e r s o d e modo qu e e l b i t 0 = p r i m e r s ím b o lo
/ / E je m p lo , F = = 4 s ím b o lo s = 0010, p o r l o t a n t o s e a lm a c e n a como 0100
/ / 0 0 0 x x x x x 0 s ím b o lo s
/ / 0 0 1 x x x x ? 1 s ím b o lo s x = no im p o r t a , ? = d a t o d e l s ím b o lo = 0 ó 1 )
/ / 0 1 0 x x x ? ? 2 s ím b o lo s
//011 x x ? ? ? 3 s ím b o lo s
//100 x ? ? ? ? 4 s ím b o lo s
//101 ? ? ? ? ? 5 s ím b o lo s
/ / l l ? ? ? ? ? ? 6 s ím b o lo s
c h a r T a b la [] = {ObOlOOOOlO, // 0 = A " . - »
OblOOOOOOl, // 1 = B
O blO O O O lO l, // 2 = C
ObOllOOOOl, // 3 = D »- . . "
ObOOlOOOOO, // 4 = E ". »
OblOOOOlOO, // 5 a F
O b O llO O O ll, // 6 a G » - - ."
OblOOOOOOO, I I 7 = H » ___ '•
ObOlOOOOOO, // 8 a I " . .11
O b lO O O lllO , II 9 = J .-- «i
O b O llO O lO l, I I 10 a K
OblOOOOOlO, // 11 = I*
O bO lO O O O ll, I I 12 a M " - - »
ObOlOOOOOl, // 13 = N " - .»

Página | 43
Programación de microcontroladores PIC en lenguaje C

O b O llO O lll/ // 14 = O “ ---- "


OblOOOOllO, // 15 = P ii ^ ___b «i
O blO O O lO ll, 16 = ii__ _ _ ii
// Q
ObOllOOOlO, // 17 = R 11. - . 11
ObOllOOOOO, // 18 = S ■i ii
ObOOlOOOOl, // 19 = T
ObOllOOlOO, // 20 = U ii ^ _ ii
OblOOOlOOO, // 21 = V n __ H

O bO llO O llO , // 22 = W ".--"


OblOOOlOOl, // 23 = X
O blO O O llO l, // 24 = y
OblOOOOOll, // 25 = z - . . "
O b lO llllll, // 26 = 0
O b lO lllllO , // 27 = i " . ------"
O b lO llllO O / 28 = 2 ii ____ ii
//
O b lO lllO O O , // 29 = 3
OblOllOOOO, // 30 = 4 n . - 11

OblOlOOOOO, // 31 = 5 ii ii

OblOlOOOOl/ // 32 = 6 "- ______ "


OblOlOOOll/ // 33 = 7
O b lO lO O lll, 33 = 8 ii ------ - . »
//
O b lO lO llll, // 34 = 9 n-------- . «
O b llllO O ll/ // 36 = ,
O b lllO lO lO // 37 =
};
v o i d fla sh L E D (c h a r p u n tu a c ió n ) {
c h a r c o u n t;
c o u n t = (p u n tu a c ió n » 5) & ObOOOOOlll; / / E x t r a e r l o s t r e s b i t s s u p e r io r e s
//de l a cu en ta
if (c o u n t >= 6 ) co u n t &= ObOOOOOllO; //Comprobar s i es un c a r á c t e r de
/ / p u n tu a ció n
fo r ( i n t i = 0 ; i < c o u n t; i+ + ) {
RB 0=1;
i f ( (p u n tu a c ió n & ObOOOOOOOl) == 0) //Punto
__ d e la y _ m s ( 1 0 ) ;
e ls e //Raya
__ d e la y _ m s ( 3 0 );
p u n tu a ció n = p u n tu a c ió n >> 1 ;
RB0=0;
_ d e la y _ m s ( 1 0 ) ; / / R eta rd o e n t r e s ím b o lo s
>
v o i d m orse (c h a r t x t S t r i n g [ ] ) {
f o r ( i n t i = 0; t x t S t r i n g [ i ] J= 1\ 0 1; i+ + ) {
i f ( t x t S t r i n g [ i ] >= ' a ' && t x t S t r i n g [ i ] <= ' z ' )
fla s h L E D (T a b la [t x t S t r in g [i] - ' a ' ] ) ;
e l s e i f ( t x t S t r i n g [ i ] >= 'A * && t x t S t r i n g [ i ] <= 1Z ' )
fla s h L E D (T a b la [t x t S t r in g [i] - ' A ' ] ) ;
e l s e i f ( t x t S t r i n g [ i ] >= '0 ' && t x t S t r i n g [ i ] <= ' 9 ' )
fla s h L E D (T a b la [t x t S t r in g [i] - '0 ' + 2 6 ]);
e l s e i f ( t x t S t r i n g [ i ] == ')
fla s h L E D (T a b la [ 3 6 ] ) ;
e l s e i f ( t x t S t r i n g [ i ] ==
fla s h L E D (T a b la [ 3 7 ] ) ;
e l s e i f ( t x t S t r i n g [ i ] == ')
__ d e la y _ m s (6 0 ); / / R e ta rd o e n t r e p a l a b r a s . Se l e suma a l
/ / d e l ú lt im o s ím b o lo
__d e la y _ m s ( 2 0 ) ; / / R eta rd o e n t r e c a r a c t e r e s . Se l e suma a l d e l
/ / ú ltim o s ím b o lo

Página | 44
2. Puertos de entrada y salida digitales

- Comprueba el funcionamiento mediante la utilización del simulador MPLAB SIM y


el visualizador de señales digitales (menú View=> Simulator Logic Anaiyzer)
observando la salida RBO

Logic Anslyztr * r ‘ " ¿ P


Tugger Ponlion TnggciPC- Ttfr«Ba:o Uoóa
Si«t o CerJei End | Now~¡[ Geei j Cyc ▼ Simple O m rt J

1 + • & ! <a.l®U ; ¡M f b lH ls ia l

'MITI u n JUIÍ1 ^ rn j i jur


i— i— i— i—t— i— i— i— i— i— i i i i i i i i i i i i i i i i— i— i— i— i— :— ¡----- :------ :— — :— :— i------:— — i— :— i------:-----------------
0.0 100000.0 200000.0 300000.0 400000.0 500000.0 600000.0 700000.0 8000000 SOOOOO.O I jOOCX:

Figura 2.7: Simulación del ejercicio 2.1.3.

2.1.4 Generación de la señal acústica SOS mediante


un Zumbador Piezoeléctrico
Escribe un programa que genere la señal de socorro internacional SOS en código morse ( . . .
-----. . . ). La salida activará el zumbador piezoeléctrico conectado al puerto RC2, de modo
indefinido hasta que se pulse el pulsador conectado a RBO que generará una interrupción
para finalizar el programa.

Los tiempos de cada pitido serán los siguientes:


- pulso corto: 200 ms
- pulso largo (raya): 500 ms
- espacio entre pulsos: 200 ms
- pausa entre dos señales SOS: 500 ms
- periodo de la onda cuadrada que excita el zumbador: 4 ms

+5V

Página | 45
Programación de microcontroladores PIC en lenguaje C

Solución:

Se generan tres funciones: una para el punto, otra para la raya y la última para la pausa
entre las dos señales. En cada función se genera una onda cuadrada de semiperiodo 2 ms
(__delay_ms(2))que activa el zumbador durante un tiempo controlado por un for. Mediante
la interrupción externa producida por RBO/INT se deja de enviar la señal al zumbador al
cambiar el terminal RC2 de salida a entrada.

Código fuente

//ARCHIVOS DE DEFINICIONES
# in c lu d e < h tc .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
#d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o de 4MHZ
__ CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FO SCXT & L V P_O F F);

//DEFINICION DE VARIABLES
in t x;

//DEFINICION DE FUNCIONES
v o id p u n to (v o id ){ //Fu n ción p a ra g e n e r a r e l pu n to
f o r (x = 0 ;x < 1 0 0 ;x + + ){
RC2 = -RC2;
__ d e la y ms ( 2 ) ;
}
__ d e la y m s( 2 0 0 ) ;
}
v o id r a y a (v o id ){ //Fu n ción p a ra g e n e r a r l a ra y a
f o r (x = 0 ; x < 2 5 0 ; x + + ){
RC2 = -RC2;
___d e la y ms ( 2 ) ;
}
__ d e la y m s( 2 0 0 ) ;
} ;
v o id p a u s a (v o id ){ //Fu n ción p a ra g e n e r a r l a pau sa e n t r e d o s SOS
__ d e la y _ m s (5 0 0 );

//PROGRAMA PRINCIPAL
v o id m a in (v o id ){
TRISB = ObOOOOOOOl; / / C o n fig u r a r RB0 como e n tra d a
TRISC = ObOOOOOOOO; / C o n fig u r a r RC2 como s a l i d a
RC2=1;
G IE =1; / / H a b i l i t a r in t e r r u p c io n e s ( R e g i s t r o INTCON)
INTE=1; / / H a b i l i t a r i n t e r r u p c ió n de RB0 ( R e g i s t r o INTCON)
INTEDG=0 ; / / In t e r r u p c ió n e x t e r n a RBO/INT p o r f l a n c o de b a ja d a
w h ile ( 1) {
p u n to () ;
p u n to () ?
p u n to () ;
ra ya () ;
ra ya ();
ra ya ();
p u n to ( ) ;
p u n to ( ) ;
p u n to ();
pausa ( ) ;

Página | 46
2. Puertos de entrada y salida digitales

//INTERRUPCIÓN
/ / I n t e r r u p c ió n p o r RBO /IN T
s t a t i c v o id in te r r u p t i s r ( v o i d ) {
if(IN T F ){
IN T F = 0 ; / / D e s a c t i v a r e l FLAG d e l a i n t e r r u p c i ó n de RBO
TRISC = ObOOOOOlOO; / / C o n fig u r a r RC2 como e n t r a d a p a r a p a r a r
}
}

Se puede observar el funcionamiento mediante el analizador lógico del simulador.

__________i__________ :__________ |______


— I "

I I I f l l i l i l í
í l
1____________
9COWCOO 'jtocoooo i caíame ueooocoo nocox.o 11500000.0 laxOOCCO 125CD3XC ixoáxoc 133)0x0.3 U000B00C '« — I
1LA9SJM P1G6F377A pcO VWhbi ZDCC [Link] bankO

Figura 2.9: S imulación del ejercicio 2.1.4.

2.2 Visualizadores numéricos de 7 segmentos


Los visualizadores de 7 segmentos con diodos LED se usan sobre todo para representar
información numérica. Hay dos tipos de elementos de 7 segmentos: los de ánodo común y
los de cátodo común, según estén conectados entre sí todos los ánodos o todos los cátodos
de los LED, respectivamente. En los de ánodo común, para que se active (emita luz) un
segmento, el terminal correspondiente debe excitarse con una tensión baja
(correspondiente al nivel lógico '0', si la lógica es positiva), mientras que el ánodo común
debe estar puesto a una tensión positiva alta (VDD). En los elementos de cátodo común la
situación es la inversa: cada segmento se activa con una tensión alta (correspondiente al
nivel lógico '1') y el cátodo común debe estar a 0 V (VSS).

Página | 47
Programación de microcontroladores PIC en lenguaje C

Figura 2.10: Diagrama interno de un display 7 segmentos .

2.2.1 Control de 1 display


Muestra de manera indefinida por el display de 7 segmentos (figura 2.11) uno de los dígitos
hexadecimales encendiéndose y apagándose con una cadencia de un segundo. El dígito
elegido es E.

R epresentación de lo s d ígitos 0-F en


código 7 segm entos, binario v h exadeclm al
HEX h q f e d c b a 7SEG 7SEG
0 0 0 1 1 1 1 1 1 3F CO
1 0 0 0 0 0 1 1 0 06 F9
2 0 1 0 1 1 0 1 1 5B A4
3 0 1 0 0 1 1 1 1 4F B0
4 0 1 1 0 0 1 1 0 66 99
5 0 1 1 0 1 1 0 1 6D 92
6 0 1 1 1 1 1 0 1 7D 82
7 0 0 0 0 0 1 1 1 07 F8
8 0 1 1 1 1 1 1 1 7F 80
9 0 1 1 0 1 1 1 1 6F 90
A 0 1 1 1 0 1 1 1 77 88
B 0 1 1 1 1 1 0 0 7C 83
C 0 0 1 1 1 0 0 1 39 C6
D 0 1 0 1 1 1 1 0 5E A1
E 0 1 1 1 1 0 0 1 79 86
F 0 1 1 1 0 0 0 1 71 8E

Figura 2.11: Conexión de un display de 7 segmentos con el PIC16F877A. Código 7 segmentos


y complementado de las cifras hexadecimales (0-F).

Solución:

Debido al inversor 74LS540 hay que enviar el complemento del código 7 segmentos de la
letra E al PORTD.

Página | 48
2. Puertos de entrada y salida digitales

Código fuente
//ARCHIVOS DE DEFINICIONES
# i n c l u d e < h t c . h> / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
# in c lu d e " p o r t s . h "
# d e f i n e _XTAL_FREQ 4000000 / / O s c i l a d o r I n t e r n o d e 4MHZ
__ CONFIG(WRT_OFF & WDTE_OFF & PWRTE OFF & F O S C X T & LVP O F F );

//D EFIN IC IÓ N DE VARIABLES


/ / T a b la co n e l c ó d ig o d e 7 se g m e n to s co m p le m en ta d o p a r a l a s c i f r a s de 0 a F .
/ / ( tam año b y t e )
u n s ign ed ch a r c o d ig o [] ={0xC 0, 0xF9, 0xA4,OxBO, 0x99/ 0x92/ 0 x 8 2 ,0 x F 8 ,0x80,0x90,
0 x 8 8 ,0 x 8 3 ,0xC 6, O xA l,0 x 8 6 ,0 x 8 s } ;

u n s ig n e d c h a r D IG IT O ; / / D ig it o que s e q u ie r e sacar

//PROGRAMA P R IN C IPA L
v o id m a in (v o id ){
s e t _ a l l _ d i g i t a l () ; / / D e s a c t iv a PORTA como e n t r a d a s a n a l ó g i c a s
TRISA=ObOOOOOOOO ; / / C o n fig u r a e l PORTA como s a l i d a s
T R IS D =0 x0 0 ; / / C o n fig u r a e l PORTD como s a l i d a s
P O R T A =l; / / A c t i v a r d i s p l a y d e RAO
D IG ITO =0x0E ; / / C a r g a r E en D IG ITO

w h ile (1) {
P O R T D = cod igo [D IG IT O ] ; / / S aca e l D ÍG ITO p o r e l p u e r t o D
__ d e la y _ m s ( 1 0 0 0 ) ; / / D í g i t o m o s t r a d o d u r a n t e 1 seg u n d o
PORTD= OxFF; //Apagar e l d is p la y
__ d e la y _ m s ( 1 0 0 0 ) ; / / D is p la y a p a g a d o d u r a n t e 1 seg u n d o
}

Se puede observar el funcionamiento mediante el analizador lógico del simulador.

■ logn Anatyici________________________________________________
Tiggei Posfion Tigrjn PC ■ TmeBa:r Mods
Slatt o Cenlei En«J [ New |[~Oeat ) Cye - Sir*ie > a rK

F * l a|SLl : |.R| íblHlSlR]

PORTD 086 OFF 066 OFF

0,0 ÍOCOOOOO 2000CC0.0 30000000 4000000 0

Figura 2.12: S imulación del ejercicio 2.2.1.

2.2.2 Control de un visualizador con 4 displays


La figura 2.13 muestra un visualizador o display de 4 elementos de cátodo común
conectados a los puertos A y D de un microcontrolador PIC. Las resistencias Re = 220 O

Página | 49
Programación de microcontroladores PIC en lenguaje C

limitan la corriente que circula por los segmentos, mientras que las resistencias Rb = 47 O
deben garantizar la saturación de los transistores que activan los terminales de selección de
cada elemento. Los transistores actúan como interruptores y van a saturación con un nivel
lógico T en los terminales del puerto A y a corte con un nivel lógico '0'. La frecuencia
mínima de las señales en cada uno de terminales de selección (RA3, RA2, R A I y RAO) debe
estar entre 40 Hz y 200 Hz para que no se perciba parpadeo alguno. Cada elemento está
seleccionado durante una cuarta parte del tiempo. Si consideramos una frecuencia de 50
Hz, cada uno de los displays se refrescará cada 20 ms y estará seleccionado durante 5 ms.

Se pide mostrar en el visualizador los dígitos 3-2-1-0.


+5V

Figura 2.13: M ultiplexación de displays.


Soluciones:

Código fuente 1

//ARCHIVOS DE DEFINICIONES
# in c lu d e < h t c .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
tt in c lu d e " p o r t s . h '1
# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ
__ CONFIG(W RTOFF & WDTE_OFF & PWRTEOFF & F O S C X T & LVP OFF) ; / / C o n fig u r a c ió n
/ / d e l P IC

//PROGRAMA PRINCIPAL
v o i d m a in () {
//IN IC IA LIZ A C IO N E S PARA EL PIC
s e t_ a ll_ d ig ita l(); / / D e s a c tiv a m o s PORTA como e n t r a d a s
/ / a n a ló g ic a s
TR IS A =0x00 ; / / T e r m in a le s PORTA como s a l i d a s
TRISD=OxOO; / / T e r m in a le s PORTD como s a l i d a s

Página | 50
2. Puertos de entrada y salida digitales

w h ile ( 1) {
/ / C ó d ig o p a r a m o s t r a r l o s d í g i t o s y a c t i v a r l o s d i splay3
R A 3 = 0 ;R A 2 = 0 ;R A 1 = 0 ;R A 0 = 1 ; / / A c tiv a m o s D ISPLAY 0 y los otros desactivados
PORTD = OxCO; / / M ostram os p o r p u e r to D e l d ígito 0
__ d e l a y m s ( 5 ) ; / / R e t a r d o d e 5 ms p a r a e v itar el p a rpadeo

RA3=0; RA2=0; RA 1=1; RA0=0; / / A c tiv a m o s D ISPLAY 1 y l o s o t r o s desactivados


PORTD = 0 x F 9 ; / / M ostra m os p o r p u e r to D e l d í g i t o 1
__ d e l a y m s ( 5 ) ; / / R e t a r d o d e 5 ms p a r a e v i t a r e l par p a d e o

RA 3=0; R A 2=1;R A 1=0; RA0=0; / / A c tiv a m o s DISPLAY 2 y l o s o t r o s d e s a c t iv a d o s


PORTD = 0xA 4; / / M ostram os p o r p u e r to D e l d í g i t o 2
__ d e l a y m s ( 5 ) ; / / R e t a r d o d e 5 ms p a r a e v i t a r e l p a rp a d e o

R A 3 =1;R A 2=0;R A 1 =0;R A 0= 0; / / A c tiv a m o s D ISPLAY 3 y l o s o t r o s d e s a c t iv a d o s


PORTD = OxBO; //M ostram os p o r p u e r to D e l d í g i t o 3
__ d e la y _ m s ( 5 ) ; / / R e t a r d o d e 5 ms p a r a e v i t a r e l p a rp a d e o

Se puede observar el funcionamiento mediante el analizador lógico del simulador.

JL!) Logic Analy 2er es ' iD ;U &

Tngger Ponlion Tngger PC = Time Ba:e Mode


Staii o Cenlei End | Now~|[~Clear ¡ Cyc ▼ Simple Channeh 1

!+■ »! Q.1®.! : í|>h|

* PORTD oco 0F9 OAA 0B0 OCO 0F9 0A4 0B0

0.0 10000.0 20000.0 30000.0 40000.0

Figura 2.14: S imulación del ejercicio 2.2.2.

Código fuente 2

//ARCHIVOS DE DEFINICIONES
# in c lu d e < h t c .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
# in c lu d e " p o r t s . h "
# d e fin e XTA LFREQ 4000000 / / O s c i l a d o r I n t e r n o d e 4MHZ
— CONFIG(WRT_OFF í W DTEOFF & PWRTE OFF & F O S C X T & L V P O F F ) ; / / C o n fig u r a c ió n
/ / d e l P IC

Página | 51
Programación de microcontroladores PIC en lenguaje C

/ / T a b la co n e l c ó d ig o 7seg m en tos com p lem en tad o


u n s ig n e d c h a r c o d i g o [ ] = {0 x C 0 , 0x F 9 /0 xA 4, O xBO }; //O, 1 , 2 y 3
/ / T a b la co n e l c ó d ig o d e a c t i v a c i ó n de l o s d i s p l a y
u n s ig n e d c h a r d i s p l a y [] = {0 x 0 1 , 0 x 0 2 ,0 x 0 4 ,0 x 0 8 }; / / D is p la y 0, d i s p l a y 1 ,
/ / d is p la y 2 y d is p la y 3

u n s ig n e d c h a r x = 0 ; / / ín d ic e de lo s c ó d ig o s

// PROGRAMA PRINC IPAL


v o i d m a in ( ) {
//IN IC IA LIZ AC IO N E S PARA EL P IC
s e t_ a ll_ d ig ita l(); / / D e s a c tiv a m o s PORTA como e n t r a d a s
// a n a l ó g i c a s
TR ISA =0x00; / / T e r m in a le s PORTA como s a l i d a s
TR ISD =0x00; / / T e r m in a le s PORTD como s a l i d a s

w h ile (1) {
fo r (x = 0 ;x < 4 ;x + + ){
P O R T A = d is p la y [x ]; / / A c tiv a r d is p la y
P O R T D = c o d ig o [x ]; / / e n v ia r c ó d i g o
__ d e l a y m s ( 5 ) ; / / D is p la y y c ó d i g o a c t i v a d o 5 ms
}
}
>

2.3. Exploración de teclado maíricial


Un teclado matricial está compuesto por teclas interconectadas formando una matriz
(véase figura 2.15). Las teclas son simples interruptores mecánicos y cada una ocupa la
intersección de una fila con una columna. Cuando se pulsa una tecla, se ponen en contacto
eléctrico la fila y la columna donde está dicha tecla. Las filas y columnas de esta matriz se
pueden conectar a los terminales de uno o más puertos paralelos.

Teclado matricial de 16 teclas conectado al puerto B


P1C16F877A

Página | 52
2. Puertos de entrada y salida digitales

LECTURA TECLADO
Si RB0 = 0 y tecla ;0 ' pulsada => RB4 = 0
tecla '0 no pulsada => RB4 = 1

Si RB0 = 1 y teda '0’ Pasada RB4 = 1


1 tecla *0' no pulsada RB4 = 1
Figura 2.15: Exploración de teclado matricial conectado al puerto B.

Para explorar un teclado matricial se envían señales hacia las filas de la matriz por las líneas
de exploración y se recoge información por las columnas, que entonces constituyen las
líneas de retorno. Básicamente se parte de que, si no hay ninguna tecla pulsada, todas las
líneas de retorno están en el nivel lógico '1'. Las líneas de exploración son puestas (sucesiva
o simultáneamente) a '0'. Este valor lógico solo aparece en la línea de retorno donde está la
tecla pulsada, mientras que las restantes líneas de retorno mantienen el valor '1'. Con la
información enviada hacia la matriz y la que retorna, se conforma un código único para
cada tecla, llamado código de exploración. Para garantizar que las líneas de retorno
permanezcan en T si no hay tecla pulsada, se conectan resistencias entre cada línea de
retorno y la tensión de alimentación (VDD).

El código que retornará el teclado será el valor de la tecla pulsada. Conectando al puerto D
un display de 7 segmentos (véase figura del ejemplo 2.2.1) se podrá ver dicho valor en el
display.

Configuración

Hay que configurar los terminales de los puertos empleados:


B: RB7-RB4 como terminales de entrada y RB3-RB= como terminales de salida,
D: todos los terminales de salida y
A: el terminal RAO de salida.

Como se van a utilizar las resistencias internas de polarización del puerto B, hay que
indicarlo en el registro OPTION_REG (véase apéndice A2.2)
Con OPTION_REG=Ox7F se habilitan dichas resistencias.
Código fuente
//ARCHIVOS DE DEFINICIONES
# in c lu d e < h t c .h > / / In c lu im o s lib r e r ía d e l m ic r o a u s a r
# in c lu d e " p o r t s . h "
# d e f i n e _XTAL_FREQ 4000000 / / O s c i l a d o r I n t e r n o d e 4MHZ

__ CONFIG(W RTOFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & LVP OFF) ;

//DEFINICIÓN DE VARIABLES
/ / T a b la con e l c ó d ig o de 7 s e g m e n to s co m p le m en ta d o p a r a l o s d í g i t o s
/ / d el 0 a l F y apagado.
u nsign ed ch ar c o d ig o [] ={0 x C 0 ,0 xF 9 , 0xA4, 0xB0,0 x 9 9 ,0 x 9 2 ,0 x 8 2 ,0xF8,0x80,
0 x 9 8 ,0 x 8 8 ,0 x 8 3 ,0xC6, O xAl,0 x 8 6 ,0x8E,0xFF>;
u n s ig n e d c h a r t e c l a ; / / ín d ic e de l i s t a de c ó d ig o

Página | 53
Programación de microcontroladores PIC en lenguaje C

//PROGRAMA PRINC IPA L


v o id m a in (v o id ){
s e ta lld ig ita lO ; //Hay qu e c o n f i g u r a r PAO-3 como d i g i t a l e s
TR ISA = ObOOOOOOOO; / / C o n fig u r a e l PORTA como s a l i d a s
TRISD =0x00; / / C o n fig u r a e l PORTD como s a l i d a s
TR ISB =0xF0; / / C o n fig u r a como s a l i d a s RB0-RB3 y como
/ / e n tr a d a s RB4-RB7
OPTION REG=0x7F; / / H a b i l i t a R E S IS . De p u l l - u p i n t e r n a s d e l
/ / p u e r to B.
PO RTA=l; / / A c t i v a r d i s p l a y de RAO

w h ile ( 1 ) { / / B u c le i n f i n i t o .

PORTB=OxFE; // S aca 0 a F i l a 1
if(R B 4 == 0 ) { t e c l a = 0 ; }
if(R B 5 == 0 ) { t e c l a = 1 ; }
i f ( R B 6 == 0 ) { t e c l a = 2 ; }
if(R B 7 == 0 ) { t e c l a = 3 ; }
PORTB=0xFD; // S aca 0 a F i l a 2
i f ÍRB4 == 0 ) { t e c l a = 4 ; }
if(R B 5 == 0 ) { t e c l a = 5 ; }
i f ( R B 6 == 0 ) { t e c l a = 6 ; }
if(R B 7 == 0 ) { t e c l a = 7 ; }
PORTB=0xFB; // S aca 0 a F i l a 3
if (R B 4 == 0 ) { t e c l a = 8 ; }
if (R B 5 == 0 ) { t e c l a = 9 ; }
i f ( R B 6 == 0 ) { t e c l a = 1 0 ; }
if(R B 7 == 0 ) { t e c l a = 1 1 ; }
PORTB=0xF7; // S aca 0 a F i l a 4
if (R B 4 == 0 ) { t e c l a = 1 2 ; }
if (R B 5 == 0 ) { t e c l a = 1 3 ; }
if ( R B 6 -= 0 ) { t e c l a = 1 4 ;}
if(R B 7 == 0 ) { t e c l a = 1 5 ; }
PORTD = c o d i g o [ t e c l a ] ; / / S a c a r c ó d i g o de 7 seg m en tos a l d i s p l a y
i f ( (RB4 t a RB5 && RB6 && R B 7)== 1 ) { t e c l a = 1 6 ; } / /A pagado e l d i s p l a y

}
}

2.4 Control de pantallas LCD


Para los siguientes ejercicios nos vamos a basar en la conexión con un display LCD de dos
líneas y 16 caracteres por línea el cual está diseñado sobre el controlador Hitachi HD44780.
Consultar las hojas de características en:
[Link]
[Link] HD44780 LCD controller
El display dispone de 14 líneas para su alimentación, control del contraste y para la
comunicación con el microprocesador. Cada carácter consiste en una matriz de puntos de
5x8.

Página | 54
2. Puertos de entrada y salida digitales

Figura 2.16: Pantalla LCD.

20pF _j_ - j- 20pF

Figura 2.17: Conexión del PIC16F877A con la pantalla LCD HITACHI HD 44780.

La comunicación con el microprocesador se ha implementado empleando un bus de datos


de 4 bits.
En la conexión con el microprocesador el puerto D controla el display mediante las
siguientes líneas:
- Encendido / Apagado del display: RD7
- Bus de datos: RDO - RD3
- Bus de control:
• Enable (E): RD6: Cuando está a nivel bajo el display está deshabilitado.
• Read/Write (R/W): RD5: cuando está a nivel bajo los datos se escriben en el LCD.
Cuando es alto, los datos se leen del LCD.
• Register Select (RS): RD4: Sirve para distinguir entre instrucciones y caracteres. A
nivel bajo se envían instrucciones y a nivel alto caracteres.
Cuando el LCD se inicializa está preparado para recibir caracteres. Si recibe un carácter lo
escribe en el display y mueve el cursor a la siguiente posición. Los caracteres mostrados en
el display se almacenan en la memoria DDRAM.

Página | 55
Programación de microcontroladores PIC en lenguaje C

El display LCD contiene tres bloques de memoria:


- DDRAM - Display Data RAM
- CGRAM - Character Generator RAM
- CGROM - Character Generator ROM
Para mandar un carácter al display, se escribe en la DDRAM. La CGROM contiene las
matrices de puntos del juego de caracteres por defecto.
También es posible generar nuevos caracteres definidos por el usuario mediante la CGRAM,
una memoria de 64 bytes. Cada carácter necesita 8 bytes para almacenarse, por lo que
disponemos de 8 caracteres definidos por el usuario. Para almacenar el mapa de un
carácter, debemos iniciar la dirección de la CGRAM y escribir datos al display.

Antes de acceder a la DDRAM después de la definición del carácter, el programa debe


establecer la posición de la DDRAM donde escribir el nuevo carácter.

Las posiciones de la DDRAM para la primera fila son las direcciones 0x00 a OxOF. Para la
segunda fila comienzan en la 0x40 y terminan en ia 0x4F

Cuando se envía una instrucción o un dato al display es necesario esperar un cierto tiempo
antes de enviar el siguiente, para que el display pueda procesarlo adecuadamente. Esto se
puede hacer monitorizando el flag de Busy o respetando los tiempos de ejecución indicados
por el fabricante.

2.4.1 Envío de cadenas de caracteres al LCD


Realiza un programa que escriba en las dos líneas de una pantalla LCD 16x2.

Solución:

En la línea 1 aparecerá el texto "LA PRIMERA LÍNEA" y en la línea 2 el texto "La segunda
línea".
Al crear el proyecto hay que cargar además del fichero con el programa los ficheros Icd.c y
Icd.h

Código fuente

//ARCHIVOS DE DEFINICIONES
# in c lu d e < h tc .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r .
# in c lu d e ''I c d . h " / / In c lu im o s l i b r e r í a de l a p a n t a l l a l c d .
# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ
__ CONFIG(W RTOFF í WDTE_OFF & PWRTE_OFF & FOSC_XT & L V P O F F );

//PROGRAMA PRINC IPAL


v o i d m ain ( v o i d ) {

l c< i_ in it(); / / I n i c i a l i z a l a p a n t a l l a LCD.


lc d _ c le a r (); / / B o rra e l c o n t e n id o de l a p a n t a l l a lc d .

Página | 56
2. Puertos de entrada y salida digitales

w h ile (1 ) {
l c d _ g o t o ( 0 x 0 0 ); / / E s c r ib e en l a p r im e r a l í n e a de l a p a n t a l l a
//LCD (d e 0x00 a OxOF)
l c d _ p u t s ( "L A PRIMERA L I N E A " ) ; / / P r e s e n ta c ió n de l a p a n t a lla .
l c d _ g o t o (0 x 4 0 ); / / E s c r ib e en l a seg u n d a l í n e a de l a
/ / p a n t a l l a LCD (d e 0x40 a 0x4F)
l c d _ p u t s ( " L a seg u n d a l i n e a " ) ; / / P r e s e n ta c ió n de l a p a n t a lla .
}
}

2.4.2 Creación de nuevos caracteres


Realiza un programa que escriba en las dos líneas de la pantalla LCD los mensajes
PAMPLONA IRUÑA En la línea 1 y
Pamplona Iruña En la línea 2.
Solución:

Hay que crear los caracteres Ñ y ñ ya que no están disponibles en la CGROM. Para ello los
vamos a crear en la CGRAM.

Byte Bits 4,3,2,1,0 Byte Bits 4,3,2,1,0


4 3 2 i 0 4 3 2 1 0

OxOE :: L 0x00
0x11 : □ OxOE [I : □
0x11 0x16 J m
0x19 nn - 0x19 nn u
0x15 □ __ 0x11 n ■
0x13 _ _ 0x11 n
Oxll i _ 0x11 n ■
0x00 ... cursor 0x00 cursor
Figura 2.18: Caracteres ñ y ñ .

Código fuente

//ARCHIVOS DE DEFINICIONES
# in c lu d e < h tc .h >
# in c lu d e " l c d . h "
__ CONFIG(W RTOFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & LVP O F F );

# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ


# d e f i n e LCD_RS RD4

/ / D e f i n i c i ó n d e c a r a c t e r e s en a r r a y s de 8 b y t e s (5 x 8 )
/ / s ó lo s e t ie n e n en c u e n ta l o s ú l t i m o s 5 b i t s .
u n s ig n e d c h a r MAY[ 8 ] = {0 x 0 E , 0 x 1 1 ,0 x 1 1 ,0 x 1 9 ,0 x 1 5 ,0 x 1 3 ,0 x 1 1 , 0 x 0 0 };
u n s ig n e d c h a r M IN [ 8 ] = { 0 x 0 0 , OxOE,0 x 1 6 ,0 x 1 9 ,0 x 1 1 ,0 x 1 1 ,0 x 1 1 ,0 x 0 0 } ;

//D EFINICIO N DE FUNCIONES


/ / L c d D e fin e C h a r : F u n c ió n p a r a c a r g a r e l n u e vo c a r á c t e r en CGRAM
//PARAMETROl: P o s i c i ó n d e l c a r á c t e r , 0 - 7 .

Página | 57
Programación de microcontroladores PIC en lenguaje C

//PARAMETR02: C a r á c t e r b itm a p (8 b y t e s ) . (5 x 8 )
L c d D e fin e C h a r (u n s ig n e d c h a r charnum , c h a r v a l ú e s [ ] ) {
in t i ;
/ / s e le c c io n a p o s i c i ó n CGRAM
LCD_RS=0;
l c d w r it e (0 x 4 0 + 8 * c h a r n u m ) ; / / d isp C m d (0x40 + ch a rn u m * 8 ) ;
/ / in t r o d u c e e l c a r á c t e r en CGRAM
f o r ( i =0 ; i < 8 ; i+ + ) {
lc d _ p u t c h (v a lú e s [i]) ;
}
}
//PROGRAMA PRINC IPAL
v o id m a in (v o id ){
lc d _ in it (); / / I n i c i a l i z a l a p a n t a l l a LCD.
lc d c le a r (); / / B o rr a e l c o n t e n id o d e l a p a n t a l l a LCD
L c d D e fin e C h a r (0 ,M A Y ); / / In t r o d u c e e l n u evo c a r á c t e r Ñ m a y ú s cu la
/ / en p o s i c i ó n 0 y nom bre MAY
L c d D e fin e C h a r (1 ,M I N ); / / In t r o d u c e e l n u evo c a r á c t e r ñ m in ú s c u la
/ / en p o s i c i ó n 1 y nom bre MIN

l c d g o t o ( 0x 0 0 ) ; / / S e le c c io n a l a p r im e r a l í n e a p a r a e s c r i b i r
l c d _ p u t s ( "PAMPLONA IR U " ) ;
lc d _ p u t c h ( 0 x 0 0 ) ; / / E s c r ib e l a Ñ
lc d _ p u t s ( " A " ) ;

lcd_goto(0 x 4 0 ); / / S e le c c io n a l a segu nda l í n e a p a ra e s c r i b i r


l c d _ p u t s ("Pamplona Ir u ");
l c d _ p u t c h (0x 0 1 ) ; / / E s c r ib e l a ñ
l c d _ p u t s ("a");
w h i l e (1); / / B u c le i n f i n i t o
}

2.4.3 Cronómetro segundero en la pantalla LCD


Realiza un programa que para crear un cronómetro segundero. En la primera línea de la LCD
aparecerá el letrero "SEGUNDOS" y en la segunda línea aparecerán los segundos.

Solución:

Al crear el proyecto hay que cargar además del fichero.c con el programa los ficheros Icd.c y
Icd.h

Código fuente
//ARCHIVOS DE DEFINICIONES
# in c lu d e < h tc .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r .
# in c lu d e " I c d . h " / / In c lu im o s l i b r e r í a d e l a p a n t a l l a l c d .
# d e fin e XTALFREQ 4000000 / / O s c ila d o r I n t e r n o de 4MHZ
__ CONFIG(W RTOFF & WDTE_OFF & PWRTEOFF & F0SC_XT & L V P O F F ) ;

//DEFINICION DE VARIABLES
u n s ig n e d c h a r x ,s e g u n d o s , d e c e n a s ,u n id a d e s ; / / V a r ia b le s que usarem os

//PROGRAMA PRINCIPAL
v o i d m ain ( v o i d ) {

lc d _ in it(); / / I n i c i a l i z a l a p a n t a l l a LCD.
lc d c le a r O ; / / B o rra e l c o n t e n id o de l a p a n t a l l a lc d .

Página | 58
2. Puertos de entrada y salida digitales

l c d _ g o t o (0 x 0 4 ) ; / / E s c r ib e en l a p a n t a l l a LCD l a p r e s e n ta c ió n
/ / in ic ia l.
l c d _ p u t s ( "SEGUNDOS") ; / / P r e s e n ta c ió n d e l a p a n t a lla ,
w h ile (1 ) {
fo r (x = 0 ;x < 6 0 ;x + + ){
segu ndos=x; / / A c t iv a r d is p la y
/ / C ó d ig o qu e n os s i r v e p a r a p a s a r l a v a r i a b l e s e g u n d o s a BDC
decenas=segu n dos/10; //Guardam os l a s d e c e n a s d e segu n do
s egu n do s =s e gu ndo s %1 0 ;
u n id a d e s = s e g u n d o s ; //Guardam os l a s u n id a d e s de segu n do
//Sumamos 0x30 p a r a o b t e n e r su c ó d i g o a s c i i .
d e c e n a s = d e c e n a s + 0 x 3 0;
u n id a d e s = u n id a d e s + 0 x 3 0 ;
/ / C ó d ig o p a r a m o s t r a r l o s v a l o r e s p o r l a p a n t a l l a l c d .
l c d g o t o (0 x 4 7 );
lc d _ p u t c h (d e c e n a s );
l c d _ g o t o (0 x 4 8 );
lc d _ p u tc h (u n id a d e s );
__ d e l a y m s (1 0 0 0 ); / / R e t a r d o de 1 seg u n d o
}
}
}

Página | 59
3. Temporizadores
3.1. Tem porizador 0
3.2. Tem porizador 1
3.3. Tem porizador 2
3.4. Watchdog

Los temporizadores del PIC, junto a su sistema de interrupciones, ayudan a construir


sistemas que realizan varias tareas dependientes del tiempo simultáneamente. Un ejemplo
es un cronómetro que usa displays de 7-segmentos para visualizar la cuenta. Por un lado,
cuenta el tiempo de forma muy precisa y por otro refresca los displays de manera periódica.
Para realizar estas tareas el microcontrolador debe usar un temporizador que le indique el
momento exacto en que debe iniciar cada rutina.

El PIC 16F877A tiene tres temporizadores, TimerO, Tim erl y Timer2, que se pueden utilizar
para crear retardos, realizar tareas periódicas, generar señales PWM o contar pulsos
externos. Al tratarse de dispositivos hardware independientes de la CPU, todas estas
funciones tienen lugar de manera simultánea, y a la vez que el micro puede estar realizando
otra tarea.

RAO/ANO
RA1/AN1
RA2/AN2/VREF VCVREF
RA3/AN3/VREF»
RA4/ /C10UT < “
RA5/AN4/SSS/C20UT
TOCKI
3 RBOÍJNT) Entrada de flancos
9 RB1^-<
RB2 , para TMRO en
RB3/PGM
RB4 I modo contador
RB5 I
RB6/PGC
RB7/PQD

Rcom
RC 1óso/TICKI
01SI/CCP2 -
RC1
2F/CTCP
RC3/SCK/SCL
T1CKI
Entrada de flancos
para TMR1 en
modo contador

La configuración de los
temporizadores se realiza
mediante la carga de
ciertos registros presentes
en RAM

Figura 3.1: Los temporizadores del microcontrolador PIC16F877A.

Página | 61
Programación de microcontroladores PIC en lenguaje C

3.1. Temporizador 0
El Temporizador 0 dispone de un contador/temporizador de 8 bits además de un predivisor de
8 bits programable. La fuente de pulsos puede ser interna o externa. En este segundo caso, se
sincroniza con el reloj interno y es posible seleccionar el flanco en que se produce la cuenta.

El funcionamiento como temporizador se selecciona poniendo a cero el bit TOCS del registro
OPTION. En este modo el temporizador se incrementa en cada ciclo de instrucción (sin
tener en cuenta el pre-divisor). Cuando se escribe en el registro TMRO, la cuenta se inhibe
durante los dos siguientes ciclos.

El modo contador se selecciona poniendo a "1" el bit TOCS. En este modo cuenta los pulsos
que se aplican al pin TOCKI. El flanco se determina mediante el bit TOSE del registro OPTION.

Para asignar el pre-divisor al Temporizador 0 es necesario borrar el bit PSA del registro
OPTION. En otro caso se asigna al Watchdog.

Cuando la cuenta se desborda (pasa de OxFF a 0x00) se pone a 1 el flag TOIF del registro
INTCON. TOIF debe ser borrado por la rutina de atención a la interrupción para rehabilitar
esta interrupción.

Entrada reloj interno


CLKOUT (Fosc/4)
Entrada pulsos ext( TMRO Flag TOIF a 1
RA4/T0CKI ' — ■* al desbordarse

I
TO SE TOCS

El tiempo que tarda en desbordarse el TimerO es:

Temporización del TimerO = Td = (256 - N tmro ) x Px T


Ntmro el número con el que hay que cargar el registro TMRO.
P el factor de división del pre-divisor (P = 2, 4, 8, 16,32, 64,128, 256)
Ti el periodo de los pulsos internos o externos de entrada al pre-divisor.

NOTA: Para ser precisos, habría que añadir 2T¡ en eí cálculo de la temporización ya que cada vez que se
recarga el TMRO se pierden dos ciclos de máquina hasta el siguiente incremento como se explica en e ma™
de referencia de Microchip (DS33023). Sin embargo, en los ejercicios propuestos se considerará despreci
este tiempo.

Re gistro s aso ciad o s al TimerO


Reaistro Bit 7 | Bit 6 I Bit 5 I Bit 4 I Bit 3 I Bit 2 I Bit 1 I Bit 0 Ver APENDICE 2
TMRO Registro del módulo Timern
INTCON GIE PEIE TOIE INTE RBIE TOIF INTF RBIF A2.5
OPTION REG RBPU# INTEDG TOCS TOSE PSA PS2 PS1 PSO A2.2
TRISA Regis ro de direcciones de dato >del POFIT A

Fig u m 3.2: Representación en bloques del funcionamiento del T imer 0.

Página | 62
3. Temporizadores

3.1.1 Utilización del i emporizador 0 sin interrupción


Se pretende activar y desactivar el LED D I del circuito de ia figura correspondiente a la
placa de PICDEM2+ con una cadencia de 1 segundo.

Vss VDD

4 7 00

PIC16F877A

OSC1______ O SC2

" P fli-5J 4MHZ


20pF —1— —1—20pF

Figura 3.3: C onexión del LED al PIC16F877A para encenderlo y apagarlo con el T imer O.

Solución:

En este ejercicio la cadencia de encendido y apagado del LED se conseguirá con el


temporizador 0 y sin utilizar interrupciones.

Configuración

La temporización o tiempo de desbordamiento del TimerO es Td = (256 - N tmro ) * P * Ti


donde
Ti es el período de los pulsos,
P es el predivisor,
N tmro es el valor con el que hay que cargar el temporizador 0.
Con un oscilador de Fosc = 4M Hz (Ti = 4/4M Hz = l microsegundo), la máxima
temporización que se alcanza con el TimerO es de 65,5 ms (con N tmro = 0 y P = 256). Para
poder llegar a temporizar 1 s hace falta que el TimerO se desborde varias veces. Si se
configura para que se desborde cada 50 ms, al cabo de 20 desbordamientos (controlados
con un contador cont) se tendrá la temporización de 1 segundo.

El TimerO se configura con el registro OPTION_REG (véase apéndice A2.2)

Con OPTION_REG = O b llO O O lll = 0xC7 el TimerO actúa como temporizador


(Ti = 4/4 MHz = 1 ps) y con predivisor P = 256.

Página | 63
Programación de microcontroladores PIC en lenguaje C

Para conseguir que el tiempo de desbordamiento sea de 50 ms hay que cargar TMRO con
N tmro = 60 .

Código fuente

//ARCHIVOS DE DEFINICIONES
# in c lu d e < h t c .h > / / in c lu im o s l i b r e r í a d e l m ic r o a u s a r
# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ
__ CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & L V P O F F ) ;

//PROGRAMA PRINCIPAL
void main(void){
unsigned char cont; / / C o n ta d o r de d e s b o r d a m ie n to d e TMRO
TRISB=0x00; / / C o n fig u r a e l PORTB como s a l i d a s
PORTB=0; // Todos l o s l e d a p a ga d o s
OPTION_REG=OxC7; //TMRO como t e m p o r iz a d o r con p r e d i v i s o r P=256
TMR0=60; / / P a ra qu e Td sea n 50ms
while(1){
if(T0IF){
T0IF=0; / / D e s a c t iv a r e l FLAG de TMRO
TMR0=60; / / R e c a r g a r TMRO
cont++; / / In c re m e n ta r c o n ta d o r de d e s b o rd a m ien to de TMRO
if(cont==20){ / / S i s e han l l e g a d o a 20 d e s b o r d a m ie n t o
// (1 seg u n d o )
PORTBbi ts.RB1 ~ P O R T B b its . RB1; //Cambia e s t a d o de RB1
cont=0; // R e i n i c i a c o n t a d o r de d e s b o r d a m ie n to s

Se puede observar el funcionamiento mediante el analizador lógico del simulador.


' i I331C An;l.:tr
lRJ7«PcW«n IiíD«rc- TnwBs:* Mcde
Stal o Ctrlti End [Ñ ^ l[ u « J C,c - | Ctori-, 1

¡ + j¡ _ SIS) M * |H |# |& |

FBI
1
L
50X000 100X00.0 15000000 xocococ rsxcnoo

F igura 3.4: Simulación del ejercicio 3.1.1.

3.1.2 Utilización del Temporizador 0 con interrupción


Muestra en el display de 7 segmentos (véase figura del ejercicio 2.2.1) los dígitos del 9 al 0
de manera indefinida. Los dígitos cambiarán con una cadencia de 2 segundos.

Solución:

La cadencia de cambio de los dígitos se conseguirá con el temporizador 0 y, en este caso, se


utilizarán interrupciones.

Página | 64
3. Temporizadores

Configuración

Con OPTION_REG = O b llO O O lll = 0xC7 el TimerO actúa como temporizador


(Ti = 4/4 MHz = 1 ps) y con predivisor P = 256.

Para conseguir que el tiempo de desbordamiento (interrupción) sea de 50 ms hay que


cargar TMRO con N TMro = 60.

Para conseguir la cadencia de 2 segundos será necesario un contador cont que cuente 40
interrupciones.

Código fuente
//ARCHIVOS DE DEFINICIONES
# in c lu d e < h t c .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
# in c lu d e " t i m e r s . h " / / In c lu im o s l i b r e r í a d e t im e r s
# d e fin e XTA LF R E Q 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ
CONFIG (WRT_OFF & WDTE OFF & PWRTE OFF & FOSC XT & L V P _ O F F );

//D EFINICIÓ N DE VARIABLES


/ / T a b la co n e l c ó d ig o de 7 s eg m en to s co m p le m en tad o p a r a l o s d í g i t o s d e l 0 a l 9.
/ / (ta m a ñ o b y t e )
u n s ig n e d c h a r c o d i g o ü = { 0 b l l 0 0 0 0 0 0 , O b l l l l l O O l , O blO lO O lO O , O b lO llO O O O ,O b lO O llO O l,
O b i0 0 1 0 0 1 0 ,O blO O O O O ll,O blllllO O O /O blO O O O O O O ,O b lO O llO O O };
u n s ig n e d c h a r x ; / / ín d ic e de l i s t a de c ó d ig o
u n s ig n e d c h a r c o n t ; / / C o n ta d o r d e d e s b o r d a m ie n t o d e TMRO

//PROGRAMA PRIN C IPA L


v o id m a in (v o id ){
ADCONl= 6 ; / / D e s a c t iv a PORTA como e n t r a d a s a n a l ó g i c a s
TR IS A = ObOOOOOOOO; / / C o n fig u r a e l PORTA como s a l i d a s
TR ISD =0 x00 ; / / C o n fig u r a e l PORTD como s a l i d a s
PO R T A sl; / / A c t i v a r d i s p l a y d e RAO
setu p tim e rO (R T C C _IN T E R N A L | R T C C _D IV 2 5 6 ) ; // TMRO como t e m p o r iz a d o r
/ / p r e d iv is o r = 2 5 6
s e t _ t im e r 0 (6 0 ); / / P a ra que T d s e a n 50ms
e i () ; / / H a b ilit a r in te r r u p c io n e s
T 0 IE = 1 ; / / H a b i l i t a r i n t e r r u p c i ó n d e TMRO
x=9; / / I n i c i o í n d i c e de l a l i s t a co n 9.
P O R T D = c o d ig o [x ]; //Saca e l v a l o r que c o r r e s p o n d e p o r e l p u e r t o D
w h ile ( 1 ) ; / / B u c le i n f i n i t o .

//INTERRUPCIÓN p o r Tim erO


s t a t i c v o id in te r r u p t i s r ( v o i d ) {
if(T 0 IF ){
T 0 IF = 0 ; / / D e s a c t iv a r e l FLAG d e l a i n t e r r u p c i ó n d e TMRO
s e t t i m e r O (6 0 ); / / R e c a r g a r TMRO
c o n t+ + ; / / In c r e m e n t a r c o n t a d o r de i n t e r r u p c i o n e s
i f (c o n t = = 4 0 ){
x --; / / D ecrem e n to í n d i c e l i s t a
P O R T D = c o d ig o [x ]; //Saca e l v a l o r que c o rr e s p o n d e p o r e l p u e r to D
if(x = = 0) {
x=10; / / S i g u i e n t e a l ú l t i m o de l a l i s t a
}
c o n t= 0 ; //Ponemos a c e r o e l c o n t a d o r de i n t e r r u p c io n e s
}
}
}

Página | 65
Programación da microconrroladoras PIC an langnaia C

observar el funcionamiento mediante el analizador lógico del simulador.


Se puede

j~ Oxraris

F igura 3.5: S imulación del ejercicio 3.1.2.

3.1.3 Utilización del Tem porizador 0 com o contador de pulsos


Realiza un contador ascendente de dos dígitos que se incremente cada vez que se accione
el pulsador conectado al puerto A (RA4) (figura 3.4). El valor del contador queda reflejado
en el encendido de los displays.

pi

Figura 3.6: Conexiones con el PIC16F877A del pulsador que introduce los pulsos externos al T imer 0
Y DE los displays de 7 segmentos que muestran los pulsos introducidos .

Solución:

En este ejercicio se utiliza el temporizador 0 como contador de los pulsos que entran por
RA4/T0CKI.
Con cada pulso se desborda el TimerO y se produce la interrupción que permite incrementar
la cuenta de los displays.

Página | 66
3. Temporizadores

Configuración

El TimerO se configura con el registro OPTION_REG (véase apéndice A2.2)

Con OPTION_REG = O b lllllO O O = 0xF8 el TimerO actúa como contador de los pulsos
externos que entran por TOCKI. El pre-divisor vale P = 1 ya que se asigna al Watchdog.
Cargando TMRO con N tmro = 255, el desbordamiento se producirá con cada pulso externo.

Código fuente

//ARCHIVOS DE DEFINICIONES
# i n c lu d e < h t c .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
# i n c lu d e " t i m e r s . h " / / In c lu im o s l i b r e r í a d e t im e r s
# i n c lu d e " p o r t s . h " / / In c lu im o s l i b r e r í a de p u e rto s
# d e fin e X TA LF R E Q 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ
CONFIG(WRT OFF & WDTE OFF PWRTE OFF & FOSC XT & LVP O F F );

//D EFIN IC IÓ N DE VARIABLES


/ / T a b la co n e l c ó d ig o de 7 s eg m en to s co m p lem en tad o / p a r a l o s d íg ito s del 0 al 9.
/ / (ta m a ñ o b y t e )

u n s ig n e d c h a r c o d i g o [1 = {0 x C 0 ,0 x F 9 ,0 x A 4 ,O x B O ,0x99, 0 x 9 2 ,0 x 8 2 ,0 x F 8 , 0 x 8 0 , 0 x 9 0 } ;
u n s ig n e d c h a r c o n t = 0 ; / / C o n ta d o r d e i n t e r r u p c i o n e s
u n s ig n e d c h a r C 2 =0,C 1 =0; / / L leva m o s l a c u e n ta d e 00 a 99

//PROGRAMA PRIN C IPA L


v o id m a in (v o id ){
s e t a l l d i g i t a l () ; / / D e s a c t iv a PORTA como e n t r a d a s a n a l ó g i c a s
T R IS A = 0 x l0 ; //PORTA con RA4 como e n tr a d a y r e s t o como s a l i d a s
TR ISD =0x00; / / T e r m in a le s PORTD como s a l i d a s

/ / C o n fig u r a r e l TIMERO como c o n t a d o r de p u ls o s e x t e r n o s p o r RA4 co n p r e d i v i s o r 1


s e t u p _ t im e r 0 (R T C C E X T F A L L | R T C C _ D IV 1 );
s e t t i m e r O (2 5 5 );

e i () ; / / H a b ilit a r in te r r u p c io n e s
T 0 IE = 1 ; / / H a b i l i t a r i n t e r r u p c i ó n d e TMRO

w h ile (1 ){ / / B u cle i n f i n i t o
/ / C ó d ig o p a r a m o s t r a r l o s d í g i t o s
RA 1=0;RA 0=1; / / A c tiv a m o s D IS PLA Y 0 y l o s o t r o s d e s a c t i v a d o s
PORTD = c o d i g o [ C l ] ; //M ostram os p o r p u e r to D l a s u n id a d e s
__ d e l a y m s( 5 ) ; / / R e ta rd o d e 5 ms p a r a e v i t a r e l p a r p a d e o

RA 1=1;RA 0=0; / / A c tiv a m o s D IS PLA Y 1 y l o s o t r o s d e s a c t i v a d o s


PORTD = c o d i g o [ C 2 ] ; //M ostram os p o r p u e r to D l a s d e c e n a s
__ d e l a y m s ( 5 ) ; / / R e ta r d o d e 5 ms p a r a e v i t a r e l p a rp a d e o
}
}
//INTERRUPCION p o r Tim erO
s t a t ic v o id in te rru p t i s r ( ) {
if(T 0 IF ){
T 0 IF = 0 ; // D e s a c tiv a m o s e l FLAG d e l a i n t e r r u p c i ó n de TMRO
s e t _ t im e r 0 (2 5 5 ) ; / / R ecarga m o s TMRO
C 1++; / / in c r e m e n to c o n t a d o r p u ls o s
if(C l= = 1 0 ){
C 1=0; / / R e s e te a m o s l a s u n id a d e s
C2 + + ; / / In crem en ta m o s l a s d e c e n a s

Página | 67
programación de microcontroladores PIC en lenguaje C

if(C 2 = = 1 0 ){ / / S i hemos l l e g a d o a 10 d e c e n a s
C2 = 0 ; / / R esetea m o s l a s d e c e n a s
}
}
}
}

Se puede observar el funcionamiento mediante el analizador lógico del'simulador donde se


ha configurado RA4 como entrada de estímulo externo en modo de pulso alto de duración
100 ciclos de instrucción.

F ig u r a 3.7: S imulación del ejercicio 3.1.3.

3.2. Temporizador 1
El Temporizador 1 es un módulo que contiene un temporizador/contador de 16 bits
accesible mediante dos registros de 8 bits (TMR1H:TMR1L). Cuando se desborda (pasando
de OxFFFF a 0x0000) se activa el flag de interrupción (TMR1IF). Esta interrupción se puede
habilitar o deshabilitar mediante el bit TMR1IE.

Dispone de tres modos de funcionamiento:


- Temporizador síncrono.
- Contador síncrono
- Contador asincrono

Página | 68
3. Temporizadores

8 bits 8 bits

E l tiempo que tarda en desbordarse el Tim erl es:

Temporización del Tim erl = Td = (6 5 5 3 6 - N tm r -i ) * P * T


N t m r i es el valor que hay que cargar en TM R1 en su conjunto al com enzar la
temporización, se descompondrá en un número binario de 16 bits los 8 bits altos se
cargarán en TM R1H y los 8 bits bajos en TM R 1L.
P el factorde división del pre-divisor (P = 1, 2, 4, 8).
T i el período de los pulsos internos o externos de entrada al pre-divisor.

Registros asociados ai Timerl


Reqistro Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 BitO Ver APENDICE 2
INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF A2.5
PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF A2.7
PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE A2.6
TMR1L Registro que contiene el bvte menos siqnificativodel reqistro TMR1 de 16 bits
TMR1H Reqistro que contiene el bvte más significativo del reqistro TMR1 de 16 bits
T1CON T1CKPS1 T1CKPSC T10SCEN T1SYNC# TMR1CS TMR10N A2.3

F ig u r a 3.8: R e p r e s e n t a c ió n en b l o q u e s d e l f u n c io n a m ie n t o d e l T im e r 1.

3.2.1 Utilización del Temporizado!- 1 sin interrupción


Muestra en el display de 7 segmentos (véase la figura del ejercicio 2.2.1) las cifras hexa-
decimales de 0 al F de manera indefinida. Las cifras cambiarán con una cadencia de 500 ms.

Solución:

La cadencia de cambio de 500 ms se conseguirá con una función de retardo de 500 ms. Dicha
función de retardo se realizará con el temporizador 1 sin utilizar las interrupciones del mismo.

Configuración

La temporización o tiempo de desbordamiento del Timerl es Td = (65536 - TMR1) * P * Ti donde

Página | 69
Programación de microcontroladores PIC en lenguaje C

T¡ es el período de los pulsos,


p es el pre-divisor,
TMR1 es el valor con el que hay que cargar el temporizador 1 (TMR1 = TMR1H //
TMR1L)

El Tím erl se configura con el registro T1CON (véase apéndice A2.3)

Con T1CON = 0x31 = ObOOllOOOl el Tim erl actúa como temporizador (Ti = 4/4 MHz = 1 ps)
y predivisor P = 8.

Para 500 ms, el valor con el que hay que cargar el temporizador 1 es:
TMR1 = 3036 = OxOBDC => TMR1H = OxOB y TMR1L = OxDC

Teniendo en cuenta estos valores se realiza la función de retardo DELAY500ms

Código fuente

//ARCHIVOS DE DEFINICIONES
# i n c lu d e < h t c . h> / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
# in c lu d e " t i m e r s . h " / / In c lu im o s l i b r e r í a de t im e r s
# in c lu d e " p o r t s . h " / / In c lu im o s l i b r e r í a de p u e r t o s
# d e f in e XTA LFREQ 4000000 / / O s c ila d o r I n t e r n o de 4MHZ

CONFIG(W RTOFF & WDTEOFF & PWRTEOFF & FO S C X T & L V P O F F ) ;

//DEFINICIÓN DE VARIABLES
/ / T a b la co n e l c ó d ig o d e 7 s eg m en to s co m plem en tad o p a r a l a s c ifr a s d e 0 a F.
/ / (tam año b y t e )

u n s ig n e d c h a r c o d i g o [ ] = {0 x C 0 ,0 x F 9 ,0 x A 4 , OxBO,0 x 9 9 ,0 x 9 2 ,0 x 8 2 ,0 x F 8 ,0x80,
0 x 9 0 ,0 x 8 8 ,0 x 8 3 ,0 x C 6 ,O x A l,0 x 8 6 ,0x8E>;
u n s ig n e d c h a r x ; / / í n d i c e d e l i s t a de c ó d ig o

// DEFINICION DE FUNCIONES
/ / F u n ció n de r e t a r d o de SOOmseg
v o i d D E L A Y 5 0 0 m s (void ){
s e t tim e r l(O x O B D C ); / / A ju s t a l o s r e g i s t r o s c o n t a d o r e s d e l T i m e r l
s e t u p _ t im e r l(T l_ O N | T 1 I N T | T 1 D I V 8 ) ; / / T im er 1 ON co n c o n t a d o r i n t e r n o
//y p r e d i v i s o r 8
w h ile (T M R 1 IF == 0) c o n t in u é ; / / E sp era m ie n t r a s no s e d e s b o r d e e l
/ / T im er 1
TM R1IF=0;
}
// PROGRAMA PRINCIPAL
v o id m a in (v o id ){
s e t a l l d i g i t a l () ; / / D e s a c t iv a PORTA como e n t r a d a s a n a l ó g i c a s
TR ISA = ObOOOOOOOO; / / C o n fig u r a e l PORTA como s a l i d a s
TRISD =0x00; / / C o n fig u r a e l PORTD como s a l i d a s
PO R T A=l; / / A c t i v a r d i s p l a y de RAO
x=0; / / ín d ic e de l a l i s t a p a r a l a p r im e r a c i f r a .
w h ile (1 ) {
P O R T D = c o d ig o [x ]; //Saca e l v a l o r que c o rr e s p o n d e p o r e l p u e r to D
D ELAY500m s(); / / E sp era 500 ms
X+ + ; / / In c re m e n ta í n d i c e de l a l i s t a d e c ó d i g o s

Página | 70
3. Temporizadores

if< x = = 1 6 ){ / / S i s e ha b a r r i d o to d a l a l i s t a
x =0 ; / / R e s e t e a r í n d i c e de l a l i s t a
}
}
}

Se puede observar el funcionamiento mediante el analizador lógico del simulador.

li«aF«ton Tiro*PC» Troce»:» Mcrt;


St*i u Carta-.'. Fnd . Ni». 11CÜT] C,c » Srfi? [Link].
+ > s m j ±i « '« - a .

roniD oco
- I — j r
1 i 1 1
100X0.0 7TXOOC0 00X00 4OXTO.0 WXttl.O 01X010 7UXCOO (0X000 ooctcoo (OOOCCi :

Figura 3.9: S imulación del ejercicio 3.2.1.

3.2.2 Utilización del Temporizador 1 con interrupción


Se pretende realizar un letrero con la palabra HOLA que se vaya desplazando de derecha a
izquierda con una cadencia de 1 segundo. Se quiere disponer de dos pulsadores: uno para
que el letrero empiece a desplazarse (Pl) y el otro (P2) para parar el letrero como se
muestra en la siguiente figura.

Figura 3.10: Conexiones del PIC16F877Aa los 4 displays ( multiplexados) del letrero
Y A LOS PULSADORES DE MARCHA Y PARADA.

Página | 71
p

Programación de microcontroladores PIC en lenguaje C

Solución:
Se utilizará el temporizador 1 con interrupciones para conseguir ia
e l temporizador 0 sio interropcionet para
activado cada displav para q u eco parpadee. ^ haV <H* m antener

Configuración

El Tim erl se configura con el registro T1CON (véase apéndice A2.3)

Con TlCON=0x31=0b00110001 el Tim erl actúa como temporizador (Ti = 4/4 MHz = 1 ps),
con predivisor P=8 y habilitado.

Como no se puede conseguir un tiempo de desbordamiento de 1 segundo, se calcula TMR1


para que sea de 500 ms y con 2 desbordamientos se tendrá 1 segundo. Entonces, para
500 ms, el valor con el que hay que cargar el temporizador 1 es:

TMR1 = 3036 = OxOBDC => TMR1H = OxOB y TMR1L = OxDC

Código fuente
//ARCHIVOS DE DEFINICIONES
# i n c lu d e < h t c . h> / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ
__ CONFIG(W RTOFF & WDTEOFF & PWRTEOFF & FO S C X T & L V P O F F ); / / C o n fig u r a c ió n
/ / d e l P IC

/ / V a r ia b le s g l o b a l e s p a r a qu e sea n a c c e s i b l e s en l a i n t e r r u p c i ó n
/ / T a b la con e l c ó d ig o 7 se gm e n to s com plem en tad o
u n s ig n e d c h a r D 4=0x89, D3=0xC0, D 2 = 0 x C 7 ,D l= 0 x 8 8 ; / / c ó d ig o 7 segm en t0 s d e H O L A
u n s ig n e d c h a r AUX; / / v a r ia b le a u x i l i a r p a ra l a r o t a c ió n d e l l e t r e r o ,
u n s ig n e d c h a r c o n t = 0 ; / / C o n ta d o r de i n t e r r u p c i o n e s
b i t ESTADO; / / F la g p a r a a c t i v a r o d e s a c t i v a r e l d e s p la z a m ie n t o
//del le t r e r o
//(MARCHA es ESTADO=l) y (PARADA es ESTADO=0)

//PROGRAMA PRINCIPAL
v o i d m a in ( ) {
ADCONl = ObOOOOOHO; / / D e s a c tiv a m o s PORTA como e n t r a d a s a n a l ó g i c a s
T R IS A = 0 x l0 ; //PORTA con RA4 como e n t r a d a y r e s t o como s a l i d a s
TRISB = 0 x 0 1 ; / / T e rm in a l RB0 como e n t r a d a
TRISD =0x00; / / T e r m in a le s PORTD como s a l i d a s

/ / C o n fig u r a c ió n d e l TIMER1 p a ra p r o d u c i r i n t e r r u p c i o n e s ca d a 500ms.


TMRlH=0x0B;
TMRlL=0xDC,
TlCON=Ox31, //TIMER1 t e m p o r iz a d o r T i = 1 m ic r o s e g , con P =8 y
/ / h a b ilita d o
G IE =1 ; / / In t e r r u p c io n e s G lo b a le s h a b i l i t a d a s
P E IE = 1 ; / / In t e r r u p c ió n p o r TMR1 h a b i l i t a d a
TMR1IE=1; / / In t e r r u p c ió n p o r TMR1 h a b i l i t a d a

Página | 72
3. Temporizadores

w h ile (1 ) {
i f ( R A 4 == 0 ) { //S e ha p r e s io n a d o l a MARCHA
ESTADO=l //Ponem os l e t r e r o en MARCHA
}
if(R B O == 0 ) { //S e ha p r e s io n a d o l a t e c l a de PARADA
ESTADO = 0; //Ponem os l e t r e r o en PARADA
D 4=0x89;
D3=0xC0;
D2=0xC7;
D l= 0 x 8 8 ; / / R es etea m o s e l l e t r e r o p a r a em p eza r HOLA
}
/ / C ó d ig o p a r a m o s t r a r l o s d í g i t o s
RA3 = 0 ; RA2 = 0 ; RAI = 0 ; RAO = 1 ; / / A c tiv a m o s D ISPLAY 0 y l o s o t r o s d e s a c t i v a d o s
PORTD = D I ; //M ostram os p o r p u e r to D l a l e t r a qu e h ay en D I

__ d e l a y m s ( 5 ) ; / / R e ta r d o de 5 ms p a r a e v i t a r e l p a rp a d e o

R A 3=0;R A 2=0;R A1 =1;R A O =0; / / A c tiv a m o s D ISPLAY 1 y l o s o t r o s d e s a c t i v a d o s


PORTD = D2; //M ostram os p o r p u e r to D l a l e t r a qu e h ay en D2

__ d e la y _ m s ( 5 ) ; / / R e ta rd o d e 5 ms p a r a e v i t a r e l p a rp a d e o

RA3 = 0 ; RA2 = 1 ; RAI = 0 ; RAO = 0; / / A c tiv a m o s D IS PLA Y 2 y l o s o t r o s d e s a c t i v a d o s


PORTD = D3; //M ostram os p o r p u e r to D l a l e t r a qu e h ay en D3

__ d e l a y m s ( 5 ) ; / / R e ta rd o d e 5 ms p a r a e v i t a r e l p a rp a d e o

RA3 = 1 ; RA2 = 0 ; RAI = 0 ; RAO = 0; / / A c tiv a m o s D ISPLAY 3 y l o s o t r o s d e s a c t i v a d o s


PORTD = D4; //M ostram os p o r p u e r to D l a l e t r a qu e h ay en D4

__ d e l a y m s ( 5 ) ; / / R e ta rd o de 5 ms p a r a e v i t a r e l p a rp a d e o

}
//INTERRUPCIÓN
s t a t i c v o id in te r r u p t i s r ( ) {
if(T M R 1 IF ){ / / S i l a i n t e r r u p c i ó n l a ha g e n e r a d o TMR1,
/ / e je c u ta m o s e l c ó d i g o
TMR11F= 0; / / D e s a c tiv a m o s e l FLAG d e l a i n t e r r u p c i ó n
//de TMRl
TMRlH=0x0B;
TMRlL=0xDC;
if(E S T A D O ){ / / S i e l l e t r e r o e s t á en m archa
co n t+ + ; // In crem en ta m o s l a c u e n t a de i n t e r r u p c i o n e s
i f ( c o n t == 2 ) { / / S i s e ha c o m p le ta d o e l segu n d o = 500ms * 2
/ / in te r r u p c io n e s
cont = 0 ; / / R es etea m o s l a c u e n ta d e i n t e r r u p c i o n e s
AUX = D4; // Rotam os l a s l e t r a s
D4 = D3;
D3 = D2;
D2 = DI?
D I = AUX;

Página | 73
Programación de microcontroladores PIC en lenguaje C

3.2.3 Utilización del Tem porizador 1 com o contador de pulsos


Se quiere que el led D I se encienda o se apague cada vez que el led DO se ha encendido y
apagado 30 veces. La cadencia de encendido y apagado del led DO será de 500 ms.

+5V

Figura 3.11: Conexiones del PIC16F877A. Los pulsos que salen por RBO (generados por T imer O)
son los pulsos externos que ENTRAN POR T1CKI AL TlMERl.

Solución:

Se utilizará el timerO para generar los pulsos que encienden y apagan el led DO. Se utilizará el
timerl como contador de los 30 pulsos generados por el timerO para encender o apagar el led DI.

Configuración

El TimerO se configura con el registro OPTIOI\l_REG (véase apéndice A2.2)


Con OPTION_REG = O b llO O O lll = 0xC7 el TimerO actúa como temporizador
(Ti = 4/4 MHz = 1 ps) y con predivisor P = 256.
Para conseguir que el tiempo de desbordamiento (interrupción) sea de 50 ms hay que
cargar TMRO con N = 60.
tmro

Con 10 desbordamientos o interrupciones (controladas por cont) se tendrán 500ms y se


cambiara RBO.
El Tim erl se configura con el registro T1CON (véase apéndice A2.3)
Con T1CON = 0x07 = 0b00000111 el Tim erl actúa como contador de pulsos externos que
entran porTICKI, con predivisor P=1 y habilitado.
Los pulsos externos que entran por T1CKI son los pulsos que salen por RBO producidos por
el TimerO y que son de 1 segundo de periodo.
Para que RB1 (DI) cambie cada 30 segundos, el Tim erl se tendrá desbordar con 30 pulsos
para ello hay que cargar el temporizador 1 con:

Página | 74
3. Temporizadores

TMR1 = 65536 - 30 = 65506 = 0xFFE2 => TMR1H = OxFF y TMR1L = 0xE2

Código fuente
//ARCHIVOS DE DEFINICIONES
# i n c l u d e < h t c .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u sa r
# in c lu d e " t im e r s .h " / / In c lu im o s l i b r e r í a d e t im e r s
# in c lu d e " p o r t s .h " / / In c lu im o s l i b r e r í a de p u e r to s
# d e fin e X T A L F R E Q 4000000 / / O s c ila d o r I n t e r n o de 4MHZ
__ CONFIG(WRT_OFF & W DTEOFF & PWRTE_OFF & FOSC XT & LVP O F F );

//D E F IN IC IÓ N DE VARIABLES
u n s ig n e d c h a r c o n t ; / / C o n ta d o r d e d e s b o r d a m ie n to de TMRO

//PROGRAMA P R IN C IP A L
v o id m a in (v o id ){
TR ISB = 0b00000000; / / C o n fig u r a e l PORTB como s a l i d a s
T R IS C = 0 x F F ; / / C o n fig u r a e l PORTC como e n t r a d a s
PORTB=0; / / T od os l o s l e d a p a ga d o s

/ / C o n fig u r a c ió n d e l TIMER0 p a r a p r o d u c i r i n t e r r u p c i o n e s c a d a 50 m s.
setu p _tim er0 (R T C C _IN T E R N A L | R T C C _D IV 2 5 6 ) ; //TIMER0 como t e m p o r iz a d o r
/ / con p r e d i v i s o r P=256
s e t t i m e r O (6 0 ); / / P a ra que Td sea n 50ms
e i () ; / / H a b ilit a r in te r r u p c io n e s
T 0 IE = 1 ; / / H a b i l i t a r i n t e r r u p c i ó n d e TMR0
T 0 IF = 0 ; / / D e s a c t iv a r e l FLAG de TMR0
/ / C o n fig u r a c ió n d e l TIMER1 p a r a p r o d u c i r i n t e r r u p c i o n e s c a d a 30 p u ls o s e x t e r n o s
s e ttim e r l(0 x F F E 2 );
s e t u p _ t im e r l(T l_ O N | T 1 _ E X T | T 1 _ D IV 1 ); //TIM ERl c o n t a d o r p u ls o s e x t e r n o s
/ / p o r T 1 C K I, co n P=1 y ON
P E IE = 1 ; / / H a b i l i t a r i n t e r r u p c i ó n de TMR1
TM R1IE=1; / / H a b i l i t a r i n t e r r u p c i ó n de TMR1
TM R 1IF =0; / / D e s a c t iv a r e l FLAG d e TMR1
w h ile (l); / / B u cle i n f i n i t o .
}
//INTERRUPCIÓN p o r Tim erO y t i m e r l
s t a t i c v o id in te r r u p t i s r ( v o i d ) {
i f ( T 0 I F && ! T M R 1 IF ){
T 0 IF = 0 ; / / D e s a c t iv a r e l FLAG de l a i n t e r r u p c i ó n de TMR0
TMR0=60; / / R e c a r g a r TMR0
c o n t+ + ; / / In c r e m e n ta r c o n t a d o r de i n t e r r u p c i o n e s
i f (c o n t = = 1 0 ) { //10 i n t e r r u p c i o n e s ca d a 50 ms da l u g a r a 500 ms
P O R T B b its . RB0 = -P O R T B b its.R B 0 ; //Cam bia e s t a d o de RB0
c o n t= 0 ; / / R e i n i c i a r c o n t a d o r d e d e s b o r d a m ie n to s
}
}
i f(T M R 1 IF == 1 ) {
TM R 1IF =0; / / D e s a c t iv a r e l FLAG de l a in t e r r u p c ió n de TMR1
s e t_ tim e r l(0 x F F E 2 ); / / R e c a r g a r TMR1
PO R T B b its.R B 1 = -P O R T B b its .R B 1 ; //Cambia e s t a d o de RB1
}

3.2.4 Utilización del Temporizador 1 con un oscilador externo


Se quiere que los LED se enciendan y apaguen cada 5 segundos. Empiezan encendidos D3-D0 y
apagados D2-D1. Después de 5 segundos se apagan D3-D0 y se encienden D2-D1 y así
sucesivamente.

Página | 75
Programación de microcontroladores PIC en lenguaje C

+5V

Figura 3.12: Conexiones con ee PIC16F877A del oscilador externo de 32.76 KHz para controlar el T imer I.

Solución:

Se utilizará el Tim erI para generar la temporización de 5 segundos. Se utilizará un oscilador


externo de 32.76 KHz y se emplearán interrupciones.

Configuración

El Tim erI se configura con el registro T1CON (véase apéndice A2.3)

Con T1CON = 0x3F = O b O O llllll el Tim erI actúa como contador de pulsos externos, con
predivisor P = 8 y habilitado. Los pulsos externos que entran son generados por el oscilador
externo de 32.76 KHz y cuyo periodo es de 30.52 ps.
Para que se desborde o se produzca interrupción cada 5 segundos hay que cargar el
temporizador 1 con:

TMRl = 65536----------- —--------- = 45061 = 0xB005 => TM1H = OxBO y TMR1L = 0x05
8* (1 / 32.76KHz)
Con cada interrupción se cambiarán los LED encendidos y apagados.

Código fuente

//ARCHIVOS DE DEFINICIONES
# in c lu d e < h tc .h > / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
ffd e fin e XTAL FREQ 4000000 / / O s c ila d o r I n t e r n o de 4MHZ
__ CONFIG(W RTOFF & WDTEOFF & PWRTE_OFF & FOSC_XT & L V P _O F F );

Página | 76
3. Temporizadores

//PROGRAMA P R IN C IP A L
v o id m a in (v o id ){
T R IS B = ObOOOOOOOO; / / C o n fig u r a e l PORTB como s a l i d a s
PORTB=0b00001001; / / E n c e n d id o s D3-D0 y a p a ga d o s D2-D1

/ / C o n fig u r a c ió n d e l TIMER1 p a r a p r o d u c i r i n t e r r u p c i o n e s ca d a 5 segu ndos


TM R lH =0xB 0;
T M R lL = 0 x 0 5 ;
TlC O N=O x3F; //TIMER1 c o n t a d o r p u ls o s e x t e r n o s g e n e r a d o s p o r o s c i l a d o r
/ / e x t e r n o de 3 2 .7 6 KH z, co n P =8 y h a b i l i t a d o
G IE = 1 ; / / H a b ilit a r in te r r u p c io n e s
P E IE = 1 ; / / H a b i l i t a r i n t e r r u p c i ó n de TMR1
TM R 1IE=1; / / H a b i l i t a r i n t e r r u p c i ó n de TMR1
TMR1IF= 0 ; / / D e s a c t iv a r e l FLAG de TMR1
w h ile ( 1) ; / / B u c le i n f i n i t o .
}
//INTERRUPCIÓN p o r T im e r l
s t a t ic v o id in te r r u p t i s r ( v o i d ) {
if(T M R 1 IF ){
TM R 1IF =0; / / D e s a c t iv a r e l FLAG d e l a i n t e r r u p c i ó n d e TMR1
TMRlH=0xB0; / / R e c a r g a r TMR1
TM R lL=0 x0 5 ;
PORTB = -PORTB; //Cam bia e s t a d o de l o s LED
}
}

Se puede observar el funcionamiento mediante el analizador lógico del simulador. Para ello
se ha definido un estímulo de tipo reloj por RCO con un tiempo de subida y bajada idéntico
correspondiente a aproximadamente un semiperiodo de la señal de 32.76 KHz.

Logic Analyzer = ¡_■ _!


Tngget Position Tngger PC = TimeBase Mode
Start • Center . End _ CK00002B Now Clear Cyc v Simple Channel:
_________________________ ___________ ____________
[+•&! 0.1®.! ^Halalal___________

RCO

RBO

RB1

RB2

RB3

0 .0 5 0 0 0 .0 1 0 0 0 0 .0 1 5 0 0 0 ,0 2 0 0 0 0 .0 2 5 0 0 0 .0 30000 0

Figura 3.13: S imulación del ejercicio 3.2.4.

Nota: Para acelerar la simulación se ha ajustado el contador del Timer 1 para una
cadencia de 5 ms.

Página | 77
Programación de microcontroladores PIC en lenguaje C

3.3. Temporizador 2

El temporizador 2 es un temporizador de 8 bits con predivisor, postdivisor y registro de


período. Usando el predivisor y postdivisor a sus valores máximos el tiempo necesario para
que se desborde es el mismo que el de un temporizador de 16 bits.

El temporizador 2 se usa también para establecer la base de tiempo cuando el módulo CCP
se utiliza para generar ondas PWM.

El postdivisor cuenta el número de veces que el registro TMR2 coincide con el registro PR2,
lo que ayuda a reducir la carga de la CPU.

8 b its

8 b its

El tiempo que tarda en desbordarse el Timer2 es:


Te m po rizaclón del Tim er2 = T d = P1 * (NPR2+1) * P2 * T

NPR2 el valor que hay que cargaren el registro PR2.


P1 el factor de división del pre-divisor (P1 =1,4,16).
P2 el factor de división del post-divisor(P =1,2 ,3 ,..., 16).
Ti el periodo de los pulsos internos de entrada al módulo (Ti = 4/Fosc = 4 * Tose)

R e g is tro s a s o c ia d o s al Tim er 2
Reoistro Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 BitO Ver APENDICE 2
INTCON GIE PEIE TOIE INTE RBIE TOIF INTF RBIF A2.5
PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF A2.7
PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE A2.6
TMR2 Registro de módulo de Timer2
T2CON |t OUTPS3| TOUTPS2 It OUTPS i It OUTPS cI TMR20N |t 2CKPS1 IT2CKPS0 A2.4
PR2 Reqistro de periodo de Timer2

F igura 3.14: Representación en bloques del funcionamiento del T imer 2.

Página | 78
3. Temporizadores

3.3.1 Utilización del Temporizador 2 sin interrupción


a) Programa el Timer2, sin interrupción, para obtener por RB3 una señal de 50 Hz. El Timer2
debe activar el flag TMR2IF cada milisegundo, siendo la frecuencia de oscilador principal de
4 MHz

b) Simula el funcionamiento del programa mediante el analizador lógico de MPLAB SIM

+5V

f = 50Hz

10ms
< -W
„ 20ms

F igura 3.15: O btener por el terminal RB3 una onda cuadrada de 50 Hz.

Solución:

Se utilizará el Timer2 para generar la temporización de 1 ms.

Configuración

La temporización o tiempo de desbordamiento del Timer2 es Td = P1*(NPR2 + 1) * P2 * Ti


donde
Ti es el período de los pulsos,
P1 es el predivisor,
P2 es el postdivisor
NPr2 es el valor con el que hay que cargar PR2

El Timer2 se configura con el registro T2CON (véase apéndice A2.4)


Con T2CON = ObOlOOllOl el Timer2 actúa como temporizador (Ti = 4/4 MHz = 1 ps), con
P1 = 4 y P2 = 10 y habilitado
Para Td = 1 ms, el valor con el que hay que cargar el PR2 es NPR2 = 24.

Página | 79
Programación de microcontroladores PIC en lenguaje C

La señal de 50 Hz tiene un período de 20 ms. El semiperiodo de ia señal será de 10 ms, es


decir, cada 10 desbordamientos de Timer2 (controlados por un contador x) se cambiará el
estado del bit en RB3.

Código fuente
//ARCHIVOS DE DEFINICIONES
#include<htc.h> //Incluimos librería del micro a usar
#define _XTAL_FREQ 4000000 / /Oscilador Interno de 4MHZ
CONFIG (WRT OFF & WDTEOFF & PW RTEOFF & FO S C X T & LVP OFF) ;

//DEFINICION DE VARIABLES
i n t XJ

//DEFINICION DE FUNCIONES
// F u n ció n d e 1 ms
v o i d D E L A Y lm s (v o id ){
w h ile (T M R 2 IF == 0 ) ¡ / / E s p e ra m ie n t r a s no s e d e s b o r d e e l T im e r 2
’ TMR2IF=0; / / D e s a c t iv a r e l FLAG de TMR2
}
//PROGRAMA PRIN C IPA L
v o id m a in (v o id ){
TR IS B =0x00; / / C o n fig u r a e l PORTB como s a l i d a s
PORTB=0; / / N i v e l b a j o RB3
T2C0N = O b O lO O llO l; //TMR2 co n P l= 4 y P2=10 y e n c e n d id o
PR2 = 24; / / C a rga p a r a 1 ms
w h ile (lí{
f o r ( x = 0 ;x < 1 0 ;x + + ){ / / E sp era d u r a n t e
D ELAYlm s( ) ; / / 1 0 ms
}
RB3 = -R B 3 ; //C am biar e s t a d o d e RB3
}
}

b) Para ver el funcionamiento se puede utilizar el Stopwatch del simulador con un


breakpoint. Se observa que el semiperiodo de la señal es 10.004 ms

También se puede observar el funcionamiento mediante el analizador lógico del simulador.


El período de la señal es de 20016 ciclos (20016 p s ).

Página | 80
3. Temporizadores

Figura 3.17: S imulación del ejercicio 3.3.1 (Logic A nalyzer).

3.3.2 Utilización del Temporizador 2 con interrupción


Se pretende realizar un cronómetro digital que cuente segundos y centésimas de segundo,
es decir, un cronómetro de 00.00 a 59.99 incrementándose en centésimas de segundo
(véase figura 3.18). Se quiere disponer de dos pulsadores: uno (Pl) para que funcione el
cronómetro y el otro (P2) para pararlo.
+5V

F igura 3.18: Conexiones del PIC16F877A a los 4 displays (multiplexados ) del cronómetro
Y A LOS PULSADORES DE MARCHA Y PARADA.

Solución:

Se utilizará el temporizador 2 con interrupciones para conseguir la cadencia de 10 ms


(centésima de segundo) que incremente el display 0 y los 5 ms que hay que mantener
activado cada display para que no parpadee.

Página | 81
Programación de microcontroladores PIC en lenguaje C

configuración

El Timer2 se configura con el registro T2C0N (véase apéndice A2.4)


Con T2C0N = ObOlOOllOl el Timer2 actúa como temporizador (Ti = 4/4MHz = 1 ps); con
P1 _ 4 y P2 = 10 y habilitado
Para Td = 5 ms, el valor con el que hay que cargar el PR2 es NPR2 = 124.

Con cada desbordamiento (interrupción) se activará un display y con cada dos


interrupciones se incrementará el display 0.

Código fuente
//ARCHIVOS DE DEFINICIONES
# in c lu d e < h t c . h> / / In c lu im o s l i b r e r i a d e l m ic r o a u s a r
# in c lu d e " t i m e r s . h " / / In c lu im o s l i b r e r í a de t im e r s
# d e f in e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ
__CONFIG(WRT_OFF & WDTE_OFF & P W R T E O F F & F O S C X T & L V P O F F ) ; //Configuración
/ / d e l P IC

/ / T a b la con e l c ó d ig o 7 se g m e n to s com p lem en tad o


u n s ig n e d c h a r c o d i g o [ ] = {0 x C 0 , 0 xF 9, 0 xA 4, OxBO,0 x 9 9 , 0 x 9 2 ,0 x 8 2 ,0 x F 8 ,0 x 8 0 , 0 x 9 0 } ;
/ / S in p u n to
u n s ig n e d c h a r c o d i g o l []= { 0 x 4 0 ,0 x 7 9 , 0 x 2 4 ,0 x 3 0 ,0 x 1 9 ,0 x 1 2 ,0 x 0 2 ,0 x 7 8 ,0 x 0 0 , 0 x 1 0 };
//Con p u n to

/ / V a r ia b le s g l o b a l e s p a r a qu e sea n a c c e s i b l e s en l a i n t e r r u p c i ó n
u n s ig n e d c h a r c o n t = 0 ; / / C o n ta d o r de i n t e r r u p c i o n e s
u n s ig n e d c h a r S 2=0, S 1=0, C2=0, C 1=0; / / L le v a m o s l a c u e n ta de 0 0 .0 0 a 5 9 .9 9
b i t ESTADO; / / F la g p a r a a c t i v a r o d e s a c t i v a r l a cu e n ta
//(MARCHA es ESTADO=l) y (PARADA e s ESTADO=0)
u n s ig n e d c h a r ROTADOR; / / M áscara con e l 1 qu e se r o t a p a r a a c tiv a r
/ / lo s d i s p l a y s .
u n s ig n e d c h a r DISPLAYS; / / C o n tie n e e l v a l o r d e l d i s p l a y qu e se a c t iv a
u n s ig n e d c h a r x ; / / d e f i n i c i ó n de una v a r i a b l e 16 b i t s s in
/ / s ig n o

# d e fin e ROTA I I ( x ) x = (x << 1) (x » 7) //M acro qu e r o t a un b i t a la


// iz q u ie r d a .

//PROGRAMA PRINCIPAL
v o id m a in (v o id ){
//CONFIGURACIÓN
ADCONl=0b00000110; / / D e s a c tiv a m o s PORTA como e n t r a d a s a n a l ó g i c a s
T R IS A = 0 x l0 ; //PORTA co n RA4 como e n t r a d a y r e s t o como s a l i d a s
TR IS B =0x01; / / T e rm in a l RB0 como e n t r a d a
TR ISD =0x00; / / T e r m in a le s PORTD como s a l i d a s
e i () ; / / In t e r r u p c io n e s G lo b a le s h a b i l i t a d a s
PEIEsl; / / I n t e r r u p c ió n p o r TMR2 h a b i l i t a d a
TMR2IE=1; / / In t e r r u p c ió n p o r TMR2 h a b i l i t a d a
s e tu p tim e r 2 (T 2 _ON¡T2_PRED_ DIV4|T2 POST D IV IO ) ; //TIMER2 co n P l= 4 y P2 = 10
/ / y e n c e n d id o
s e t t i m e r 2 (1 2 4 ); / / C arga p a ra 5 ms
ESTADO = 0; //Em pieza en PARADO e l c r o n ó m e tro
ROTADOR = 0x11; / /M áscara con 1 en e l b i t 0 y 1 en e l b i t 4.
DISPLAYS = 0;

Página | 82
3. Temporizadores

w h ile ( 1 )
{ if(RA4 == 0) //Se ha p r e s io n a d o l a MARCHA
{ ESTADO=l; //Ponemos e l c r o n o en MARCHA
S 2 = 0 ;S 1 = 0 ;C 2 = 0 ;C 1 = 0 ; / / R esetea m o s e l c r o n ó m e tro
}
if(R B O == 0) //Se ha p r e s io n a d o l a t e c l a de PARADA
{ ESTADO = 0; //Ponemos e l c r o n o en PARADA
}
/ / C ó d ig o p a r a m o s t r a r l o s d í g i t o s
D ISPLA YS = ROTADOR & OxOF
if(D IS P L A Y S = = 1 )
{RA3 = 0 ; RA2 = 0 ; RA1=0; RA0 = 1 ; //Se a c t i v a D ISPLAY 0 y l o s o t r o s
/ / d e s a c t iv a d o s
PORTD = c o d i g o [ C l ] ; //Se m u es tra p o r p u e rto D l a s c e n t é s im a s
//de segu ndo
}
if(D IS P L A Y S = = 2 )
{RA3 = 0 ; RA 2=0; RA1 = 1 ; RA0 = 0 ; //Se a c t i v a D ISPLAY 1 y l o s o t r o s
/ / d e s a c t iv a d o s
PORTD = c o d i g o [ C 2 ] ; //Se m u es tra p o r p u e r to D l a s d éc im a s
//de segu ndo
}
if(D IS P L A Y S = = 4 )
{R A 3 = 0 ; RA 2=1; RA1=0; RA0=0; //Se a c t i v a D ISPLAY 2 y l o s o t r o s
/ / d e s a c t iv a d o s
PORTD = c o d i g o l [ S I ] ; //Se m u es tra p o r p u e r to D l a s u n id a d e s
//de segu ndo
}
if(D IS P L A Y S = = 8 )
{R A 3 = 1 ; RA 2=0; RA1=0; RA0=0; //Se a c t i v a D ISPLAY 3 y l o s o t r o s
/ / d e s a c t iv a d o s
PORTD = c o d i g o [ S 2 ] ; //Se m u es tra p o r p u e r to D l a s d e c e n a s
//de segu ndo
}
>
}
//ATENCIÓN A LAS INTERRUPCIONES
s t a t ic v o id in te r r u p t i s r ( )
{
if(T M R 2 IF ){ //Comprueba s i e s l a i n t e r r u p c i ó n d e l TMR2
TM R 2IF=0; / / D e s a c t iv a e l FLAG d e l a i n t e r r u p c i ó n de TMR2
R O T A 1 I (ROTADOR); //Cada 5 ms r o t a l a m á sc a ra qu e a c t i v a l o s
/ / d is p la y s
if(E S T A D O ){ / / S i e l c r o n ó m e tr o e s t á en marcha
c o n t+ + ; / / In c r e m e n ta l a c u e n ta de i n t e r r u p c i o n e s
i f ( c o n t == 2 ) { //Comprueba s i han t r a n s c u r r i d o 2
/ / i n t e r r u p c i o n e s (1 0 ms)
cont = 0 ; / / R e s e te a l a c u e n ta d e i n t e r r u p c i o n e s
C1+ + ; / / In c r e m e n ta l a s c e n t é s im a s d e segu ndo
i f ( C l == 1 0 ) { / / S i han l l e g a d o a 10 c e n t é s im a s d e segu ndo
C1 = 0; / / R e s e te a l a s c e n t é s im a s d e segu ndo
C2 + + ; / / In c r e m e n ta l a s d éc im a s d e segu ndo
i f ( C 2 == 1 0 ) { / / S i han l l e g a d o a 10 d éc im a s de segu ndo
C2 = 0; / / R e s e te a l a s d éc im a s d e segu ndo
S1 + + ; / / In c r e m e n ta l a s u n id a d e s de segu ndo
i f (S I == 1 0 ) { / / S i han l l e g a d o a 10 u n id a d e s
//de segu ndo
SI = 0 ; / / R e s e te a l a s u n id a d e s segu ndo

Página | 83
Programación de microcontroladores PIC en lenguaje C

S2 + + ; / / In c r e m e n ta l a s d e c e n a s d e
/ / seg u n d o
if(S 2 == 6 ) { / / S i han l l e g a d o a 6 d e c e n a s
/ / d e seg u n d o
S2 = 0 ; / / R e s e te a l a s d e c e n a s de
// s egun do
}
}
}
}
}
}
}
}

3.4. WATCHDOG
\ La función del Watchdog es impedir que el sistema entre en un bucle infinito, provocando
un RESET cuando esto sucede. El Watchdog es un oscilador RC interno independiente del
oscilador principal del microcontrolador, por lo que funciona incluso cuando se detiene la
ejecución mediante la instrucción SLEEP.

Se habilita/deshabilita mediante el bit de configuración WDTE. No puede ser deshabilitado


por software. Poniendo el bit PSA a "1" se habilita el postdivisor del watchdog, mediante el
cual se pueden establecer períodos entre 0.018 y 2.30 segundos.

Cuando el Watchdog se desborda, se resetea el microcontrolador, por lo que antes de que


esto suceda se debe borrar mediante la instrucción CLRWDT.

Figura 3.19: Representación en bloques del funcionamiento del W atchdog.

Página | 84
3. Temporizadores

3.4.1 Uso de TIMER 0, TIMER 1 y WATCHDOG


Se desea realizar un programa que, utilizando el pulsador conectado a RA4 y los LED
conectados a RBO, RB1, RB2 y RB3 (véase figura 3.20) haga lo siguiente:
Al principio, aparecen todos los led apagados y así continúan hasta que se actúa sobre el
pulsador, en ese momento se encienden todos los led y se produce una intermitencia de
manera que cada 0,5 s los LED conectados a RB3 y RB2 se encienden y los LED conectados a
RB1 y RBO se apagan y esto durante un total de 10 s, al cabo de los cuales se retorna al
estado inicial.

+5V

Figura 3.20: Conexiones con el PIC16F877A de los LEDs y pulsador necesario.

Solución:

Se temporizan los 0,5 s de parpadeo con el TIMER 0 y un contador CONTO. Se configura el


TIMER0 como temporizador (contador de pulsos del oscilador de 4 MHz), con un pre-divisor
de 256 y se carga con NTMR0 = 60 para obtener el desbordamiento o interrupción al cabo
de 50 ms. Cargando un contador CONTO con 10 que se decrementa con cada interrupción,
al cabo de 500 ms = 0,5 s valdrá 0.

Se temporizan los 10 s de funcionamiento con el TIMER 1 y un contador CONT1. Se


configura el TIMER 1 como temporizador (contador de pulsos del oscilador de 4 MHz), con
un predivisor de 8 y se carga con NTMR1 = 3036 = BDCh para obtener el desbordamiento o
interrupción al cabo de 500 ms. Cargando un contador CONT1 con 20 y que se decrementa
con cada interrupción, al cabo de 10 s valdrá 0.

La vuelta al estado inicial se consigue dejando que el Watchdog se desborde (al cabo de
18 ms ya que el postdivisor está asignado al TIMER 0) y resetee al microcontrolador.

Página | 85
Programación de microcontroladores PIC en lenguaje C

rriHiflo fuente

#include<htc.h> / / In c lu im o s l i b r e r í a d e l m ic r o
td e fin e XTA LFREQ 4000000 / / O s c ila d o r I n t e r n o de 4MHZ
CONFIG(WRT_OFF WDTE_ON & PWRTE_OFF &r FOSC XT & LVP OFF) ;

//D EFIN IC IÓ N DE VARIABLES


u n s ig n e d c h a r c o n tO ; / / C o n ta d o r d e d e s b o r d a m ie n t o d e TMR0
u n s ig n e d c h a r c o n t l ; / / C o n ta d o r d e d e s b o r d a m ie n t o d e TMR1
u n s ig n e d c h a r MASCARA; //M á sca ra d e l e d s e n c e n d id o s y a p a g a d o s

//PROGRAMA PR IN C IPA L
v o id m a in (v o id ){
CLRWDT( ) ; / / R e s e t d e l W atch dog
TRISB = ObOOOOOOOO; / / C o n fig u r a e l PORTB como s a l i d a s
PORTB= 0x00; / / T o d o s l o s l e d a p a ga d o s

i f ( R A 4 == 0) { //S e ha p r e s io n a d o l a MARCHA
/ / C o n fig u r a c ió n d e l TIMER 0 p a r a p r o d u c i r i n t e r r u p c i o n e s ca d a 50 m s.
OPTION_REG=OxC7; //TIMER0 como t e m p o r iz a d o r con p r e d i v i s o r P=256
G IE = 1 ; / / H a b ilit a r in te r r u p c io n e s
T 0 IE = 1 ; / / H a b i l i t a r i n t e r r u p c i ó n d e TMR0
T 0 IF = 0 ; / / D e s a c t iv a r e l FLAG de TMR0
/ / C o n fig u r a c ió n d e l TIMER1 p a r a p r o d u c i r i n t e r r u p c i o n e s ca d a 500 ms
TlCON=0x3 0; / / C o n fig u r a r TIMER 1 como t e m p o r iz a d o r , co n
//P =8 y p a ra d o
P E IE = 1 ; / / H a b i l i t a r i n t e r r u p c i ó n d e TMR1
TMR1IE=1; / / H a b i l i t a r i n t e r r u p c i ó n d e TMR1
TM R1IF=0; / / D e s a c t iv a r e l FLAG d e TMR1
TMR0=60; // Para que Td de TMR0 sean 50ms y em piece e l TMR0
TMRlH=0x0B; / / P a ra qu e Td d e T im e r 1 sea n 500 m s.
TMRlL=0xDC;
TMR10N=1; / / A c t iv a d o e l TIMER 1
PORTB=0xFF; // T o d o s l o s L ed s e n c e n d id o s .
MASCARA^ O b llO O O O ll; //RB3-RB2 a p a ga d o s y RB1-RB0 e n c e n d id o s .
w h ile { 1 ) {
CLRWDT( ) ; / / R e s e t d e l W atch dog
}
}
}
//INTERRUPCIÓN p o r Tim erO y t i m e r l
s t a t i c v o id in te r r u p t i s r ( v o i d ) {
if(T 0 IF ! T M R 1 IF ){
T 0 IF = 0 ; / / D e s a c t iv a r e l FLAG de l a i n t e r r u p c ió n de TMR0
TMR0=60; / / R e c a r g a r TMR0
c o n t 0 ++; / / In c r e m e n ta r c o n t a d o r de i n t e r r u p c i o n e s d e
/ / T im er 0.
i f ( c o n t 0 == 1 0 ) { //10 i n t e r r u p c i o n e s ca d a 50 ms da l u g a r a
//500 ms
MASCARA = -MASCARA;
PORTB = MASCARA; //Cam bia e s t a d o d e RB0
c o n t0=0 ; / / R e i n i c i a r c o n t a d o r de d e s b o r d a m ie n t o s
}
}
if(T M R 1 IF == 1 ) {
TM R1IF=0; / / D e s a c t iv a r e l FLAG de l a i n t e r r u p c i ó n de TMR1
TMRlH=0x0B; / / R e c a r g a r TMR1
TMRlL=0xDC;
c o n t l+ + ; / / In crem en ta r c o n ta d o r de i n t e r r u p c io n e s de T im e r 1.
if(c o n tl= = 20) { //20 i n t e r r u p c i o n e s ca d a 500 ms da l u g a r a lO s
TMR10N=0; / / D e s a c t iv a r e l TIMER

Página | 86
3. Temporizadores

G IE = 0 ; / / D e s h a b ilita r in te r r u p c io n e s
w h ile (l); / / B u c le i n f i n i t o

//Como y a t r a s c u r r i e r o n l o s 10 s e g u n d o s , n os quedamos en e s t e b u c le i n f i n i t o
//sin r e s e t e a r e l W a tch d o g h a s ta que d e s b o r d e y r e i n i c i e e l m i c r o c o n t r o l a d o r .
//Tras 18 m seg ( v a l o r t í p i c o ) e l m ic ro se r e s e t e a r á p o r d esborda m ien to d e l Watchdog
}
}
}
Comprobamos el funcionamiento mediante el cronómetro del simulador:
Stopwatch : =, r s

Stopwatch Total Simulated


jSynchj Instiuction Cyclec 10000686 10000686

[Zeto 1,me ,Se(:s) 10 000686 10.000686

Pioceisor Ffequertcy (MHz ] 4 000000

F igura 3.21: S imulación del ejercicio 3.4.1 (stopwatch ).

Página | 87
j
4. Módulos de Captura, Comparación y
Modulación de Anchura de Pulsos (PWM)
4.1. Módulo Captura
4.2. Módulo Comparación
4.3. Módulo PWM

El microcontrolador PIC16F877A contiene dos módulos de captura/comparación y


modulación de anchura de pulsos. Estos módulos denominados CCP1 y CCP2 funcionan de
forma idéntica con la única excepción del evento especial asociado al funcionamiento en
modo comparación. Ambos módulos tienen asociados dos registros de 8 bits CCPRLx (bit
bajo) y CCPRHx (bit alto), un registro para su configuración CCPRxCON (A2.9), los bits que
permiten a los módulos trabajar mediante interrupciones y el terminal asociado al módulo
RC1 para el módulo CCP2 y RC2 para el módulo CCP1.

Figura 4.1: Los módulos ccp del microconitroiador PIC16F877A.

Página | 89
programación de microcontroladores PIC en lenguaje C

4 .1 . Módulo Captura
Los módulos CCP trabajando en modo captura permiten que al producirse un evento se
almacene el valor de 16 bits del contador asociado al Timer 1 en los registros CCPRxL y
CCPRxH del módulo CCPx. Los eventos a detectar estarán relacionados con la señal en el
terminal de entrada del módulo CCPx a elegir entre un flanco de bajada, un flanco de
subida, cuatro flancos de subida o 16 flancos de subida. El valor almacenado en los registros
del módulo permanecerá hasta que se produzca un nuevo evento.
MÓDULO CCP EN MODO CAPTURA

(pulsos externos)

Figura 4.2: Representación en bloques del funcionamiento del módulo captura .

4.1.1. Cálculo del período de una señal


Se desea diseñar un sistema que calcule el período de una señal periódica, de período
desconocido. Para ello se deberá realizar un programa que emplee el módulo de captura
del PIC16F877A funcionando a 4 MHz. El cálculo del período se deberá realizar cada vez que
se pulse un interruptor conectado al terminal RBO del microcontrolador y se almacenará en
una variable de 16 bits.

a) Indica las conexiones necesarias con el microcontrolador.


b) Realiza el programa para el cálculo del período.
c) Simula el funcionamiento del programa utilizando MPLABSIM.
d) ¿Cuál es la resolución del sistema?
e) Indica las frecuencias máximas y mínimas que pueden ser obtenidas con dicho sistema.

Solución:

a) Para el funcionamiento del microcontrolador es necesario conectar correctamente las


entradas V dd y V ss a +5V y OV respectivamente. Además, será necesario conectar el

Página | 90
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

oscilador, en este caso un oscilador de cristal a 4 MHz a las entradas OSC1 y OSC2 tal y
como aparece en la figura inferior.
El Interruptor se conectará a una entrada digital del mlcrocontrolador. En este caso se ha
utilizado la entrada RBO, que se corresponde con la entrada de Interrupción externa del
microcontrolador, lo que permitirá al programa funcionar en modo interrupción en caso de ser
necesario.
La utilización del módulo captura Implica que la señal periódica deberá estar conectada a
uno de los terminales asociados a estos módulos. En este caso se utilizará el módulo CCP1
por lo que la señal de entrada se conectará al terminal RC2.

Figura 4.3: Esquema de conexiones del PIC16F877A para determinar el periodo de una señal.

b) Para la determinación del período de la señal se capturará el valor del TIMER1 entre dos
flancos de subida consecutivos (también se puede realizar la captura en los flancos de
bajada). Así, conocido el valor de cada incremento del TIMER1 y los valores capturados para
cada uno de los flancos consecutivos se puede obtener el tiempo transcurrido en un
periodo T de la señal.

Configuración

El módulo CCP se configurará en modo captura para la detección de flancos de subida con
predlvisor 1, lo que permitirá la detección de cada uno de los flancos de la señal de entrada
por RC2.

El Timer 1 asociado al modo captura del módulo CCP se configura como temporlzador con
predlvisor 1 por lo que se incrementará cada 4 ciclos de reloj (1 ciclo de Instrucción), es
decir, cada mlcrosegundo.

Página | 91
Programación de microcontroladores PIC en lenguaje C

código fuente

# in c lu d e < h tc .h >
# in c lu d e < s t d i o . h >
# in c lu d e " c c p . h "
# in c lu d e " t i m e r s . h "

C O N F IG (FOSC HS & WDTE_OFF & LVP__OFF & PWRTE_ON) ;


j d e f i n e _XTAL_FREQ 4000000

t y p e d e f u n ió n {
u n s ig n e d c h a r b y t e s [ 2 ] ;
u n s ig n e d i n t e n t e r o ; } u b y t e 2 ;

u b y te 2 P e r i o d o l , P e r i o d o 2 ;

v o id C a p tu r a (v o id );

v o id m a in (v o id ){
T R IS B b it s .T R IS B 0 = 1 ; //RB0 c o n f i g u r a d o como e n t r a d a
T R I S C b it s . T R IS C 2 = 1 ; / /RC2 c o n f i g u r a d o como e n t r a d a
d i(); / / D e s h a b ilita r la s in te r r u p c io n e s
w h ile (1 ){
w h i l e (PORTBbits .RB 0==0) CapturaO; //Rea l i z a r la ca p t u r a m i e n t r a s
//RB0 no p u ls a d o
}
}
v o id C a p tu r a (v o id ){
s e tu p c c p l(C C P _ O F F ); / / R e s e t e a e l m ódu lo CCP1
s e t u p t im e r l(T 1 _ I N T | T 1 _ D I V 1 | T 1 _ 0 F F ) ; / / C o n fig u r a r e l T i m e r l como tem p,
/ / p r e d = l, d e t e n i d o
s e t _ t i m e r l (0 x 0 0 ); / /P on er a c e r o e l c o n ta d o r d e l T im e r l
P I R l b i t s . C C P1IF =0; / / P o n e r a c e r o e l f l a g de c a p t u r a
s e tu p _c c p l(C C P _C A P T Ü R E _ R E ); //Modo c a p t u r a co n f l a n c o d e s u b id a
s ta r t_ tim e r l( ) ; / / A rra n c a r e l T im e r l
w h ile (P IR lb its .C C P 1 IF = = 0 ); //C om probar s i ha l l e g a d o un f l a n c o
P e r io d o l. e n te r o = g e t_ c c p l(v a lu é ); / / C o p ia e l v a l o r d e l a c a p t u r a
P I R l b i t s . C C P1IF=0; / / B a ja e l f l a g d e c a p t u r a
w h ile (P IR lb its .C C P 1 IF = = 0 ); / / co m p rob a r s i ha l l e g a d o un n u e vo
/ / fla n c o
P e r io d o 2 . e n t e r o = g e t _ c c p l ( v a l u é ) ; / / C o p ia e l v a l o r d e l a c a p t u r a
P e r io d o l. e n te r o = P e r io d o 2 . e n t e r o - P e r i o d o l . e n t e r o ; / / c a lc u la l a d i f e r e n c i a
s e tu p c c p l(C C P OFF) ; / / R e s e t e a e l m ó du lo CCP1
s to p t i m e r l ( ) ; / / D e t ie n e e l T i m e r l
p r i n t f ( "P e r io d o = % d m ic r o s e g u n d o s \ n " , P e r i o d o l . e n t e r o ) ; / / M u estra e l p e r i o d o
}
v o i d p u t c h (u n s ig n e d c h a r b y t e ) {
TXSTA=0x2 6;
//RCSTA|=0x80; //
R C S T A b its . SPEN=1;
TXREG=byte;
w h i l e ( ! T X I F )c o nti n u é ;
T X IF = 0 ;
>

c) Para la simulación del programa del apartado b) será necesario seleccionar la


herramienta MPLABSIM del menú debugger y ajustar la frecuencia del oscilador a 4MHz
(menú debugger/ settings).

Página | 92
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

Debugger ] Programmer Tools Configure Wmdow Help


SelectTool ► None
Clear Memory ► 1 Proteus VSM
Run F9 2 MPLAB ICD 2
Anímate 3 PICkit 3
Halt F5 4 MPLABICE 4000 ____________
StepInto F7 V 5 MPLAB SIM SimulatorSettings
Step Over F3 6 MPLAB ICE 2000
CodeCoverage / Rsatnv? Lúdete: ".
l.—* 2
Step Out Ose/ Trace BreakOpóons ! SbtaJM Uatí 10
Reset ► 3 Starter Kit on Board Proce::or Frequency Umtr
9 PICkit 2
Breakpoints... 10 MPLAB ICD3 4 ; KHr
StopWatch 11 PIC32 Starter Kit H2
Complex Breakpoints 12 Starter Kits TraceOpborts
Stimulus ► 13 Licensed Debugger TraceAil BufferSire (1K•455SCK1
Profile dJ BreakonTraceEiifer Fui 64 3 rb»
M5ne:
Clear Cede Coverage
Refresh PM lió n .

Settings... ! Aceptar [ Cancela.*

F ig u ra 4.4: Configuración de MPLAB SIM para simular el ejercicio 4.1.1.

La generación de las señales de entrada se realizará mediante el menú debugger/ Stimulus


/ New Workbook donde se creará una señal periódica de tipo dock Stimulus por RC2 y una
señal asincrona que simulará el pulsador conectado a RBO.

fVi/srn Auan WtSh / Msüej»

A<í.ancí^ ►•erro.* 1l'eJc'fKC'-i '.e? t

Figura 4.5: Configuración de los estímulos externos para simular el ejercicio 4.1.1.

Si se ajusta una señal de entrada con período 1 ms a la entrada de RC2 se obtiene que tras
activar el pulsador RBO se ha guardado en la variable Periodol el valor 0x03E8 (1000 en
decimal) que es el período de la señal en microsegundos.
Una vez ejecutado el programa se pueden observar las señales en RBO y RC2 mediante el
analizador lógico (menú View/Logic Analyzer), el mensaje que indica el período en la
pestaña SIM U artl de la ventana output y el valor de la variable en la ventana Watch (menú
ViewlWatch).

Página | 93
Programación de microcontroladores PIC en lenguaje C

Logic Analyzer Q E

Ruild VersiónControl FindmFiles MPLABSIM SIM ^ ------------


jPenodo=100G mlcrosegundos Watch 1 ■=> í 13 1M3»1
^AddSFR ADCONO v Add Symbol
Symbol llame | Decimal
3 Perio d o l {X ;' •

nnuuuirjui
-E bytes
entero

Watch 1 Walch 2 Walch 3 Walch 4


—i—i—r- “i i i— i— i— i— i— r~
35000.0 55000.0 60000.0

Figura 4.6: S imulación del ejercicio 4.1.1.

d) Dado que el período se calcula según los Incrementos del TIMER1 y el TIMER1 está
configurado para incrementarse cada ps, la resolución del sistema será de ± lp s .

e) Las frecuencias máximas y mínimas del sistema vendrán determinadas por el intervalo de
tiempo almacenado en la variable perlodo2 que se corresponden con los incrementos en
mlcrosegundos capturados del TIM ERl. Así pues, los valores mínimo (0x0000) y máximo
(OxFFFF) corresponderán a las frecuencias de 1 MHz y 15.259 Hz respectivamente.

Modifica el programa del apartado b) para que funcione mediante las interrupciones
asociadas a RBO y al módulo CAPTURA.
¿Sería posible modificar el programa para mejorar la resolución del sistema? Indica cómo,
en caso de ser posible.
Indica qué modificaciones habría que introducir en el programa para que el sistema
pudiera capturar frecuencias menores a las indicadas en el apartado e).

4.1.2. Medidor de distancias


Se ha desarrollado un sistema digital portátil de medición de distancias destinado a uso
inmobiliario. Para medir distancias (figura 4.7), el sistema emitirá un tono de ultrasonidos
(f > 20 KHz) a través un emisor E; esta señal rebotará en la pared opuesta cuya separación
se desea medir y será detectada por el sistema a través del receptor R. Calculando el tiempo
que tarda la onda en su viaje de ida y vuelta, y teniendo en cuenta que la velocidad del
sonido en el aire (a 20 °C es aproximadamente 340 m/s), el sistema puede estimar la
distancia entre ambas paredes.

Página | 94
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

F igura 4.7: F uncionamiento del sistema medidor de distancias del ejercicio 4.1.2.

Para la ¡mplementación de este sistema (figura 4.8) se emplea un PIC16F877A, en concreto


su módulo CCP1 funcionando en modo captura.
Cuando se pulsa el pulsador P el emisor emite el tono y a la vez empieza a funcionar el
Tim erl del PIC. Cuando el receptor recibe el tono, genera un impulso que se aplica al
terminal CCP1 del módulo CCP1 y se captura el valor del Timerl.

JUUUL

ju iiiT L

Figura 4.8: C onexiones del sistema medidor de distancias del ejercicio 4.1.2 con el microcontrolador .

A continuación, se muestra el listado del programa que controla el sistema de medición.

Código fuente

# in c lu d e < h t c .h >
# i n c lu d e < s td io .h >

Página | 95
Programación de microcontroladores PIC en lenguaje C

CONFIG(FOSC_HS & WDTE_OFF & L V P O F F & PWRTE_ON) ;


# d e fin e XTA LF R E Q 4000000

t y p e d e f u n ió n {
u n s ig n e d c h a r b y t e s [ 2 ] ;
u n s ig n e d i n t e n t e r o ; } u b y t e 2 ;

u b y te 2 N;

v o i d C a p t u r a (v o id ) ;

v o id m a in (v o id ){

TMR1H=0; / / B o rra r lo s c o n ta d o r e s d e l T im e r l
TMR1L=0;
TlCON=0x20; / / C o n fig u r a r e l T i m e r l
CCP1CON=0; / / R e s e t e a r e l m ódu lo CCP1
TRISA=0X10; / / C o n fig u r a r RA4 como e n t r a d a
TRISCbits.TRISC2 = 1 ; / / C o n fig u r a r RC2 como e n t r a d a
PIElbits.TMR1IE=0; / / I n h a b i l i t a r i n t e r r u p c i ó n d e l T im e r l
PIElbits.CCP1IE=0 ; / / I n h a b i l i t a r i n t e r r u p c i ó n d e l m ódu lo CCP1.
PIR1=0; / / P o n e r a 0 l a s b a n d e ra s ( f l a g s ) d e i n t e r r u p c i ó n .
CCP1CON=OX04; / / C o n fig u r a r e l m ódu lo CCP1 en modo c a p t u r a , f l a n c o
//de b a ja d a en RC2
while(PORTAbits.RA4==1) / / E s p e r a r a qu e b a j e RA4
TICONbits.TMR10N=1; / / I n i c i a r e l c o n t e o d e l TMR1
Captura();
}
v o id C a p tu r a (v o id ){
P I R l b i t s . C C P 1 IF = 0 ; / / P o n e r a 0 e l i n d i c a d o r de c a p t u r a .
w h i l e ( P I R l b i t s . C C P 1 I F = = 0) ; / / ¿C C P1IF = 1?
P I R l b i t s . C C P 1 IF = 0 ; / / p o n e r a 0 e l i n d i c a d o r de c a p t u r a
N . b y t e s [ 0 ] =CCPR1L; / / g u a rd a r e l v a l o r c a p tu r a d o en NH y N L.
N . b y t e s [ 1 ] =CCPR1H;
p r i n t f ( "N=%d, d is t a n c i a = % 5 . 3 f
m \n ", N . e n t e r o , 4 * ( f l o a t ) N . e n t e r o *0 0 0 0 0 0 1 *3 4 0 / 2 );
}

v o i d p u t c h (u n s ig n e d c h a r b y t e )
{
TXSTA=0x26;
//RCSTA|=0x80; //
R C S T A b its . SPEN=1;
TXREG =byte;
w h i l e ( ! T X I F )c o n t in u é ;
T X IF = 0 ;
>

Se pide:

a) Calcula la distancia entre las paredes si al final de la captura se tiene en N el valor 40E2h
b) Calcula la máxima distancia que se podrá medir con dicho sistema.

Solución:

a) Calcula la distancia entre las paredes si al final de la captura se tiene en N el valor 40E2h

Página | 96
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

El Tim erl empieza con sus registros a cero, con predivisor P = 4 y como temporizador cuenta
impulsos de duración Ti = 4/Fosc = 4/4 MHz = 1 ps.

La captura se hace con el primer impulso que entra por RC2, luego el tiempo empleado por el
tono en recorrer 2 veces la longitud L es:
Tiempo = N * P * Ti = 40E2h * 4 * lp s = 66440 ps
Luego:
2L = velocidad del sonido * Tiempo => 2L = 340 m/s * 66,44 ms => L = 11,29 m

b) Calcula la máxima distancia que se podrá medir.


b.l) Si consideramos la máxima cuenta N = FFFFh tenemos:
Tiempo = N * P * Ti = FFFFh * 4 * 1 ps = 262140 ps
2L = velocidad del sonido * Tiempo => 2L = 340 m/s * 262,14 ms => L = 44,56 m
b.2) Si consideramos la máxima cuenta N = FFFFh y además configuramos el predivisor de
Tim erl con el mayor valor P = 8 tenemos:
Tiempo = N * P * Ti = FFFFh * 8 * 1 ps = 524280 ps
2L = velocidad del sonido * Tiempo => 2L = 340 m/s * 524,28 ms => L = 89,12 m

4.1.3. Medidor de anchura de pulsos


Se pide implementar un medidor de distancias basado en un sistema microcontrolador
PIC16F877A trabajando a 4 MHz. Especificaciones del sistema:
- El cálculo de la distancia se realizará mediante la activación de un pulsador.
- Para la obtención de la distancia se utilizará el módulo de captura del microcontrolador
funcionando en modo interrupción combinado con el dispositivo HC-SR04.
- La distancia calculada en cm se guardará en una variable de 16 bits.
El módulo de ultrasonidos HC-SR04 ([Link] se utiliza
para la medición de distancias entre 2 cm y 400 cm y se basa en la combinación de un
emisor (altavoz) y un receptor (micrófono). Dicho dispositivo cuenta con cuatro conexiones,
como se muestra en la figura inferior izquierda.

Trigger
SkWH:

Tx

Echo

Figura 4.9: R epresentación esquemática y funcionamiento del sensor de ultrasonidos HC-SR04.

Página | 97
Programación de microcontroladores PIC en lenguaje C

El funcionamiento, como se observa en la figura superior derecha, consiste en tres sencillos


pasos.
1. Activación de la entrada trigger del dispositivo durante 10 ps.
2. Emisión de 8 pulsos a 40 KHz.
3. Generación de un pulso por la salida echo proporcional a la distancia.

La duración del pulso será proporcional a la distancia recorrida por el sonido en el viaje de
¡da y vuelta y vendrá dada por la fórmula:

D _ (T*340)
2

Donde T es la duración del pulso en segundos y 340 m/s es la velocidad aproximada del
sonido en el aire a 20 °C.
Se pide:

a) Indica las conexiones con el microcontrolador


b) Realiza el programa para el cálculo de la distancia.
c) Simula el funcionamiento del programa utilizando MPLABSIM
d) Indica la resolución del sistema propuesto.

Solución:

a) Para el funcionamiento del microcontrolador es necesario conectar correctamente las


entradas VDd y Vss a +5 V y 0 V respectivamente. Además, como el PIC16F877A no cuenta
con oscilador interno, será necesario conectar el oscilador (en este caso un oscilador de
cristal a 4 MHz) a las entradas OSC1 y OSC2 tal y como aparece en la figura 4.10.
El interruptor se conectará a una entrada digital del microcontrolador. En este caso se ha
utilizado la entrada RB0, que permitirá el funcionamiento mediante interrupción.
La utilización del módulo de captura implica que la señal generada por el módulo HC-SR04
[echo) deberá estar conectada a uno de los terminales asociados a estos módulos
(RC1/RC2). En este caso se utilizará el módulo CCP1 por lo que la señal de entrada se
conectará al terminal RC2 (también se podría haber utilizado el módulo CCP2 conectando la
salida echo al terminal RC1.
La entrada trigger del módulo HC-SR04 se conectará a una salida digital del
microcontrolador (se ha elegido RC0 en este caso) y los terminales de alimentación y tierra
del módulo se conectarán a +5 V y 0 V respectivamente.

Página | 98
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

F igura 4.10: C onexiones del sensor de ultrasonidos HC-SR04 con el microcontrolador para el ejercicio 4.1.3.

b) Para la determinación de la anchura del pulso se capturará el valor del TIMER1 entre un
flanco de subida y un flanco de bajada. Así, conocido el valor de cada incremento del
TIMER1 y los valores capturados para cada uno de los flancos se puede obtener la duración
del pulso.

Configuración

El terminal RBO se configurará para funcionar mediante interrupción por flanco de subida
(por defecto) y se encargará de la generación de los pulsos por la salida RCO (trigger).
El módulo CCP se configurará en modo captura para la detección de flancos de subida con
predivisor 1 lo que permitirá la detección del primer flanco de subida y a continuación se
configurará para la detección de flancos de bajada permitiendo detectar el final del pulso
por RC2.
El Timer 1 asociado al modo captura del módulo CCP se configura como temporizador con
predivisor 1 por lo que se incrementará cada 4 ciclos de reloj (1 ciclo de instrucción), es
decir, cada microsegundo.

Código fuente

#include < h t c.h>


#include < s t d i o . h >

__ CONFIG (FOSC_HS & WDTE_OFF & LVP_OFF & PWRTE_ON) ;

Página | 99
Programación de microcontroladores PIC en lenguaje C

# d e f i n e _XTAL_FREQ 4000000

t ypedef unión {
un s i g n e d char b y t e s [2];
u n s i g n e d int entero;} ubyte2;

u b y te 2 D i s t , D is tT e m p ;

float Distancia;
u n s i g n e d char Aux;

void Pulsador(void);
void F l a n c o (void);
void Tempor(void);
void Trigger(void);

v o i d m ain(void){
Aux=0;
T1CON=0;
CCP1CON=0;
T R I S B b it s ,T R IS B 0 = 1 ; / / C o n fig u r a r RB0 y RC2 como e n tr a d a , RC0 como s a l i d a
T R IS C b its .T R IS C O L O ;
T R IS C b it s ,T R IS C 2 = 1 ;
e i(); / / H a b ilit a r in te r r u p c io n e s g lo b a le s
O P T IO N _R E G b its. INTEDG=0; / / I n t e r r u p c i ó n e x t e r n a como f l a n c o de b a ja d a
P I E l b i t s . TM R 1IE=1; / / H a b i l i t a r l a s i n t e r r u p c i o n e s de CCP1 y
T im e r l
P I E l b i t s . C C P1IE =1;
P IR 1 = 0 ; / / P o n e r a c e r o l o s f l a g s de i n t e r r u p c i ó n
w h ile (1 ) ;
}
v o i d p u t c h (u n s ig n e d c h a r b y t e )
(
TXSTA=0x26;
//RCSTA|=0x80; //
RCSTAbi t s . SPEN=1;
TXREG =byte;
w h i l e ( 1T X I F )c o n t in u é ;
T X IF = 0 ;
}
v o id in te r r u p t IS R (v o id ){

if(I N T C O N b it s .I N T F = = 1 ) P u l s a d o r O ; //Comprueba s i s e ha p u ls a d o RB0


e l s e i f (P I R lb it s .C C P 1 I F = = 1 ) F l a n c o ( ) ; / / S i s e ha g e n e r a d o una
i n t e r r u p c i ó n de CCP1
e l s e i f (P I R lb it s .T M R 1 IF = = 1 ) T e m p o r( ) ; / / S i h ay una i n t e r r u p c i ó n d e l
/ / T im e r l

}
v o id P u ls a d o r (v o id ){
IN T C O N b its . IN T F = 0 ; / / B a ja e l f l a g de i n t e r r u p c i ó n
i f (A u x = = l) r e t u r n ; //Comprueba s i e s t á r e a l i z a n d o una m e d ic ió n
T r ig g e r ( ) ; //G en era e l p u ls o de t r i g g e r
PIRlbits.CCP1IF=0; / / B a ja e l f l a g d e l m ódulo CCP1
CCPlCON=0x05; / / C o n fig u r a r e l CCP1 en modo c a p t u r a
[Link]=1; / / H a b ilit a in te r r u p c io n e s de lo s p e r i f é r i c o s
TMR1L=0; / / R e s e te a e l T im e r l
TMR1H=0;

Página | 100
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

T I C O N b it s . TMR10N=1; / / I n i c i a e l c o n t e o d e l T im e r l
A u x = l; / / A c t iv a e l i n d i c a d o r de m edida en c u rs o
}
v o i d F la n c o ( v o i d ) { / / C a lc u la l a d i s t a n c i a
P I R l b i t s . C C P1IF=0
i f (C C P lC O N b it s .C C P lM O = = l){
D i s t . b y t e s [ 0 ] =CCPR1L;
D i s t . b y t e s [ 1 ] =CCPR1H;
CC PlC O N =0x04;
}
e ls e {
T 1CONb i t s . TMR10N= 0;
D is t T e m p . b y t e s [ 0 ] =CCPR1L;
D i s t T e m p . b y t e s [ 1 ] =CCPR1H;
D i s t . e n t e r o = D is t T e m p . e n t e r o - D i s t . e n t e r o ;
CCP1CON=0;
IN T C O N b it s . PE IE =0 ;
D i s t a n c i a = ( f l o a t ) D i s t . e n t e r o * 3 4 0 .0 / 2 .0 *0 .0 0 0 0 0 1 ;
p r i n t f ( " D is t a n c ia = % 5 . 3 f m \n ", D i s t a n c i a ) ;
__ delay__m s (5 0 ) ;
A u x=0;
}
}
v o id T e m p o r (v o id ){
P I R l b i t s . TM R 1IF =0; / / B a ja e l f l a g
T1CON=0; / / P a ra e l T im e r l
CCP1CON=0; / / R e s e te a e l CCP1
D is t . e n te ro = 0 ;
Aux=0 ;
}
v o id T r i g g e r ( v o i d ) {
P O R T C b it s . RC 0=1; / / P u ls o de d is p a r o
__ d e l a y u s ( 1 0 ) ;
P O R T C b its .R C 0 = 0 ;

c) Para la simulación del programa del apartado b) será necesario seleccionar la


herramienta MPLABSIM del menú debugger/Select Tool y ajustar la frecuencia del oscilador
a 4MHz (menú debugger/ settings).
La generación de las señales de entrada se realizará mediante el menú debugger/ Stimulus
/N ew Workbook donde se creará una señal asincrona que simulará el pulsador conectado a
RB0. Para la simulación del pulso de medida se utilizarán las funciones que aparecen en la
pestaña Advanced Pin/Register. En este caso se crearán dos condiciones que activarán el
inicio y el fin del pulso de medida por RC2. En ambos casos la condición será que se active el
pulso de trigger por RC0, como se puede observar en la siguiente figura:

Página | 101
Programación de microcontroladores PIC en lenguaje C

FIGURA 4.11: CONFIGURACIÓN DE LOS ESTÍMULOS EXTERNOS PARA LA SIMULACIÓN DEL EJERCICIO 4.1.3.

Si se ajusta un pulso de entrada por RC2 de duración 1 ms a la entrada de RC2 se obtiene


1 que tras activar el pulsador RBO se ha guardado en la variable Dist el valor 0x0011 (17 en
decimal) que es la distancia en cm a la que se encuentra el objeto y que coincide con el
valor obtenido con la fórmula.

La visualización de la señal generada en los terminales RBO, RCO y RC2 se realizar'


accediendo al menú view/SimulatorLogicAnaiyzerdonde pulsando en el botón ch a n n e lsZ
agregarán los canales correspondientes a los pines RBO, RCO y RC2

[VievvJ Project Debugger Programo*


•/ Piojrct
V Output

Tcolbars *
i
j CPU Registeis
Cali St«k
; Disassembly listing
EEPROM
j File Registeis
* Flash Data
: Hardware Stack
• LCD P<*el
Locáis
Memory
Program Memory
l SFR / Penpherals
Spccul Function Regatéis
Watch

1 Memory Usage Gauge

SimuLitcr Trace
Srmulator log>c Analyier

F igura 4.12: Configuración de las señales a visualizar para la simulación del ejercicio 4.1.3.

Una vez ejecutado el programa y activada la condición de disparo (pulsar RBO) se puede observar la señal en
los term inales RBO, RCO y RC2.

Página | 102
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

F igura 4.13: S imulación del ejercicio 4.1.3 (logicanalyzer ).

d) La duración del pulso viene determinada por los incrementos del TIMER1, que está
configurado para incrementarse cada microsegundo. Por lo tanto, el sistema no detectará
variaciones en la anchura del pulso menores a 1 microsegundo. Así pues, aplicando la
fórmula para obtener la distancia se obtiene que para 1 microsegundo se han recorrido
0.068 cm por lo que en este caso sí se satisface la resolución de 0.3 cm del dispositivo HC-
SR04. Sin embargo, la representación del resultado en cm limita la resolución real del
sistema a ±1 cm.

4.1.4. Calculo de la velocidad de un motor


Se desea realizar un programa que permita medir la velocidad de un motor en revoluciones
por segundo utilizando un encoder de 16 rejillas fijado al eje del motor y un fotodiodo
conectado a RC2 que detecta el paso de luz ('1') a través de cada una de las rejillas (Véase
figura inferior).

F igura 4.14: S istema de detección óptica basado en encoder de rejillas .

Se pide:

Realiza el programa utilizando el módulo de captura del microcontrolador PIC16F877A


trabajando a 4MHz.
Simula el funcionamiento del programa utilizando MPLAB_SIM.

Página | 103
Programación de microcontroladores PIC en lenguaje C

¿Cuáles serán las velocidades máxima y mínima que se podrán detectar utilizando el
sistema propuesto?

Solución:

a) Para utilizar el módulo de captura será necesario conectar la entrada del módulo CCPx
(RCx) al fotodiodo. En este caso se utilizará el módulo CCP1 por lo que se deberá conectar el
fotodiodo a la entrada RC2.

Configuración

El módulo CCP se configurará en modo captura para la detección de flancos de subida con
predivisor 1 lo que permitirá la detección del tiempo entre dos flancos de subida
consecutivos (tiempo de duración de rejilla).
i El Timer 1 asociado al modo captura del módulo CCP se configura como temporizador con
predivisor 1 por lo que se incrementará cada 4 ciclos de reloj (1 ciclo de instrucción), es
decir, cada microsegundo.
Como se necesita calcular la velocidad en rps se utilizará la siguiente fórmula.
10• » / , 62500 vueltas ¡
rp s =
ttmri s
1 - ™ . . 1 0 re/" ' “ /,v u e lt a

Código fuente
t t in c lu d e < h tc .h >
# i n c lu d e < s t d i o . h >
# i n e lu d e " t i m e r s . h "
# in e lu d e " c c p . h "

__ CO N FIG(FO SC H S & W DTEOFF & LVP_OFF & PW R TE O N );


#d e f i n e XTA LFR E Q 4000000

t y p e d e f u n ió n {
u n s ig n e d c h a r b y t e s [ 2 ] ;
u n s ig n e d i n t e n t e r o ; } u b y t e 2 ;

u b y te 2 V e l , D iv , T ,T te m p ;

f l o a t V e lo c id a d ;
v o id C a p t u r a (v o id );

v o id m a in (v o id ){
d i(); / / D e s h a b ilita in te r r u p c io n e s
C a p tu ra ( ) ; / / C a lc u la l a v e l o c i d a d
w h ile (1 );
}
v o i d p u t c h (u n s ig n e d c h a r b y t e ) { / / F u n ció n p a r a p e r m i t i r e l u so d e p r i n t f con
/ / e l p u e r to s e r ie
TXSTA=0x26;
R C S T A b its . SPEN=1;

Página | 104
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

T X R E G = b y te;
w h i l e ( ! T X IF )c o n tin u é ;
T X IF = 0 ;
}
v o id C a p t u r a (v o id ){
s e tu p c c p l(C C P _ O F F ); / / R e s e t a l m ódulo CCP1
s e t u p _ t i m e r l (T 1 _ IN T |T1_DIV11 T l_O F F ) / / T im e r l como t e m p o r iz a d o r ,
/ / p r e d = l y d e t e n id o .
s e t t i m e r l ( 0x 0 0 ) ;
P I R l b i t s . C C P 1 IF = 0 ; / / P o n er a 0 e l in d i c a d o r (fla g ) de
ca p tu ra
s e t u p c c p l(C C P CAPTURE RE) ; ; / / S e le c c io n a r modo c a p t u r a con 1 f l a n c o
//de s u b id a
s ta r t_ tim e r l( ) ; / / A rr a n c a r e l TIMER1
w h i l e ( P I R l b i t s . C C P 1 I F = = 0) ; //Comprobar s i ha l l e g a d o un n uevo
/ / fla n c o de s u b id a
T . e n t e r o = C C P R l; // R ecu p era l a p r im e r a c a p tu r a
P IR lb its .C C P 1 IF = 0 ;
w h ile (P IR lb its .C C P 1 IF = = 0 ) ; //Comprobar s i ha l l e g a d o un n uevo
/ / fla n c o de s u b id a
T te m p . e n t e r o = C C P R l; / / R ecu p era l a segu nda c a p tu r a
T .e n t e r o = T t e m p .e n t e r o - T . e n te r o ;
s e tu p _ c c p l(C C P O F F ); / / R e s e t a l m ódulo CCP1
s to p tim e r l(); / / P a ra e l T im e r 1
V e l . e n tero = 6 2 5 0 0 / T . e n t e r o ; / / V e lo c id a d en rp s
V e lo c id a d = 6 2 5 0 0 . 0 / T . e n t e r o ;
p r i n t f ( " V e lo c id a d = % d rp s ( % 5 . 3 f ) " , »1 . e n t e r o , V e l o c i d a d ) ;
}
b) Para la simulación del programa del apartado b) será necesario seleccionar la
herramienta MPLABSIM del menú Debugger/Select Tool y ajustar la frecuencia del oscilador
a 4MHz (menú debugger/ settings).
La generación de las señales de entrada se realizará mediante el menú debugger/ Stimulus
/N e w Workbook donde se creará una señal periódica de entrada por RC2. En este caso se
elegirá una señal periódica de 1 ms por lo que aplicando la fórmula vista en el apartado a)
se obtiene que dicha señal representa una velocidad de 62.5 rps.

100000.0 120000.0

Figura 4.15: Simulación del ejercicio 4.1.4.

Página | 105
Programación de microcontroladores PIC en lenguaje C

Si se ejecuta el programa con la señal de entrada por RC2 se observa el resultado


almacenado en la variable Velocidad se corresponde con la velocidad en rps dada por la
fórmula del apartado a).
c) A la vista del sistema propuesto en el apartado a) se puede deducir que la velocidad
máxima y mínima del sistema vendrán determinadas por la fórmula:
62500
rps = v u e lta s !
T'tmrx

Donde T tmri es el tiempo almacenado en los registros asociados al Timer 1 en


microsegundos. El valor almacenado por el Timer 1 va de 1 a 65535 pero se toma desde 1 a
62500, ya que para el valor 0 el motor iría demasiado rápido para poder ser medido y para
valores mayores a 62500 el sistema iría por debajo de 1 rps. Así pues, el rango de
velocidades de medida del sistema estaría entre 62500 y 1 rps.
Siendo estrictos, la velocidad máxima que se puede obtener con dicho programa no
alcanzaría las 62500 rps ya que se necesitan ejecutar una serie de instrucciones entre una
captura y la siguiente (aproximadamente 8 ciclos de instrucción, 8 ps, lo que haría que la
velocidad máxima real fuese de 7812 rps).

Modifica el programa de! apartado a) para que funcione mediante interrupciones.

4.2. Módulo Comparación


El funcionamiento de los módulos CCPx en modo comparación permite al microcontrolador
PIC16F877A generar un evento cuando el valor del contador de 16 bits asociado al Timer 1
iguala al valor almacenado en los registros CCPRxH:CCPRxL del módulo CCPx. Los posibles
eventos podrán estar o no relacionados con el terminal de salida asociado al módulo. Estos
eventos permitirán desde únicamente activar el flag indicador de que se ha producido el
evento (CCPxIF) a inicializar el terminal asociado al módulo en '0' y ponerlo a T o viceversa
o en el caso del evento especial hacer un reset al Timer 1 (módulo CCP1) o hacer un reset al
Timer 1 y lanzar una conversión analógica digital en el caso de que el módulo conversor esté
habilitado (módulo CCP2).

Página | 106
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

Figura 4.16: E s q u e m a d e b l o q u e s d e l m ó d u l o c o m p a r a c ió n .

4.2.1. Temporizador automático de 16 bits


Realiza un programa en C que genere una señal de período 10 ms a la salida del puerto RB3
mediante la utilización del modo comparación de un microcontrolador PIC16F877A
funcionando a 4 MHz y simular su funcionamiento con MPLAB_SIM.

Solución:
Para la realización del programa es necesario configurar el Timerl como temporizador de
16 bits empleando los registros CCPR1H y CCPR1L para almacenar el módulo de conteo.
Para ello se programa el módulo CCP1 en modo comparador, usando la variante de generar
un reset al Tim erl cuando la comparación entre los registros CCPR1 y TMR1 sea positiva. En
este ejemplo, el Tim erl se programa como temporizador, con un factor de división de 1
para su pre-divisor (se incrementa cada microsegundo) por lo que en el módulo de
comparación se deberá cargar el valor de 5000 equivalente a un semiperiodo de la señal,
que es cuando se debe cambiar.
Código fuente

t t in c lu d e < h t c .h >
__ CONFIG (FOSC_HS & WDTEOFF & LVP OFF & PWRTE ON) ;
# d e fin e X T A L F R E Q 4000000

v o id m a in (v o id ){
T1CON=0; / / T im e r l como te m p o r iz a d o r , p r e d = l ( l p s ) , d e t e n id o .
CCP1CON=0; / / R e s e t a l módulo CCP1.
INTCON= 0 ; / / D e s h a b ilit a in t e r r u p c i o n e s .
T R I S B b i t s . T R IS B 3 = 0 ; / / C o n fig u r a r e l t e r m in a l RB3 como s a l i d a .

Página | 107
Programación de microcontroladores PIC en lenguaje C

P2£l=0; //Poner a 0 las banderas de interrupción.


CCPlCON=OxOB; //Seleccionar modo comparador, con reset al Timerl.
CCPR1=5000; //Carga el módulo comparador
T lC O H b it s .T M R lO N ssl; //Iniciar conteo del Timerl.
while(1){
w h ile (P IR lb its .C C P 1 IF = = 0 ) c o n tin u é ; //¿CCPR1 = TMR1?
P O R T B b its.R B 3 = ! P O R T B b its . RB3; / / N e g a r e l e s t a d o d e RB3
P I R l b i t s .C C P 1 IF = 0 ; / /Pone a 0 el i n d i c a d o r de compar a c i ó n .
}

C) Para la simulación del programa del apartado b) será necesario seleccionar la


herramienta MPLABSIM del menú debugger y ajustar la frecuencia del oscilador a 4 MHz
(menú debugger/settings).

La visualización de la señal generada por el terminal RB3 se realizará accediendo al menú


view/Simulator Logic Analyzer donde pulsando en el botón channels se agregará el canal
correspondiente al pin RB3.
Configure Channels U a -i

Available Signal: Selecled Signaos)


^ ~ | Configure Bu;(i) | j Movcllp |
RA2
RA3 ! MoveDown |
RA4
RA5
RBO
RB1 | Remove <■ |
RB2 =
RB4 i
RB5
RBG
RB7
RCO
1
RC1
RC2 II

! OK | i Cancel [__ Help

--------- ------ 1---------------------------------J¡


Figura 4.17: C onfiguración de las señales a visualizar para la simulación del ejercicio 4.2.1.

Una vez ejecutado el programa se puede observar la señal a la salida del terminal RB3 y
obtener su período aproximado utilizando los cursores.

Figura 4.18: S imulación del ejercicio 4.2.1.

Página | 108
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

Modifica el program a anterior para que funcione mediante interrupciones.

4.2.2. Contador de cajas en cinta transportadora


Se desea implementar un sistema que cuente las piezas que pasan por una cinta
transportadora. El sistema deberá parar la cinta cuando haya contado 10 piezas y arrancará
de nuevo cuando se active un pulsador. El sistema estará formado por un detector inductivo
que detecta el paso de las piezas metálicas por la cinta transportadora ( T ), un pulsador
on/off ('O '/'l') y un relé marcha/paro ('l'/'O') que controlará el motor de la cinta
transportadora.

Figura 4.19: Representación esquemática de los elementos que se utilizarán en el ejercicio 4

Se desea implementar el sistema utilizando un microcontrolador PIC16F8


(Fose = 4 MHz) utilizando el modo comparación.
Se pide:
a) Indica las conexiones de los diferentes elementos con el microcontrolador.

b) Realiza el programa en C que controle el sistema.


c) Simula el funcionamiento del programa con MPLAB_SIM.

Solución:

a) Para el funcionamiento del microcontrolador es necesario conectar correctamente las


entradas V dd y Vss a +5 V y 0 V respectivamente. Además, como el PIC16F877A no cuenta
con oscilador interno, será necesario conectar el oscilador (en este caso un oscilador de
cristal a 4 MHz) a las entradas OSC1 y OSC2 tal y como aparece en la figura 4.20.
El pulsador se conectará a una entrada digital del microcontrolador. En este caso se ha
utilizado la entrada RBO, que permitirá el funcionamiento mediante interrupción.
La utilización del módulo comparación implica que el valor almacenado en los registros
TMR1H:TMR1L será comparado con el valor almacenado en los registros CCPxH:CCPxL. En
este caso se utilizará el TIMER1 como contador por lo que la entrada del sensor se deberá
conectar al terminal RC0/T1CKI. Además, el módulo comparador permite ser configurado de
forma que cuando el valor almacenado en el TIMER1 iguale al valor almacenado por el
módulo comparador se modifique la salida asociada a dicho módulo. Por lo tanto, si se
utiliza el módulo CCP1 se conectará la salida RC2 al relé que controla el motor (en el caso de
utilizar el módulo CCP2 se debería conectar el relé a la salida RC1).

Página | 109
Programación de microcontroladores PIC en lenguaje C

P U LSA D O R

F igura 4.20: Esquema de conexiones con el microcontroiador del sistema contador


DE CAJAS EN CINTA TRANSPORTADORA DEL EJERCICIO 4.2.2.

b) Para contar las piezas que pasan por la cinta transportadora se utilizará el TIMER1
configurado en modo contador de pulsos (flancos de subida) por el terminal RC0/T1CKI que
se incrementará cada vez que se detecte una pieza y que combinado con el módulo
comparador permitirá evaluar si se ha llegado al número de piezas deseado.
Configuración

El terminal RBO se configurará para funcionar mediante interrupción por flanco de subida
(por defecto).
El TIMER1 se configurará en modo contador por RCO con predivisor 1 (un incremento por
cada pieza).
El módulo CCP se configurará en modo comparador de forma que la salida RC2, que
controla el motor, pase a estado bajo ('0') cuando se alcance el valor 10 almacenado en los
registros del comparador.
Código guente
# i n c l u d e < h t c .h >
# in c lu d e < s td io .h >
t t in c lu d e " i n t e r r u p t s . h"
# in c lu d e " p o r t s .h "
# in c lu d e " t i m e r s . h "
# in c lu d e " c c p . h "

CONFIG (FOSC_HS & WDTE OFF & LVP__OFF & PWRTE ON) ;
í d e f i n e _XTAL~FREQ 4000000
# d e f i n e P i e z a s 10;

v o id P u ls a d o r (v o id );
v o id C o m p a r a (v o id ) ;

Página | 110
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

v o id m a in (v o id ){
e n a b l e _ i n t (GLOBAL |IN T_E X T |IN T_CC P1) ; / / H a b ilit a i n t e r r u p c io n e s
b i t c l e a r (T R IS C , 2 ) ; / / C o n fig u r a r e l te r m in a l RC2 como
/ / s a lid a .
O P T IO N _R E G b its . INTEDG=0; / / In t e r r u p c ió n e x t e r n a p o r fla n c o
//de b a ja d a .
w h ile ( 1 ) ;
}
v o id in te r r u p t IS R (v o id ){
i f ( IN T C O N b its . IN T F = = l& & IN T C O N b its . IN TE ) P u ls a d o r O ; //Comprueba s i se ha
/ / p u lsa d o RBO
e ls e if ( P I R l b i t s . C C P lIF = = l& & P IE lb it s . CCP1IE) C o m p ara O ; //Comprueba
/ / in te rru p c ió n CCP1
}
v o id P u ls a d o r (v o id ){
IN T C O N b it s .IN T F = 0 ; / / B a ja e l f l a g de i n t e r r u p c i ó n p o r RBO
if(P O R T C b its .R C 2 = = l) re tu r n ; //Comprueba s i e l m o to r e s t á p a ra d o .
P IR 1 = 0 ; / / Pon er a 0 la s b a n d era s de
/ / in te r r u p c ió n .
e n a b le _ in t (P E R I P H E R A L ); ; / / H a b ilit a in te r r u p c io n e s de p e r i f é r i c o s
s e tu p _ tim e r l(T lE X T | T 1 _ D IV 1 | T I / / T im e rl c o n ta d o r de p u ls o s , p r e d = l ,
/ / d e t e n id o .
s e t t i m e r l ( 0x 0 0 ) ; //Pone a 0 l o s c o n ta d o r e s d e l TIMER1
s e t_ c c p l(P ie z a s ); //Carga l o s v a l o r e s p a ra e l módulo
/7com parador
s e t u p _ c c p l(C C P COMPARE FALL) ; / / S e le c c io n a r modo co m p a rad or, con
/ / p u esta a 'O 'd e RC2
s ta rt t im e r l( ) ; / / In ic ia e l co n teo d e l T im e r l.
}
v o i d C o m p a r a (v o id ){
P IR lb its .C C P 1 IF = 0 ; / / B a ja e l f l a g d e l módulo CCP1
s e t u p c c p l(C C P OFF) ; / / R e s e t a l módulo CCP1
s to p tim e r l(); / / Para e l T im e r l.
d is a b le _ in t (P E R IP H E R A L ) ; / / D e s h a b ilit a l a s i n t e r r u p c i o n e s de
/ / p e r ifé r ic o s .
}
c) Para la simulación del programa del apartado b) será necesario seleccionar la
herramienta MPLABStM del menú debugger y ajustar la frecuencia del oscilador a 4MHz
(menú debugger/settings).
La simulación del pulsador se realizará mediante el menú debugger / Stimulus / New
Workbook donde se creará un estímulo asincronos asociados a la entrada RBO (pulsador) y
un estímulo periódico asociado al fotodetector RCO (fotodetector). Para facilitar la
simulación se seleccionará una señal de frecuencia elevada en RC2 (por ejemplo 100 KHz).

Página | 111
Programación de microcontroladores PIC en lenguaje C

Stirrulv- [Untilledl -• -‘i e Stimulus - [Untitled]


Pn/ Ror ,-r>■'■-¿re AdvjnMdPn 1 Oxl. SlnJu: • Iryoclion Rottlei Trae Asv»^ P« / R;o:tef Aclixc AtívanctdPn/RegUei Obek Slinúj; R.<j:!e

Frs Pn / S R Ación Wdh Unís Coírooríi 11

= j

d
Bejr End
— i S'AlSlart (5) Novel
O pc - '«f/Utel OPC • Fc-Aitd
O Cyelo « dee ¿1ndUotaao O Oyelo - des

i OFr> • » OPt> - “

Renove Dele!» R o/i AOvarcíd Aj*1/ Rcmove DerlaRow Savo Exi

F igura 4.21: Configuración de los estímulos externos para la simulación del ejercicio 4.2.2.

La visualización de las señales generadas se realizará accediendo al menú i/¡ew/Simulator


Logic Analyzer donde pulsando en el botón channels se agregarán los canales
correspondientes a los terminales RBO (pulsador), RCO (fotodetector) y RC2 (relé).

Se ejecutará el programa en modo anímate y se irán activando los estímulos (fire)


comenzando por RBO y siguiendo por RC2. Por simplicidad, se ha simulado en la figura
inferior un contador de 15 piezas.

*3 Logic Analyzer l-o -H -B ¡|p&-[


Tngget Posilion Ttigget PC = Time Base M0de
StartO ConlerO End® Nora Clear Cyc v Simple Channels

[+ «¡1 Q M I H ■■"I

Figura 4.22: Simulación del ejercicio 4.2.2.

4 .3 . M ó d u io PW M
Cuando el módulo CCPx funciona en modo PWM permite generar a través de su terminal
asociado una señal cuadrada periódica con ciclo de trabajo variable con una resolución
máxima de 10 bits en el mejor de los casos. El período de la señal vendrá fijado por la

Página | 112
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

temporización del Timer 2 (excluyendo el postdivisor) mientras que el ciclo de trabajo se


fijará mediante el registro CCPRxL.

Registros de Duty Cycle


D C xB 9 :D CxB0 CargarM
MÓDULO C C P EN MODO PWM
(M) | CCPRxL (8 bits) | CCPRxH (esclavo)

CCPxCON<5:4>
T |
3Ü L
Comparador f
Terminal
' -H - - — Del registro CCPx / RCy
Entrada reloj Pre-DIVISOR TRISC<y>
interno Fosc/4"* TM R 2
1 ,4 ,1 6
3E =T
im n a r a r ln r I 1 ■■
T2CKPS1 '.T2CKPS0 I Co™paradOr
MÓDULO TIM ER2 >1"
(N) | PR2 l

T = (N p R 2 + 1) * P * 4 * Tose T on = M * P * Tose
Figura 4.23: Esquema de bloques del módulo pw m .

4.3.1. Generación de tonos


Se desea generar un tono de frecuencia lKHz y ciclo de trabajo 50 % a través del zumbador
conectado al terminal RC2 de un microcontrolador PIC16f877A trabajando a 4 MHz (véase
Figura). Para ello se utilizará el módulo CCP1 configurado en modo PWM.

Figura 4.24: Conexiones con el microcontrolador para la generación de un tono de 1 KHz del ejercicio 4.3.1.

Se pide:

a) Implementa el código en ensamblador que cumpla las especificaciones descritas en


el enunciado.

Página | 113
Programación de microcontroladores PIC en lenguaje C

b) Indica la frecuencia máxima y mínima de las señales PWM que pueden ser generadas
con dicho sistema.

c) Simula el funcionamiento del programa con M PIABJSIM


Solución:

a) Para la generación de una señal periódica con frecuencia 1 KHz y ciclo de trabajo 50 % se
utilizará el módulo CCP1 asociado al Timer 2 cuya salida se corresponde con el terminal RC2.

Configuración

El período T de la señal PWM se fija mediante el valor N depositado en el registro PR2. Así
pues, para una señal de frecuencia 1 KHz tenemos un período T = 1 ms.

T = (N + 1 ) * P * 4 * Tose = > lm s = (N + l ) * P * 4 * 0,25 ps => 1000 = (N + 1) * P

Si se escoge el factor de división del pre-divisor del Timer2 P=4, el valor que hay que colocar
en el registro PR2 es N = 249.
Utilizando solo el registro CCPR1L (Ms) para fijar el valor de T on de los pulsos. Los bits
CCP1C0N<5:4> (M2) se mantendrán permanentemente en 0. Entonces:

T on = 4 * Ms * P * T 0Sc = > 50 % * 1 ms = 4 * Ms * 4 * 0,2 ps = > M8 = 125

Código fuente
# i n c l u d e < h t c .h >

__ CONFIG(FOSC_HS & W DTEOFF & LVP_OFF & PWRTE_ON);


# d e f i n e _XTAL_FREQ 4000000

v o id m a in (v o id ){

T2CON=0x01; / / P ro g ra m a r p o s t - d i v i s o r = 1, T im er2 d e t e n i d o y p r e -
/ / d i v i s o r = 4.
CCP1CON=0; / / R e s e t a l m ódu lo CCP1
TMR2 = 0; / / P o n e r a 0 e l T im er2
CCPR1L=125; //La s e ñ a l PWM s a l d r á co n 50%
PR 2 =249; //M ódu lo de c o n t e o d e l T im er2 que es e l p e r í o d o d e l a
/ / s e ñ a l PWM.
P I E l b i t s . TMR2IE=0 ; / / I n h a b i l i t a r i n t e r r u p c i ó n d e l T im er2
P I E l b i t s . CCP1IE=0 ; / / I n h a b i l i t a r i n t e r r u p c i ó n d e l m ódu lo CCP1.
T R IS C b i t s . TRISC2 = 0 ; / / C o n fig u r a r e l t e r m in a l CCP1/RC2 como s a l i d a .
P IR 1 = 0 ; / / D e s a c t iv a r l a s b a n d e ra s ( f l a g s ) d e i n t e r r u p c i ó n .
CCPlCON=0x0C; / / E l m ódulo CCP1 en modo PWM con l o s b i t s
//DC1B1: DC1B0 en 0 (M 2 = 0 ).
T2C O N [Link] R 20N =1; / / I n i c i a r c o n t e o d e l T im e r 2 .
w h ile (1 );
}

Página | 114
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

b) Las frecuencias máximas y mínimas de la señal PWM vendrán determinadas por los
valores de configuración de la temporización del Timer 2 sin tener en cuenta el postdivisor.
Así pues, tomando los valores máximos y mínimos para cada caso se obtiene:

Tmax = (255 + 1) * 16 * lps = 4096ps; / m¡n~244.1Hz


Tpwm = (PR2 + 1) * p * 4 * Tosc=>
Tmin = (1 + 1) * 1 * lp s = 2ps; / max = 0.5MHz

Es importante destacar que en el cálculo del período mínimo no se puede introducir un


valor de PR2 = 0 ya que siempre se cumpliría que TMR2 = PR2 y no avanzaría el contador
TMR2.

c) Para observar la señal generada por el terminal RC2 es necesario acceder al menú
view/Simulator Logic Analyzer donde pulsando en el botón channels se agregará el canal
correspondiente al pin RC2.
Una vez ejecutado el programa o ejecutándolo en modo animóte se puede observar la señal
a la salida del terminal RC2 y comprobar su período y ciclo de trabajo.

Logic Analyzer j = ¡, s
Tngger Positrón Tngger PC » Time Base Mode
S ta itC Ceniet " End Now Cleai Cyc v Simple Chame!;

lí+ <e| 0 . 1 ® . ! : 1 * í M H la ia l 3

F igura 4.25: S imulación del ejercicio 4.3.1.

4.3.2. Señal periódica con ciclo de trabajo variable


Se desea generar una señal PWM con un período constante de 0,1 ms y ciclo de trabajo
variable (inicialmente con valor 25 %). El ciclo de trabajo se doblará por cada pulsación de
RBO hasta llegar al 100 % volviendo al 25 % en la siguiente pulsación.

a) Implementa el código en ensamblador para un microcontrolador PIC16F877A


trabajando a 4 MHz que cumpla las especificaciones del problema.
b) Simula el funcionamiento del programa utilizando MPLAB_SIM.

Página | 115
Programación de microcontroladores PIC en lenguaje C

c) Indica la resolución (variación mínima del ciclo de trabajo de la señal PWM) del
sistema propuesto
Solución:

a) Para la generación de una señal periódica con ciclo de trabajo variable se utilizará el
módulo CCPx del mlcrocontrolador asociado al Timer 2. Para la modificación del ciclo de
trabajo se utilizará la interrupción externa conectando el pulsador al terminal RBO del
microcontrolador.

Configuración

El período T de la señal PWM se fija mediante el valor N depositado en el registro PR2.


T = (N + 1 ) * P * 4 * Tosc => 0,1 ms = (N + 1) * P * 4 * 0,25 ps => 100 = (N + 1) * P

donde P es el factor de división del pre-divisor del Timer2, P = 1, 4,16.

Si se escoge P = 1, el valor que hay que colocar en el registro PR2 será N = 99.
La duración TON de los pulsos queda determinada por el valor M de los 10 bits distribuidos
entre los 8 bits del registro CCPR1L (que constituyen los 8 bits más significativos de M, es
decir, Ms) y los 2 bits CCP1C0N<5:4>, que forman los 2 bits menos significativos de M, es
decir, M2.
Como solo es necesario variar el ciclo de trabajo entre el 25 %, 50 % y 100 % solo será
necesario utilizar el registro CCPR1L (Ms) para fijar el valor de T o n . Los bits CCP1C0 N<5:4>
se mantendrán permanentemente en 0.
Entonces inicialmente:
T on = 4 * Ms * P * T 0Sc => 25% * 0,1 ms = 4 * Ms * 1 * 0,25 ps => Ms = 25
La duración (variable) de los pulsos PWM se logra colocando un valor entre 0 y 99 en el
registro CCPR1L. En este caso la duración de los pulsos se incrementará en un factor de 2
por lo que bastará con rotar el valor del registro CCPR1L una posición hacia la izquierda por
cada pulsación hasta que alcance el valor de 100.

Código fuente
# in c lu d e < h t c .h >
# in c lu d e < s t d i o . h >
# in c lu d e " t i m e r s . h "
# in e lu d e " c c p .h "

CO N FIG(FO SC H S & WDTE_OFF & L V P O F F & PWRTE_ON);


# d e f i n e _XTAL_FREQ 4000000

t y p e d e f u n ió n {
u n s ig n e d c h a r b y t e s [ 2 ] ;
u n s ig n e d i n t e n t e r o ; } u b y t e 2 ;

Página | 116
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

u b yte2 D u tC y ;

v o i d I n ic _ p w n ( v o i d ) ;

v o id m a i n ( v o i d ) {
D u tC y .b y te s [0 ]= 2 5 ;
I n ic _ p w n ( ) ; / / p r o g r a m a r e l m ódulo CCP1 en modo PWM pa ra g e n e r a r
//u na s e ñ a l PWM de p e r io d o 0 ,1 ms y c i c l o de t r a b a jo d e l 25%.
IN TC O N =0x90; / / H a b i l i t a i n t e r r u p c io n e s g l o b a l e s e in t e r r u p c ió n e x te r n a
w h ile (1 ) ;
}
v o i d p u t c h (u n s ig n e d c h a r b y t e ) {
T X S TA =0x26;
R C S T A b it s . S PEN=1;
T X R E G = b yte;
w h i l e (!TXIF ) c o n t i n u é ;
T X IF = 0 ;
}
v o id I n i c p w n ( v o i d ) {
s e t u p _ t im e r 2 (T 2 POST DIV1 |T2 0FF |T2_PRED_DIV1) ; //Tim er2 d e t e n id o ,
//PRED=P0STD=1
s e t u p _ c c p l (CCP_OFF) ; / / R es et a l módulo C C Pl.
s e t _ p w m l_ d u t y (D u tC y . e n t e r o < < 2 ) ; / /S eñal PWM s a ld r á con c i c l o de t r a b a j o
//25 %.
s e t _ t i m e r 2 (9 9 ) ; //M ódulo de c o n te o d e l Tim er2 que es e l p e r i o d o de
/ / la sen PWM
T R I S C b i t s . T R IS C 2 = 0 ; //Poner e l te r m in a l CCPl como s a l i d a .
s e t u p c c p l(C C P P W M ); / / E l módulo CCPl en modo PWM
s t a r t t im e r 2 ( ) ; / / I n i c i a r c o n te o d e l Tim er2
}
v o id in t e r r u p t I S R ( v o i d ) {
i f (IN T C O N b it s . IN T F = = 0 ) re tu r n ; //Comprueba l a i n t e r r u p c i ó n e x t e r n a
IN T C O N b it s . IN T F = 0; //B aja e l in d ic a d o r de in t e r r u p c i ó n
/ / e x te rn a
DutCy . b y t e s [0 ] « = 1 ; / / M u lt ip lic a p o r 2 e l c i c l o de t r a b a j o
i f (D u t C y . b y t e s [0 ]> 1 0 0 ) D u tC y .b y te i [0 ]= 2 5 ; //Comprueba s i e l c i c l o de
/ / t r a b a jo es d e l 1 0 0 %
s e t _ p w m l_ d u t y (D u tC y . e n t e r o < < 2 ) ; / / A ju s ta e l c i c l o d e t r a b a j o
p r i n t f ( "D C =% d\n ", C C PR 1L );
}

b) Para la simulación del programa del apartado a) será necesario seleccionar la


herramienta MPLABSIM del menú debugger y ajustar la frecuencia del oscilador a 4MHz
(menú debugger/ settings).
La simulación del pulsador se realizará mediante el menú debugger / Stímulus / New
Workbook donde se creará una señal asincrona de duración 5 ciclos de instrucción asociada
a RB0 (pulse low).
La visualización de la señal generada por el terminal RC2 se realizará accediendo al menú
view/Simulator Logic Analyzer donde pulsando en el botón channels se agregará el canal
correspondiente al pin RC2.
Una vez ejecutado el programa se puede observar la señal a la salida del terminal RC2 y
comprobar su ciclo de trabajo tras cada pulsación de RB0 (fire).

Página | 117
Programación de microcontroladores PIC en lenguaje C

c) La resolución del sistema propuesto en el apartado a) dependerá del valor asignado a


PR2. En este caso PR2 = 99 por lo que el ciclo de trabajo de la señal PWM se podrá ir
incrementando de 0 % a 100 % en incrementos de 0.25 % en el caso de utilizar los bits
CCP1C0N<5:4> o en incrementos del 1% en el caso de no utilizarlos. Así pues, el
incremento mínimo del ciclo de trabajo será:
T 0 .1
U tiliza n d o C C P 1 C O N < 5 : 4 > = > R e so lu c ió n ( m s ) = — —------- =
-------------------= 0 . 0 0 0 2 5 m s
(P R 2 + 1) * 4 (9 9 + 1) * 4
T 0 .1
S in u t iliz a r C C P 1 C O N < 5 : 4 > => R e so lu ció n ( m s ) = ———-------- = — -— — = O .O O lm s
(P R 2 + 1 ) (9 9 + 1)

4.3.3. Control motor DC


Se desea controlar la velocidad de un motor DC mediante la variación del ciclo de trabajo de
la señal de alimentación.
Para ello se utilizará el módulo CCP1 configurado en modo PWM de un microcontrolador
PIC16F877A trabajando a 4 MHz (Tose = 0,25 ps).
Para evitar alimentar el motor con un rizado de corriente alto, y por lo tanto de par, la señal
PWM tendrá un periodo superior a 20KHz. Con esto se conseguirá que el motor gire a una
velocidad más estable.
Además, el sistema contará con un pulsador que variará la tensión media aplicada al motor
entre 0 %, 25 %, 50 %, 75 %, 100 %, 0 %, 25 %, etc., por cada pulsación detectada.

FIGURA 4.27: MOTOR DE CORRIENTE CONTINUA.

Página | 118
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

a) Indica las conexiones del sistema microcontrolador.


b) Implementa el código del programa en ensamblador que cumpla las especificaciones
del problema.

c) Simula el funcionamiento del programa utilizando MPLAB_SIM.

Solución:

a) Para el funcionamiento del microcontrolador es necesario conectar correctamente las


entradas V dd y V ss a + 5 V y O V respectivamente. Además, será necesario conectar el
oscilador, en este caso un oscilador de cristal a 4MHz a las entradas OSC1 y OSC2 tal y como
aparece en la figura inferior.
El interruptor se conectará a una entrada digital del microcontrolador. En este caso se ha
utilizado la entrada RBO, que se corresponde con la entrada de interrupción externa del
microcontrolador, lo que permitirá al programa funcionar en modo interrupción.
La utilización del módulo CCP1 implica que la señal PWM saldrá por el terminal RC2 que
deberá conectarse al motor. Sin embargo, la corriente demandada por un motor supera
generalmente el máximo de corriente suministrada por el terminal (20 mA) por lo que es
necesaria la utilización de una etapa de salida (en este caso se utiliza un buffer con entrada
ENABLE por RCO). Además, se ha añadido un diodo de protección para evitar
sobretensiones en el driver cuando se corta la corriente. Las conexiones con el motor y el
micro pueden variar en función del driver utilizado.

PULSADOR

Figura 4.28: C onexiones del controlador para el sistema de control de velocidad


DE UN MOTOR DC DEL EJERCICIO 4.3.3.

b) Para la generación de una señal periódica con ciclo de trabajo variable se utilizará el
módulo CCPx del microcontrolador asociado al Timer 2. Para la modificación del ciclo de

Página | 119
Programación de microcontroladores PIC en lenguaje C

trabajo se utilizará la interrupción externa conectando el pulsador al terminal RBO del


microcontrolador.

Configuración
El período T de la señal PWM se fija mediante el valor N depositado en el registro PR2. Así,
para una frecuencia superior a 20 kHz se tendrá un período T < 50 ps.
T = ( N + 1 ) * P * 4 * Tosc => 50 ps = (N + 1) * P * 4 * 0,25 ps => 100 = (N + 1) * P
donde P es el factor de división del pre-divisor del Timer2, P = 1,4,15.
Si se escoge P = 1, el valor que hay que colocar en el registro PR2 será N = 49.
La duración TON de los pulsos queda determinada por el valor M de los 10 bits distribuidos
entre los 8 bits del registro CCPR1L (que constituyen los 8 bits más significativos de M, es
decir, Ms) y los 2 bits CCP1C0N<5:4>, que forman los 2 bits menos significativos de M, es
| decir, M2.
Como sólo es necesario variar el ciclo de trabajo entre el 25%, 50%, 75 % y 100% se
utilizará una tabla donde se almacenarán los valores que se cargarán en el registro CCPR1L
(Mg) y en los bits CCP1C0N<5:4> para ajustar el valor de T on.
Los valores para cada ciclo de trabajo se obtienen utilizando la siguiente fórmula:
T on = DC * T = (M8:M2) * P * Tosc

Código fuente
# i n c l u d e < h t c .h >
# in c lu d e < s t d io .h >

__ CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF & PWRTE_ON);


#d e fin e X TA LF R E Q 4000000

t y p e d e f u n ió n {
u n s ig n e d c h a r b y t e s [ 2 ] ;
u n s ig n e d i n t e n t e r o ; } u b y t e 2 ;

u n s ig n e d c h a r C o n ta d o r ;

/ / T a b la co n l o s v a l o r e s qu e h a y que c a r g a r en CCPR1L
u n s ig n e d c h a r T a b l a l [ 5 ] = { 0 x 3 2 , 0 x 2 5 , 0 x 1 9 , 0 x 0 C ,0 x 0 0 } ;

/ / T a b la con l o s v a l o r e s que h ay que c a r g a r en CCPC0N<5:4> en l a p o s i c i ó n adecuada


u n s ig n e d c h a r T a b l a 2 [5 ]= {0 x 0 0 ,0 x 2 0 ,0 x 0 0 ,0 x 2 0 , 0 x 0 0 } ;

void I n i c p w n ( v o i d ) ;
v o i d Ton p w m ( v o i d ) ;

i n t m a in ( )
{
C o n ta d o r= 5 ; / / I n i c i a e l c o n t a d o r co n e l número de v a l o r e s q u e pu ede
/ / tom a r e l DC.
In ic p w n ( ) ; / / p ro g ra m a r e l m ódulo CCP1 en modo PWM p a r a g e n e r a r PWM
//de 20 kH z, DC=0
INTCON=0x90; / / H a b ilit a in te r r u p c io n e s g lo b a le s e in te r r u p c ió n e x te rn a

Página | 120
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

O P T IO N _ R E G b its . INTEDG =0; / / In t e r r u p c ió n p o r fl a n c o de b a ja d a


w h ile ( 1) ;
}
v o i d p u t c h (u n s ig n e d c h a r b y t e )
{
T X S TA =0x26;
R C S T A b it s . SPEN=1;
T X R E G = b y te;
w h i l e (1 T X I F ) c o n t i n u é ;
T X IF = 0 ;
}
v o id I n ic _ p w n (v o id ){
T2CON=0; / / P ro g ra m a r p o s t - d i v i s o r = 1, Tim er2 d e t e n id o y p r e -
/ / d iv is o r = 1
CCP1CON=0; / / R e s e t a l m ódulo CC Pl.
TMR2=0; / / P o n e r a 0 e l Tim er2
CCPR1L=0; //L a s e ñ a l PWM s a ld r á con c i c l o de t r a b a j o d e l 0%.
P R 2 =49; //M ódulo de c o n t e o d e l Tim er2 que es e l p e r io d o de l a
/ / s e ñ a l PWM.
T R I S C b i t s . TR ISC 2=0 r / / P o n e r e l t e r m in a l CCPl como s a l i d a
T R I S C b i t s . TR ISC 0=0 ; / / P o n e r e l t e r m in a l RCO como s a l i d a
P O R T C b it s . RC 0=1; / / H a b i l i t a r l a e n tr a d a ENABLE d e l DRIVER
CCPlCON=OxOC; / / E l módulo CCPl en modo PWM con l o s b i t s
//DC1B1: DC1BO en 0 (M 2 = 0 ).
T2CONbi t s . TMR20N=1 / / I n i c i a r c o n t e o d e l T im er2 .
}
v o id in t e r r u p t I S R ( v o i d ) {
i f (IN T C O N b its . IN T F = = 0 ) re tu rn ; //Comprueba s i ha s a l t a d o l a
/ / in t e r r u p c ió n e x t e r n a
IN T C O N b its .IN T F = 0 ; / / B a ja e l in d ic a d o r de i n t e r r u p c i ó n
//externa
i f ( - -C o n ta d o r = = 0 ) C o n ta d o r= 5 ; //Decrementa el contador y recarga si
//es cero
Ton pwm( ) ; //Ajusta el nuevo ciclo de trabajo
}
v o id T o n p w m (v o id ){
C C P R lL = T a b la l [C o n ta d o r - 1 ] ; / / A ju s ta e l c i c l o de t r a b a j o
C C P R lH = T a b la l [C o n ta d o r - 1 ] ;
CCP1CON|=Tabla2 [C o n ta d o r - 1 ] ;
CC PlCON &=Tabla2 [C o n ta d o r - 1 ]+ 0 x 0 F ;
p r i n t f ( ” CCPRlL=%d, CCPlCON=%d, Contador=% d\n" , CCPR1L, CCP1CON, C o n ta d o r) ;
}

c) Para la simulación del programa del apartado b) será necesario seleccionar la


herramienta MPLABSIM del menú debugger y ajustar la frecuencia del oscilador a 4MHz
(menú debugger/ settings).
La simulación del pulsador se realizará mediante el menú debugger / Stimulus / New
Workbook donde se creará una señal asincrona de duración 5 ciclos de instrucción asociada
a RBO (pulse low).
La visualización de la señal generada por el terminal RC2 se realizará accediendo al menú
view/SImulator Logic Analyzer donde pulsando en el botón channels se agregará el canal
correspondiente al pin RC2.
Se ejecutará el programa en modo animóte y se observará la señal a la salida del terminal
RC2 tras cada pulsación de RBO (fire).

Página | 121
Programación de microcontroladores PIC en lenguaje C

F igura 4.29: Configuración de estímulos externos y simulación del el ejercicio 4.3.3.

4.3.4. Creación de melodías


Se pide ¡mplementar un sistema basado en un PIC16F877A trabajando a 4 MHz para
\ integrarlo en una postal navideña. La postal cuenta con un interruptor conectado a RBO que
se abrirá o cerrará (1/0) al abrir y cerrar la postal respectivamente. Además, se cuenta con
un zumbador conectado a RC2 para reproducir la melodía, que solo sonará cuando la postal
esté abierta.
La melodía a reproducirse corresponde con la partitura inferior.

si sol mi mi fu mi re do lu sol la re si

F igura 4.30: Partitura de la melodía utilizada en el ejercicio 4.3.4.

La frecuencia de cada una de las notas se encuentra en la tabla inferior.

Frecuencias (Hz)
Sol: 391,995
La: 440
Si: 493,883
Do: 523,25
Re: 587,33
M i: 659,26
Fa : 689,46

Página | 122
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

La duración de cada nota se establecerá según la siguiente relación:

1 Blanca = 2 Negras = 4 Corcheas

Para una duración de corchea de 0.25 segundos. Se pide:

a) Implementa el código en C que satisfaga las condiciones del problema utilizando el


módulo PWM del microcontrolador para la generación de las notas.
NOTA: La frecuencia de las notas se aproximarán al valor más cercano.
b) Indica el error de aproximación en frecuencia cometido para la nota la.
Solución:
a) Para la generación de las diferentes notas musicales se ajustarán diferentes señales PWM
a la frecuencia de cada una. El ciclo de trabajo en todos los casos será del 50 % por lo que se
obtendrá directamente desplazando el valor del periodo un bit hacia la derecha.
La duración de cada una de las notas se obtendrá utilizando una rutina de espera de 250 ms
que se ejecutará el número de veces necesario para obtener la duración de la nota.
Configuración

El período T de la señal PWM se fija mediante el valor N depositado en el registro PR2. Así,
se puede obtener el valor a asignar a PR2 para cada nota utilizando la fórmula:
T = (N + 1) * P * lp s
donde P es el factor de división del pre-divisor del Timer2, P = 1, 4,16.
Se escoge P = 16 ya que N > 255 y se obtienen los siguientes valores para cada nota:

Frec. (Hz) PR2 CCPR1L CCPlCON<5>


Sol: 391,995 158 79 o
La: 440 141 70 1
Si: 493,883 126 63 0
Do: 523,25 118 59 _ ± _
Re: 587,33 105 52 i
Mi : 659,26 94 ____ « _ 0
Fa : 689,46 90 0
«

Para controlar la duración de cada una de las notas se utilizará el temporizador TIMER1 en
modo temporizador para contabilizar 250 ms funcionando en modo interrupción.

Página | 123
Programación de microcontroladores PIC en lenguaje C

Código fuente

# in c lu d e < h t c .h >

__ CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF & P W R T E O N );


# d e fin e X TA LF R E Q 4000000

// D e f i n i c i ó n d e l o s v a l o r e s de PR2 p a r a c a d a n o t a
# d e f i n e S o l 158
# d e f in e La 141
# d e fin e S i 126
# d e f i n e Do 117
# d e f i n e Re 105
# d e fin e Mi 94
# d e f i n e Fa 90
# d e fin e S ile n c io 0
# d e f i n e F in OxFF

/ / D e fin ic ió n de la d u r a c ió n d e ca d a t i p o de n o ta ( m ú l t i p l o de 0 .2 5 se g u n d o s )
# d e f i n e C o rc h e a 1
# d e fin e N e gra 2
# d e f i n e B la n c a 4

v o id P u ls a d o r (v o id );
v o id T e m p o r (v o id );
v o id T o n p w m (v o id );
v o id In ic _ p w m (v o id );

u n s ig n e d c h a r T a b la P , Tem po;
u n s ig n e d i n t T ie m p o l= 6 0 0 0 0 ; / / A ju s t e d e l Tiem po
/ / T a b la c o n l a p a r t i t u r a
c o n s t c h a r N o t a s [6 0] = { S i l e n c i o , B l a n c a , S o l , N e g r a ,D o ,N e g r a ,D o ,C o r c h e a ,
R e, C o r c h e a ,D o ,C o r c h e a , S i , C o r c h e a ,L a ,B la n c a ,L a ,N e g r a ,
R e , N e g r a , R e , C o r c h e a , M i , C o r c h e a ,R e ,C o r c h e a , Do,
C o r c h e a , S i , B l a n c a , S o l , N e g r a ,M i , N e g r a ,
M i,C o r c h e a ,F a ,C o r c h e a , M i,C o r c h e a ,R e ,C o r c h e a ,
Do,N e g r a , L a , N e g r a , Sol,N e g r a ,L a ,N e g r a ,
Re,Negra,Si,Negra,Do,Blanca, Fin};

i n t m a in ( ) {
INTC0N= 0 x 9 0 ; / / H a b ilit a in te r r u p c io n e s g lo b a le s e in te r r u p c ió n e x te rn a
w h ile (1 ) {
w h ile (P O R T B b it s . R B 0 = = 1 ); //Comprueba e l e s t a d o d e l a t a r j e t a ON/OFF
IN T C O N b it s . P E IE = 0 ; / / D e s h a b i l i t a i n t e r r u p c i o n e s de p e r i f é r i c o s
T1CON=0; / / p a ra e l TIMER1, e l TIMER2 y e l M ódu lo CCPl
T2CON=0;
CCP1CON=0;
}
v o id in te r r u p t IS R (v o id ){
i f ( IN T C O N b it s . IN T F = = 1 ) P u ls a d o r ( ) ; //Comprueba s i ha s a l t a d o la
/ / in te r r u p c ió n e x te rn a
e ls e if(P IR lb it s .T M R lIF = = l) T e m p o r( ) ; //Comprueba s i ha s a l t a d o la
/ / in te r r u p c ió n TIM ERl

v o id P u ls a d o r (v o id ){
IN T C O N b its .IN T F = 0 ; / / B a ja e l f l a g d e i n t e r r u p c i ó n
if(P O R T B b it s .R B 0 = = 0 ) r e t u r n ; //Comprueba e l p u ls a d o r
I n i c p w m (); / / p ro g ra m a r m ódulo CCPl con l a p r im e r a
/ / n o ta
}

Página | 124
4. Módulos de Captura, Comparación y Modulación de Anchura de Pulsos (PWM)

v o id T e m p o r (v o id ){
P I R l b i t s . T M R 1 IF = 0 ; / / B a ja e l f l a g de i n t e r r u p c ió n d e l TIMER1
T M R l= T ie m p o l; / / R e c a rg a e l v a l o r de l o s c o n ta d o re s d e l TIMER1
/ / p a ra v o l v e r a c o n t a r 0 .2 5 s
i f ( - -T e m p o = = 0 ) Ton p w m (); / /D ecrem enta e l c o n ta d o r d e l tiem p o de n o ta
}
/ / ************************************************ ****************************
/ / In ic _ p w m : P r o g r a m a r e l m ódu lo CCP1 en modo PWM, e i n i c i a r l a m e lo d ía .
/ / ************************************************ ****************************
v o id In ic _ p w m ( v o i d ) {
T2C O N=0x02; / / P ro g ra m a r p o s t - d i v i s o r = 1, Tim er2 d e t e n id o , y p r e -
/ / d i v i s o r = 16.
T lC O N = 0 x 3 0 ; / / P ro g ra m a r p r e d i v i s o r = 8, T im e r l d e t e n id o
T M R l= T ie m p o l; //C a rga e l v a l o r de l o s c o n ta d o r e s d e l TIMER1 p a ra c o n t a r
/ / 0 .2 5 s
// TM R1=100; / / C a rga e l v a l o r de l o s c o n t a d o r e s d e l TIMER1 p a ra c o n t a r
/ / 0 .2 5 s

CCP1CON=0; / / R e s e t a l módulo CCP1


CCPR1L=0; / / P o n e r a 0 e l c i c l o de t r a b a j o (0%)
T a b la P = 0 ; / / R e i n i c i a e l a p u n ta d o r de l a t a b l a de n o ta s a l a p r im e r a
/ / p o s ic ió n
T R I S C b i t s . T R IS C 2 = 0 ; / / P o n e r e l t e r m in a l CCP1 como s a l i d a .
IN T C O N b it s .P E IE = 1 ; / / H a b i l i t a in t e r r u p c io n e s de p e r i f é r i c o s
P I E l b i t s . TM R 1IE=1; / / H a b i l i t a in t e r r u p c i ó n d e l TIMER1.
CCP1CON|=0x0C; / / E l módulo CCPI en modo PWM
Tonpwm ( ) ;
T 2C O N [Link] R 20 N =1; / / A rra n ca e l TIMER2
T I C O N b it s . TMR10N=1; / / A rra n ca e l TIMER1
}
/ / ******************* ****************************************** **************
//TONpwm : A j u s t a e l p e r io d o de l a s e ñ a l PWM según e l v a l o r d e p o s it a d o en l a
//TABLA NOTAS
//con un c i c l o d e t r a b a j o d e l 50% y o b t ie n e l a d u ra c ió n de l a n o ta en fu n c ió n
/ / d e l núm ero
//de d e s b o r d a m ie n t o s d e l TIMER1 en l a v a r i a b l e TEMPO
/ / ******************************************************************************
v o id T o n p w m (v o id ){
CCP1CON=0; / / R es et a l m ódulo CCPI
CCPR1L=0; / / Pon er a 0 e l c i c l o de t r a b a j o (0%)
i f (N o t a s [T a b la P ]= = 0 x F F ) T a b la P = 0 ; / / O b tie n e e l v a l o r de PR2
C C P R lL = N o ta s [T a b la P ]/ 2 ; //G uardar PR2/2 en CCPR1L
CCPICONbi t s . C C P lX =N ota s [T a b la P ] %2 ; //Guarda e l r e s t o en e l b i t CCP1X
P R 2 = N o ta s [T a b la P ] ; / / A ju s ta e l p e r io d o de l a p r im e r a n o ta
CCP1CON|=0x0C; / / A ju s ta e l módulo CCPI en modo PWM con
//CCP1X: CCP1Y en 0 (M 2 = 0 ).
T e m p o = N o ta s [ + + T a b la P ] ; / / O b tien e l a d u r a c ió n de l a n o ta
T a b la P + + ;
}

c) El error de aproximación en frecuencia cometido en la nota la vendrá dado por el error de


aproximación introducido al calcular el valor de PR2. Así pues, para el valor de PR2
calculado para la nota la se obtiene:

Tla-pwm - (141+ 1) * 16 * ljus = 2272 JUS =>/ ia-pwm = 440.14 Hz

Lo que equivale a un error de 0.032 %.

Página | 125
5. Módulos analógicos
5.1. Módulo generador de tensión de referencia (CVref)
5.2. Módulos comparadores de tensión
5.3. Módulo conversor analógico digital (CAD)

5.1. Módulo generador de tensión de referencia (CVref)


El módulo generador de tensión de referencia integrado en el microcontrolador PIC16F877A
consiste en un divisor de tensión resistivo en escalera de dieciséis escalones conectado a un
multiplexor analógico. Este módulo proporciona un valor de tensión de referencia ajustable
que puede ser utilizado como referencia V - para el comparador analógico digital, como
ref

entrada V in* por los comparadores analógicos o como tensión de salida de referencia por
RA2/AN2 siempre y cuando se utilice como salida conectada a una carga de alta
impedancia, aunque está realmente pensado para utilizarse simplemente como
comprobación del valor de tensión entregado al comparador. El módulo CVref proporciona
dos rangos de ajuste de tensión y puede ser apagado en caso de no ser utilizado para
reducir el consumo de energía. La configuración de este módulo se realiza mediante el
registro CVRCON (A2.12).

V dd 16 ETAPAS

PORTA TR ISA : TRISA2=1 para funcionar como salida analógica


F igura 5.1: Esquema de bloques del módulo cvref .

Página | 127
Programación de microcontroladores PIC en lenguaje C

5.1.1. Generación de señal analógica


Utiliza el módulo generador de tensión de referencia para generar una señal diente de sierra.

Solución:

Para generar la señal diente de sierra se hará uso del generador de tensión de referencia
Integrado en el mlcrocontrolador PIC16F877A.

Configuración

La configuración del módulo de tensión de referencia se realizará ajustando el registro


CVRCON (A2.12). Para facilitar el ajuste del módulo se definirán varias constantes que harán
referencia al modo de funcionamiento del módulo y que se utilizarán mediante la función
'OR' como argumento de una macro. La definición de las constantes y de la macro se
| Incluirán en el archivo de definiciones "analog.h" y quedarán de la siguiente manera:

# d e fin e CVR_ON 0x80 //M ódulo h a b i l i t a d o


# d e fin e C V R O F F 0x00 //M ódulo d e s h a b i l i t a d o
# d e fin e CVR_LOW 0x20 //Rango b a j o d e fu n c io n a m ie n t o
# d e fin e CVR_HIGH 0x00 //Rango a l t o d e fu n c io n a m ie n t o
# d e fin e CVR_OUT_ON 0x40 / / S a lid a CVREF h a b i l i t a d a p o r RA2
# d e fin e SET_CVREF(MODE) CVRCON=MODE / / F u n ció n d e c o n f i g u r a c i ó n

Para la generación de la tensión de referencia habrá que tener en cuenta también el tiempo de
respuesta definido por el fabricante, en este caso 10 ps. Los valores de tensión de referencia
vendrán dados en función del modo de funcionamiento por las siguientes fórmulas:

CVR < 3 :0 >


R a n g o B a jo -* CVREF =
24 ) *
CVR < 3 :0 >-
RSRC
32

Cuyos valores dependerán de la exactitud de CVRSRC = VDD - VSAT.

Código fuente
# in c lu d e < h tc .h >
# in c lu d e " a n a l o g . h "
# d e f i n e _XTAL_FREQ 4000000 / / O s c i l a d o r I n t e r n o d e 4MHZ
CONFIG(WRT_OFF & WDTEJDFF & P W R T E O F F & F O S C X T & L V P O F F ) ;

u n s ig n e d c h a r i ;
d i () ; //Se d e s h a b i l i t a n in te r r u p c io n e s
w h ile ( 1 ) {

}
}

Página | 128
5. Módulos analógicos

Modifica el program a de form a que permita conmutar entre un ajuste en rango alto y un
ajuste en rango bajo. Este modo de funcionamiento se conmutará mediante un pulsador
conectado a RBO.

Modifica e l program a de form a que se muestre la tensión generada con dos decimales y el
modo "fino/grueso" de ajuste de la tensión de salida en una pantalla LCD.

5.2. ¡VlóduSos Comparadores de Tensión Analógica


El microcontrolador PIC16F877A contiene dos comparadores analógicos cuyas entradas
están multiplexadas con los terminales RA0-RA3 y las salidas con los terminales RA4 y RA5.
Además, el módulo generador de tensión de referencia también puede utilizarse como
referencia de tensión en la entrada no inversora de los comparadores. El modo de
funcionamiento de los comparadores viene determinado por el valor almacenado en el
registro CMCON (A2.13).
El flag de interrupción, bit CMIF del registro PIR2, asociado a los módulos comparadores se
activará siempre que haya un cambio en el valor de salida de cualquiera de los
comparadores por lo que será necesario registrar la información de salida de los
comparadores para poder determinar el cambio que se ha originado.
En el caso de que se desee que se genere una interrupción cuando cambie el valor a la
salida de los comparadores se deberá activar el bit CMIE del registro PIE2 y los bits PEIE y
GIE del registro INTCON.

RA4 o RA5

BUS DE
DATOS

■ CMIF

DEL OTRO
INTCON PIE2 COMPARADOR
t
PEIE CMIF

Figura 5.2: Esquema de bloques del módulo comparador analógico .

Página | 129
Programación de microcontroladores PIC en lenguaje C

5.2.1. Comparar dos señales analógicas


Realiza un programa que compare dos señales analógicas A y B (0-5V) y active un led en
caso de A>B.

a) Indica las conexiones necesarias con el microcontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.

Solución:

a) La solución propuesta va a utilizar uno de los comparadores analógicos integrados en el


microcontrolador PIC16F877A. Para ello se conectarán las señales analógicas A y B a las
entradas de uno de los dos comparadores. Para el funcionamiento del microcontrolador
también será necesario conectar correctamente las entradas VDD y VSS a +5V y OV
respectivamente además de un oscilador, en este caso un oscilador de cristal a 4 MHz, entre
las entradas OSC1 y OSC2. Por último, se conectará un LED con su resistencia para limitar la
corriente al terminal RBO tal y como aparece en la figura inferior.

Figura 5.3: Esquema de conexiones con el microcontrolador para comparar el valor


DE DOS SEÑALES DE ENTRADA ANALÓGICAS PROPUESTO EN EL EJERCICIO 5.2.1.

b)

Configuración

Para configurar el módulo comparador analógico será necesario ajustar el registro CMCON
(véase anexo A2.13). Esto se realizará mediante la definición de diferentes constantes que
se utilizarán para definir el modo de funcionamiento y se incluirán en el archivo de
definiciones "analog.h". Las constantes harán referencia a la configuración de los
comparadores del recuadro inferior y serán las siguientes:

Página | 130
5. Módulos analógicos

# d e fin e CA RESET 0x 00
# d e fin e CA A0 A3 NC NC ON A4 0x 01
# d e fin e CA A0 A3 Al A2 0x 02
# d e fin e CA A0 A3 Al A2 ON A4 A5 0x03
# d e fin e CA A0 A3 Al A3 0x04
# d e fin e CA A0 A3 Al A3 ON A4 A5 0x05
# d e fin e CA A0 VR Al VR 0x06
# d e fin e CA A3 VR A2 VR OxOE
# d e fin e CA NC NC NC NC OFF 0x07
# d e fin e CA C 1 IN V 0x 10
# d e fin e CA C 2 IN V 0x 20

Comparators Reset Comparators Off (POR Default Valué)


CM2:CM0 = o d o CM2:CM0 = l l i
RAQ/ANQ ■ RAO/ANO ■
- O f (Read as ’C) ■ Off (Read a=
RA3/AN3 ■ RA3/AN3 -

RA1/AN1 • RA1/AN1 - _ •

- Off (Read as C2 •Off (Read as ’0 ')


RA2/AN2 • RA2/AN2 -

Two Independent Comparators with Outputs


Two Independen! Comparators CM2:CM0 = O lí
CM2:CMQ = 010
RAO/ANO ■
V r .+
RA3/AN3 -
+ C>
RA4jT 0C Kl/C t C UT

RAIZAN1 —----- —
RA2WI2 A 'A,,t SP RA2ZAN2 -Ó----- —
RAE/AN4/SS;C20UT

Two Comraon Referen ce Comparators Two Common Reference Comparators with Outputs
CM2;CM0 = 100 CM2:CM0 = 101
Vv-
RA0/AN0 ■
RA3/AN3 v cC
+
RA4/T0CKI/C1OUT
RA1/AN1 -
v •»-
RA2>‘AN2 - RAIZAN! —-----
C2
RA2/AN2 -2 - + /
RA5/ANMSS/C20UT

One Independen! Compar3tor with Output Four Inputs Multiplexed to Two Comparators
CM2:CM0 = 0 3 1 CM2:CM0 = 110

RAQ-'ANQ —------^ RAO,'ANO -4_> _ CIS - o VtN-


RA3/AN3 ------ — cC -C10U T RA3ÍAN3 az - 1
VlM'f ( c
RA4.TÜCKL'C 10üT
RA1/AN1 — > CIC- WN. l \
RA2ZAN2 - 4 - . CIS- 1 ViMf c
RA1/AN1 -
- Off (Read as *3')
RA2ÍAN2 . c\ RE-

Figura 5.4: Resumen de los modos de funcionamiento de los comparadores analógicos.

Página | 131
Programación de microcontroladores PIC en lenguaje C

Una vez definidas las constantes se utilizará una macro, que también se incluirá en el
archivo de definiciones "analog.h", para ajustar la configuración del módulo. La macro
tendrá la siguiente estructura:

# d e f i n e SETUP_COMPARATOR(CONFIG_COMPARATOR) \
CMCON=CONFIG_COMPARATOR;

Código fuente

# i n e l u d e < h t c .h >
# in e lu d e " a n a lo g .h "

« d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ


__ CONFIG (WRT_OFF & WDTE OFF & PWRTE_OFF & FOSC_XT & LVP OFF) ;

v o id m a in (v o id ){
T R IS B = 0 x F E ; / / T e r m in a l RB0 como s a l i d a
\ di O; //S e d e s h a b i l i t a n i n t e r r u p c i o n e s
' SETUP_COMPARATOR (C A _A O _A3_NC _NC_O N _A41CAC 1IN V) ; / / C o n fig u r a e l
/ / co m p a ra d or 1 co n
/ / e n t r a d a s p o r RAO y
//RA3 y s a l i d a
/ / i n v e r t i d a p o r RA4
w h i l e ( 1 ) {_
i f ( C lO U T ) RB0 = 1 ;
e ls e RB 0 = 0;
}
}

Modificar el programa para que el led se active cuando la señal en B es mayor que en A.

5.2.2. Comparación de una señal analógica con una señal de referencia


Se propone diseñar un sistema basado en un microcontrolador PIC16F877A trabajando a
4 MHz que encienda un LED si una señal analógica, V ini supera los 2.2 V.

a) Indica las conexiones necesarias con el microcontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.

Solución:

a) Para el funcionamiento del microcontrolador es necesario conectar correctamente las


entradas VDD y VSS a +5V y 0V respectivamente. Además, será necesario conectar el
oscilador, en este caso un oscilador de cristal a 4 MHz a las entradas OSC1 y OSC2 tal y
como aparece en la figura 5.5. Por otro lado, se conectará la señal analógica V in a una de las
entradas del módulo comparador RA0/AN0/C1IN-, la salida del módulo generador de
tensión de referencia RA2/AN2/CVREF a la otra entrada del comparador 1 RA3/AN3/C1IN+ Y
el LED a la salida correspondiente del comparador RA4/C10UT. Dado que la salida del
comparador RA4/C10UT es en drenador abierto será necesario utilizar una resistencia de
PULL-UP conectada a +5 V y al ánodo del LED según se muestra en la siguiente figura.

Página 1 132
5. Módulos analógicos

Figura 5.5: Esquema de conexiones con el microcontrolador para comparar el valor de una señal de entrada
ANALÓGICA CON UN VALOR DE REFERENCIA PROPUESTO EN EL EJERCICIO 5.2.2.

b) Para su correcto funcionamiento el programa deberá configurar el módulo generador de


tensión de referencia para obtener una tensión de 2.2 V. Por otro lado, se configurará el
módulo comparador C1 con entradas analógicas por RA0/AN0/C1IN- y RA3/AN3/C1IN+ y su
salida RA4/C10UT habilitada y conectada a la salida del módulo generador de tensión de
referencia RA2/AN2/CVREF.

Configuración

Para la generación de 2.2 V se utilizará el módulo generador de tensión de referencia


trabajando en rango alto y se aplicará la siguiente fórmula:
fCVR < 3:0 > \
cvREF = -CV r^4s r c +' V 32 j
*CVR:

Si se sustituye C V E F = 2 . 2 V y C V
r = 4 . 4 V y se despeja se obtiene que CVR = 8. Una vez
r s r c

obtenido el valor de CVR se configura el módulo utilizando la siguiente instrucción:


SETCVR EF (CVR_ON | CVR HXGH | CVR_OUT_ON | 8 ) ; / / A ju s t e CVREF= 2 .2V con
/ / s a lid a h a b i l i t a d a

Por otro lado, se deberá configurar el módulo comparador 1 con entradas analógicas por
RAO/ANO/CUN- y RA3-/AN3/C1IN+ y salida RA4/C10UT habilitada. Se utilizarán para ello las
siguientes instrucciones.

T R IS A 4 = 0 ; //Se h a b i l i t a l a s a l i d a p o r RA4
s e t a dc in p u t s (AN0 A N 1 A N 3 ) ¡ //Se h a b i l i t a n e n tra d a s a n a ló g ic a s ANO,
//AN1 y AN3
SETUP COMPARATOR( CA_A0 A3_NC NC_ON A4) // C o n fig u ra e l coinp arador a n a ló g ic o 1
//con e n tra d a s p o r R A O (-) y R A 3 U )
//y s a l i d a p o r RA4

Página 1 133
Programación de microcontroladores PIC en lenguaje C

Código fu en te

# in c lu d e < h tc .h >
# in c lu d e "a n a lo g .h "
# d e f i n e _XTAL_FREQ 4000000 / / O s c i l a d o r I n t e r n o d e 4MHZ
__ CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & L V P _ O F F );
v o id m a in (v o id ){
d i () ; //S e d e s h a b i l i t a n i n t e r r u p c i o n e s
SET_CVREF(CVR_ON | CVR_HIGH | CVR_OUT__ON | 8 ) ; / / A ju s t e d e l a t e n s i ó n de
/ / r e fe r e n c ia
T R IS A 4 = 0 ; //Se h a b i l i t a l a s a l i d a p o r RA4
s e t_ a d c _ in p u t s (A N 0 _ A N 1 _ A N 3 ) ; //Se h a b i l i t a n e n t r a d a s a n a l ó g i c a s
ANO, AN1 y AN3
SETUPCOMPARATOR(CA A0 A 3_N C _N C _O N _A 4); / / C o n fig u r a e l c o m p a ra d o r
/ / a n a ló g ic o 1 c o n e n t r a d a s p o r
/ /RAO( - ) y R A 3 ( + ) y s a l i d a p o r RA4
w h ile (1 );
}

M odificar el programa para que se ilumine el led cuando la señal de entrada sea inferior a
0.5V.

5.2.3. Sensor de luminosidad TSL251RD


Se pretende realizar un programa basado en un microcontrolador PIC16F877A trabajando a
4MHZ que encienda un led cuando detecte que la luz ambiente se ha reducido por debajo
de un nivel de referencia ajustable. Para ello se cuenta con el sensor de luminosidad
TSL251RD que proporciona un valor de tensión de salida proporcional a la irradiancia
recibida.

a) Indica las conexiones necesarias con el microcontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.

Solución:

a) Para el funcionamiento del microcontrolador es necesario conectar correctamente las


entradas VDD y VSS a +5V y 0 V respectivamente. Además, será necesario conectar el
oscilador, en este caso un oscilador de cristal a 4MHz a las entradas OSC1 y OSC2 tal y como
aparece en la figura 5.6.
El integrado TSL251RD se conectará siguiendo las indicaciones de la hoja de
especificaciones con su salida analógica conectada a la entrada analógica AN1/RA1/C2IN- y
la tensión de referencia analógica se conectará a la entrada analógica AN3/RA3. La salida
del módulo comparador 2 RA5/AN4/C20UT se conectará a un LED utilizando una resistencia
que limitará la corriente del diodo cuyo cátodo estará conectado a 0 V como se muestra en
la figura siguiente.

Página | 134
5. Módulos analógicos

+5V

£ 470Í2
nrrtlNC nc Iíhsj
1KÍ2 VDD

lO O n F .
TSL251RD
VW\r
[2ZI: NC j---- iOUT C7J------- RA1 RA5 —VWV— —
e n : nc I— vDD||Ejs- DO
+5V
-sn GND NC C5J PIC16F877A

470Q
RA3
Vss
OSC1 OSC2

4MHz
—Of-
20pF 20pF

I I
Figura 5.6: Esquema de conexiones con el microcontrolador para utilizar
EL SENSOR DE LUMINOSIDAD TSL251RD PROPUESTO EN EL EJERCICIO 5.2.3.

b) Para la realización del sistema será necesaria la utilización de uno de los comparadores
analógicos de los que dispone el PIC16F877A con sus entradas conectadas a las señales
analógicas (salida del TSL251RD y tensión de referencia del potenciómetro). En este caso se
utilizará el comparador 2 como se observa en las conexiones de la figura superior con su
salida habilitada por RA5, que permitirá de forma automática encender el LED cuando la
tensión de salida del sensor de luminosidad supere el valor de referencia.

Configuración

La configuración del módulo comparador se realizará habilitando el comparador 2 y con sus


entradas analógicas por RA1/AN1/C2IN- y RA3/AN3 y su salida digital asociada
RA5/AN4/C20UT mediante las siguientes instrucciones:
T R IS A 5 = 0 ; //Se h a b i l i t a l a s a l i d a p o r RA5
s e t a d c i n p u t s (AN0_AN1_AN3) ; //Se h a b i l i t a n e n tra d a s a n a ló g ic a s
//ANO, A N l y AN3
SETUP COMPARATOR (CA_AO_A3_A1_A3_ON_A4_A5) / / C o n fig u ra e l com parador
// a n a ló gico 2 con entradas por R A I( - )
//y RA3(+ ) y s a l i d a p o r RA5

Código fu en te

# in c lu d e < h t c .h >
# in c lu d e " a n a l o g . h "

t d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r In t e r n o de 4MHZ


__ CONFIG (WRT OFF & WDTE_OFF & PWRTE OFF & FOSC_XT & LVP_OFF) ;

Página | 135
Programación de microcontroladores P1C en lenguaje C

d i() ; //Se d e s h a b i l i t a n i n t e r r u p c i o n e s
T R IS A 5 = 0 ; //Se h a b i l i t a l a s a l i d a p o r RA5
s e t a d c i n p u t s (AN0_AN1_AN3) ; //S e h a b i l i t a n e n t r a d a s a n a l ó g i c a s
SETUP COMPARATOR (CA_A O _A 3_A 1_A 3_O NI_A4__A5)
_A 4_A 5) ; / / C o n fig u r a e l c o m p a r a d o r 2
/ / co n e n t r a d a s p o r R A l ( - ) y
// R A 3(+ ) y s a l i d a p o r RA5
w h ile (1 );
}

5.3. Módulo Conversor Analógico Digital (CAD)


Los registros de configuración asociados al módulo CAD son ADCONO (A2.10) y ADCON1
(A 2 .ll) y el resultado de la conversión se almacena en los registros ADRESH y ADRESL.

El CAD integrado en el P1C16F877A es un conversor de 10 bits que cuenta con 8 entradas


\ analógicas (AN0-AN7) que se reparten entre el PORTA y el PORTE. La selección del canal de
conversión se realiza mediante los bits CHS2:CHS0 del registro ADCONO.

El amplificador de muestreo y retención está compuesto básicamente por un condensador


(sin amplificadores de entrada ni de salida), que empieza a cargarse en cuanto se selecciona
en el multiplexor el canal deseado. La tensión en el condensador sigue la evolución de la
tensión de entrada, y cuando se da una orden el condensador se desconecta de la entrada
analógica y empieza la conversión. La tensión de referencia para la conversión A/D puede
ser la tensión de alimentación del microcontrolador (valor por defecto) o una tensión
externa que se aplique entre los terminales de referencia AN3/VREF+ y AN2/VREF-. Esta
selección se realiza mediante los bits PCFG3:PCFG0 del registro ADCON1. Las conversiones
A/D se realizan en sincronismo con una señal de reloj. Este reloj se obtiene o bien del
oscilador principal del microcontrolador mediante un divisor programable, o bien de un
oscilador RC interno de frecuencia fija. Para que el CAD funcione mientras el
microcontrolador está en el modo de bajo consumo (s/eep), hay que seleccionar el oscilador
RC interno.

Para iniciar una conversión A/D hay que activar el bit de control GO/DONE#. Cuando el
resultado de la conversión está ya disponible en ADRESH y ADRESL se desactiva
automáticamente el bit de estado GO/DONE# y se activa el bit ADIF del registro PIR1 para
solicitar interrupción. Si el bit ADIE del registro PIE1 está activo y el sistema de interrupción
del microcontrolador está habilitado el microcontrolador recibe una solicitud de
interrupción.

Página | 136
5. Módulos analógicos

Registros de control

A N O /R AO
DONE#
A N 1 /R A 1 K >

A N 2 A /R E F -/R A 2 IS >

A N 3 /V r b ^ / R A 3 CS>

A N 4 /R A 5

Figura 5.7: Esquema de bloques del módulo conversor analógico digital.

5.3.1. Configuración del módulo CAD


En este ejemplo se pretende crear una función que configure el módulo CAD de un PIC16F877A
para trabajar con un oscilador a 4 MHz, utilizando todas las entradas analógicas disponibles.

Solución:

La solución propuesta va a considerar el caso del microcontrolador trabajando a 4 MHz


utilizando todas las entradas analógicas pero se extenderá para un cualquier caso genérico
de configuración del módulo CAD pudiendo utilizarse para cualquier configuración del
módulo a partir de los parámetros que se le pasen a las funciones.

Configuración

Para la creación de la función será necesario definir diferentes constantes que determinen el
modo de trabajo del módulo y que permitan ajustar los registros de configuración ADCONO y
ADCON1. Así, se definirá la constante ADCLK_FREQ_DIV que tomará el valor de la constante
_XTAL_FREQ dividida por 1.25 MHz de forma que permita obtener el factor divisor a aplicar al
reloj principal en el caso de que el CAD trabaja con dicho reloj y cumplir con las especificaciones
de funcionamiento del fabricante. También se definirá la constante ADCLK_RC que seleccionará
el reloj interno del CAD. Estas constantes junto con la definición de la función setup_adc se
incluirán en el fichero analog.h que tendrá la siguiente estructura.
t d e f i n e A D C C L K R C OxCl
# d e f i n e ADC_FREQ_DIV ( f l o a t ) (_XTAL_FREQ/1250000)
e x t e r n v o i d s e t u p a d c ( u n s i g n e d c h a r mode) ;

Página | 137
Programación de microcontroladores PIC en lenguaje C

Además se utilizará una función adicional set_adc_¡nputs() que permitirá definir las
entradas analógicas con las que se trabajará. Para ello se definirán nuevas constantes que
permitirán ajustar el registro de configuración ADCON1 y que se incluirán junto con la
definición de la función también en el fichero analog.h.

#define ADCOFF 0x00


#define ALLDIGITAL 0x06
#define ALL_ANALOG 0x00
#define ALL_ANALOG_V 0x01
#define ALL_ANALOG_V_V- 0x08
#define ANO OxOE
#define AN0_V_V- OxOF
#define AN0AN1JV 0x05
#define AN0_AN1_V_V- 0x0D
#define AN0_AN1_AN3 0x04
#define AN0AN4 0x02
#define AN0_AN4_V 0x03
#define AN0_AN4_V_V- OxOC
fldefine AN0AN5 0x09
#define AN0_AN5_V OxOA
#define AN0_AN5_V_V- OxOB

extern void set_adc_inputs(unsigned char analog);

El código de las funciones setup_adc() y set_adc_¡nputs() se incluirá en el fichero analog.c


que deberá añadirse dentro del proyecto en el que se utilice el módulo CAD así como la
sentencia #include "analog.h'1. como se muestra en el ejemplo siguiente.

Código fuente
//Ajusta las entradas analógicas/digitales
extern void set_adc_inputs(unsigned char analog){ //Selecciona las entradas
//analógicas
ADCONl=(ADCONl&OxFO)|analog;
}
//Selecciona el modo de reloj del CAD, ajusta el canal 0, enciende el módulo y
//ajusta a la izquierda
extern void setup_adc(unsigned char mode){ //Selecciona el modo de reloj
if (mode==0x00){ //CAD apagado
ADCONO = 0x0 0;
ADCONl&=0x06; //E/S digitales
}
e l s e if (m o d e = = 0 x C l){ //Reloj RC
ADCONO=0xCl; //con ajuste derecho
ADCONl&=0xBF;
}
e ls e {
if(A D C _ F R E Q _ D IV < = 1 ){ //Fose <= 1.25MHz
ADCONO= 0x01; //ADCS1=0, ADCS0=0, Canal 0,
//Módulo encendido
ADCONl&=0xBF; //ADFM=1(ajuste a la derecha), ADCS2=0
}
e ls e if(A D C _ F R E Q _ D IV < = 2 ){ //Fose <= 2.5MHz
ADCONO=0x01; //ADCS1=0, ADCS0=0, Canal 0,
//Módulo encendido
ADCON1|=0xC0; //ADFM=1(ajuste a la derecha), ADCS2=1
}

Página | 138
5. Módulos analógicos

e ls e if(A D C _F R E Q _ D IV < = 4 ) { //Fose <= 5MHz


ADCONO=0x41; //ADCS1=0, ADCS0=1, C anal 0,
//Módulo en c e n d id o
ADCONl&=OxBF; //A D FM =1 (aju ste a l a d e r e c h a ), ADCS2=0
}
e ls e i f (ADC_FREQ_DIV<: = 8 ) { //Fose <= 10MHz
ADCONO=0x41; ; //ADCS1=0, ADCS0=1, C anal 0,
//Módulo en c e n d id o
ADCON11=0xC0; //A D FM =1(aju ste a l a d e r e c h a ), ADCS2=1
}
e ls e if(A D C _F R E Q _D IV < = 1 6 ) { //Fose <= 20MHz
ADCONO=Ox81; //ADCS1=1, ADCS0=0, C anal 0,
//Módulo en c e n d id o
ADCONl&= OxBF; / /A D FM =1(aju ste a l a d e r e c h a ), ADCS2=0
}
e ls e { //Fose <= 40MHz
ADCONO=0x81; //ADCS1=1, ADCS0=0, C anal 0,
//Módulo en c e n d id o
//A D FM =1(aju ste a l a d e r e c h a ), ADCS2=1

5.3.2. C o nversió n analógica digital en un canal


Se pretende utilizar el módulo CAD para realizar una conversión del valor de tensión (0-5 V)
a la entrada del puerto RAO y que muestre el valor de los cuatro bits más significativos
obtenidos de la conversión en los led conectados a las terminales del puerto B (RB3-RB0).

a) Indica las conexiones necesarias con el mlcrocontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.

Solución:

a) En la figura inferior se muestran las conexiones necesarias con el microcontrolador.

Figura 5.8: Esquema de conexiones con el microcontrolador para convertir una señal de entrada analógica.

Página | 139
Programación de microcontroladores PIC en lenguaje C

b)

Configuración

Una vez configurado el módulo CAD en el canal 0 utilizando la función del ejemplo anterior
setup_adc() y habiendo esperado el tiempo de adquisición es necesario lanzar la conversión
poniendo a '1' el bit GO del registro ADCONO. Para esto se definirá la macro
START_ADC_CONV. Por último se creará una función que recoja el valor obtenido tras la
conversión read_adc().
# d e f i n e START_ADC_CONV GO=l / / L a n za una c o n v e r s i ó n a n a l ó g i c o d i g i t a l
e x t e r n u n s ig n e d i n t r e a d _ a d c ( v o i d ) ;

La estructura de la función anterior y la macro se incluirá dentro del fichero analog.h y el


código correspondiente que aparece a continuación en el fichero analog.c.

// R e c o g e e l v a l o r d e l a c o n v e r s i ó n d e 10 b i t s
e x t e r n u n s ig n e d i n t r e a d _ a d c ( ) {
w h ile (G O )c o n t in u é ; / / e s p e r a a qu e f i n a l i c e la c o n v e r s ió n
r e t u r n ( (A D R E S H «2 ) + (ADRESL>> 6 ) ) ;
}

Una vez creada la función anterior junto con las que se mostraron en el ejemplo anterior
solo será necesario ir llamándolas una tras otra desde el programa principal para obtener el
valor de la conversión. Es necesario también un último detalle que consiste en configurar el
puerto B como salidas ya que por defecto se configurarán como entradas al arrancar el
microcontrolador. Para ello basta con utilizar la instrucción:
TRISB = 0x00;
Código fuente
# in c lu d e < h t c .h >
# in e lu d e "a n a lo g .h "

# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ


CONFIG(WRT OFF & WDTE OFF & PWRTE OFF & FOSC XT & LVP O F F );

void main(void){
int x;
di () ; //S e d e s h a b i l i t a n i n t e r r u p c i o n e s
TRISB = 0x00; / / P u e r to B c o n f i g u r a d o como s a l i d a
setup_adc (A D C C L K O S C ); / / I n i c i a l i z a e l m ódu lo CAD en e l c a n a l 0
s e t a d c i n p u t s (A N O );
_d e l a y u s (50); / / E s p e ra e l tie m p o de a d q u i s i c i ó n (a p r o x 44us)
while(1){
START_ADC_CONV; / / L a n za l a c o n v e r s i ó n
x=read_adc(); / / O b tie n e e l v a l o r d e l a c o n v e r s ió n
PORTB = (x>>6);

Página | 140
5. Módulos analógicos

5.3.3. Conversión analógica digital de varios canales


En este ejemplo se pretende utilizar el módulo CAD para realizar la conversión de 8 señales
analógicas y almacenar los valores obtenidos en una tabla que se actualice de forma
continua con los nuevos valores.

Solución:

En el ejemplo anterior no era necesario seleccionar el canal ya que se trabajaba con el canal
0, que es el que se establece por defecto al arrancar el módulo, pero ahora será necesaria
una función que permita seleccionar el canal a convertir de entre las 8 entradas posibles.

Configuración

Para ello se definirá en "analog.h" la estructura de una nueva función que permita
seleccionar el canal analógico set_adc_channel():
e x te rn v o id s e t _ a d c _ c h a n n e l(u n s ig n e d ch a r ch a n n el) ;

El código de la función anterior se incluirá en el archivo "analog.c y lo que hará será


modificar el registro ADCONO para seleccionar el canal según se muestra a continuación.
/ / S e le c c io n a e l c a n a l d e c o n v e r s ió n
//Cada v e z qu e s e c a m b ia de c a n a l es n e c e s a r io e s p e r a r
/ / e l t ie m p o d e a d q u i s i c i ó n (a p r o x 44us) p a ra que
/ / se e s t a b i l i c e l a t e n s ió n a l a e n tr a d a d e l CAD
/ / a n te s d e l a n z a r una c o n v e r s ió n n u eva.

e x t e r n v o i d s e t _ a d c _ c h a n n e l(u n s ig n e d ch a r ch a n n el) {
ADCONO = ( ADCONO&0xC7) | ( (ch a n n el% 8 ) « 3 ) ;

De esta manera únicamente será necesario crear un array de tipo int para ir almacenando
los valores obtenidos tras la conversión de cada canal y utilizar un contador que indique el
canal a convertir en cada momento.
Código fuente

t fin c lu d e < h t c .h >


# in c lu d e " a n a l o g . h "

# d e fin e X TA LF R E Q 4000000 / / O s c ila d o r I n t e r n o de 4MHZ


__ CONFIG (WRT_OFF & WDTE OFF & PWRTE OFF & FOSCXT & LVP_OFF) ;

v o id m a in (v o id ){

u n s ig n e d c h a r i ;
in t t a b la [8] ;
i =0 ;
di O ; //Se d e s h a b i l i t a n i n t e r r u p c io n e s
s e t u p a d c (A D C C L K O S C ) ; / / I n i c i a l i z a e l m ódulo CAD
s e t _ a d c _ in p u t s (A L L _ A N A L O G );

Página | 141
Programación de microcontroiadores PIC en lenguaje C

w h ile (1 ) {
s e t _ a d c _ c h a n n e l(i% 8 ) ;
__ d e l a y u s ( 5 0 ) ; / / E s p e ra e l t ie m p o d e a d q u i s i c i ó n
START_ADC_CONV; / / L a n za l a c o n v e r s i ó n
t a b l a [i% 8 ] = r e a d _ a d c ( ) ; / / O b tie n e e l v a l o r d e l a c o n v e r s i ó n
i+ + ;
}
}

5.3.4. Sensor de Temperatura TC1047A


Se pretende realizar un programa basado en el microcontrolador PIC16F877A trabajando a
4 MHz que recoja el valor de temperatura proporcionado por el sensor TC1047A (consultar
nota de aplicación de Microchip© DS00938A para más información sobre el funcionamiento
del sensor) y lo muestre en la pantalla LCD HITACHI HD44780.

a) Indica las conexiones necesarias con el microcontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.

Solución:

a) Para el funcionamiento del microcontrolador será necesario conectar correctamente las


entradas VDD y VSS a +5 V y 0 V respectivamente y el oscilador, en este caso un oscilador de
cristal a 4 MHz, a las entradas OSC1 y OSC2 tal y como aparece en la figura inferior. El
sensor de temperatura TC1047A se conectará siguiendo las indicaciones de la hoja de
especificaciones con su salida conectada a una de las entradas analógicas del
microcontrolador (RA0/AN0). La conexión de la pantalla LCD se realizará siguiendo las
instrucciones del fabricante para utilizar el modo de comunicaciones de 4 bits a través de
los terminales RD0-RD4.

Figura 5.9: Esquema de conexiones con el microcontrolador para utilizar el sensor de temperatura
ANALÓGICO TC1047 PROPUESTO EN EL EJERCICIO 5.3.4.

Página | 142
5. Módulos analógicos

b) Para realizar el programa será necesario configurar el módulo CAD con entrada analógica
por RAO además de definir los terminales del puerto D como salidas. El manejo de la
pantalla LCD se realizará utilizando las funciones definidas en la librería "Icd.h".

Configuración

El módulo CAD se configurará con entrada analógica por RAO y utilizando el reloj interno del
microcontrolador mediante las siguientes instrucciones:

s e t u p _ a d c (ADC_CLK_OSC) ; / / I n i c i a l i z a e l modulo CAD


s e t _ a d c _ in p u t s (ANO) ; / / C o n fig u ra l a s e n tra d a s a n a ló g ic a s
s e t_ a d c _ c h a n n e l( 0 ) ; / / S e le c c io n a e l c a n a l de e n tra d a d e l c o n v e r s o r

Para representar el valor de temperatura en la pantalla LCD será necesario convertir el valor
de tensión leído a la salida del sensor a °C utilizando la siguiente fórmula:

VOUT = (10 mV/°C) (Temperature °C) + 500 mV

Una vez obtenido el valor de temperatura en °C se deberá representar en la pantalla LCD.


Para ello se hará uso de la función printf incluida en la librería "stdio.h". Esta función se
encarga de dar formato a una cadena de caracteres en código asen y va llamando a la
función putch para enviar cada uno de los caracteres de la cadena. En este caso se definirá
la función putch de forma que lo que haga sea enviar un carácter a la pantalla LCD de la
siguiente manera:

v o i d p u t c h (c h a r x ) {
le d p u t c h (x );
}

Código fuente

# in c lu d e < h t c .h >
# in c lu d e < s t d i o . h >
# in c lu d e " a n a l o g . h "
# in c lu d e " I c d . h "

# d e fin e X TA LF R E Q 4000000 / / O s c ila d o r I n t e r n o de 4MHZ


__ CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & L V P _O F F );

v o id p u tc h (c h a r );
v o id m a in (v o id ){
f l o a t tem p; // V a r ia b le p a ra a lm a cen a r l a te m p e ra tu ra
l e d i n i t (); / / I n i c i a l i z a c i ó n de l a p a n t a l l a LCD
d i () ; //Se d e s h a b i l i t a n i n t e r r u p c i o n e s
s e tu p _a d c(A D C _C L K _O S C ); / / I n i c i a l i z a e l módulo CAD
s e t _ a d c _ in p u t s (A N O ); //Se c o n f ig u r a RAO como e n tra d a
/ / a n a ló g ic a
s e t_ a d c _ c h a n n e l( 0 ) ; //Se s e l e c c i o n a e l c a n a l de e n tra d a
/ / a n a ló g ic o en RAO
w h ile (1) {
START_ADC_CONV; //Lanza l a c o n v e r s ió n
t e m p = (flo a t )r e a d a d e () ; // R ecoge e l v a l o r de l a c o n v e r s ió n
temp= ( ( t e m p *4 . 8 8 ) - 5 0 0 ) /10; / / C o n v ie r t e e l v a l o r a g ra d o s

Página | 143
Programación de microcontroladores PIC en lenguaje C

l c d g o t o ( 0) ; / / P o s ic io n a e l c u r s o r a l i n i c i o d e l a
/ / p a n t a l l a LCD
p r i n t f ( "Temp = % .2 f C " ,te m p ) / / M u e s tra e l v a l o r d e t e m p e r a t u r e p o r
/ / la p a n t a l l a LCD
__ d e l a y m s ( 5 0 0 ) ; / / E s p e ra m e d io S egu n do a n t e s d e l a n z a r
/ / o tr a c o n v e r s ió n
}
}
v o i d p u t c h (c h a r x ) {
lc d _ p u tc h (x );
}

Página | 144
6. Módulos de comunicaciones
En este capítulo se presentan los módulos de comunicaciones serie que integra el
microcontrolador PIC16F877A. En particular, el PIC16F877A integra dos módulos de
comunicaciones serie independientes que utilizan los terminales asociados al PORTC. Estos
módulos son el módulo USART (Universal Synchronous Asynchronous Receiver Transmitter)
y el módulo MSSP (Master Synchronous Serial Port).

6.1. Módulo USART (Universal Synchronous Asynchronous Receiver Transmitter


6.2. Módulo MSSP (Master Synchronous Serial Port)

6.1. Módulo USART


El microcontrolador PIC16F877A integra un módulo transmisor/receptor
asíncrono/síncrono universal (Universal Synchronous Asynchronous Receiver Transmitter,
USART) también denominado como interfaz de comunicaciones serie (Serial
Communications Interface, SCI). Este módulo se utiliza generalmente en modo full-duplex
para comunicaciones asincronas con ordenadores personales aunque también puede
emplearse en modo half-duplex para comunicaciones síncronas con otros periféricos como
memorias, conversores analógico/digitales, etc. (para más información sobre
comunicaciones síncronas utilizando el módulo USART consultar las hojas de
especificaciones del microcontrolador). Este módulo permite por tanto la comunicación del
microcontrolador utilizando los protocolos RS232, RS422 y RS485 siempre y cuando se
adapten los niveles de señal utilizados por el microcontrolador (generalmente 5V) a los
utilizados por los protocolos anteriores mediante la utilización, por ejemplo, del integrado
MAX232 o similar.

Dado que el módulo USART es un módulo periférico integrado en el microcontrolador, este


requerirá para su funcionamiento de una configuración inicial al comienzo del programa.
Una vez configurado, el módulo USART funcionará de forma autónoma requiriendo la
atención del microcontrolador sólo cuando sea necesario ya sea mediante interrupciones,
cuando estas estén habilitadas, o únicamente activando los indicadores "flags" asociados ai
módulo. La configuración de los módulos transmisor y receptor se realiza mediante los
registros TXSTA (A2.14), RCSTA (A2.15) y SPBRG mientras que el envío y recepción de datos
se realiza utilizando los registros TXREG y RCREG respectivamente.

Con respecto al módulo transmisor, el bit TXIF del registro PIR1 se pone a '0' cada vez que
escribimos un nuevo dato sobre el registro TXREG y, pasa a '1' cuando el contenido de este
buffer se copia sobre el TSR para dar inicio a la transmisión del nuevo carácter. En este
momento, si se desea, se puede provocar una interrupción al controlador. El bit TRMT del
registro TXSTA, indica el estado del registro de desplazamiento TSR. Se pone a '1' cuando se
encuentra vacío, sin nada que transmitir.

Página | 145
Programación de microcontroladores PIC en lenguaje C

Pueden realizarse transmisiones de 9 bits por cada carácter. En este caso, los 8 bits de menos
peso se cargan en el registro TXREG mientras que el noveno (bit 8) se carga en el bit TX9D del
registro TXSTA. Esta característica se habilita mediante el bit TX9 del mismo registro.

El módulo transmisor se habilita mediante el bit TXEN. En ese momento interviene el circuito
generador de baudios, que determina la frecuencia o ritmo con el que se transmite cada bit.
La frecuencia del circuito generador de baudios, que determinará la velocidad de
comunicación, se establece mediante el registro SPBRG asociado al generador de baudios,
una serie de bits de control y el oscilador principal del sistema (Fose). Por último, el bit SPEN
habilita la puerta serie y configura el terminal RC6/TX/CK, que puede actuar como línea TX de
transmisión de datos en el modo asincrono o como línea CK de reloj en el modo síncrono.

El circuito de recepción cuenta con un registro de desplazamiento de entrada serie y salida


paralelo llamado RSR (Receiver Shift Register) al que no se puede acceder directamente. El
bit SPEN del registro RCSTA, se emplea para habilitar la puerta serie, y con ello configurar el
terminal RC7/RX/DT como línea Rx de recepción asincrona, o bien como línea DT de datos
en el modo síncrono. Por este terminal se van recibiendo los bits, que se van almacenando
en el registro RSR para posteriormente copiarse al registro de recepción RCREG una ver
recibidos los caracteres de 8/9 bits. El RCREG funciona internamente como un buffer de
entrada tipo FIFO (primero en entrar primero en salir) capaz de almacenar dos caracteres.
Cuando el RSR recibe un carácter, se copia sobre el primer nivel de la FIFO, el propio RCREG.
Al recibir un segundo carácter, sin leer el primero se almacena en el segundo nivel. Al leer
RCREG el programa lee el primer carácter recibido y si hubiera un carácter sin leer pasaría
automáticamente al RCREG. En el caso de recibir un tercer carácter sin leer los dos
anteriores se genera un error de desbordamiento que se refleja en el bit OERR. Otro tipo de
error que se puede producir en la recepción es el llamado "error de trama" que se ve
reflejado en el bit FERR.

Página | 146
6. Módulos de comunicaciones

Siempre que en el registro RCREG haya un carácter disponible, el bit RCIF del registro PIR1
se pone a nivel 'Y . En este momento, si el bit RCIE del registro PIE1 estuviera también a
nivel ‘Y , se generaría una interrupción por recepción de un carácter.
El sistema de recepción se habilita mediante el bit CREN. El circuito generador de baudios
(el mismo utilizado en la sección de transmisión) determina la frecuencia o ritmo con la que
se recibe cada bit.

6.1.1. Crea una macro que permita configurar del módulo USART
en modo asincrono
Solución:
En este ejemplo se va a configurar el módulo USART para comunicaciones en modo
asincrono de forma genérica. Para ello se creará una macro que permitirá introducir los
valores necesarios en los registros de configuración.

Configuración

Para la creación de la macro será necesario definir diferentes constantes que determinen el
modo de trabajo del módulo y que permitan ajustar los registros de configuración TXSTA,
RCSTA y SPBRG. En este caso se definirá una máscara que ajuste el modo de trabajo en alta
velocidad HIGH_SPEED = 0x04 y otra que ajuste el modo de funcionamiento en 9 bits
NINE_BITS=0x40. Estas máscaras se utilizarán junto con la función OR (|) para ajustar los
registros de configuración TXSTA y RCSTA. El registro SPBRG que determinará la velocidad
del módulo obtiene su valor a partir del oscilador principal y el modo de funcionamiento a
alta o baja velocidad a partir de las siguientes fórmulas:

Página | 147
Programación de microcontroiadores PIC en lenguaje C

Baja velocidad -> SPBRG = ---- — —


64 (X + 1)
F
Alta velocidad -> SPBRG = ---- — —
16(X + 1)

Así pues, la macro para configurar el módulo USART en modo asincrono tendrá la siguiente
estructura:

ffdefine INIT_USART(BAUD, SPEED, NINE)

Para utilizar esta función será suficiente con incluir el código fuente que aparece a
continuación dentro del programa o de una forma más elegante incluir el código en un
archivo de definiciones denominado usart.h y añadirlo a nuestro programa principal
mediante la sentencia ffinclude "usart.h"

Código fuente
(tifn d e f _S E R IA L_H _
# d e fin e _S E R IA L _H _
# d e fin e H IG H SPEE D 0x04 //Modo a l t a v e l o c i d a d
# d e fin e LOW_SPEED 0 //Modo b a j a v e l o c i d a d
# d e fin e N I N E B I T S 0x40 //Modo t r a n s m is ió n 9 b i t s
# d e fin e E IG H T B IT S 0 //Modo t r a n s m is ió n 8 b i t s
# d e fin e _XTAL_FREQ 4000000 / / F r e c u e n c ia d e l o s c i l a d o r p r i n c i p a l
# d e fin e R X P I N TRISC7 / / D e fin e e l p i n RC7 como p i n p a r a
/ / r e c e p c ió n de d a t o s
# d e fin e T X P I N T R IS C 6 / / D e fin e e l p in RC6 como p i n p a r a
/ / t r a n s m is ió n de d a t o s

/*MACRO PARA CONFIGURAR EL MÓDULO USART EN MODO ASINCRONO*/


//BAUD: V e l o c i d a d de c o m u n ic a c io n e s (9 6 0 0 , 19200, 28800, e t c . )
//SPEED: Modo a l t a v e l o c i d a d p a r a e l g e n e r a d o r d e b a u d io s => TRUE = On
/ / N IN E : U t i l i z a t r a n s m is s io n de 9 b i t s => FALSE= 8b i t
# d e f i n e IN IT_U S A R T(B A U D ,S PE E D ,N IN E )\
R X P IN = 1; / / D e fin e l o s p in e s RC6 y RC7 p a r a p o d e r
T X P IN = 1 ; / / s e r u t i l i z a d o s p o r e l m ódu lo USART
i f (SPEED)SPBRG = ( (in t)(_ X T A L _ F R E Q / ( (16UL * BAUD) + 1 6 ) ) ) ; / / A ju s t a l a
/ / v e lo c id a d
e l s e SPBRG = ( ( i n t ) ( X T A L F R E Q / ( (64UL * BAUD) + 6 4 ) ) ) ; / / d el gen era d or
/ / d e b a u d io s
RCSTA = (N IN E | 0 x 9 0 ); / / C a rga l a c o n f i g u r a c i ó n d e l m ódu lo
/ / re c e p to r
TXSTA = (SPEED|NINE|0x20) / / C a rga l a c o n f i g u r a c i ó n d e l m ódu lo
// t r a n s m is o r

v o i d p u t c h (u n s ig n e d c h a r ) ; / / D e f i n i c i ó n de l a fu n c ió n p u tc h
# e n d if

Simulación

Se puede probar el funcionamiento de la macro anterior llamando a la función


INIT_USART(9600, HIGH_SPEED, EIGHT_BITS); desde el programa principal y observando el
valor que toman los registros de configuración TXSTA, RCSTA y SPBRG.

Página | 148
6. Módulos de comunicaciones

V/atch

ÍAdd SFR| ADCOMO ▼ ¡Add Symbol _pstnngiWs

Update Addreas Symbol llame | Valué j Decimal | Binar-/


■ tK Ü
OIS RCSTA 0x90 144
099 SPBRG OxlA 26

Walch 1 Walch2 j Walch 3 |Walch 4

Figura 6.3: S imulación de la configuración el módulo USART (Watch ).

6.1.2. Envío de datos utilizando el módulo USART


A partir del ejemplo anterior de configuración del módulo USART se pretende crear un
programa que se comunique con el puerto serie del ordenador personal y escriba a través
de un terminal la típica frase de iniciación en la programación "Hola Mundo!".

a) Indica las conexiones necesarias con el microcontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.

Solución:

o)

Consideraciones eléctricas

A la hora de conectar el microcontrolador PIC con el puerto serie del ordenador es


importante tener en cuenta los niveles de tensión con los que se está trabajando. El puerto
serie del ordenador sigue el estándar RS232 y los niveles de tensión con los que trabaja van
de entre +3 y +15 V para el T lógico y de -3 a -15 V para el '0' lógico mientras que el
microcontrolador trabaja con niveles de tensión entre 0 V y 3,3-5 V típicamente por lo que
es necesario utilizar un convertidor de tensión del tipo MAX232 o similar para adaptar los
niveles de señal. El esquema de la figura inferior muestra las conexiones necesarias entre el
microcontrolador y el ordenador utilizando el integrado MAX232.

F igura 6.4: Esquema de conexiones con el microcontrolador para utilizar el módulo


DE COMUNICACIONES U S A R T PROPUESTO EN EL EJERCICIO 6 . 1 . 2 .

Página | 149
Programación de microcontroladores PIC en lenguaje C

b)

Configuración

Para la configuración del módulo USART se utilizará la función IN ITJJSA R T detallada en el


ejemplo anterior y cuyo código se incluirá dentro de la librería usart.h a la que se añadirá la
definición de una nueva función que se encargará de enviar un byte de datos a través del
módulo USART. Esta nueva función denominada void putchfunsigned char byte) tendrá
como argumento un dato de tamaño byte y se encargará de transmitir el dato escribiéndolo
en el registro TXREG cuando el módulo esté disponible (b itTX IF=T).

El código fuente de la función putch se incluirá dentro de la librería usart.c y tendrá la


siguiente estructura:

v o i d p u t c h (u n s ig n e d c h a r b y t e ) {

w h ile (!T X IF ) //Se p o n e a uno cuando e l m o du lo e s t á lib r e


c o n tin u é ;
TXREG = b y t e ;
}

El envío de datos utilizando la función putch se realiza byte a byte por lo que para enviar
una cadena de caracteres sería necesario llamar a la función putch de forma consecutiva
por cada carácter a enviar utilizando un código similar al inferior:
v o id m a in (v o id ){
c o n s t u n s ig n e d c h a r t e x t o [ 1 1 ] = " H o la M u n d o !";
u n s ig n e d c h a r i = 0 ;
IN IT _ U S A R T (9 6 0 0 ,HIGH_SPEED, E IG H T_B ITS ) ; / / C o n fig u r a e l m odu lo USART
w h ile (1 ) {
fo r (i= 0 ;i< ll;i+ + ){ / / E n v ía l a ca d en a de c a r a c t e r e s
p u tc h ( t e x t o [ i ] ) ;
}
}
}
Aunque el envío de la cadena de caracteres de la forma indicada anteriormente es
completamente válida existe una librería en C denominada stdio.h que integra funciones
que facilitan esta tarea. En particular la función printf se encarga de dar formato a una
cadena de caracteres y enviarla a través del puerto de salida llamando a la función putch las
veces que sean necesarias hasta completar la cadena.

En este caso se utilizará la sentencia printf("\n Hola Mundo!\n"); a la que se le han añadido
los caracteres especiales de salto de línea "\n" al comienzo y al final del texto.

Código fuente
# i n c lu d e < s td io .h > / / L i b r e r í a con fu n c io n e s p a r a e l c o n t r o l de
/ / e n tra d a s y s a l i d a s
# in c lu d e < h t c .h > / / L i b r e r í a que i n c l u y e l a s d e f i n i c i o n e s d e l
/ / m ic r o c o n t r o la d o r

Página | 150
6. Módulos de comunicaciones

# in c lu d e "u s a rt.h " / / L i b r e r í a p a ra e l m ódulo de


/ / c o m u n ic a c io n e s USART

# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o de 4MHZ


__ CONFIG (WRT_OFF & WDTE_OFF & PWRTE OFF & FO SCX T & LVP OFF) ;

v o id m a in (v o id ){

I N I T USART (9 6 0 0 , H IG H S PE E D , EIG H T_BITS) ; / / C o n fig u ra e l modulo USART


w h ile (1 ) {
p r i n t f ( " \ n H o la M u n d o l\ n "); / / E s c r it u r a u t i l i z a n d o l a
/ / fu n c ió n p r i n t f
}
}

Simulación

Se puede comprobar el funcionamiento del programa mediante el simulador MPLAB SIM


habilitando la visualización del módulo de comunicaciones UART a través de la ventana
OUTPUT (menú debugger/settings) como se muestra en la figura inferior.

Figura 6.5: Configuración de MPLAB SIM para utilizar el módulo USART y simulación del ejercicio 6.1.2.

En caso de disponer del hardware necesario para conectar el microcontrolador al


ordenador se puede observar el funcionamiento del programa utilizando el hyperterminal
de Windows o el programa de libre distribución HERCULES que se puede descargar de la
siguiente dirección:

[Link] [Link]

Una vez instalado el programa HERCULES se configurará del puerto serie de comunicaciones
para que coincida con la configuración del módulo USART (9600 baudios, 8 bits y sin
paridad) y se abrirá el puerto de comunicaciones. Al ejecutar el programa se observa su
funcionamiento en la ventana de HERCULES como se muestra en la figura inferior.

Página | 151
Programación de microcontroladores PIC en lenguaje C

Figura 6.6: Simulación del ejercicio 6.1.2 utilizando el progrma HERCULES.

6.1.3. Recepción de datos utilizando el módulo USAR!


En este ejemplo se pretende utilizar el módulo USART para establecer una comunicación
bidireccional entre el ordenador y el microcontrolador. Para ello es necesario conectar el
microcontrolador como se indica en el ejemplo 6.1.2. El programa en cuestión preguntará al
usuario por su nombre y edad. Almacenará los datos recibidos y saludará al interlocutor
mostrando un mensaje como el siguiente:

"Hola NOMBRE de EDAD años"

Solución:

Configuración

Para establecer la comunicación entre el microcontrolador y el ordenador se utilizará el


módulo USART del microcontrolador configurado en modo 8 bits a 9600 baudios.

Para recibir los caracteres del módulo USART se creará una nueva función getche que se
encargará de recoger el dato recibido del registro RCREG. La función tendrá la siguiente
estructura:
u n s ig n e d c h a r g e t c h e ( v o i d )

La definición de esta nueva función se deberá incluir en el archivo usart.h y el código que se
muestra a continuación se incluirá en el archivo usart.c junto con la función putch.

Página | 152
6. Módulos de comunicaciones

u n s ig n e d c h a r g e t c h e O {

w h ile (IR C IF ) //Se pon e a ' 1 # cuando se ha r e c i b i d o un d a to


c o n t in u é ;
r e t u r n RCREG;
}

Como la función getche recibe los datos byte a byte es necesario llamar a la función las
veces necesarias hasta recoger todos los caracteres correspondientes tanto al nombre
como a la edad hasta encontrar el carácter especial de salto de línea (LF) o retorno de carro
(CR). De esto se encargará la función gets() incluida en la librería stdio.h, al igual que lo
hacía la función printf con la función putch. La función getsQ recibe como parámetro un
puntero a una cadena de caracteres donde almacenará los datos recibidos a través del
teclado hasta encontrar los caracteres especiales LF o CR.

Al recibir el dato de la edad en forma de cadena de caracteres puede ser necesario para
trabajar con este valor convertirlo a un número entero para lo que se puede utilizar en este
caso la función ato¡() incluida en la librería stdlib.h que convierte el valor ascii a entero.

e _ d a d = a t o i(e d a d );

Por último, el programa mostrará un mensaje utilizando la función fprintff) que construirá
una cadena de caracteres utilizando las dos variables buf y e_dad.

printf("\n Hola %s de %3¡ años.\n",buf,e_dad);

Código fuente
t fin c lu d e < h t c .h >
t fin c lu d e < s t d i o . h >
# in c lu d e < s t d l i b . h > / / L i b r e r í a con fu n c io n e s a d i c i o n a l e s a t o i ( )
t fin c lu d e " u s a r t . h "

# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r In t e r n o de 4MHZ


__ CONFIG (WRT_OFF & WDTE OFF & PWRTE_OFF & FOSC_XT & LVP OFF) ;

v o i d m a in ( v o i d ) {
u n s ig n e d c h a r b u f [ 8 0 ] , e d a d [ 3 ] , e_ d a d ;
d i(); / / D e s a b i l i t a in t e r r u p c i o n e s

I N I T USART(9 6 0 0 ,HIGH _SPEED ,EIG H T_BITS); / / C o n fig u ra e l modulo USART

w h ile (1 ) {
p r i n t f ( " \ n H o la ] ¿Como t e LL am as?") //M en saje de s a l i d a
g e ts (b u f); //Alm acena l a r e s p u e s t a d e l
/ / u s u a rio en b u f
p r i n t f ( " \ n ¿C u an tos años t i e n e s ? " ) ; //M ensaje de s a l i d a
g e ts (e d a d ); //Alm acena l a r e s p u e s t a d e l
/ / u s u a rio en edad
e _ d a d = a to i(e d a d ); / / C o n v ie r t e l a edad a número
/ / e n te ro
p r i n t f (" \ n H o la %s d e %3i a ñ o s . \ n " / b u f ,e _ d a d ); / / R esp u esta

Página | 153
Programación de microcontroladores PIC en lenguaje C

Simulación

Como se indicó en el ejemplo anterior se utilizará el programa HERCULES para comprobar el


funcionamiento del programa. El funcionamiento se muestra en la siguiente figura:

F igura 6.7: S imulación el ejericio 6.1.3 utilizando el programa HERCULES.

6.1.4. Adivina el número


En este ejemplo se pretende realizar un programa que genere un número aleatorio entre 0
y 99 y le rete al usuario a adivinar de qué número se trata. En caso de no acertar el número
el programa indicará si el número en cuestión es menor o mayor que el introducido. Cuando
se acierte el número el programa indicará el número de intentos realizados por el usuario y
le preguntará si desea volver a jugar.

Solución:

Configuración

El programa consistirá en utilizar el puerto de comunicaciones serie USART para


comunicarse con el usuario mostrando mensajes de texto y recogiendo los valores
introducidos. Para ello será necesario configurar el módulo USART.

IN IT _U S A R T (9 6 0 0 , HIGH_SPEED, EIG H T_BITS) ,-

Para mostrar los mensajes se utilizará la función printf() y para guardad los datos recibidos
la función gets() combinada con la función atoif) que convierte de ascii a entero tal y como
se ha mostrado en el ejemplo anterior.

Además, será necesario utilizar la función rand() incluida en la librería stdlib.h que permite
generar un número aleatorio entre 0 y 32767. Esta función se combina junto con la función

Página | 154
6. Módulos de comunicaciones

srand() también de la librería stdlib.h que inicializa el generador de número aleatorios a


partir de un número o semilla. Para evitar que cada vez que se inicie el programa por
primera vez se repitan la secuencia de números se utilizará el temporizador TIMERO como
semilla, tomando el valor de TMRO en el momento en el que se comienza el juego.

Código fuente

# i n c lu d e < h t c .h >
# i n c lu d e < s t d i o . h >
# in c lu d e < s t d l i b . h > / / L i b r e r í a con fu n c io n e s a d i c i o n a l e s a t o i ( )
# in c lu d e " u s a r t . h "

# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r In t e r n o de 4MHZ


__ CONFIG (WRT_OFF & WDTE_OFF & PWRTE OFF & FOSC_XT & LV P_O F F);

v o id m a in (v o id ){
u n s ig n e d c h a r v a l o r , num[1 0 ] , n u m e r o , i , a c i e r t o ; / / d e f i n i c i ó n de
/ / v a r ia b le s
d i (); //desabilita interrupciones
T0C S=0; / / a rra n c a e l tim erO
I N I T U S A R T (9 6 0 0 ,HIGH SPEED ,E IG H T_B ITS); / / C o n fig u ra e l m odulo USART -
//Preferencias definidas en usart.h
w h ile (1 ) {
p r i n t f ( " \ n A d iv in a un numero d e l 0 a l 991 " ) ; //M en sa je de s a l i d a

p r i n t f ( " \ n Q u ie r e s ju g a r ? [S / N ]: " ) //Mensaje de salida


v a lo r = g e tc h e ( ) ; //Lee la respuesta del usuario
if(v a lo r = = ' S ' ) {
i =0 ; / / I n i c i a e l c o n t a d o r de i n t e n t o s
a c ie r to = 0 ; / / d e s a c tiv a e l in d ic a d o r de a c i e r t o
s r a n d í(in t ) T M R O ) ; / / i n i c i a l i z a e l g e n e r a d o r de n °s
/ / a le a t.
v a l o r = r a n d ( ) %1 0 0 ; / / o b t ie n e un n° a l e a t o r i o e n t r e 0
//y 99
w h i l e (1 a c i e r t o ) {
i+ + ;
p r i n t f ( " \ n In t r o d u c e un numero d e l 0 a l 99: "); //M en sa je de
/ / s a lid a
g e t s (n u m ) ; //Lee l a r e s p u e s t a d e l u s u a r io
n u m e ro = a to i(n u m ); / / C o n v ie r t e e l v a l o r l e i d o a
//número e n t e r o
i f ( v a lo r = = n u m e r o ){
a c ie r to = l; / / a c t iv a e l i n d i c a d o r de a c i e r t o
p r i n t f ( " \ n ENHORABUENA!!! Has a c e r t a d o en %3i
in te n to s . \ n ", i ) ;
}
e ls e if(v a lo r c n u m e r o ){
p r i n t f ( " \ n E l numero %3i es mayor que e l numero
b u s c a d o . \ n " , n u m e ro );
}
e ls e {
p r in tf("\ n E l numero %3i es menor que e l numero
b u s c a d o . \ n " , n u m ero );
}
}

Página | 155
Programación de microcontroladores PIC en lenguaje C

Simulación

Como se indicó en el ejemplo anterior se utilizará el programa HERCULES para comprobar el


funcionamiento del programa conectado al puerto serie del ordenador. El funcionamiento
se muestra en la siguiente figura:

Figura 6.8: Simulación del ejercicio 6.1.4 utilizando el programa HERCULES.

Realiza un programa que utilice el módulo USART para implementar un juego en el que el
usuario tenga que adivinar una palabra. El usuario irá introduciendo caracteres en
mayúsculas y el programa le indicará si la palabra contiene ese carácter y la posición o
posiciones que ocupa en la palabra.

6.2. Módulo MSSP (Master Synchronous Serial Port)


El modulo MSSP es un interfaz de comunicaciones serie muy utilizado para comunicar el
microcontrolador con dispositivos periféricos o con otros microcontroladores. Entre los
dispositivos que utilizan habitualmente este módulo de comunicaciones se pueden
encontrar memorias EEPROM, registros de desplazamiento, controladores de displays,
conversores analógico/digitales, etc.

El módulo MSSP tiene asociados tres registros. El registro de status SSPSTAT (A2.17) y dos
registros de control SSPCON (A2.18) y SSPCON2 (A2.19) que determinarán el

Página | 156
6. Módulos de comunicaciones

funcionamiento del mismo en modo l2C o SPI tanto funcionando en modo maestro como en
modo esclavo.

Los terminales del microcontrolador asociados al módulo MSSP son los siguientes:

TERMINAL SPI l2C


RC3 Serial Clock (SCK) Serial Clock (SCL)
RC4 Serial Data In (SDI) Serial Data (SDA)
RC5 Serial Data Out (SDO) -
RA5 Slave select (55) _
Registros de control

SSPCON SSPCON2 SSPSTAT

MODO SPI MODO l2C

Figura 6.9: Esquema de bloques del módulo MSSP.

6.2.1. Configuración del módulo MSSP en modo l2C maestro


Configura el módulo l2C del microcontrolador PIC16F877A para trabajar en modo maestro.

Solución:

Para configurar el módulo será necesario ajustar correctamente los registros de


configuración SSPSTAT (A2.17), SSPCON (A2.18) y SSPC0N2 (A2.19). Para ello se utilizará la

Página | 157
Programación de microcontroladores PIC en lenguaje C

función i2c_in¡t(). Además, se definirán diferentes funciones adicionales que permitirán


interactuar de forma sencilla con el módulo tales como ¡2c_start(), ¡2c_restart(), ¡2c_stop(),
¡2c_¡dle(), i2c_read(), i2c_write() y ¡2c_sendnack() cuya definición y código se introducirán
en los archivos "¡2c.h" e "i2c.c" respectivamente.

Configuración

La función de configuración deberá configurar los pines SDA y SCL para su control a través
del módulo MSSP (TRISC4 = 1; TRISC3 = 1;), ajustar el registro SSPCON (A2.18) para
encender el módulo y establecer modo maestro (SSPCON = 0x28), ajustar la velocidad del
reloj (SSPADD = OxOA), bajar los flags (SSPCON2 = 0;) y habilitar el control de velocidad
(SSPSTAT=0x80;).

Código fuente

//Configuración del módulo I2C


v o id i2 c _ in it (){
TRISC 3 = 1 ; / / SLC
TR ISC 4 = 1 ; //SDA
SSPADD = OxOA; / / R e lo j a lOOKHz
SSPSTAT = 0 x 8 0 ; / / H a b i l i t a e l c o n t r o l de v e l o c i d a d d e l m ódu lo
SSPCON2 = 0 x 0 0 ; / / B a ja l o s f l a g s
SSPCON = 0 x 2 8 ; //Modo m a e s tr o , m ódulo I2 C e n c e n d id o
}
Envía secuencia de Start

v o id i2 c _ s ta r t(){
i 2 c _ i d l e () ; //Comprueba qu e e s t á l i b r e
S S P C O N 2 b its .S E N = l; / / E n v ía l a c o n d i c i ó n de i n i c i o
w h ile (S S P C O N 2 b it s . SEN==1) ; / / E s p e ra a qu e s e e n v íe
w h ile (S S P I F = = 0 ) ; //Comprueba que s e ha e n v ia d o
S S P IF = 0 ; / / B a ja e l f l a g
>
Envía secuencia de Restart
v o id i 2 c _ r e s t a r t () {
S S P C O N 2 b its. RSEN=1; / / E n v ía l a s e c u e n c ia r e s t a r t
w h ile (S S P C O N 2 b it s . R S E N ); / / E sp era a qu e s e e n v íe
w h i l e ( S S P IF = = 0 ) ; //Comprueba que s e ha e n v ia d o
S S P IF = 0 ; / / B a ja e l f l a g
}
Envía Secuencia de Stop
v o id i2 c _ s to p (){
S S P C O N 2 b its. PEN=1; / / E n v ía l a s e c u e n c ia de S to p
w h ile (S S P C O N 2 b it s .P E N ); / / E s p e ra a que s e e n v í e
w h ile (S S P IF = = 0 ); //Comprueba q u e s e ha e n v ia d o
S S P IF = 0 ; / / B a ja e l f l a g
}

Página | 158
6. Módulos de comunicaciones

Comprueba si el módulo está ocupado


v o id i 2c _ i d l e ( ) {
w h i l e ( ( SSPCON2 & O x lF ) | S S P S T A T b its .R n W ) ; //Comprueba que e l módulo
/ / está l i b r e
}
Lee un byte
u n s ig n e d c h a r i 2c _ r e a d (){
i 2c _ id le ( ) ;
S S P C O N 2 b its .R C E N = l; / / A c t iv a e l modo r e c e p c ió n
w h ile (S S P C O N 2 b it s . RCEN==1) ; / / E sp era a r e c i b i r e l b y te
w h ile (S S P S T A T b it s .B F = = 0) ; / / E sp era a que e l b u f f e r e s t é l l e n o
r e t u r n SSPBUF; / / D evu elv e e l d a to
}
Envía un byte - Devuelve 0 en caso de error
u n s ig n e d c h a r i 2 c _ w r it e ( u n s i g n e d c h a r b y t e ) {
i 2c _ i d l e ( ) ;
S S P B U F = b y te;
w h ile (S S P S T A T & 0 x 0 5 ); //Comprueba s i hay tr a n s m is ió n en c u rs o R/W y
/ / s i e l b u f f e r e s t á v a c í o BF
if(S S P C O N 2 b its .A C K S T A T = = l) { //No ha r e c i b i d o c o n fir m a c ió n
S S P C O N 2 b its . PEN=1; // E n vía s e c u e n c ia de S to p
re tu rn 0 ; / / d e v u e lv e 0
}
e ls e { //Ha r e c i b i d o c o n fir m a c ió n
w h ile (S S P IF = = 0 ); //Comprueba que ha t r a n s m it id o
S S P IF = 0 ; / / B a ja e l f l a g
re tu r n 1 ; / / D evu elv e 1
}
}
Envía secuencia NACK
v o id i 2c_sen d n ack ( ) {
SSPC O N 2bits.A C KD T=1;
S SP C O N 2 b its.A C K E N =l;
w h i l e ( S S P C 0 N 2 b its . ACKEN==1) ;
}

6.2.2. Sensor de temperatura TC74


Realiza un programa que utilice el sensor digital de temperatura TC74 (DS21462D) para
mostrar la temperatura en la pantalla LCD HITACHI HD44780.

a) Indica las conexiones necesarias con el microcontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.

Solución:
a) Para el funcionamiento del microcontrolador será necesario conectar correctamente las
entradas VDD y VSS a +5 V y 0 V respectivamente y el oscilador, en este caso un oscilador de
cristal a 4 MHz, a las entradas 0SC1 y 0SC2 tal y como aparece en la figura inferior. El
sensor de temperatura TC74 se conectará siguiendo las indicaciones de la hoja de

Página | 159
Programación de microcontroladores PIC en lenguaje C

especificaciones con sus salidas SDA y SCL conectadas a los terminales de comunicaciones
l2C del microcontrolador RC4 y RC3 respectivamente. Se utilizarán además dos resistencias
de pull-up conectadas a las líneas de comunicaciones l2C que mantendrán estas líneas en
alto '5 V' cuando estén sin utilizar. La conexión de la pantalla LCD se realizará siguiendo las
instrucciones del fabricante para utilizar el modo de comunicaciones de 4 bits a través de
los terminales RD0-RD4.

Figura 6.10: E s q u e m a d e c o n e x io n e s c o n e l m ic r o c o n t r o l a d o r p a r a u t il iz a r el sen so r


DE TEMPERATURA DIGITAL TC74 PROPUESTO EN EL EJERCICIO 6.2.2.

b) Para la comunicación del sensor de temperatura digital será necesario configurar el


módulo de comunicaciones l2C del microcontrolador en modo maestro como se mostró en
el ejemplo anterior. Una vez configurado el módulo se deberá establecer la comunicación
con el dispositivo siguiendo las indicaciones de la hoja de especificaciones del sensor de
temperatura TC74.

Configuración
Para leer el valor de la temperatura del módulo TC74 es necesario seguir las instrucciones
del fabricante. El protocolo a seguir para leer la temperatura se detalla en la figura inferior.
Read Byte Format
s Address WR ACK Command ACK Address RD i ACK Data NACK
S -
7 Bits 8 Bits 7 Bits 8 Bits
Slave Address Command Byte: selects Slave Address- repeated Data Byte: reads from
which register you are due to change ¡n data- the register set by the
reading from. flow direction. command byte.

F ig u r a 6.11: E s q u e m a p a r a la l e c t u r a d e d a t o s u t il iz a n d o e l s e n s o r d e t e m p e r a t u r a d ig it a l TC74.

Para leer la temperatura se creará una función TC74_i2c_readbyte() que se encargue de la


comunicación. Esta función hará uso de la librería "¡2c.h" donde se encuentran definidas
todas las funciones de comunicaciones para trabajar con el módulo l2C (véase ejemplo
anterior). Así, la función tendrá la siguiente estructura:

Página | 160
6. Módulos de comunicaciones

# d e f i n e WRITE 0
# d e f i n e READ 1

s ig n e d c h a r T C 7 4 _ i2 c r e a d b y t e (u n s ig n e d c h a r a d d , u n s ig n e d ch a r d a t o ) {
s i g n e d c h a r tem p = 0 ;
i 2c _ s t a r t ( ) ; / / E n vía l a s e c u e n c ia de S t a r t (S)
if(i2 c _ w r ite (a d d + W R IT E )= = 0 ) { / / E n vía l a d i r . d e l m ódulo TC74
//en modo e s c r i t u r a
re tu r n 0 ; / / R e to rn a 0 en c a s o de e r r o r
}
If(i2 c _ w r ite (d a to )= = 0 ) { / / E n vía e l r e g i s t r o que se va
//a l e e r (d a t o )
re tu r n 0; / / R eto rn a 0 en c a s o de e r r o r
}
i 2c _ r e s t a r t ( ) ; / / E n vía l a s e c u e n c ia de R e s t a r t
i f ( i 2 c _ w r i t e ( add+READ)= = 0) { / / E n vía l a d i r e c c i ó n d e l m ódulo TC74
//en modo l e c t u r a
re tu r n 0; / / D evu elv e 0 en c a so de e r r o r
}
te m p = i2 c _ r e a d ( ) ; //Guarda e l v a l o r de r e c i b i d o
i 2c_sen d n ack ( ) ; / / E n vía s e c u e n c ia NACK
i 2c _ s to p (); / / E n vía s e c u e n c ia de S to p
r e t u r n tem p; / / D evu elv e e l v a l o r o b t e n id o
}

Una vez obtenido el valor de la temperatura se deberá representar en la pantalla LCD. Para
ello se hará uso de la función printf incluida en la librería "stdio.h" como ya se comentó en
ejemplos anteriores.

Código fuente

# in c lu d e < h t c .h >
# in c lu d e ,,i 2 c . h "
tr in c lu d e " l c d . h "
# in c lu d e " s t d i o . h "
# in c lu d e "T C 7 4 .h "
# d e fin e X TA LF R E Q 4000000 / / O s c ila d o r I n t e r n o de 4MHZ
# d e f i n e TC74ADDRESS 0x9A / / D ir e c c ió n d e l m ódulo TC74
# d e f i n e TC74 TEMP REG 0x00 / / D ir e c c ió n d e l r e g i s t r o de
/ / tem p era tu ra
__ CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSCXT & L V P_O F F);

v o i d p u t c h (u n s ig n e d c h a r x ) ; / / D e fin ic ió n de l a fu n c ió n p u tch

v o id m a in (v o id ){ / /Fu n ción p r i n c i p a l
s ig n e d c h a r tem p; / / V a r ia b le p a ra a lm a cen a r l a
/ / tem p era tu ra
d i () ; / / D e s h a b ilit a i n t e r r u p c i o n e s
l c d i n i t () ; / / I n i c i a l a p a n t a l l a LCD
i 2c _ i n i t ( ) ; / / I n i c i a e l m ódulo I2C
w h i1 e ( 1 ) { / / B u cle i n f i n i t o
tem p = T C 7 4 _i2 c_read b yte (TC74_ADDRESS TC74TEMPREG) ? // L ee l a te m p e ra tu ra
/ / d e l TC74
if(t e m p != 0 ){ //Comprueba que se haya l e í d o c o r r e c t a m e n t e
lc d _ g o to (0 ); / / P o s ic io n a e l c u r s o r a l co m ien zo de l a LCD
p r i n t f ( "Temp = %+d C " , t e m p ); //M u estra l a tem p e ra tu ra
__ d e l a y m s (1 0 0 ); / / E sp era lOOms p a ra v o l v e r a l e e r Temp
}

Página | 161
Programación de microcontroladores PIC en lenguaje C

v o i d p u t c h (u n s ig n e d c h a r x ) { lc d p u t c h (x ); }

6.2.3. Memoria EEPROM 24LC256


Realiza un programa basado en un microcontrolador PIC trabajando a 4 MHz que almacene
en la posición de memoria 0x0000 de una memoria EEPROM externa 24LC256 (DS21203M)
el número de veces que se ha arrancado el programa almacenado en el PIC (se supondrá un
estado inicial de los registros de memoria 0XFF).

a) Indica las conexiones necesarias con el microcontrolador.


b) Implementa el programa que cumpla las especificaciones indicadas.
Solución:

a) Para el funcionamiento del microcontrolador será necesario conectar correctamente las


entradas VDD y VSS a +5 V y 0 V respectivamente y el oscilador, en este caso un oscilador de
cristal a 4 MFIz, a las entradas OSC1 y OSC2 tal y como aparece en la figura inferior. La
memoria 24LC256 se conectará siguiendo las indicaciones de la hoja de especificaciones con
sus salidas SDA y SCL conectadas a los terminales de comunicaciones l2C del
microcontrolador RC4 y RC3 respectivamente. Se utilizarán además dos resistencias de pull-
up conectadas a las líneas de comunicaciones l2C que mantendrán estas líneas en alto '5 V'
cuando estén sin utilizar. Los terminales A0-A2 que determinan los tres últimos bites de la
dirección se conectarán a tierra '0V ' determinando una dirección del dispositivo
ObOlOlOOO. El terminal WP (write-protect) se conectará también a tierra '0 V'.

Figura 6.12: E s q u e m a d e c o n e x io n e s c o n e l m ic r o c o n t r o l a d o r p a r a u t il iz a r
LA MEMORIA E E P R O M 2 4 L C 2 5 6 PROPUESTO EN EL EJERCICIO 6 .2 .3 .

b) Para la comunicación de la memoria EEPROM será necesario configurar el módulo de


comunicaciones 12C del microcontrolador en modo maestro como se mostró en el ejemplo
6.2.1. Una vez configurado el módulo se deberá establecer la comunicación con el
dispositivo siguiendo las indicaciones de la hoja de especificaciones para las operaciones de
lectura y escritura que se detallan en la figura inferior.

Página | 162
6. Módulos de comunicaciones

LEER BYTE

Configuración

Para realizar la comunicación con la memoria EEPROM se crearán dos funciones


EEPROM_i2c_readbyte() y EEPROM_/2c_ivr/tebyfe(7, que se encargarán de leer y escribir en
la memoria EEPROM respectivamente. Estas funciones harán uso de la librería "i2c.h"
donde se encuentran definidas todas las funciones de comunicaciones para trabajar con el
módulo l2C (véase ejemplo 6.2.1). Así, las fundones tendrán la siguiente estructura:
/ / L e e un b y t e d e l d i s p o s i t i v o I2 C e s c l a v o de DIRECCION=add en su REGISTRO=reg
u n s ig n e d c h a r E E P R O M _ i2 c _ re a d b y te (u n s ig n e d c h a r add, u n s ig n e d i n t r e g ) {
u n s ig n e d c h a r tem p= 0 ;
i2 c _ s ta r t(); / / E n vío de l a s e c u e n c ia de S t a r t
i f ( i2 c _ w r it e (a d d + W R I T E ) = = 0 ) { / / E n vío de l a d i r . i 2 c de l a EEPROM en
//modo e s c r i t u r a
re tu r n 0 ;
}
i f ( i 2 c _ w r i t e ( (u n s ig n e d c h a r) (r e g > > 8 ) ) = = 0 ){ / / E n vía l a p a r t e a l t a de l a
/ / d ir . d e l r e g i s t r o
re tu rn 0;
}
i f ( i 2 c _ w r i t e ( (u n s ig n e d c h a r ) ( r e g ) ) = = 0 ) { / / E n vía l a p a r t e b a ja de l a
/ / d ir . d e l r e g i s t r o
re tu rn 0;
}
i2 c _ r e s ta r t( ) ; / / E n vío de l a s e c u e n c ia de R e s t a r t
i f ( i 2 c _ w r i t e (add+READ) ==0) { / /E n vío de l a d i r e c c i ó n i2 c de l a EEPROM
//en modo l e c t u r a
re tu r n 0;
}
t e m p = i2 c _ r e a d ( ) ; / / L e c tu ra d e l d a t o s e le c c io n a d o
i 2c_sendn ack( ) ; / / E n vío de l a s e c u e n c ia NACK
i 2c _ s to p ( ) ; / / E n vío de l a s e c u e n c ia de S to p
r e t u r n tem p; / / R eto rn o d e l d a to
}
/ / E s c r ib e e l BYTE=dato en e l d i s p o s i t i v o I2C e s c l a v o de DIRECCION=ADD en su
//REGISTRO=reg

Página | 163
Programación de microcontroladores PIC en lenguaje C

unsigned char EEPR0M_i2c_writebyte(unsigned char a d d , u n s ig n e d i n t r e g ,


u n s ig n e d c h a r d a t o ) {
i2c_start();
if(i2c_write(add+WRITE)==0){
return 0;
}
if(i2c_write((unsigned char)(reg>>8))==0){ / / E n v ía l a p a r t e a l t a de la
/ / d ir . d e l r e g i s t r o
return 0;
}
if(i2c_write((unsigned char)(reg))==0){ / / E n v ía l a p a r t e b a j a de la
/ / d ir . d e l r e g i s t r o
return 0;
}
if(i2c_write(dato)==0) { / / E s c r i t u r a d e l d a t o en e l
/ / r e g is t r o s e le c c io n a d o
return 0;
}
i2c_stop(); //Envío de la s e c u e n c ia d e S to p
return 1;
}

Código fuente

# i n c l u d e < h t c .h >
# i n c l u d e l,i 2 c . h " / / L i b r e r í a co n l a s r u t i n a s a s o c ia d a s a l m ó du lo i 2 c
# i n c l u d e "2 4 L C 2 5 6 . h " / / L i b r e r í a co n l a s r u t i n a s a s o c ia d a s a l a m em oria
//EEPROM

# d e fin e X T A L F R E Q 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ


«d e fin e EEPROM_ADDRESS OxAO / / D ir e c c ió n d e l m ódu lo EEPROM ( v é a s e
// e s p e c i f i c a c i o n e s )
«d e fin e EEPROM_REG 0x0000 / / D ir e c c ió n d e l r e g i s t r o d e m em oria ( v é a s e
//e s p e c i f i c a c i o n e s )

__ CONFIG(W RT_0FF & WDTE_OFF & PWRTE_OFF & F0SC_XT & LVP_0FF) ?
v o i d p u t c h (u n s ig n e d c h a r x ) ;

v o id m a in (v o id ){
u n s ig n e d c h a r d a t o , i ; / / D e f i n i c i ó n de v a r i a b l e s de p ro g ra m a
di (); //S e d e s h a b i l i t a n l a s i n t e r r u p c i o n e s
i 2c _ in it ();
d a to = E E P R O M _ i2 c _ r e a d b y te ( EEPROM_ADDRESS, EEPROMREG); / / L ectu ra d e l v a lo r
/ / a lm a cen a d o
d a to + + ; //Se in c r e m e n ta e l v a l o r en 1
i=E E P R O M _i2c_w ritebyte(E E PR O M _A D D R E S S , EEPROM REG, d a t o ) ; //S e e s c r i b e e l
/ / n u evo v a l o r
w h ile (l); / / F in d e l p rog ra m a
}
Realiza un programa que permita borrar todos los registros de la memoria EEPROM
(ponerlos a OxFF).
Realiza un programa que permita ir almacenando los valores de temperatura mostrados
en el ejercicio 6.2.2 en la memoria EEPROM cada hora y permita mostrarlos en la pantalla
LCD al accionar un pulsador.

Página | 164
7. Módulos periféricos
7.1. Memoria interna EEPROM
7.2. Circuito de Reset
7.3. Perro Guardián

7.1. Memoria interna EEPROM


El microcontrolador PIC16F877A cuenta con una memoria EEPROM interna de 256 bytes. La
memoria EEPROM no es accesible directamente a través de las direcciones de memoria del
microcontrolador sino que se accede a ella a través de varios registros especiales de
memoria EEADR y EEDAT utilizando los registros de control EECON1 y EECON2.

La utilización de esta memoria se puede realizar de forma sencilla mediante la utilización de


macros o funciones pre-programadas incluidas en la librería "htc.h". Las macros y funciones
que se utilizan para leer/escribir en la EEPROM son las siguientes:

MACROS

Inicia los datos en memoria EEPROM en bloques de 8 bytes comenzando en la dirección


0x00 e incrementando la dirección en 8 posiciones cada vez que se llama. Solo se puede
utilizar al comienzo del programa y sirve para inicializar la memoria EEPROM en el
momento de la programación del microcontrolador.
__ E E P R O M _ D A T A (a ,b ,c ,d ,e , £ , g , h )

Escribe el dato de tamaño byte almacenado en valué en la posición de memoria EEPROM


indicada por addr.
# d e f i n e E E P R O M W R ITE (ad dr, v a lu é ) \
do{ \
w h i l e (WR) c o n t in u é ; EEADR= (a d d r ) ; EEDATA= ( v a lu é ) ; \
CARRY=0 ; i f (G IE ) CARRY=1; G IE =0; \
WREN=1;EECON2 = Ox55;EECON2 = OxAA; WR=1;WREN=0; \
if(CARRY)GIE=1; \
}w h ile (0 )

Lee el byte almacenado en la dirección addr de memoria EEPROM y lo almacena en


EEDATA.
# d e f in e EEPROM_READ (a d d r ) ( (EEADR= (a d d r ) ) , (RD=1) , EEDATA)

FUNCIONES

Escribe el dato de tamaño byte almacenado en valué en la posición de memoria EEPROM


indicada por addr.

Página | 165
Programación de microcontroladores PIC en lenguaje C

e e p r o m _ w r it e (u n s ig n e d c h a r a d d r , u n s ig n e d c h a r v a l u é ) {
E E P R O M W R ITE (ad dr, v a l u é ) ;
}

Devuelve el dato de tamaño byte almacenado en la posición de memoria EEPROM indicada


por addr.

u n s ig n e d c h a r e e p r o m _ r e a d (u n s ig n e d c h a r a d d r ) {
w h i l e (WR) c o n t in u é ;
r e t u r n EEPRO M _RE AD (addr);
}

7.1.1. A lm acen am ie nto de datos no volátiles en m em oria interna EEPRO M


Se pretende crear un programa para un microcontrolador PIC16F877A que lleve la cuenta
del número de veces que se ha reiniciado el programa en el registro de dirección 0x00 de
memoria EEPROM interna.

Solución:

Para la realización del programa será necesario iniciar el registro 0x00 de la EEPROM interna
en el momento de programación asignándole el valor 0x00 utilizando la siguiente macro:

__EEPROM_DATA(0x00,OxFF,OxFF,OxFF,OxFF,OxFF,OxFF,OxFF); //Inicializa los 8 primeros


//bytes de la EEPROM interna

A continuación, en el código del programa, se deberá leer el primer registro, incrementarlo


y almacenarlo de nuevo en la misma posición de memoria.

Código fu en te

# i n c l u d e < h t c . h> / / In c lu im o s l i b r e r í a d e l m ic r o a u s a r
__ CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & L V P O F F ) ;
# d e f i n e _XTAL_FREQ 4000000 / / O s c ila d o r I n t e r n o d e 4MHZ

u n s ig n e d c h a r s [ 1 0 ] j

v o id m a in (v o id ){
u n s ig n e d c h a r d a t a ;
EEPROM DATA( 0 x 0 0 , O x F F ,O x F F ,O x F F ,O x F F ,O x F F ,O x F F ,O x F F ); / / In ic ia liz a e l
/ / c o n ta d o r a ' 0 '
d i () ; //Se d e s h a b i l i t a n i n t e r r u p c i o n e s
d a ta = eep ro m _ rea d ( 0 ) ; //S e l e e e l c o n t a d o r
d a ta + + ; //Se in c r e m e n ta e l c o n t a d o r
e e p r o m w r i t e ( 0 , d a ta ); //Se a lm a cen a e l c o n t a d o r
NO P( ) ; / / F in d e l p ro g ra m a

Simulación

Se ejecuta el programa utilizando el simulador MPLABSIM® a la vez que se visualizan los


valores almacenados en los registros de memoria EEPROM interna (menú View/EEPROM).

Página | 166
7. Módulos periféricos

Cada vez que hace un 'reset' y se vuelve a ejecutar el programa el valor almacenado en el
registro de memoria 0x00 se incrementa en 1.

Figura 7.1: Simulación de la escritura en la memoria EEPROM interna propuesto en el ejercicio 7.1.1.

Realiza un programa que almacene los números del 0 al 255 en cada una de las posiciones
de la memoria EEPROM.

7.2. Circuito de Reset


El microcontrolador PIC16F877A integra un circuito lógico conectado a la entrada de Reset
que permite diferenciar entre varios motivos de Reset.

El estado de algunos registros no se modifica ante un Reset pero muchos otros ven alterado
su valor ante un Reset (véase Anexo 2). En la figura inferior se muestra un diagrama
simplificado del circuito de Reset.

Página | 167
Programación de microcontroladores PIC en lenguaje C

7.2.1. Com probación del origen de reset al inicio del program a


Se propone crear un programa basado en un microcontrolador PIC16F877A trabajando a
4 MHZ que verifique el motivo por el que se ha reiniciado el programa.
Solución:

El reinicio del programa se puede deber principalmente a tres motivos:

1. Conexión de la alimentación.
2. Caída de tensión por debajo de los límites permitidos.
3. Desbordamiento del perro guardián sin encontrarse en modo bajo consumo.

Los motivos 1 y 2 vienen reflejados en los bits POR y BOR del registro PCON (A2.16) y el
tercer motivo se refleja en el bit TO del registro STATUS (A2.1).

Configuración

Para verificar el origen del reset será necesario habilitar los motivos de reset en la palabra
de configuración (A2.20) del microcontrolador utilizando la directiva __CONFIG de la
siguiente manera:
__ CONFIG (WRT_OFF S: WDTE_ON & PWRTE_OFF & FOSC_XT & BORENON & LVP_OFF) ;

La verificación del origen de reset se realizará comprobando el estado de los bits asociados
a cada uno de los motivos anteriores y enviando a través del módulo USART un mensaje
que indique dicho motivo. Para ello se empleará la librería utilizada en el ejemplo 6.2.1
"usart.h".

Código fuente
# in c lu d e < s td io .h >
# in c lu d e < h t c .h >
# in c lu d e "u s a r t.h "

# d e f i n e _XTAL_FREQ 4000000 / / O s c i l a d o r I n t e r n o d e 4MHZ


__ C O N FIG (W R TO F F & WDTE_ON & PWRTE_OFF & FO S C X T & BOREN_ON & L V P _ O F F );

v o id m a in (v o id ){
I N I T U S A R T (9 6 0 0 ,HIGH_SPEED, E IG H T_B ITS ) ; / / C o n fig u r a e l m odu lo USART
i f ( ín P O R ){ / / C o m p ro b a ción d e i n i c i o p o r
// c o n e x ió n
n P O R = l;
p r in tf("\ n R e s e t p o r e n c e n d id o I\ n ") ; / / E s c r itu r a a t r a v é s d e l p u e rto
/ / s e r ie
}
if(!n B O R ){ / / C o m p ro b a ción d e i n i c i o por
/ / c a íd a de t e n s i ó n
n B O R =l;
p r in t f(" \ n R e s e t p o r c a i d a de t e n s i ó n ! \ n " ) ; / / E s c r itu r a a t r a v é s
/ / d el p u e rto s e r ie
}

Página | 168
7. Módulos periféricos

i f (!n T O ){
p r in tf("\ n R e s e t p o r d e s b o rd a m ie n to d e l W D T !\ n "); / / E s c r it u r a p u e r to
/ / s e r ie
}
w h ile (1) ;
}

Simulación

Para la simulación del programa se utilizará MPLABSIM® y se habilitará la pestaña SIM Uart
de la ventana OUTPUT para visualizar los mensajes. En la figura inferior se muestra el valor
de los registros antes de comenzar la ejecución del programa.

13 Watch X
Add SFñ ADCONO ▼ | Add Symbol| _p:tiing:bits ▼

U rd a te A dd ress | Symbol Ñame Valué | Decimal j 3 in a ry j Char j


00A PCLATH 0x00 0 00000000 '.•
002 PCL 0x00 0 00000000 ' .'
OBE PCON 0x01 1 00000001
003 STATUS OxlE 30 00011110 ' .'

Watch 1 Watch 2 ¡Watch 3 | Watch 4'

Figura 7.3: Simulación del sistema para la detección del origen de RESET propuesto en el ejercicio 7.2.1 (W atch).

Para poder observar el reset producido por el desbordamiento del WatchDog es necesario
modificar la configuración del simulador desde el menú Degugger/Settings. En la ventana
que aparece se deberá seleccionar la pestaña Break Optíons y en WDT Timeout elegir la
opción Reset como se muestra en la figura inferior.

Figura 7.4: Configuración de MPLAB SIM para la simulación del ejercicio 7.2.1.

Una vez ajustado el parámetro anterior se pueden generarán los diferentes reset desde el
menú Debugger/Reset y ejecutar el programa mientras se observa la ventana OUTPUT que
deberá mostrar los mensajes que aparecen en la figura inferior.

Página | 169
Programación de microcontroladores PIC en lenguaje C

Omput_______________________ _ i o II O llüSbl
lu id Vellón Control ¡Findin Res ;1*ÍS a B S Í m J SIMUartl

Reset por encendido!


Reset por caída de tensión!
Reset por desbordamiento del WDT>

Reset por desbordamiento del WDT!

Reset por desbordamiento del WDT!

Reset por desbordamiento del WDT!

Reset por desbordamiento del WDT!

Reset por desbordamiento del W DT'

Figura 7.5: Simulación del programa de detección de origen de RESET propuesto en el ejercicio 7.2.1.

En caso de ejecutar indefinidamente el programa se mostrará continuamente el mensaje de


desbordamiento por WDT al ser el único motivo de reset automático.

Página | 170
A l. Librerías en C

A l.l. p o rts
A l . 2. ¡n te rru p ts
A l . 3. tim e rs
A l . 4. ccp
A l . 5. a n a lo g
A l . 6. u sa rt
A l . 7. ¡2c
A l . 8. Icd

A l.l. ports
ports.h
//CONSTANTES, MACROS Y FUNCIONES PARA LOS PUERTOS DE ENTRADA Y SALIDA DIGITALES

#define setalldigital() ADCONl=0x06


#define rol_8(valué,b) value= (value<<b) |(value>>(8-b))
#define ror_8 (valué,b) value= (value>>b) |(value<< (8-b))
#define bit_set(valué,b) value=value|(l<<b)
#define bit clear (valué,b) value= value& (~ (l<<b))

A l.2. iníermpts
interrupts.h
//CONSTANTES, MACROS Y FUNCIONES PARA LOS PUERTOS DE ENTRADA

#define GLOBAL 0x000080


#define PERIPHERAL 0x000040
#define INTTO 0x000020
#define INTEXT 0x000010
#define INTPORTB 0x000080
#define INT_T1 0x000100
#define INTT2 0x000200
#define INTCCPl 0x000400
#define INTSSP 0x000800
#define INTTX 0x001000
#define INT_RX 0x002000
#define INTAD 0x004000
«define INT_PSP 0x008000
#define INTCCP2 0x010000
#define enable int(valué) INTCON|=valué; \
PIE1|=((value&OxOOFFOO)>>8);
PIE2¡=((value&OxFFOOOO)»16)
#define discdsle int (valué) INTCON&=(-valué); \
PIE1&=(-((value&0x00FF00)>>8) ¡
PIE2&=(-((value&OxFFOOOO)»16))
PIE2&=(-(value>>16))

Página | 171
Programación de microcontroladores P1C en lenguaje C

A1.3. timers
timers.h

//CONSTANTES, MACROS Y FUNCIONES PARA EL TIMER 0

#define RTCCINTERNAL 0x00


«define RTCCEXT RISE 0x20
«define RTCC_EXT_FALL 0x30
«define RTCCDIVl OxOF
«define RTCCDIV2 0x00
«define RTCCDIV4 0x01
«define RTCC DIV8 0x02
«define RTCCDIV16 0x03
«define RTCCDIV32 0x04
«define RTCCDIV64 0x05
«define RTCC_DIV128 0x06
«define RTCCDIV256 0x07

«define setup_timerO(valué) OPTION_REG=((OPTIONREG&OxCO)|value)


«define set timerO(valué) TMR0=valué
«define get_timerO() TMR0

// CONSTANTES, MACROS Y FUNCIONES PARA EL WATCHDOG

«define WDT_18MS 0x08


«define WDT36MS 0x09
«define WDT72MS OxOA
«define WDT144MS OxOB
«define WDT288MS OxOC
«define WDT576MS OxOD
«define WDT1152MS OxOE
«define WDT2304MS OxOF

«define setup wdt(valué) OPTION REG=(OPTIONREGAOxFO)|valué


#define restartwdt() CLRWDTO

//CONSTANTES, MACROS Y FUNCIONES PARA EL TIMER 1

#define T1_DISABLED 0x00


#define Tl_OFF 0x00
#define TION 0x01
#define T1INT 0x00
iídefine T1_EXT 0x02
^define T1DIV1 0x00
#define T1DIV2 0x10
#define T1DIV4 0x20
#define T1_DIV8 0x30
#define Tl_OSC_EN 0x08

#define setuptimerl(valué) TlCON=value


#define set timerl(valué) TMRl=value
#define get timerl() TMR1
#define starttimerl() T1CON|=0x01
#de£ine stop_timerl() TlCON&= OxFE

//CONSTANTES, MACROS Y FUNCIONES PARA EL TIMER

#define T2DISABLED 0x00


#define T20FF 0x00
#define T20N 0x04
#define T2POSTDIV1 0x00
#define T2POSTDIV2 0x08
#define T2POSTDIV3 0x10
#define T2 POST DIV4 0x18

Página | 172
Anexos

#define T2_POST_DIV5 0x20


#define T 2PO S T D I V 6 0x28
#define T 2PO S T D I V 7 0x30
#define T2_POST_DIV8 0x38
#define T 2PO S T D I V 9 0x40
#define T2_POST_DIV10 0x48
#define T2POSTDIV11 0x50
#define T2_POST_DIV12 0x58
#define T2POSTDIV13 0x60
#define T2POSTDIV14 0x68
#define T 2POSTDIV15 0x70
#define T 2POSTDIV16 0x78
#define T2_PRED_DIV1 0x00
#define T 2 P REDDIV4 0x01
#define T2 PREDDIV16 0x02
#define T2PREDDIV64 0x03
#define setup timer2(valué) T2CON=valué
#define set timer2(valué) PR2=value; \
TMR2=0
#define get_timer2() TMR2
#define start_timer2() T2CON|=0x04
#define stop_timer2() T2CONfic=OxFB

A1.4. ccp

ccp.h
//CONSTANTES, MACROS Y FUNCIONES PARA LOS MODULOS CCP
tfdefine CCPOFF 0x00
^define CCPCAPTUREFE 0x04
#define CCPCAPTURERE 0x05
#define CCPCAPTUREDIV4 0x06
#define CCP_CAPTURE_DIV16 0x07
#define CCPCOMPARERISE 0x08
#define CCPCOMPAREFALL 0x09
#define CCPCOMPAREINT OxOA
#define CCP_COMPARE_SPECIAL OxOB
#define CCPPWM OxOC
#define setup_ccpl(valué) CCPlCON=value
#define set pwml_duty(valué) CCPR1L= (value»2) ; \
CCPlCON=(CCPICON&OxCF)|((value&0x0003)«4)
#define get_ccpl(valué) CCPR1
#define setccpl(valué) CCPRl=value
#define setup_ccp2(valué) CCP2CON=value
«define set_pwm2_duty(valué) CCPR2L= (value»2) ; \
CCP2CON=(CCP2CON&OXCF)|((value&0x0003)«4)
«define get_ccp2(valué) CCPR2
#define set_ccp2(valué) CCPR2=value

A l. 5. analog

analog.h
//CONSTANTES, MACEOS Y FUNCIONES PARA EL CONVERSOR ANALÓGICO DIGITAL
Sdefine ADCOFF 0x00
«define ALL_DIGITAL 0x06
#define ALL_ANALOG 0x00
#define ALLA N A L O G V 0x01
#define ALLANALOG V V- 0x08

Página | 173
Programación de microcontroladores PIC en lenguaje C

«define ANO OxOE


«define AN0_V_V- OxOF
#define AN0AN1V 0x05
#define AN0_AN1_V_V- OxOD
#define AN0_AN1_AN3 0x04
«define AN0_AN4 0x02
#define AN0_AN4_V 0x03
#define AN0_AN4_V_V- OxOC
«define AN0_AN5 0x09
«define AN0AN5V OxOA
«define AN0_AN5_V_V- OxOB
#define XTALFREQ 4000000
«define ADC_CLK_RC OxCl
#define ADC_CLK_OSC 0X01
#define ADC_FREQ_DIV (float)(XTALFREQ/1250000)
«define START_ADC_CONV GO=l

extern void set_vref(unsigned char vref);


extern void set_adc_inputs(unsigned char analog);
extern void setupadc(unsigned char mode);
extern void set_adc_channel(unsigned char channel);
extern unsigned int readadc(void);

//CONSTANTES, MACROS Y FUNCIONES PARA EL COMPARADOR ANALÓGICO

#define CARESET 0x00


#define CA_AO_A3_NC_NC_ON_A4 0x01
^define CA_A0_A3_A1_A2 0x02
^define CA_AO_A3_A1_A2_ON_A4_A5 0x03
#define CA_A0_A3_A1_A3 0x04
ttdefine CA_AO_A3_A1_A3_ON_A4_A5 0x05
#define CA_A0_VR_A1_VR 0x06
#define CA_A3_VR_A2_VR OxOE
#define CA_NC_NC_NC_NC_OFF 0x07
#define CAC1INV 0x10
#define CA_C2INV 0x20

#define SETUPCOMPARATOR(CONFIG_COMPARATOR) \
CMCON=CONFIG_COMPARATOR;

//CONSTANTES, MACROS Y FUNCIONES PARA EL MÓDULO CVREF

#define CVRSRC 4.416


#define CVRON 0x80
«define CVROFF 0x00
«define CVR_LOW 0x20
«define CVR_HIGH 0x00
«define CVROUTON 0x40
«define CVR_OUT_OFF 0x00
«define CVRR0 0x00
«define CVRR1 0x01
«define CVRR2 0x02
«define CVRR3 0x03
«define CVRR_4 0x04
«define CVRR5 0x05
«define CVRR6 0x06
«define CVRR_7 0x07
«define CVRR8 0x08
«define C VRR9 0x09
«define CVRR10 OxOA
«define CVRR11 OxOB
«define CVRR12 OxOC
«define CVRR_13 OxOD
«define CVRR14 OxOE
«define CVRR15 OxOF

«define SET_CVREF(MODE) CVRCON=MODE


extern void setup_cvref(unsigned char mode, float volt);

Página | 174
Anexos

analog.c
# in c lu d e < h tc .h >
# in c lu d e " a n a lo g .h "

e x t e r n v o id set_a d c_in p u ts(u n s ig n ed char analog) { / /S eleccion a la s entradas analógicas


ADC0N1=(ADCONl&OxFO)|analog;
}
e x te rn v o id s e tu p a d c (u n s ig n e d char mode) { //S eleccion a e l modo de r e l o j
i f (mode==0x 00 ) { //CAD apagado
ADCONO=0x00;
ADCONl&= 0x06; // E/S d i g i t a l e s
}
e ls e i f (m ode==0xCl){ //Reloj RC
ADCONO=0xCl; //con a ju s te derecho
ADCONl&=OxBF;
}
e ls e {
if(ADC_FREQ_DIV< =1) { //Fose <= 1.25MHz
ADCONO=0x01; //ADCS1 =0, ADCS0=0, Canal 0, Módulo encendido
ADCONl&=0xBF; //ADFM=1(ajuste a l a d erech a ), ADCS2=0
}
e ls e if(ADC_FREQ_DIV<=2){ //Fose <= 2.5MHz
ADCONO=0x01; //ADCS1=0, ADCS0=0, Canal 0, Módulo encendido
ADCON1|=0xC0; //ADFM=1(ajuste a l a d erech a ), ADCS2=1
}
e ls e if<ADC_FREQ_DIVe=4){ //Fose <= 5MHz
ADCONO=0x41; //ADCS1=0, ADCS0=1, Canal 0, Módulo encendido
ADCONl&=0xBF; //ADFM=1(ajuste a la d erech a ), ADCS2=0
}
e ls e if(ADC_FREQ_DIV<= 8 ) { //Fose <= 10MHz
ADCONO=0x41; ; //ADCS1=0, ADCS0=1, Canal 0, Módulo encendido
ADCON1j =0xC0; //ADFM=1(ajuste a l a d erech a ), ADCS2=1
>
e ls e if(A D C FREQ_DIV<=16) { //Fose <= 20MHz
ADCONO=0x81; //ADCS1=1, ADCS0=0, Canal 0, Módulo encendido
ADCONl&=0xBF; //ADFM=1(ajuste a la d erech a ), ADCS2=0
}
e ls e { //Fose <= 40MHz
ADCONO=0x81; //ADCS1=1, ADCS0=0, Canal 0, Módulo encendido
ADCON1 |=0xC0; //ADFM=1(ajuste a la d erech a ), ADCS2=1
}
}
}
e x te rn v o id set_a d c_ch a n n el(u n sign ed char channel) { //Selecciona e l canal de con versión
//Cada v e z que se cambia de canal es n ecesa rio esp erar e l tiempo de a d q u isició n
/ / (a p ro x 44us) para que se e s t a b i l i c e l a ten sión a la entrada d e l CAD cuites de la n za r
//una c o n v e rs ió n nueva.
ADCONO = (ADCONO&OxC7) I ( (channel&0x07) « 3 ) ;
}
e x te rn u nsign ed i n t r e a d _ a d c (){ //Recoge e l v a lo r de l a conversión
w h ile (G O )c o n tin u é ;
r e t u m ( (ADRESH«2) + (ADRESL» 6 ) ) ;
}
e x te rn v o id s e tu p _ c v re f(u n s ig n e d char mode, f l o a t v o l t ) {
i f (mode&0x20) CVRCON= ( ( i n t ) ( (volt/CVRSRC) *24) &0x0F) |mode;

e ls e CVRCON=( ( i n t ) ( ( ( v o l t - (0.25*CVRSRC)) /CVRSRC)*3 2 )fcOxOF)Imode;


}

Página | 175
Programación de microcontroladores PIC en lenguaje C

A l.6. usart.h / usart.c


usart.h
#ifndef _SERIAL_H_
#define _SERIAL_H_
#define HIGHSPEED 0x04 //Modo alta velocidad
#define LOWSPEED 0 //Modo baja velocidad
#define NINEBITS 0x40 //Modo transmisión 9 bits
#define EIGHT_BITS 0 //Modo transmisión 8 bits
#define XTALFREQ 4000000 //Frecuencia del oscilador principal

#define RX_PXN TRXSC7 //Define el pin RC7 como pin para recepción de datos
#define TX_PIN TRISC6 //Define el pin RC6 como pin para transmisión de datos

/♦MACRO PARA CONFIGURAR EL MÓDULO USART EN MODO ASINCRONO*/


//BAUD: Velocidad de comunicaciones (9600, 19200, 28800, etc.)
//SPEED: Modo alta velocidad para el genereador de baudios => TRUE = On
//NINE: Utiliza transmission de 9 bits => FALSE=8bit
#define INIT_USART(BAUD,SPEED,NINE)\
R X P I N = 1; \ //Define los pines RC6 y RC7 para poder
TX_PIN = 1 ; \ //ser utilizados por el módulo USART
if (SPEED)SPBRG = ((int)(_XTAL_FREQ/((16UL * BAUD) +16))); \ //Ajusta la
//velocidad del
else SPBRG = ((int)(_XTAL_FREQ/((64UL * BAUD) +64))); \ //gen. de baudios
RCSTA = (NINE|0x90); \ //Carga la configuración del módulo receptor
TXSTA = (SPEED|NINE|0x20) //Carga la configuración del módulo transmisor

#endif

void putch(unsigned char byte); //Definición de la función putch


unsigned char getche(void); //Definición de la función getche
unsigned char getch(void); //Definición de la función getch

usart.c
#include <htc.h>

void putch(unsigned char byte){

while(!TXIF) //Se pone a '1' cuando se ha enviado el dato


continué;
TXREG = byte;
}
unsigned char getche() {

while(!RCIF) //Se pone a cuando se ha recibido un dato


continué;
return RCREG;
}
unsigned char getch() {

while(!RCIF) //Se pone a cuando se ha recibido un dato


continué;
return RCREG;
}

Página | 176
Anexos

A l. 7. i2c.h / ¡2c.€

i2c.h
#include <htc.h>

#define WRITE 0
#define READ 1

void i2c_init(); //Configura el módulo i2c


void i2c_start 0 ; //Envía la secuencia de start
void i2c_restart() ; //Envía la secuencia de restart
void i2c_stop(); //Envía la secuencia de stop
void i2c_idle(); //Comprueba si el módulo i2c está libre
void i2c_sendnack() ; //Envía la secuencia de nack
unsigned char i2c_write (unsigned char byte) ; //Envía un byte y devuelve 0
//en caso de error
unsigned char i2c_read(); //Lee un byte

¡2c.c
#include <htc.h>
#include ui2c.h"

//Configura el modulo I2C

void i2c_init(){
TRISC3 = 1; //SLC
TRISC4 = 1; //SDA
SSPADD = OxOA; //Reloj a lOOKHz
SSPSTAT = 0x80; //Habilita el control de velocidad del módulo
SSPCON2 = 0x00; //Baja los flags
SSPCON = 0x28; //Modo maestro, módulo I2C encendido
}
//Envía la secuencia de Start

void i2c_start(){
i2c_idle(); //Comprueba que está libre
[Link]=1; //Envía la condición de inicio
while([Link]==l) ; //Espera a que se envíe
while(SSPIF==0); //Comprueba que se ha enviado
SSPIF=0; //Baja el flag
}
//Envía la secuencia de (re)start

void i2c_restart(){
SSPCON2bi [Link]=1; //Envía la secuencia restart
while([Link]) ; //Espera a que se envíe
while(SSPIF==0); //Comprueba que se ha enviado
SSPIF=0; //Baja el flag
}
//Envía la secuencia de Stop

void i2c_stop(){
[Link]=1; //Envía la secuencia de Stop
while([Link]); //Espera a que se envíe
while(SSPIF==0); //Comprueba que se ha enviado
SSPIF=0; //Baja el flag
}

Página | 177
Programación de microcontroladores PIC en lenguaje C

//Comprueba que el modulo I2C está libre

Void i2c_idle(){
while ( ( SSPC0N2 & OxlF ) | SSPSTATbits.R_nW ) ; //Comprueba que el módulo está libre
}
//Lee un byte

unsigned char i2c_read(){


i2c_idle() ;
[Link]=1; //Activa el modo recepción
while([Link]==l); //Espera a recibir el byte
while([Link]==0); //Espera a que el buffer esté lleno
retura SSPBUF; //Devuelve el dato
}
//Envía un byte al esclavo y devuelve 0 en caso de error

unsigned char i2c_write(unsigned char byte){


i2c_idle();
SSPBUF=byte;
while(SSPSTAT&OxOS); //Comprueba si hay transmisión en curso
if([Link]==1){ //No ha recibido confirmación
[Link]=1; //Envía secuencia de Stop
re t u m 0 ; //devuelve 0
}
else{ //Ha recibido confirmación
while(SSPIF==0); //Comprueba que ha transmitido
SSPIF=0; //Baja el flag
re t u m 1; //Devuelve 1
}
}
//Envía la secuencia Nack

void i2c_sendnack(){
[Link]=1;
SSPC0N2b [Link]=1;
while([Link]==1);

A 1 .8 . Icd.h / Icd.c

Icd.h
/* Escribe un byte en la pantalla LCD en modo 4 bits */
extern void lcdwrite(unsigned char);

/* Limpia la pantalla LCD */

extern void lcdclear(void);

/* Escribe una cadena de caracteres en la pantalla LCD */

extern void lcd_puts(const char * s) ;

/* Posiciona el cursor en la posición indicada */

extern void lcd_goto(unsigned char pos);

/* Inicializa la pantalla LCD - utilizar anter de cualquier otra función */

extern void lcdinit(void);

Página | 178
Anexos

/* E s c r ib e en l a p a n ta lla LCD e l c a rá c te r cuyo có d igo ASCII se in d ica */

e x te r n v o id lc d _ p u tc h (c h a r) ;

/* E s ta b le c e l a p o s ic ió n d e l cu rsor */

# d e fin e lc d c u r s o r (x ) lc d _ w r i t e ( ( (x)&0x7F) |0x80)

Icd.c

/*
* Rutinas para trabajar con la pantalla LCD Hitachi HD44780.
* Utiliza comunicaciones en modo 4 bit de la siguiente forma:

* PORTD bits 0-3 conectados a los bits de datos 4-7 de la LCD (high nibble)
* PORTD bit 4 conectado a la entrada LCD RS (selección de registro)
* PORTD bit 5 conectado a la entrada LCD RW (lectura/escritura)
* PORTD bit 6 conectado a la entrada LCD EN (reloj)
* PORTD bit 7 conectado a la entrada LCD ON bit (LCD power)
*/
#ifndef XTALFREQ
//Se asume una frecuencia de trabajo de 4MHz a menos que se haya especificado
//con anterioridad
«define XTALFREQ 4000000
#endif

«inelude <htc.h>
«inelude “lcd.h"

#define LCDRS RD4


#define LCD R W RD5
«define LCD E N RD6

«define LCDDATA PORTD

«define LCD_STROBE() ((LCD_EN = 1),(LCD_EN=0))

/* envía un byte a la LCD en modo 4 bits */

void lcdwrite(unsigned char c){


_delayus(40);
LCDDATA = (LCDDATA & OxFO) | ( ( c » 4 ) & OxOF );
LCDSTROBE();
LCD DATA = (LCD DATA & OxFO) | ( c & OxOF );
LCDSTROBE();
}
/* Limpia la pantalla LCD */
void lcd_clear(void) {
LCDRS = 0;
lcd_write(0x1) ;
_delay_ms(2) ;
}
/* envía una cadena de caracteres a la LCD */
void lcd puts(const char * s) {
LCDRS = 1; // write characters
while(*s)
lcd_write(*s++);
}
/* escribe un character en la LCD */
void lcdputch(char c){
LCDRS = 1; // write characters
lcd_write( c );
}

Página | 179
Programación de microcontroladores PIC en lenguaje C

/* D esp la za e l c u rs o r a l a p o s ic ió n in d ic a d a */
v o id lc d _ g o to (u n s ig n e d char p o s ) {
LCDRS = 0;
l c d w r it e (0 x 8 0 + p o s );
}

/* I n i c i a l i z a l a p a n t a lla LCD en modo 4 b i t s */


v o id l c d i n i t ( ) {
ch a r i n it _ v a lu e ;

in i t _ v a l u e = 0x3;
TRISD=0;
RD7=1; //enciende l a p a n t a lla LCD
LCD_RS = 0;
LCD_EN = 0;
LCDRW = 0;
__ d e l a y m s (1 5 ); //espera 15ms
LCDDATA = (LCDDATA & OxFO) | in it_ v a lu e ; //en vía e l conunando de i n i c i o
LCDSTROBE( ) ;
__ d e l a y m s ( 5 ) ;
LCDSTROBE( ) ;
__ d e la y _ u s ( 2 0 0 ) ;
LCDSTROBE( ) ;
__ d e la y u s (2 00 ) ;
LCDDATA = (LCD_DATA & OxFO) | 2; //Modo 4 b i t s
LCDSTROBE( ) ;

l c d _ w r i t e (0 x 2 8 ); //Longitu d d e l c a r á c t e r
lc d _ w r it e (O x F ); / / D isp la y On, Cursor On, Cursor B lin k
lc d _ c le a r ( ) ; //Limpia l a p a n ta lla
l c d w r i t e ( 0x 6 ) ; //Modo de en trada On
}

Página | 180
A2. Registros de Funciones Especiales (SFRs)
A2.1. STATUS
A2.2. OPTION_REG
A2.3. T I CON
A2.4. T2CON
A2.5. INTCON
A2.6. PIE1
A2. 7. PIR1
A2.8. PIE2 y PIR2
A2.9. CCPxCON
A2.10. ADCONO
A 2 .ll. ADCON1
A2.12. CVRCON
A2.13. CMCON
A2.14. TXSTA
A2.15. RCSTA
A2.16. PCON
A2.17. SSPSTAT
A2.18. SSPCON
A2.19. SSPCON2
A2.20. PALABRA DE CONFIGURACION

A2.1. STATUS
R/W-0 R/W-0 R/W-0 R-1 R-1 R/W-x R/W-x R/W-x Valores de los bits después de un reset
R egistro S T A T U S
(d ireccio ne s 03h, IRP RP1 RPO TO# PD# Z DC R = el bit se puede leer
C
W = el bit se puede escribir Nota:
83h, 103h, 183h) bit 7 bitO x = Valor desconocido TO# = 7 0 j

bit 7 IRP: Selecciona el Banco de Memoria de datos en el bit 2 Z (Z ero): Indicador de cero
direccionamiento indirecto.
1 = Si el resultado de una operación antmética o lógica es cero
0 = Bancos 0 y 1 (OOh - FFh) (256 bytes) 0 = Si el resultado de una operación aritmética o lógica es no
1 = Bancos 2 y 3 (1 OOh - 1FFh) (256 bytes) es cero
bit 6-5 RP1 :RP0: Seleccionan el Banco de Memoria bit 1 DC (D ig it carry/bo rrow ): Indicador de acarreo o
de datos en el direccionamiento directo. préstamo auxiliar en las operaciones aritméticas de suma o
resta (instrucciones ADDWF, ADDLW, SUBLW, SUBWF)
00 = Banco 0 (OOh - 7Fh) (128 bytes)
1 = Si hay acarreo del bit 3 al 4 en el resultado de una
01 = Banco 1 (80h - FFh) (128 bytes) operación aritmética de suma binaria o si no hay préstamo en
110 = Banco2(1 OOh-17Fh) (128 bytes) una operación de resta
' 11 = Banco 3 (180h - 1FFh) (128 bytes) 0 = Si no hay acarreo en la suma o si hay préstamo del bit 4 al
bit 3 en una operación de resta
bit 4 TO# (T im e -o u t ) : Indicador de desbordamiento del
perro guardián W TD (W atch d og Timer) bit 0 C (C arry/bo rro w ): Indicador de acarreo o préstamo en las
0 = Cuando se desborda el WTD operaciones aritméticas de suma o resta (instrucciones
ADDWF. ADDLW. SUBLW, SUBWF)
1 = Después de un reset por encendido (pov/er-up ) y con
las instrucciones CLRWDT y SLEEP 1 = Si hay acarreo en el resultado de una operación aritmética
de suma binaria o si no hay préstamo en una operación de
bit 3 PD# (P o w e r-d o w n ): Indicador de modo de bajo resta
consumo. 0 = Si no hay acarreo en la suma o si hay préstamo en una
0 = Cuando entra en bajo consumo con la instrucción operación de resta
SLEEP
1 = Después del encendido o con la instrucción CLRWDT

Página | 181
Programación de microcontroladores PIC en lenguaje C

A2.2. Registro OPTION_REG


R/W-1 RW-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1
Registro OPTION_REG
(direcciones 0x81 h, 0x181 h RBPU# INTEDG TOCS TOSE PSA PS2 PS1 PS0
de la memoria de datos RAM) B it 7 Bit 6 B it 5 Bit 4 Bit 3 B it 2 B it 1 BitO

bit 7 RBPU#: Habilita/deshabilita las resistencias internas de bit 3 PSA: asigna el pre-divisor al TimerO (P SA = 0) o al
Pull-up del puerto B. Perro Guardián WDT (P SA =1)

1 = P O R TB pull-ups deshabilitadas Bits 2,1 y 0 PS2:PS1:PS0: programan el factor de


0 = P O R TB pull-ups habilitadas división del pre-divisor.

bit 6 INTEDG: Selección del planeo para la generación de la


interrupción externa por RBO. Factor división Factor división
PS2 PS1 PS0
para T1VIR0 oara WDT
1 = Interrupción externa RBO/INT por flanco de subida 000 2 1
0 = Interrupción externa RBO/INT por flanco de bajada 001 4 2 I
010 8 4
bit 5 TOCS: configura al Timert) com o temporizador (TOCS = 011 16 8
0) o com o contador (TOCS = 1). 100 32 16 !
bit 4 TOSE: configura el flanco de la señal externa con el que 101 64 32
s e incrementa el TimerO si ha sido programado como 110 128 64 I
contador (TOSE = 0 para flanco de subida y TSOE = 1 para 111 256 128
flanco de bajada).

A 2 3 . TICO iM
U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
Registro T1CON
(dirección 0x10 de la T1CKPS1 T1CKPS0 T10SCEN T1SYNC# TMR1CS TMR10N j
memoria de datos RAM) B it 7 B it 6 B it 5 B it 4 B it 3 B it 2 B it 1 BitO

bit 7-6 No implementados: s e leerían com o '0'. bit 2 T1SYNC: Bit de control de la sin cro n izació n del
reloj externo del Tim erl
bit 5-4 T1CKPS1 :T1CKPS0: B its de sele cció n del factor de Cuando TM R1CS=1:
d ivisió n del pre-divisor para la entrada de reloj del Tim erl 1 = No sincroniza la entrada de reloj externo
0 = Sincroniza la entrada de reloj externo
T 1C K P S 1 -T 1C K P S 0 Factor de división Cuando TM R 1C S = 0:
00 1 Este bit s e ignora, pues TIMER1 u sa el reloj
01 2 interno que ya está sincronizado.
10 4
11 8 bit 1 TMR1CS: Bit de se le cció n de reloj para el TIM ER 1
1 = Reloj externo del pin RC0/T1O SÓ /T1CKI
bit 3 T10 S C EN : B it de habilitación (enable) del oscilado r (flancos de subida)
extem o (T 1 0 S C ) del TMR1 0 = Reloj interno (FOSC/4)
1 = O scila d o r habilitado
0 = O scilla d o r apagado bit 0 TMR10N: Bit para arranque/paro del Tim ert.
1 = Tim erl cuenta p u lsos
0 = Tim erl parado

Página | 182
Anexos

A 2 .4 . T2COÍM

U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0


Registro T2CON
TO U TPS3 TO U TPS2 TO U TPS1 TO U TPSO TMR20N T2CKPS1 T2CKPSS
la
■ AM) b it 7 b it 6 b it 5 b it 4 b it 3 b it 2 b it 1 bit 0

bit 7 No implementado: S e lee com o 0 bit 2 TMR20N: Bit de paro/arranque del TMR2
1 = Timer2 on (habilitado)
bit 6:3 TOUTPS3:TOUTPSO: B its de selección del factor 0 = Timer2 off (no habilitado)
de división del post>divisor del Timer2
bit 1:0 T2CKPS1 :T2CKPS0: Bits de selección del factor de
TO U TP S3-TO U TP SO Factor de división división del pre-divisor del Timer2
0000 1
0001 2 T2 CK PS1 -T2 CK P S0 Factor de división
0010 3 00 1
0011 4 01 4
0100 5 1x 16
0101 6
0110 7
0111 8
1000 9
1001 10
1010 11
1011 12
1100 13
1101 14
1110 16
1111 16

A2.5. Registro INTCOIM


R / W -0 R /W -0 R / W -0 R / W -0 R / W -0 R /W -0 R / W -0 R / W -x

R egistro INTCON
(dire cciones OBh, G IE P E IE T O IE IN T E R B IE T O IF IN T F R B IF

8Bh, 10Bh, 18Bh) b it 7 bitO

bit 7 G IE (G lo b a l In t e rr u p t E n a b le ): Habilitación del sistema bit 3 RBIE ( R B P o rt C h a n g e In te rru p t E n a b le ) Habilitación


de interrupciones del microcontrolador de la interrupción por cambio en cualquier terminal RB4-RB7
1 = Se habilitan todas las interrupciones no enmascaradas 1 = Se habilita la interrupción
0 = Se inhabilitan todas las interrupciones. 0 = Se inhabilita la interrupción
bit 6 P E IE (P e rip h e r a l In te rru p tE n a b le ): Habilitación de las bit 2T0IF (TM RO O v e rflo w In te rru p t F la g ) Señalizador del
interrupciones de los periféricos (en registros [Link].PIE2, desbordamiento del timerO
PIR2) 1 = El registro TMRO se ha desbordado (se debe limpiar,
1 = Se habilitan todas las interrupciones de los periféricos no desactivar por software)
enmascaradas 0 = el registro TMRO no se ha desbordado
0 = Se inhabilitan todas las interrupciones de periféricos.
bit 11NTF (R B O /IN T E x te rn a l In te rru p t F la g ) Señalizador de
bit 5 T 0 IE (TM RO O v e rflo w In te rru p t E n a b le ): Habilitación petición de interrupción externa
de la interrupción por desbordamiento del TimerO 1 = Se produce petición de interrupción (se debe desactivar
1 = Se habilita la interrupción por software)
0 = Se inhabilita la interrupción 0 = No se produce petición de interrupción externa
bit 4 IN TE (R B O / IN T E x t e r n a lIn t e r ru p t E n a b le ): Habilitación bit 0 RBIF (RB Port Change Interrupt Flag): Señalizador de
de la interrupción extema cambio en algún terminal RB4-RB7
1 = Habilita la interrupción extema por RBO/INT 1 = Al menos un terminal RB7-RB4 ha cambiado de estado
0 = Inhabilita la interrupción extema por RBO/INT (se debe desactivar por software).
0 = Ningún terminal RB7-RB4 ha cambiado de estado______

Página | 183
Programación de microcontroladores PIC en lenguaje C

A2.6. Registro PIE1


R egistro PIE1 R7W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W -0

(dirección 8Ch) PSPIE(’ ) ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE

bit 7 bitO

bit 7 PSP1E(1) : Permiso de interrupción para el puerto bit 3 SSPIE: Permiso de interrupción para el puerto serie
paralelo Esclavo (PSP) al realizar una operación de lectura síncrono (SSP)
/escritura 1 = Habilita la interrupción
1 = Habilita la interrupción 0 = Inhabilita la interrupción
0 = Inhabilita la interrupción
bit 2 CCP1IE: Permiso de interrupción para el módulo CCP1
bit 6 ADIE: Permiso de interrupción para el conversor A/D al cuando se produce una captura o comparación
finalizar la conversión 1 = Habilita la interrupción
1 = Habilita la interrupción 0 = Inhabilita la interrupción
0 = Inhabilita la interrupción
bit 1 TMR21E: Permiso de interrupción para el TMR2 con su
bit 5 RCIE: Permiso de interrupción para el receptor del desbordamiento.
USART cuando el bufferse llena 1 = Habilita la interrupción
1 = Habilita la interrupción 0 = Inhabilita la interrupción
0 = Inhabilita la interrupción
bit 0 TMR1IE: Permiso de interrupción para el TMR1 con su
bit 4 TXIE: Permiso de interrupción para el transmisor del desbordamiento.
USART cuando el buffer se vacía 1 = Habilita la interrupción
1 = Habilita la interrupción 0 = Inhabilita la interrupción
0 = Inhabilita la interrupción
Nota: P S P IE no existe en los PIC16F873/873A/876/876A
(m odelos de 28 term inales que no tienen el P S P )__________

A2.7. Registro PIR1


R egistro P IR I R/W-0 R/W-0 R-0 R-0 R/W-0 R/W-0 R/W-0 R/W-0
(dirección OCh) PSPIF«1> ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF

b it 7 b it 0

bit 7 PSPIF'1) : Señalizador (de interrupción) del puerto bit 2 CCP1IF: Señalizador (de interrupción) del módulo CCP1
paralelo Esclavo (PSP) al realizar una operación de lectura MODO CAPTURA:
/escritura 1 = El registro del CCP captura el valor del registro TMR1
1 = Se ha producido una operación de R/W (desactivar por (valor del Timerl) (desactivar por software)
software) 0 = No se produce la captura del registro TMR1
0 = No se ha producido operación de R/W. MODO COMPARACIÓN:
1 = Coinciden el valor del CCP con el valor del TMR1
bit 6 ADIF: Señalizador (de interrupción) del conversor A/D al
0 = No coinciden
finalizar la conversión
MODO PWM (modulación de pulsos en anchura): no se usa
1 = La conversión A/D está completada
0 = La conversión A/D no está completada bit 1 TMR2IF: Señalizador (de interrupción) por coincidencia
de TMR2 con PR2
bit 5 RCIF: Señalizador (de interrupción) del receptor del
1 = Se produce la coincidencia
USART cuando el bufferse llena
0 = No se produce la coincidencia
1 = Buffer lleno
0 = Buffer no lleno bit 0 TMR1IF: Señalizador (de interrupción) por
bit 4 TXIF: Señalizador (de interrupción) del transmisor del desbordamiento (overflow) del TMR1
1 = Desbordamiento del TMR1 (desactivar por software)
USART cuando el bufferse vacía
0 = No desbordamiento del registro TMR1
1 = Buffer vacío
0 = Buffer no vacío Note 1: PSPIE no existe en los PIC16F873/873A/876/876A
bit 3 SSPIF: Señalizador (de interrupción) del puerto serie (modelos de 28 terminales que no tienen el PSP)
síncrono (SSP)
1 = Se ha producido la condición de interrupción del SSP, es
decir, se ha producido una transmisión/recepción (desactivar
por software antes de salir de la RAI)
0 = No se produce condición de in6terrupción de SSP

Página | 184
Anexos

A2.8. Registro PIE2 y PIR2


R egistro PIE2 (dirección 8Dh) Registro PIR2 (dirección ODh)
, U-0 R/W-0 U-0 R/W-0 R/W-0 U-0 U-0 R/W-0 -U-Q- R/W-0 U-0 R/W-0 R/W-0 U-0 U-0 R/W-0
1 ' CMIE | • BCLIE | ■ - ¡CCP2IE | ■ | CMIF | | EEIF | BCLIF | • |c CP2If|
I™
bit 7 bitO bit 7 bitO
bit 7,5,2,1 Unimplemented: No implementado. Se lee '0' bit 7,5,2,1 Unimplemented: No implementado. Se lee '0'
bit 6 CIVIIE: Permiso de interrupción para el Comparador bit 6 CP71IF: Flag(de interrupción) del comparador
1 = Habilita la interrupción 1 = Ha cambiado la entrada del comparador
0 = Inhabilita la interrupción 0 = No ha cambiado
bit 4 EEIE: Permiso de interrupción por fin de escritura en la bit 4 EEIF: Flag (de interrupción) del fin de escritura en la
EEPROM de datos EEPROM
1 = Habilita la interrupción 1 = Se ha completado la operación de escritura (desactivar
0 = Inhabilita la interrupción por software)
bit 3 BCLIE: Permiso de interrupción por colisión de Bus en 0 = No se ha completado o iniciado la operación de escritura
el el puerto serie síncrono (SSP) cuando dos o más
maestros tratan de transferir al mismo tiempo. bit 3 BCLIF: Flag (de interrupción) por colisión de BUS.
1 = Ha ocurrido una colisión de bus en el SSP.
1 = Habilita la interrupción
0 = Inhabilita la interrupción 0 = No ha ocurrido la colisión
bit 0 CCP2IE: Permiso de interrupción en el módulo CCP2 bit 0 CCP2IF: Flag (de interrupción) del módulo CCP2
1 = Habilita la interrupción MODO CAPTURA:
0 = Inhabilita la interrupción 1 = El registro del CCP captura el valor del registro TMR1
(valor del Timerl) (desactivar por software)
0 = No se produce la captura del registro TMR1
MODO COMPARACIÓN:
1 = Coinciden el valor del CCP con el valor del TMR1
p = No coinciden
|MODO PWM (modulación de pulsos en anchura): no se usa

A2.9. CCPxCON
Bits
3-0 Bits de selección del modo de funcionamiento del módulo CCPx j
CCPxMO
00 00 Módulo CCPx desactivado (resetea el módulo CCPx)
00 Modo Captura Captura cada flanco de bajada
01 Modo Captura Captura cada flanco de subida
01
10 Modo Captura Captura cada 4 flancos de subida
11 Modo Captura Captura cada 16 flancos de subida
El terminal CCPx es iniciado en bajo 0 y se pone en alto t cuando el resultado de la
Modo comparación es positivo, es decir, cuando TMR1 alcanza el valor del registro de16 bits
00
Comparación ([Link]). El bit CCPxIF se activa y se pone a 1
El terminal CCPx es iniciado en alto T y se pone en bajo 0' cuando el resultado de la
Modo comparación es positivo, es decir, cuando TMR1 alcanza el valor del registro de16 bits
01
Comparación (CCPRxH:CCPRxL). El bit CCPxIF se activa y se pone a 1 '
10 El bit CCPIF es puesto a 1 cuando el resultado de la comparación es positivo, es decir, generación
10 Modo de interrupción software cuando se produce la igualdad. El terminal CCPx no se ve afectado
Comparación

Generación de disparo de evento especial (special event trigger) cuando el resultado de la


Modo comparación es positivo. El bit CCPxIF se pone a 1. El terminal CCPx no se ve afectado. CCP1
11 resetea el TMR1; CCP2 resetea el TMR1 y lanza una conversión A/D nueva (si el módulo del
Comparación
conversor A/D está habilitado.
11 XX PWM
Bits DCxB1:DCxB0 Modo Bits 0 y 1 del valor que fija el ciclo de trabajo en el modo PWM i
5-4 (CCPxX:CCPxY) PWM En los modos CAPTURA y COMPARACIÓN NO SE UTILIZAN
Bits 7-6 | No implementados Se leerían como '0’ j

Página | 185
Programación de microcontroladores PIC en lenguaje C

A2.10. ADCONO
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 U-0 R/W-0
R E G IS T R O ADCONO ADCS1 A D C S0 CH S2 CH S1 ADON
CH S0 G O /D O N E#
(dirección 1Fh)
bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bitO

bit 7-6 ADCS1:ADCS0: Selección del reloj para bit 5-3 CHS2:CHS0:
la conversión A/D (en los PIC16F87x y Selección del canal de conversión
versiones “antiguas”) y junto con ADCS2 que 000 = Canal 0 100 = Canal 4
está en ADCON1 (en los PIC16F87x A) 001 = Canal 1 101= Canal 5
010 = Canal 2 110 = Canal 6
Frecuencia del reloj del
A D C S1 :A D C S0
Fuente convertidor A/D
011= Canal 3 111= Canal 7
de reloj
A DCS2 = 0 A D CS2 = 1 bit 2 GO/DONE#:
Oscilador Estado de la conversión
00 Fosc/2 Fosc/4
principal Si ADON=1:
01 Oscilador
Fosc/8
1 = Conversión en progreso
Fosc/16
principal 0 = Conversión finalizada
Oscilador
10
principal
Fosc/32 Fosc/64 bit 0 ADON:
167 KHz
Bit de encendido del convertidor A/D
Oscilador 167 KHz
11 RC a a 1 = Módulo A/D encendido
interno 500 KHz 500 KHz 0 = Módulo A/D apagado

A 2 .ll. ADCON1
R/W-0 R/W-0 U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0

R E G IS T R O ADCON1 AD FM AD CS2 PCFG 3 PCFG 2 PCFG1 PCFG 0

(d irecció n 9Fh)
bit 7

bit 7 ADFM : Selección de formato del bit 3-0 PCFG3:PCFG0: Configuración de las
resultado entradas al módulo A/D
1 = Ajuste a la derecha PCFG 3
AN7 AN6 AN5 AN4 AN3 AN2 AN1 ANO
0 = Ajuste a la izquierda V M f. V (tE F-
RE2 RE1 REO RA5 RA3 RA2 RA1 RAO
PCFG 0
A D FM = 0 T 1 A D FM = 1
0000 A A A A A A A A V dd Vss
j Resultado 10 bits h 0001 A A A A V „ f r. A A A RA3 V ss
0010 D D D A A A A A Veo vss
0011 D D D A A A A RA3 V ss
I I I II I I lYl N°H°H-I |j|o|o|o|o|oj 111 I 11 I 0100 D D D D A D A A V od Vss
0101 D D D D D A A RA3 Vss
A D R ESH A D R ESL A D R ESH A D R ESL -
011x D D D D D D D D

1000 A A A A A RA3 RA2


A V p F.-
Resultado 10 bits Resultado 10 bits
1001 D D A A A A A A V D0 Vss
1010 D D A A V B Ft. A A A RA3 Vss
bit 6 ADCS2: Selección de reloj para 1011 D D A A A A RA3 RA2

conversión A/D junto con ADCS1 y 1100 D D D A A A RA3 RA2

ADCS0 de ADCONO 1101 D D D D A A RA3 RA2

1110 A v 00 Vss
(No existe en los PlC16F87x y versiones D D D D D D D

1111 D D A RA3 RA2


“antiguas”) D D D

D: digital y A; analógica

Página | 186
Anexos

A2.12. CVRCON

R/W-0 R'W-fl
R E G IS T R O C V R C O N
(d irecció n 9Dh)

Bit 5 CVRR: Bit de selección del rango de


Bit 7 CVREN: Bit para la habilitación de la salida CVREF (‘1’ rango bajo, ‘0’ rango alto)
referencia de tensión del comparador (‘1’
habilitado, ‘0’ deshabilitado). 1 = de 0 a 0.75 CVRSRC cada CVrsrc/24
0 = de 0.25 a 0.75 CVRSRC cada CVrsrc/32
I = Tensión de referencia CVREF habilitada
0 = Tensión de referencia CVREF bit 3-0 CVR3:CVR0: Bits para la selección del
deshabilitada valor de referencia VREF del comparador
(CVRSRc=VDD)
bit 6 CVROE: Bit para la habilitación de
la referencia de tensión de salida del Cuando CVRR = 1
comparador C V REF = (VR<3:0>/24)-(CVrsrc)
1 = Tensión de salida CVREF por RA2
0 = Tensión de salida CVREF por RA2 Cuando CVRR = 0
desconectada
CV REF =1/4-(CVrsrc) + (VR<3:0>/32)(CVr .

A2.13. CMCON

Página | 187
Programación de microcontroladores PIC en lenguaje C

A 2 .1 4 . TXSTA
RAV-0 R-1 RW-0
REGISTRO TXSTA
(dirección 0810 SYHC ^ TRIrTT J TX90
bit 1 bit O

B t 7 C S R C : Bit para la selección de reloj Bit 2 BRGH Selección del modo de funcionamiento
Modo asincrono del generador interno.
Se ignora Modo asincrono
Modo síncrono 1 = Alta velocidad
i = Master (reloj generado por el módulo BRG) 0= Baia velocidad
0= Slave (reloj externo) Modo síncrono
Bit 6 TX9 Habilitación de la transferencia en Se ignora
modo 9 bits Bit 1 TRMT: Indicador de estado del registro de
1 = Transmisión 9 bits desplazamiento de transmisión
0 = Transmisión 8 bils 1 = Registro T S R vacio
Bit 5 TXEN Habilitación de la transmisión O = Registro T S R lleno
1 = Transmisión habilitada Bit O TX9D. Noveno bit de transmisión de datos
0 = Transmisión deshabitada (puede ser el bit de pandad).
Bit 4 S Y N C Selección de modo
1 = Síncrono
O = Asincrono

A2.15. RCSTA
REGISTRO RCSTA
(dirección 18h)

Bit 7 SPEN; Bit para la selección de reloj. Bit 3 ADDEN Detección de dirección
1 = USART ON Modo asincrono 9-bits (RX9=1)
0 = USART OFF 1 = Permite detección de dirección, habilita la interrupción y la
Bit 6 RX9: Habilitación de la recepción en modo 9 carga del buffer de recepción cuando RSR<Q> está a T
bits 0 = Deshabita la detección de dirección, se reciben todos los
1 =Tx9bits 0 = Tx8bits bits y el bit 9 puede utilizarse como bit de pandad
Bit 5 SREN Recepción de 1 bit Bit 2 FERR- Indicador de error de trama
Modo asincrono 1 = Error
Se ignora 0 = Sin error
Modo síncrono - Master Bit 1 OERR: Error por desbordamiento del registro de
1 = Habilitada O = Deshabitada desplazamiento
Modo síncrono - Slave 1 = Error
Se ignora 0 = Sin error
Bit 4 CREN Recepción continua Bit 0 RX9D: Noveno bit de recepción de datos (puede
Modo asincrono ser el bit de pandad)
1 = Habilitada 0 = Deshabitada
Modo síncrono
1 = Habilitada mientras hasta que CREN es 0
O = Deshabitada

A2.16. PCON
U-0 U-0 U-0 U-0 U-0 U-0 RAV-0 R/W-1
R e g istro P CO N
PO R» BOR»
(d irecció n 8Eh)
bit 7 bitO
bit 7-2 Unimplemented: No implementado. Se lee como ’0‘
bit 1 POR (Po w er-o n R e se t Sta tu s bit): Indica si el reset es por encendido o conexión de la alimentación.
0 = Cuando se produce el reset por encendido (debe ponerse a 1 por software después de que ocurra el reset por encendido)
1 = No se produce reset por encendido
bit 0 BOR (Brow n -o ut R e s e t Statu s bit): Indica si el reset es por caída de tensión.
0 = Cuando se produce el reset por caída de tensión (debe ponerse a 1 por software después de que ocurra el reset por caída
de tensión)
1 = No se produce reset por caída de tensión

Página l 188
Anexos

A 2 .1 7 . S S P S T A T

MODO SPI
R/W-0 R/W-0 R-0 R-0 R-0 R-0 R-0 R-0 Valores de los bits después de un rese'
Registro SS P S T A T SMP CKE D/Á P S R/W UA BF R = el bitse puetíeleer ¡
(dirección 94h) W = el bitse puede escribid
bit 7 bitO x = Valor desconocido

bit 7 SP/IP (Sample bitj; Modo demuestreodedatos. bit 3 S (S t a r t b h ): Bit de inicio


Se utiliza sólo en modo PC.
1 = Muestreo de datos al final del tiempo de salida de
datos bit 2 R/W (R e ad /W rite in fo rm atio n bit)
0 = Muestreo de datos a mitad del tiempo de salida de Se utiliza sólo en modo PC.
datos
SPI Esclavo bit 1 UA (U pd a te a d d re s s bit)
Se debe ponera ‘0’ cuando funciona en modo esclavo
Se utiliza sólo en modo PC
bit 6 CKE ( S P I d o c k s e l e c t b it): Seleccionan el modo de
transmisión de datos. bit 0 BF (B u ffe r fu ll s ta tu s bit): Bit indicadorde buffer lleno.

1 = Transmite cuando la señal de reloj pasa de '1' a ‘0’. Sólo en modo recepción

0 = Transmite cuando la señal de reloj pasa de '0’ a '1 1 = Recepción completa, SSPBUF lleno

bit 5 D/A (D a ta / A d d r e s s bit) 0 = Recepción incompleta, SSPBUF vacío

Se utiliza sóloenmodoPC.
bit 4 P (S t o p bit): Bit de parada
Se utiliza sólo en modo PC. Se pone a 0 cuando el módulo
| MSSP está des habilitado (SSPEN=0)

modo i2c
R/W-0 R/W-0 R-0 R-0 R-0 R-0 R-0 R-0 |Valores de los bits después de un resetj
Registro SS P S T A T SMP CKE D/Á P S R/W UA BF R = elbitse puede leer
(dirección 94h) W = el bitse puede escribir
bit 7 bitO x = Valor desconocido

bit 7 SMP (Slew rate control bit;.- Control de velocidad bit 3 S (S ta rt bit): Bit de inicio
1 = Indica que se ha recibido un bit de inicio.
Maestro o esclavo 0 = Indica que no se ha detectado bit de inicio.
1 = Control habilitado para velocidades estándar (100KHz Se pone a '0' en un Reseto al apagar el módulo
y 1 MHz)
0 = Control deshabilitado para modo alta velocidad (400 bit 2 R/W (R e ad /W rite in fo rm a tio n b'rt)
KHz). Esclavo Maestro
1=Lectura. 1 = Transmisión en curso
bit 6 CKE (S M B U S S e l e c t bit) 0 = Escritura 0 = No hay transmisión en curso
1 = Habilita entradas específicas SMBus.
0 = Deshablllta entradas específicas SMBus. bit 1 UA (U pd a te a d d r e s s b'rt): Sólo para modo 10-bit
esclavo)
bit 5 D/A (D a ta / A d d re s s bit)
1 = El usuario debe actualizarla dirección SSPADD.
Reservado en modo maestro 0 = No se necesita actualizarla dirección SSPADD
Esclavo
bit 0 BF (B u ffe r fu li s t a t u s bit): Bit indicadorde buffer lleno.
1 =EI último byte reclbidoes un dato.
Modo Transmisión
0 = El último byte recibidoes una dirección.
1 = Recepción completa, SSPBUFIIeno
bit 4 P (S t o p bit): Bit de parada. 0 = Recepción incompleta. SSPBUFvacio
1 = Indica que se ha recibido un bit de stop. Modo Recepción
0 = Indica que no se ha detectado bit de stop. 1 = Transmisión en proceso, SSPBUFIIeno
Se pone a '0' en un Reseto al apagar el módulo 0 = Transmisión completa, SSPBUF vacio

Página | 189
Programación de microcontroladores PIC en lenguaje C

A2.18. SSPCON

MODO SPI
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 [valores de los bits después de un resetj
Registro SSPCO N R = el bitse puede leer
W C O L SSPO V SSPEN CKP SSPM3 SSPM2 SSPM1 SSPMO
(dirección 14h) W = el bit se puede escribir
x = Valor desconocido

bit 7 W C O L (W rite C o llis io n D e t e c t b it): bit indicador de bit 4 CKP ( d o c k p o la r ity s e l e c t b it ): Bit de selección de
colisión. polaridad del reloj.
1 = Colisión en el envío de datos (debe limpiarse por
1 = Estado alto ‘1’ inactivo.
software).
0 = Estado bajo ‘0’ inactivo.
0 = No hay colisión.
bits 3:0 SSPM3:SSPM0 ( S y n c h r o n o u s s e r i a l p o r t m o d e
bit 6 SSPOV ( R e c e iv e O v e rflo w In d ic a to r bit): bit
s e l e c t b it s ) : Bits de selección del modo de funcionamiento
indicador de desbordamiento.
del módulo SPI
SPJ esclavó
1 = Hay colisión en la recepción de datos (debe limpiarse
0101 = SPI esclavo dock = SCK, control SS deshabilitado
por software.
0 = No hay desbordamiento. 0100 = SPI esclavo dock = SCK, control SS habilitado
bit 5 SSPEN ( S y n c h r o n o u s S e r ia l P o r t E n a b le bit): 0100 = SPI maestro, dock = TMR2/2
Habilita el módulo MSSP.
1 = Habilita el módulo MSSP y asocia los terminales SCK, 0100 = SPI maestro, dock = Fose/ 64
SDO. SDI y SS al módulo. 0100 = SPI maestro,dock= Fose/16
0 = Deshabilita el módulo MSSP y configura los terminales
0100 = SPI maestro, dock = Fose/4
como puertos E JS .
Cuando se habilita el módulo sus pines se deben configurar B resto de combinaciones están reservadas o se utilizan
adecuadamente comoentradas/salidas únicamente en modo l2C

MODO l2C
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 |Valores de los bits después de un reseij
Registro SSPCO N R = elbitse puede leer
W CO L SSPO V SSPEN CKP SSPM3 SSPM2 SSPf.11 SSPMO
W = el bitse puede escribir
(dirección 14h) x = Valor desconocido

bit 7 W C O L (W rite C o llis io n D e t e c t b it): bit indicador de bit 4 CKP ( S C K r e le a s e c o n t r o l b it): Bit de liberación de
colisión. reloj.
Transmisión Master/Slave 1 = Libera reloj.
1 = Colisión en el envío de datos (debe limpiarse por 0 = Mantiene el reloj en bajo.
software).
0 = No hay colisión. bits 3:0 SSPM3 rSSPMO ( S y n c h r o n o u s s e r ia l p o rt m o d e
s e l e c t b its ): Bits de selección del modo de funcionamiento
bit 6 SSPOV ( R e c e iv e O v e rflo w In d ic a to r bit): bit
del módulo LC
indicador de desbordamiento.
Modo recepción 1111 = l2C esclavo, 10-bitcon interrupciones Start&Stop
1 = Hay colisión en la recepción de datos (debe limpiarse
por software. 1110 = l2C esclavo, 7-bltcpm omterri'copmes Start& Stop
0 = No hay desbordamiento. 1011 = I2C maestro controlado por Firmware
bit 5 SSPEN ( S y n c h r o n o u s S e r ia l P o rt E n a b le bit):
1000 = l2C maestro,clock= Fosc/(4*(SSPADD+1))
Habilita el módulo MSSP.
1 = Habilita"iTmódulo MSSP y asocia los terminales SDA 0111 = l2C esclavo, direcciones 10-bit
SCL al módulo. 0110= l2C esclavo, direcciones 7-bit
0 = Deshabilita el módulo MSSP y configura los terminales
como puertos E/S. B resto de combinaciones están reservadas o se utilizan
únicamente en modo SPI
Cuando se habilita el módulo sus pines SDA y SCL se deben
configurar adecuadamente comoentradas/salidas

Página | 190
Anexos

A 2 .1 9 . S SP C O N 2
MODO l2C
R/W-0 R/W-0 RWf-0 RIW-0 R/VJ-0 RW-0 RW-0 RW-0 ¡Valores délos bits después de un resed
Registro S S P C O N 2 GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN R =elbitse puede leer
(dirección 91h) W = e l bitse puedeescribirj
b it 7 b itO x = Valor desconocido

bit 7 GCEN (G e n e r a l c a li e n a b le bit) - Modo esclavo. bit 3 RCEN ( R e c e iv e e n a b le bit) - Modo maestro
1 = Habilita interrupciones cuando recibe OOOOh (general 1 = Habilita el modo de recepción l2C.
calladdress). 0 = Recepción deshabilitada.
0 = Deshabilita interrupciones al recibir OOOOh.
bit 2 PEN (S to p co n d itio n e n a b le bit) - Modo maestro
bit 6 ACKSTAT (A c k n o w le d g e s ta t u s bit) 1 = Inicia la secuencia de Stop. Se pone a '0’ al finalizar
Afedo transmisión maestro 0 = Secuencia de Stop deshabilitada.
1 = No se ha recibido confirmación de recepción del
esclavo. bit 1 RSEN (R e p e a t e d s ta rt c o n d itio n e n a b le d bit) - Modo
0 = Se ha recibido confirmación de recepción del esclavo. maestro
1 = Inicia la secuencia de Restar! Se pone a '0' al finalizar.
bit 5 ACKDT (A c k n o w le d g e data bit) 0 = Secuencia de Restartdeshabilitada.
Atodo recepción maestro
1 = No confirmar bit 0 SEN (S ta rt co n d itio n e n a b le d /stre tch bit)
0 = Confirmar Modo maestro
Valor transmitido cuando el usuario inicia una secuencia de 1 = Inicia la secuencia de Star! Se pone a ‘0’ al finalizar.
confirmaciónal final de la recepción. 0 = Secuencia de Start deshabilitada.
bit 4 ACKEN (A c k n o w le d g e s e q u e n c e e n a b le bit) Modo egc[avo
Afecto recepción maestre? 1 =Stretch de reloj habilitado en recepción y transmisión.
1 = Inicia la secuencia de confirmación. Se pone a 0 al 0 =Stretch de reloj habilitado en transmisión.
finalizar.
0 = Secuencia de confirmación desactivada.

A2.20.- PALABRA DE CONFIGURACIÓN


R/P-1 U-0 R/P-1 R/P-1 R/P-1 R/P-1 R/P-1 R/P-0 U-0 U-0 RJP-1 R/P-1 R/P-1 RJP-1
C O N FIG W ORD DEBUG WRT1 WRTO CPD LVP BOREN PW RTEN WDTEN Fose! FoscO
(dirección 2007h)

bit 13 CP (C o d e P ro te c tio n ): Protección de escritura en bit 7 LVP (L o w -V o lta g e Programming): Programación a


memoria de programa baja tensión
1 = Protección deshabilitada. 1 = Habilitada a través del terminal RB3/PGM.
0 = Protección habilitada para toda la memoria. 0 = Deshabilitada, RB3 funciona como E/S digital.

bit S BOREN (B ro w n -o u t R e s e t E n a b le bit): Reset por caída


bit 12 No implementado - ‘1’ de tensión
1 = Habilitado. o = Deshabilitado
bit 11 DEBUG : In-Circuit debug
1 = Deshabilitado, RB6 y RB7 son E/S digitales. bits 5-4 No implementados- '1'
0 = Habilitado, RB6 y RB7 son utilizadas por el debugger.
bit 3 PWRTEN (P o v/e r-u p T im e r E n a b le ) Habilitación del
bits 10-9 AWRT1:WRT0 (W ríte p ro te c tio n b its): reloj para encendido.
Protección parcial de memoria de programa. 1 = Deshabilitado. o = Habilitado.
11 = Deshabilitada.
bit 2 PEN (S to p c o n d itio n e n a b le bit) - Modo maestro
10 = OOODh-OOFFh protegida
I = Inicia la secuencia de Stop. Se pone a 0' al finalizar.
01 = 0000h-03FFh protegida.
0 = Secuencia de Stop deshabilitada.
00 = 00D0h-07FFh protegida.
bits 1-0 Focs1:Fosc0 (O s c illa t o r S e le c t io n Bits): Bits de
bit 8 CPD (C o d e p ro te c tio n data): Protección de memoria selección del modo de oscilador
EEPROM I I = Oscilador RC. 10 = Oscilador HS.
1 = Protección deshabilitada. 01 = Oscilador XT. oo = Oscilador LP.
0 = Protección habilitada.

Página | 191
A3. Introducción a MPLAB-IDE/MPLAB-SIM
con Hi-Tech
A3.0. Instalación
A3.1. Configuración
A3.2. Creación del proyecto
A3.3. Creación del fichero fuente
A3.4. Compilación del proyecto
A3.5. Simulación del proyecto
A3.6. Observando el funcionamiento
A3.7. Generador de estímulos

A3.0. Instalación
Para utilizar el entorno de programación MPLAB IDE es necesario instalar el programa, en particular
se utilizará el software "MPLAB IDE v.8.89" que se puede descargar desde la página de microchip en
la sección downloads.

[Link]

También se utilizará el compilador de ‘C Hi-Tech, que no viene incluido en la instalación de MPLAB


por lo que se deberá descargar desde:

[Link]

Más concretamente, se instalará la versión "picc_9_.83_win" junto con la herramienta


"UniversalToolsuite-1.37". Una vez realizada la instalación se arrancará el programa MPLAB IDE. Si no
se dispone de un acceso directo en el escritorio, se puede hacer desde el menú de "Archivos de
Programa" del ordenador. Una vez arrancado aparecerá la pantalla de la siguiente figura.

Página | 193
Programación de microcontroladores PIC en lenguaje C

A3.1. Configuración
Es importante que los bits de la palabra de configuración tengan los valores adecuados en función
de la aplicación. Eso se puede hacer de dos formas:

1) entrando en:
Configure > Configuraron Bits

Se puede escoger el tipo de oscilador (RC, LP, X I ó HS), y activar/desactivar el watchdog, el


temporizador de arranque o la protección del programa, entre otras opciones según los modelos de PIC.

Si se necesita cambiar alguna de las opciones que aparecen se deberá desactivar la casilla:
"Configuration Bits set in code" (figura inferior), ya que si está activada solo admite como palabra
de configuración la que venga especificada en el programa fuente.

I Configuration Bits 0 B ®
0 Configuraron Bits sel in code.

=r~ r Cscillacor \—
V.&zc'r.áca Direr c-~
Pov/er Up [Link] Cíf
3rown Out Deteco On
rr 1:': Ve Icace Frcorar. Di¿'¿oled
Daca El Read Procecc Off
Flash Frocrar Wnte Write Prccection
Code Procecc Off

2) también se puede incluir mediante la directiva "_CONFIG" en el programa fuente, que se


encarga de que los bits de la palabra de configuración tengan los valores adecuados. Por ejemplo:
__CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & LVP_OFF);

que selecciona un oscilador de cristal de cuarzo, anula el watchdog, desactiva la programación a


baja tensión y anula la protección del código.

Este método tiene la ventaja frente al camino Configure > Configuration Bits (comentado
anteriormente) de que al estar escrito en el programa fuente siempre va a determinar la palabra de
configuración, aunque se realicen modificaciones en el programa o se cambie de ordenador o de ICD2.

A3.2. Creación del proyecto


1) El siguiente paso consiste en la creación de un Proyecto. La forma más sencilla de hacerlo es
utilizar el "MPLAB Project Wizard", que se arranca en el menú:

Project > Project Wizard

Página | 194
Anexos

La pantalla toma un aspecto como el de la siguiente figura:

Seleccionar "Siguiente" para continuar.

2) Seleccionar, de la lista de dispositivos disponibles, el procesador a utilizar.

BHB88B

[ Sr :ráa || - 1 I Car-celar ] j Ay\,-da

Seleccionar "Siguiente" para continuar.

3) Seleccionar la herramienta a utilizar ("Active Toolsuite") que debe ser Microchip HI-TECH
Universal ToolSuite. Al hacerlo, nos aparecen en la ventana siguiente las herramientas disponibles
(Toolsuite Contents), como se puede observar en la siguiente figura. Esas herramientas deben ser:
HI-TECH ANSI C Compilen Y en la ventana siguiente (Location) debe figurar la trayectoria completa
de esos tres programas ejecutables:

C:\Archivos de programa\HI-TECH Softare\picc\9.83\bin\[Link]

Página | 195
Programación de microcontroladores PIC en lenguaje C

Si esa trayectoria está incompleta o es errónea se debe pulsar "Browse" para localizarlo.

Seleccionar "Siguiente" para continuar.

4) El siguiente paso es asignarle un nombre al proyecto. Debe estar en el mismo directorio donde se
encuentres los programas con el código fuente en caso de que ya existan y es conveniente darle el
mismo nombre para localizar mejor todo lo concerniente a un mismo ejercicio.

Para eso, en ia ventana "Create New Project File", pulsar en "Browse" y acceder al subdirectorio en
el que se esté trabajando.

5) La pantalla siguiente pregunta qué ficheros se van a incorporar al proyecto. En el caso de que ya
existan se deben seleccionar y añadir (pulsar en "Add"). Es conveniente que en la ventana de la
derecha y a la izquierda de la trayectoria figure una "A" (indica automático).

Página | 196
Anexos

Seleccionar "Siguiente" para continuar.

Aparece entonces una pantalla con un resumen del proyecto que se va a crear:

Project W izard

Sumrnary

Click ‘Finish’ to cteate/configure (he pro|ec( wilh thece


paramelers.

Proiecl Parameters

Device PIC16F877A

Tooliuile HI-TECH Universal ToolSuile


?
F ile : C:\Documenls and
Set ling s\cruiz.1EE\E scritorio\PR UEBASVEImc

ÍAlo new workspace will be created. and (he new proiec» added
lha( workspace

Ayuda

Si esos datos no son correctos se deberá pulsar "Atrás" y corregir donde sea oportuno. Si son
correctos, se puede pulsar en "Finalizar" con lo que se terminará de crear el proyecto y se saldrá del
"Project Wizard".

Página | 197
Programación de microcontroladores PIC en lenguaje C

Una vez creado el proyecto se abrirá MPLAB junto con las ventanas de navegador del proyecto y la
ventana "Output" además de aparecer una nueva barra de herramientas como la que aparece a
continuación, que permitirán compilar el código fuente.

Para ver el navegador de proyecto se accederá al menú: View > Project

Se pueden añadir archivos y salvar proyectos pulsando el botón derecho del ratón desde la ventana
de proyecto. Los ficheros también se pueden borrar manualmente seleccionándolos y utilizando el
botón derecho del ratón.

A3.3. Creación del fichero fuente


Para generar el programa fuente se utiliza el editor del MPLAB IDE. Seleccionando:

File > New


o
File > Add New File to Project
aparecerá en el área de trabajo una ventana en blanco en la que va a quedar escrito el programa
fuente.

Para crear el programa se puede utilizar cualquier editor de texto en caracteres ASCII y hay que
tener en cuenta las normas programación en C. descritas en el primer capítulo.

Página | 198
Anexos

En la siguiente figura se puede observar que el fichero no tiene todavía un nombre (untitled) y que
todo el texto tiene el mismo color.

Es conveniente ir guardando el texto a medida que se va escribiendo:

File > Save as


ó: File > Save

Al guardar el fichero debe tener la extensión ",c". Para eso hay que tener cuidado con el formato y
en la ventana "tipo" debe estar seleccionada la opción: "All Source Files".

Guardar como s s

1 C -ja tó ra , ' El n i o t e ? m i*

|Untiled i Guardar |

Ti» • Scurc- Res Ce.** 'asm.'as *inc:*.s *bas‘ v [ Carcefar |

Jurr.p to- C \Documert: and Setling:\ctui? IEE\Ecctitoí;o\FRUE6 v

Enccdng ¡ANSI v

i " ] Add Fie To Pro;ecl _________________

Tras guardar el programa fuente, el texto aparece en diferentes colores, que diferencian las
instrucciones, los comentarios, constantes, etc, como se puede ver a continuación. Esos colores se
pueden configurar a gusto del usuario. Para más información acudir a: Help > MPLAB Editor Help.

Página | 199
Programación de microcontroladores PIC en lenguaje C

A3.4. Compilación del proyecto


Una vez que el proyecto está creado y se cuenta con un archivo fuente es necesario compilarlo o lo
que es lo mismo, generar el código máquina. Para eso el entorno MPLAB utiliza el HI-TECH ANSI C
compiler. El procedimiento a seguir es el siguiente:

Project > Build All

También puede utilizarse el método abreviado de teclado FIO o el ¡cono correspondiente de la


barra de herramientas.

El caso más común cuando se empieza a trabajar con MPLAB es que, tras intentar compilar, en la
pantalla aparezca un mensaje semejante a este:

B u i l d C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P R U E B A S \ H i - l f o r d e v i c e
16F877A
U s i n g d r i v e r C : \ A r c h i v o s d e p r o g r a m a \ H I - T E C H S o f t w a r e \ P I C C \ 9 .8 3 \ b i n \ p i c c . e x e
M a k e : T h e t a r g e t " C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P R U E B A S \ P 3 _ l .p l "
i s o u t o f date.
E x e c u t i n g : " C : \ A r c h i v o s d e p r o g r a m a \ H I - T E C H S o f t w a r e \ P I C C \ 9 .8 3 \ b i n \ p i c c . e x e " --
p a s s l " C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P R U E B A S \ P 3 _ l .C " - g --
c h i p = 1 6 F 8 7 7 A - P - - r u n t i m e = d e f a u l t , + c l e a r , + i n i t , -kee p , + o s c c a l , - d o w n l o a d , -
r e s e t b i t s , - s t a c k c a l l , + c l i b - - o p t = d e f a u l t , + a sm, - d e b u g , - s p e e d , + s p a c e , 9 - - w a r n = 0 -
D D E B U G =1 - - d o u b l e = 2 4 - -f l o a t = 2 4 - - a d d r q u a l = i g n o r e - g - - a s m l i s t
errformat=Error [%n] %£; % l . % c %s " " - - m s g f o r m a t = A d v i s o r y [ % n ] %s "
w a r n f o r m a t = W a r n i n g [%n] %f; % l . % c % s"
E r r o r [192] C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P R U E B A S \ P 3 _ l . C; 1 4 . 1
u n d e f i n e d i d e n t i f i e r "TRIS"
E r r o r [192] C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P R U E B A S \ P 3 _ l . C ; 2 4 . 5
u n d e f i n e d i d e n t i f i e r "i"
E r r o r [312] C:\Documents and S e t t in g s \ c m iz . IE E \ E s c rito rio \ P R U E B A S \ P 3 _ l. C/ 2 6 . 1
expected
E r r o r [195] C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P R U E B A S \ P 3 _ l .C; 2 9 . 0

Página | 200
Anexos

expression syntax
E r r o r [300] C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P P . U E B A S \ P 3 l.C; 29.0
une x p e c t e d e n d o f file

********** Build failed! **********

En la última línea se puede leer: "BUILD FAILED", es decir, el compilador HI-TECH no ha sido capaz
de generar un fichero hexadecimal y por tanto no se podrá simular el comportamiento del
programa ni mucho menos grabarlo en la memoria del PIC.

Además, en la pantalla "output" también podemos tener disponible otras informaciones, como
"messages", "warnings" y "errors". De estos tres tipos, el más Importante, porque impide la
generación del fichero hexadecimal son los "errors", mientras que los otros dos tipos no impiden el
ensamblado del programa fuente. Pasemos a comentarlos a continuación:

o Errores (Error). Impiden la generación de código máquina y por lo tanto es imprescindible


corregirlos para poder continuar. Los más habituales, con su número de caracterización, son:

(192) undefined identifier : El símbolo ha sido usado en el programa pero no se ha


definido previamente.
(195) expression syntax : Error de sintaxis que indica que la expresión está mal formada.
(300) unexpected end of file: Final de código inesperado que indica que falta cerrar la
última llave.
(312) expected: Se esperaba el argumento indicado entre comillas.

Es importante tener en cuenta que la eliminación de estos errores simplemente permite obtener un
fichero ejecutable, pero no aporta ninguna Información acerca de si el programa funcionará o no
correctamente.

° A d verten cias (W arning). Estos mensajes no impiden la obtención del fichero hexadecimal,
pero advierten de algo que al programa ensamblador le parece extraño. Es conveniente
comprobarlos todos.

Para tratar los mensajes, el camino más rápido es hacer doble clic en la línea del fichero "output"
en la que está el mensaje. Eso hace que el cursor se ponga en la línea del programa fuente que da
lugar a la aparición de ese mensaje permitiendo corregirlo. A continuación, el fichero fuente se
graba de nuevo, "File > Save", y se vuelve a ensamblar: "Project > Build Air'. El proceso se repite
hasta que estén corregidos todos, momento en el que HI-TECH consigue generar el fichero
hexadecimal, apareciendo una pantalla donde se puede leer"BUILDSUCCEEDED".

M a k e : T h e t a r g e t " C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z . I E E \ E s c r i t o r i o \ P R U E B A S \ P 3 _ l .pl"
i s o u t o f d a te.
E x e c u t i n g : " C : \ A r c h i v o s d e p r o g r a m a \ H I - T E C H S o f t w a r e \ P I C C \ 9 .8 3 \ b i n \ p i c c .e x e " --
p a s s l " C : \ D o c u m e n t s a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r i o \ P R U E B A S \ P 3 _ l .C" -q - -
c h i p = 1 6 F 8 7 7 A - P - - r u n t i m e = d e f a u l t , + c l e a r , +init, -keep, + o s c c a l , - d o w n l o a d , -
r e s e t b i t s , - s t a c k c a l l , + c l i b - - o p t =default,+asm,-debug,-speed,+space,9 --warn=0 -
D __ D E B U G = 1 - - d o u b l e = 2 4 - - f l o a t = 2 4 - - a d d r q u a l = i g n o r e -g - - a s m l i s t
e r r f o r m a t = E r r o r [in] if; i l . i c is" " - - m s g f o r m a t = A d v i s o r y [ i n ] is"
w a r n f o r m a t = W a r n i n g [in] if; i l . i c is"
E x e c u t i n g : " C : \ A r c h i v o s d e p r o g r a m a \ H I - T E C H S o f t w a r e \ P I C C \ 9 .8 3 \ b i n \ p i c c . e x e " -
o H i - l . c o f - m H i - l . m a p ~ - s u m m a r y = d e f a u l t , - p s e c t , - c l a s s , + m e m , - h e x - - o u t p u t = d e f a u l t ,-
inhx032 P3_l.pl - -chip=16F877A -P - - r u n t i m e = d e f a u l t , + clear, + i n i t , - k e e p , + o s c c a l , -

Página | 201
Programación de microcontroladores PIC en lenguaje C

download,-resetbits,-stackcall,+clib - - o p t = d e f a u l t , +asm, - d e b u g , - s p e e d , + s p a c e , 9 --
w a r n = 0 - D __D E B U G = 1 - - d o u b l e = 2 4 ~ - f l o a t = 2 4 - - a d d r q u a l = i g n o r e - g - - a s m l i s t
e r r f o r m a t = E r r o r [in] if; t i . t e t s" ”- - m s g f o r m a t = A d v i s o r y [ i n ] is "
w a r n f o r m a t = W a r n i n g [in] if; t i . t e is "
HI-TECH C C o m p i l e r f o r P I C 1 0 / 1 2 / 1 6 M C U s (Lite Mode) V9.83
Copyright (C) 2 0 1 1 M i c r o c h i p T e c h n o l o g y Inc.
(1273) Omniscient Code G e n e r a t i o n not available in Lite mode (warning)

M e m o r y Summary:
Program space u sed 7l h ( 113) of 2 0 0 Oh w o r d s < 1.4i)
Data space used 8h ( 8) of 1 7 Oh bytes < 2 .2 i)
E E P R O M space used Oh ( 0) of 1 0 Oh bytes ( [Link])
Configuration bits used lh ( 1) of (100. Oi)
lh word
ID L o c ation space used Oh ( 0) of 4h bytes ( [Link])

R u n n i n g this compiler in PRO m o d e , with Omniscient Code G e n e ration e n a b l e d ,


p r o d u c e s c o d e w h i c h i s t y p i c a l l y 4 0 i s m a l l e r t h a n i n L i t e m o de.
S e e h t t p :/ / m i c r o c h i p . h t s o f t . c o m / p o r t a l / p i c _ _ p r o f o r m o r e i n f o r m a t i o n .

Loaded C:\Documents a n d S e t t i n g s \ c r u i z .I E E \ E s c r i t o r io \ P R U E B A S \ H i - 1 . c o f .

********** Quild successful! **********

La pantalla output también Informa de:

• procesador utilizado (en el ejemplo, 16F877A)


• nombre del proyecto y su trayectoria (en el ejemplo, P3_1.C)
» herramienta utilizada: [Link], con su trayectoria completa
o fecha y hora en la que se produjo la compilación
o Espacio utilizado en memoria de programa, memoria de datos, etc.

Este último apartado que hace referencia a la utilización de la memoria del PIC cobra especial
importancia a la hora de desarrollar aplicaciones complejas ya que será un indicador de la
necesidad de migrar hacia un microcontrolador con mayores prestaciones. Esta información
también está accesible de forma gráfica a través del menú ViewIMemory Usage Gauge como se
muestra en la siguiente figura.

A partir de este momento, ya se dispone de un programa ejecutable y se puede simular el


funcionamiento o grabarlo en la memoria permanente del microcontrolador. El código máquina
ejecutable del programa escrito en ensamblador se encuentra en el archivo .hex con el mismo
nombre que el archivo .c que se ha compilado. Este archivo ".hex" contiene además información
relativa a la grabación del mismo en las diferentes posiciones de memoria de programa del
microcontrolador. Se puede observar cómo se ubicaría dicho programa en la memoria del

Página | 202
Anexos

microcontrolador accediendo al menú View/Program Memory que en las pestañas inferiores


permitirá elegir entre la representación en hexadecimal de los datos como aparece en la siguiente
figura o una representación más cercana al lenguaje máquina (lenguaje ensamblador).

Program Memory => •s_


Address | 1 1 __ ASCII ;*
0000 120A USA 2812r3F ~FF OOFE0E03 1283 1303
0003 0030 0804 0031 OSOA0032 087F 0033 012OA
0010 iISA 2953 120A USA 2A42 1283 1303 0A7 --S)--3-......
0013 3020 00A2 0822 00AS 23EE082D3A25 1903 0.."... .
0020 2822 2823 282A 032D120A USA 2231 12O A "(#(-(-.... 1"..
0028 118A 28EE 01A6 2831 2904 2846 2846 2SEE ...(..1( .) F(F(.(
0030 2346 3001 07A7 30FF 0727 0084 120A1 18A

o
o
0038 2208 120A USA O AD3A00 1903 2904 3A64 •"...... :•••)d:
O
0040 1903 2846 3A0D1903 2846 2SEE0825 0 034 ..F(.:.. F(.(%...
0048 1383 0800 00A9 0A84 0800 OOAA3002 00A2
OpcodeHex M
achine Sym
bolic

A3.5. Simulación del proyecto


Llegados a este punto es necesario comprobar el funcionamiento del programa, es decir, simular su
funcionamiento.

Esta simulación se puede realizar utilizando el simulador por software MPLAB-SIM que viene
incluido con MPLAB IDE, como se explicará a continuación.

MPLAB-SIM es un simulador para los microcontroladores PIC que viene integrado en el entorno
MPLAB IDE. Permite modificar el programa y ejecutarlo a continuación, introducir estímulos
externos y observar la ejecución del programa objeto.

La velocidad de ejecución, aunque llega siempre a la máxima posible, es varios órdenes de


magnitud más baja que la del procesador real y depende del ordenador y de otros factores. Puede
llegar al orden de unos ms por instrucción (un PIC real, con un cristal de 4 MHz, emplea 1 ps por
instrucción, salvo si es de salto, que emplea 2 ps).

Para arrancar el simulador es necesario indicar que se va a utilizar la herramienta MPLAB SIM y para
ello se accederá al menú:

Debugger > Select Tool > MPLAB SIM

A continuación se producen los siguientes cambios:

1) La ventana de la izquierda de la barra de estado (parte inferior de la pantalla) cambia a MPLAB


SIM
2) Aparecen nuevas opciones en el menú "debugger"
3) En la barra de herramientas aparecen los iconos correspondientes al simulador

Página | 203
Programación de microcontroladores PIC en lenguaje C

Nuestro programa está listo para ser ejecutado. Debemos introducir ahora la frecuencia que va a
tener el oscilador.
Debugger > Settings > Osc/Trace

En primer lugar, es conveniente que el simulador empiece por ejecutar la primera instrucción del
programa, para eso se debe realizar un "reset'' del procesador:

Debugger > Reset > Processor reset

O también se puede actuar sobre el teclado o sobre el ¡cono correspondiente de la siguiente lista:

Página | 204
Anexos

Debugger Menú Bolones Hol Key


RUN > F9
HALT fl F5
ANIMATE >>
STEP INTO F7
1L
STEP OVER o F8
STEP OUT OF _ íÍ2l_
RESET ay F6
BREAKPOIMT © F2

En la siguiente pantalla aparece una flecha verde en el margen izquierdo de la ventana donde está
escrito el programa fuente. La flecha apuntará siempre a la primera instrucción que se va a ejecu ar
en cuanto se dé la orden de ejecución.

A partir de aquí existen tres posibilidades de ejecutar el programa: paso a paso, en modo animado
V total.

1) Paso a paso (Step). En esta modalidad, la CPU ejecuta las instrucciones una a una cada vez que
se acceda al menú:
Debugger > Step Into

O también actuando sobre la tecla F7 o sobre el ¡cono correspondiente.

Ejecutando el programa de esta manera es posible observar el valor de las variables colocando el
cursor sobre ellas.

Página | 205
Programación de microcontroladores PIC en lenguaje C

2) Modo animado (Anímate). En este caso, la CPU ejecuta las instrucciones una tras otra sin
esperar. Se activa en el menú:

Debugger > Anímate

Para detener la ejecución del programa se debe actuar en:

Debugger > Halt

También en este caso se puede observar el valor de las variables en ese instante colocando el
cursor sobre ellas.

3) Total (Run). En este modo, la CPU ejecuta el programa completo, es decir desde la primera hasta
la última instrucción. Se activa en:
Debugger > Run

O también actuando sobre la tecla F9 o sobre el icono correspondiente.

En barra de estado aparece la palabra "running".

Para detener la ejecución del programa se debe acceder al menú:

Debugger > Halt

O también mediante la tecla F5 o sobre el ¡cono correspondiente.

En este caso, si al colocar el cursor sobre una variable no aparecerá el valor que tiene en ese
instante. Para observarlo, primero se deberá detener la ejecución del programa.

Página | 206
Anexos

A3.6. Observando el funcionamiento


Hay varias formas de observar lo que sucede al Ir ejecutándose las instrucciones del programa.
Dentro del menú "Vlew" existen varias posibilidades:

Project: resumen del proyecto


Output: el fichero de salida, que ya conocemos
Disassembly Listing: listado del programa fuente (sin ensamblar)
EEPROM: estado de la memoria EEPROM
File Registers: valores almacenados en los registros
Hardware Stack: estado de la pila
Program Memory: estado de la memoria de programa, con las instrucciones
Special Function Registers: estado de los registros de funciones especiales
Simulator Trace: almacena todos los pasos del simulador

Cualquiera de esas posibilidades proporciona información acerca del estado del microcontrolador
durante la ejecución del programa. El inconveniente es que tanto el contenido de los registros
como su dirección pueden estar en hexadecimal por lo que es bastante engorroso. Además, hay
que tener en cuenta que en programas complejos pueden ser muchos los valores que cambian con
cada instrucción, lo que dificulta el seguimiento de unas pocas variables.

A3.6.1. Visualización de variables

Para evitar este problema se puede abrir una "ventana de observación":

View > Watch

Con eso aparecerá una nueva ventana como se observa en la siguiente figura en la que se pueden
seleccionar tanto los registros de funciones especiales (SFR) como los símbolos (variables) que se
quieren visualizar.

Página | 207
Programación de microcontroladores PIC en lenguaje C

Una vez que se tiene en la ventana el símbolo se puede escoger el formato en el que aparecerá
representado seleccionándolo y apretando el botón derecho del ratón para entrar en sus
propiedades. Ahí se podrán escoger varias opciones:

Symbol: símbolo
Size: número de bits a observar
Format: formato (aquí podemos escoger también un solo bit, binario, decimal, ascii...)

También se puede situar el cursor sobre la barra "address" y actuar sobre el botón derecho del
ratón. Eso permitirá escoger entre diferentes formatos de presentación como se muestra en la
figura inferior.

Address. .. S y n fc o l M am e
✓ Address .•\esulrada
I ✓ Symbol Ñame
<✓ V a lu é
\/ Hex
<✓ Decimal
- v« Binary
_ y' Char
✓ Update
Comment

More..

Página | 208
Anexos

A3.6.2. Visualización de señales

Además de visualizar el valor que se almacena en cada uno de los registros o variables del
programa a veces es conveniente ver cómo evolucionan durante la ejecución del mismo. Para eso
se puede utilizar el visualizador de señales "Simulator Logic Analyzer" que se encuentra en el menú
View.

View > Simulator Logic Analyzer


View Project Debuqger Proqrammer Tools Configure Window Help

Esta utilidad permite mostrar el valor que han ido tomando una o varias señales cuando se detiene
la ejecución del programa o cuando este se ejecuta en modo animado. Para ello basta con pulsar el
botón Channels y elegir el terminal que se desea visualizar o bien agrupar varios terminales de
forma conjunta formando un bus de datos.

Logic Analyzer ! _E
Trigget Posilion TnggetPC= Time Base Mode
S lo t® C e n t e i EndO Now Clear Cyc v Simple Channels

1+ .gil q j q J qa|yl#¡& |

I______I_____ I____ I I I
008 005 00F 001

i i i i i i i i 1 i i * i i i i i i i i i i i— i— i— i— i— i— i— i— |— i— i— |— |— |— i— i— |— [-
0,0 200,0 400,0 600,0 800,0 1000,0 1200,0 1400,0

Página | 209
Programación de microcontroladores PIC en lenguaje C

A3.7. Generador de estímulos

El simulador MPLAB SIM dispone también de una herramienta que permite simular estímulos
externos tales como pulsadores, entradas de reloj etc. Este simulador evalúa los estímulos y genera
todas las respuestas en los límites de cada ciclo de instrucción (Tcy = 4-Tosc). Por ese motivo,
algunos sucesos físicos no pueden simularse con precisión, en particular los sucesos puramente
asincronos y los sucesos de periodo más corto que un ciclo de instrucción.

Los estímulos permiten generar señales para el simulador y serán de gran uti i a a a ora
probar el funcionamiento de los programas cuando no se dispongan de herramientas a icion
como por ejemplo debuggers.
Debugger > Stimulus > New Workbook
Ptbuggf , Prcg-tmmer Tool: [Link] V/indon Hdp
SetectTool Checksum: 0x7d7d t- tí- p) 0* (P ® © I
■d E CJi Q 3 0
Ckar Menú

Stimulus - [Untitleó]
Hit
Sltp Into Arjrxh P»i/ n e g-Je tA d v s^ re d fV i/F le g Ja OoAStmA.1 IWji’tiliU lun Pegi’a >iae
Step Ovtr
Wiih U-4i Ccnrxtíi/Wtüage
Strp Out

6'tlkpcmtJ_
StopWitch
Complci Bfukpomti
itimulus New Woikbock
Proflh Oppn Woikbook
Otar Cede Covcragr Save WoiVbook
Refreih PM Si. e Woikbook Ai
Cloie Wefibook
ir r

También existe la opción de guardar el fichero de estímulos. Basta co Posteriormente se


i mismo nombre que al resto del proyecto y guardarlo en el mismo subdirector, .
1 puede recuperar actuando sobre:
Debugger > Stimulus > Open Workbook
L_ .
Los estímulos , a «0«
permiten poner entradas 0 oo aa . r yy cargar
& valores directamente en registros.
Existen seis tipos diferentes:
- Estímulos asincronos
- Estímulos de terminales o registros
- Estímulos avanzados sobre terminales o registros
- Estímulos de reloj
- Inserción de valores en registros
- Captura de valores de registros

^•^■ 1. Estímulos Asincronos


estímulos asincronos permiten simular+5 Vy OVen terminales ¿¡¿logo Para definirlos se
a« v an haciendo clic en el botón correspondiente de la ventana de diaiog ■
accede desde:
Anexos

Activando la pestaña "Asynch" se pueden definir los estímulos.


La primera columna {fire) es la que se tiene que pulsar para que se ejecute la simulación del
estímulo que esté configurando a su derecha.

La segunda columna (Pln/SFR) permite escoger la patilla/terminal en la que se generará el estímulo.


Basta con pulsar dentro del cuadro en blanco para que aparezcan las opciones.

En la tercera columna (Action) se escogerá la acción a simular de entre las cinco


posibilidades:

1) set high: simula una tensión "1" en la patilla seleccionada


2) set low: simula una tensión "0" en la patilla seleccionada
3) toggle: simula un cambio, es decir, si esa patilla estaba a "1" la pone a "0" y si estaba a
"0" la pone a "1"
4) pulse high: simula un pulso en "1" de corta duración
5) pulse low: simula un pulso en "0" de corta duración

Si se deséa eliminar un estímulo, basta con seleccionar la línea y pulsar en "Delete Row".

Una vez definidos todos los estímulos necesarios pueden activarse mientras se va simulando la
ejecución del programa. Basta con pulsar con el ratón en el botón correspondiente, por eso es
conveniente mantener abierta la ventana de los estímulos durante la simulación.

A3.7.2. Estímulos de terminales o registros

Los estímulos de terminales o registros permiten introducir valores en terminales o registros de


forma automática durante el tiempo definido además de poder repetir la introducción de forma
cíclica seleccionando la casilla repeat.

A3.7.3. Estímulos avanzados de terminales o registros

Los estímulos avanzados de terminales o registros permiten introducir valores en terminales o


registros de forma automática cuando se den determinadas condiciones predefinidas como que un
terminal o registro tomen o superen un determinado valor.

Página | 211
Programación de microcontroladores PIC en lenguaje C

Stimuius - [Untitled]

i A !Vn íh P r / Regisler Action; Advanced Pm / Registe Q ockStm ulu! Regislei Inieclón Registo Trace

Define T nggers

Enab'e Condtion Type Re-ArmDelay RCO PORTD Cllck heie lo Add Signáis • /s
a C0ND1 Cont 100 cyc 1
0 C0MD2 1x FF

Define Conditions

Condition WhenChanced Wait Comments


C0ND1 Pin AMO = 0 3 cyc
C 0 N P 2 1 SFR ADRESL > F1

Advanced ' Anply ñemove Pelete Row Save

A3.7.4. Estímulos de reloj

Los e s tím u lo s d e r e lo j p e r m ite n la g e n e ra c ió n d e u n a s e ñ a l p e rió d ic a e n c u a lq u ie r a d e los


te rm in a le s así c o m o d e f in ir e l m o m e n to e n e l q u e c o m e n z a r á y t e r m in a r á e s ta s e ñ a l.

■ f S tim u iu s ■ (U n t it le d )

Acynch Pin /Regnfer Aclions Advanced Pin /Registei ClockStim Remeter Iniechon Reg'Cter Trace

i Inidal ¡ Low Cyc High Cyc Begin End Comments a


Label Pin
T1CK1 i TOCKI Low 0 1 A tS lail Mevei

Begn End

Al Stail
(§) Never
hex/label
O pc - hex/label O PC
dec
O Cytle ■ dec O Cyde -

O Pin = ¡e OP¡" "

i Advanced, j Apply Remove Pelele Row

A3.7.5. Inserción de valores en registros

E s te t ip o d e e s tím u lo p e rm ite in tro d u c ir en los r e g is tro s lo s v a lo r e s q u e s e h a y a n c o lo c a d o e n un


a r c h iv o e x te r n o . E stos e s tím u lo s serán ú tile s c u a n d o s e q u ie r a s im u la r e l f u n c io n a m ie n to d e p o r
e je m p lo lo s m ó d u lo s d e c o m u n ic a c io n e s USART o el c o n v e r s o r a n a ló g ic o d ig ita l, y a que el
m ic r o c o n tr o la d o r irá re c o g ie n d o cada u n o de los v a lo re s a lm a c e n a d o s e n e l a r c h iv o d e t e x t o cada

v e z q u e a cce d a al r e g is tro a s o c ia d o a estos m ó d u lo s .

Página | 212
Anexos

A3.7.6. Captura de valores de registros

Esta opción permite almacenar en un archivo de texto los valores que van tom ando los registros,
permitiendo seleccionar el momento de comienzo y el formato en el que se alm acenarán.

Stimulus - [Untitled] GiII!_®J6Ss!


Asynch Pin i Begcfer Aclions A d van ced Pin / Regisler i Clock Slimulus R egisler In ie c lio n R eg icle r Tf<

Label R e g /V a r Tngger PC Valué W idth; Trace Filename Formal Comments


(ophonal) ADCONO Demand 1 Browse for Filename H ex (oplional)

A3.7. Interfaz de control


Otra de las utilidades que presenta MPLABSIM es el "Data M onitor Control Interface" a la que se
accede desde el menú Tools -> Data Monitor Control Interface.

P ágin a | 213
Programación de microcontroladores PIC en lenguaje C

TfcH OMCl Ce .'cure Z. n3c

Mediante esta herramienta es posible modificar los valores que van tomando las variables y
registros durante la ejecución del programa utilizando controles como barras de desplazamiento o
botones que aparecen en la pestaña "Dynamic Data Control" o los cuadros de control en la pestaña
"Dynamic Data Input".
DynamicDataControl DynamicData Input DynamicDataView
UserDefinedGroup 1 UserDefrnedGmup 2 User Defint
p| decimal □ Input 1 □ Input 1
Descnption 1

Esta herramienta también permite visualizar los valores almacenados en memoria de forma gráfica.
DMCI - Data Monitor Control Interface

r Q g£ O ~ p

Configurabon fie:

Página | 214
O pc HxOct C h a r D ec Hx Oct Html C hr

0 0 000HUI (n u il) 32 20 040 £#32; '.p a c e


1 1 0013 OH ( s t a r t o f h e a d in g ) 33 21 041 £ •# 3 3 ; ’
2 2 0023TX ( s t a r t o f te x t) 34 22 042 ( .# 3 4 ; "
3 3 003ETX (e n d o f t e x t ) 35 23 043 £#35; t
4 4 004EOT (e n d o f tr a n s m is s io n ) 36 24 044 £#36; í
S 5 005ENQ (e n q u iry ) 37 25 045 £#37; -
6 6 006ACE ( a c k n o w le d g e ) 38 26 046 £ .# 3 8 ;
7 7 007BEL ( B e ll) 39 27 047 £#39; ;
8 8 010 BS (b a c k sp a c e ) 40 28 050 £ .# 4 0 ; (
9 9 0 1 1 TAB ( h o r i z o n t a l ta b ) 41 29 051 £#41; )
10 A 0 1 2 LF (ML l i n e f e e d , n e u l i n e ¡ 42 2Á 052 £#42; ■■
11 B 0 1 3 VT ( v e r t i c a l ta b ) 43 2B 053 £#43; +
C 0 1 4 FF (NP f o r a f e e d , n e w p a g e ) 44 2C 054 £#44; ,
12
(c a rria g e re tu rn ) 45 2D 055 & #45;
13 D 0 1 5 CP
14 E 0 1 6 SO ( s h i f t o u t) 46 2E 0 5 6 £ # 4 6 ; .
15 F 017 SI ( s h i f t in ) 47 2 F 0 5 7 £ .# 4 7 ; ■
16 1 0 0 2 0 DLE (d a ta lin k escape) 48 30 0 6 0 & # 4 8 ; 0
íd e v ic e c o n tro l 1) 4 9 31 0 6 1 £#49; 1
17 11 0 2 1 DC1
1 2 0 2 2 DC2 (d e v ic e c o n tro l 2) 5 0 3 2 0 6 2 £ .# 5 0 ; 2
18
(d e v ic e c o n t r o l 3) 51 33 0 6 3 £ .# 5 1 ; :
19 1 3 0 2 3 DC3
1 4 0 2 4 DC4 í d e v i c e c o n t r o l 4 ) 52 3 4 0 6 4 £ # 5 2 ; 4
20
53 35 0 6 5 £ # 5 3 ; 5
21 1 5 0 2 5 HAK ( n e g a t i v e a c k n o w l e d g e )
54 36 066 s # 5 4 ; 6
22 1 6 0 2 6 SYS ( s y n c h r o n o u s i d l e )
(en d o f tra n s . b lo c k ) 55 3 7 0 6 7 £ # 5 5 ; 7
23 1 7 0 2 7 ETC
( c a n c e l) 56 3 8 0 7 0 £ # 5 6 ; 8
24 1 8 0 3 0 c a í;
( e n d o f m é d iu m ) 57 39 0 7 1 £ .# 5 7 ; 9
25 19 0 3 1 EH
( s u b s titu te ) 58 3Á 0 7 2 £ # 5 8 ; ;
26 1A 0 3 2 3UB
(e scap e ) 59 3B 0 7 3 £ # 5 9 ; ;
27 IB 0 3 3 ESC
(file s e p a ra to r) 60 3C 0 7 4 £ # 6 0 ;
28 1C 0 3 4 FS
(g ro u p s e p a ra to r) 61 3D 0 7 5 £ .# 6 1 ; =
29 ID 0 3 5 GS
(re c o rd s e p a ra to r) 62 3E 0 7 6 £ .# 6 2 ;
30 1E 0 3 6 RS
(u riit s e p a ra to r) 63 3 F 0 7 7 £ # 6 3 ;
31 1 F 0 3 7 US
P ágin a | 215
A4. Tabla
Dec Hx Oct Htm! Chr Dec Hx Oct Html Chr
64 40 100 «164; 0 96 60 140 s #96;
65 41 101 4*65; A 97 61 141 4*97;
66 42 102 &#66; B 98 62 142 4*98; b
6? 43 103 4*67; C 99 63 143 4*99; c Q_
68 44 104 4*68; 0 100 64 144 4*100; d
69 45 105 4#69; E 101 65 145 4*101; e fD
70 46 106 «#70; F 102 66 146 4*102; f o
71 47 107 «*71; G 103 67 147 4*103; a Os
72 48 110 4*72; H 104 68 150 4*104; h 9 .
73 49 111 4*73; I IOS 69 151 4*105; i
74 4A 112 í*74; 0 106 6A 152 s*106; j era"
75 4B 113 4175; K
76 4C 114 &*76; L
107 6B 153
108 6C 154
4*107; k
4*108; 1
o
en
77 4D 115 4*77; 11 109 6D 155 s*109; ¡u
78 4E 116 4*78; M 110 6E 156 4*110; n >
79 4F 117 4*79; 0 111 6F 157 4*111; 0 ÜO
80 50 120 4*80; F
81 51 121 4*81; Q
112 70 160 4*112; p n
113 71 161 4*113; q
82 52 122 4*82; P 114 72 162 4*114; r
83 53 123 4*83; £ 115 73 163 «#115; 3
84 54 124 4*84; T 116 74 164 4*116; t
85 55 125 4*85; U 117 75 165 4*117; u
86 56 126 4186; V 118 76 166 4*118; V
87 57 127 4*87; W 119 77 167 4*119; T«T
88 58 130 4188; 120 78 170 s*120; X
89 59 131 4*89; Y 121 79 171 4*121; Y
90 5A 132 4*90; 2 122 7A 172 s#122; z
91 SB 133 4191; [ 123 7B 173 4*123; \1
92 5C 134 4*92; \ 124 7C 174 4*124; i
93 50 135 4*93; J 125 7D 175 4*125; )
94 5E 136 4*94; 126 7E 176 4*126;
95 5F 137 4*95; 127 7F 177 4*127; DE
MICROCONTROLADORES
Ls utilissción de m icrocontroladores permite resolver de manera sencilla gran cantidad
d e problem as electrónicos cotidianos asociado^fecbnK(!’jc o n tro l;¿ d é jd Ís p o s iS y o ^ ^ ^ ^ ^ ^
y a e ra d o re s . El conocim iento del funcionam iento y la programación de estos sistemas
embebidos integran una parte fundam ental del currlculo para los estudiantes de Ingeniería y
les proporciona una visión actual de la tecnología utilizada en la industria y les prepara para
la realiMción de futuros proyectos basados en sistemas embebidos.

Este libro, elaborado por tres profesores del área de Tecnología Electrónica de la Universidad
Pública de Navarra, está pensado para servir de Introducción y apoyo práctico a todos
aquellos estudiantes de ingeniería y personas en general interesadas en el diseño electrónico
mediante la utilización de sistemas microcontroladores de 8 bits. Asi, el libro se estructura en
diferentes capítulos en los que m ediante la realización de ejercicios de diferente complejidad
se revisan los m ódulos que se encuentran generalmente integrados en estos sistemas, como
por ejem plo los puertos d g entrada /salid y d ig italesStlmDorizadores/cSñvefsór ^ á n á ^ ^ ^
com paradores y c o m u n fra c iQ b ^ n-1^ '

Los ejem plos y e je r c ic iq s 'd * ^ ^ m ^ en la arquitectura del PIC16F877A pero


se pueden extrapolar: f | c Ü j j | | j j .microcontroladores gracias al empleo de
la program ación en le rife a je ^ B I ’ífó obstante, las estructuras básicas de
program ación de este lepguaig j i g j IrRer capítulo del libro para aquellos menos
fam iliarizados con el m js jt í ó J jM capítulos siguientes están orientados a la
resolución de problem as p p M

La m etodología empleada p e rn ^ ^ p
básicos de programación de fo á ^
ni elem entos adicionales. Todo eíl
gratuita MPLAB IDE®, que ¡ntegra un simulador: y a la
de form a online en la sección de descargas del libro e

Maícombo
9 788426 724274
MICROCONTROLADORES
La u tiliz a c ió n de m icro controlad ores perm ite resolver de manera sencilla gran cantidad
p ob le m as ele ctró n ico s cotid ia nos asociados con el control de dispositivos* sensores
ma' , a , ° reSt E c o n o c im ie n to del fun cionam iento y la programación de estos sistemas
e m b e b id o s inte gran una parte fun dam enta l del currículo para los estudiantes de ingeniería*
es p ro p o rc io n a una visión actual de la tecnología utilizada en la industria y les prepara-'para
la re a liz a c ió n de fu tu ro s proyectos basados en sistemas embebidos.

Este lib ro , elab ora do por tres profesores del área de Tecnología Electrónica de laíiíniversida
P ú b lic a de N avarra, está pensado para servir de introducción y apoyo práctico a; todo
a q u e llo s e s tu d ia n te s de ingeniería y personas en general interesadas en ef diseño eledjflnibo
m e d ia n te la u tiliz a c ió n de sistem as m icrocontroladores de 8 bits. Así, el libro se estructura
d ife re n te s c a p ítu lo s en los que m ediante la realización de ejercicios de diferente complejii
se re visa n los m ó d u lo s que se encuentran generalm ente integrados en estos sistemas¡ <^on
p o r e je m p lo los pu ertos de entrada/salida digitales, tem porizadores, conversores analógico
c o m p a ra d o re s y c o m u n ic a c io n e s serie.

Los ejemplos y ejercicios del libro están basados en la arquitectura del PIC16F877
se pueden extrapolar fácilmente a otro tipo de microcontroladores gracias al em¡á)ép
la programación en lenguaje de alto nivel ‘C . No obstante, las estructuras básica?
programación de este lenguaje se revisan en el primer capítulo del libro para aquellos m§!3
familiarizados con el mismo, mientras que los capítulos siguientes están orientado^
resolución de problemas prácticos.

La metodología empleada permite seguir los ejemplos propuestos a partir de los conocimiento,
básicos de programación de los primeros capítulos y sin la necesidad de utilizar hardwa
ni elementos adicionales. Todo ello gracias a la utilización de la h e d ie n te M B m
gratuita MPLAB ID E®, que integra un simulador, y a la descarga de los maten
de forma online en la sección de descargas del libro en [Link]

Síguenos en:
M a rco n ib o
[Link] I

También podría gustarte