Está en la página 1de 85

Programacin

PIC con C
Bliblioman
Programacin C para microcontroladores PIC

Aqu hay apuntes


www.aquihayapuntes.com
[Escribir el nmero de
telfono]

17/02/2010

Programacin PIC en C

Curso para aprender a programar en lenguaje C utilizando un


compilador para PIC, en concreto el PCW compiler de la casa CCS.
Cursos sobre C en Internet a miles, pero todos los que yo he visto
estn realizados sobre compiladores de propsito general, como Vicual
C++ de Microsoft Builder C++ de Borlan, sin duda son excelentes
compiladores que nos permiten realizar aplicaciones para
ordenadores de escritorio tanto en C como en C++ (la versin
orientada a objetos de C), pero no sirven para programar PIC, es
decir con el ejecutable que generan al compilar no se puede
programar un Microcontrolador.
Lo habitual hasta ahora es que los usuarios que se inician en este
apasionante mundo de la programacin de Microcontroladores, sea de
la marca que sea, primero lo hacan utilizando el lenguaje
ensamblador, especifico no solo ya para cada marca de
microcontrolador sino para cada modelo, ya que hay que conocer
perfectamente los recursos de cada Microcontrolador (Nmero de
puertos de Entrada/Salida Relojes internos, etc. ). Al principio de los
tiempos de estos dispositivos esto era obligatorio ya que los recursos
de memoria y velocidad de procesamiento no eran muy grandes y
haba que optimizar el cdigo al mximo, esto implicaba que haba
que utilizar a la fuerza un lenguaje de programacin de bajo nivel que
bien utilizado explotara los recursos de estos dispositivos sin
desperdiciar memoria y velocidad de procesamiento, pero al igual que
ha ocurrido con los ordenadores personales las prestaciones de estos
dispositivos ha ido creciendo exponencialmente con el tiempo, siendo
ya perfectamente factible el utilizar un lenguaje de alto nivel para
programar estos dispositivos y aprovecharnos de las ventajas de
portabilidad que ofrecen este tipo de lenguajes, de esta manera por
ejemplo podemos hacer un programa para un PIC en concreto y
utilizarlo en otro de mayores prestaciones sin modificar apenas nada
del cdigo fuente.
Quien puede sacar provecho de este curso?. Este curso es para ti si:
Has programado PIC en Ensamblador y quieres hacerlo en un
lenguaje de alto nivel como el C.
No has programado nunca Microcontroladores pero conoces el
lenguaje de programacin C de haberlo utilizado para otros
propsitos.
No has programado nunca un PIC en Ensamblador, ni conoces
ningn lenguaje de alto nivel como el C. Es decir, no tienes ni
idea de Microcontroladores ni de programacin (Esto es posible
porque el curso va ha empezar desde cero es decir con el

Programacin PIC en C

clsico Hola Mundo con el que empiezan todos los libros de


iniciacin a la programacin.
Bueno alguno pensar que para aprender a programar en C vale
cualquier compilador de uso general
y lo que realmente interesa es saber las instrucciones de C que tengo
que utilizar para configurar por ejemplo un puerto como entrada o
salida, o que cdigo tengo que utilizar para utilizar los convertidores
A/D que incorporan ya casi todos los PIC, indudablemente ese es
el propsito final de este curso y para ello paralelamente a l va
haber otro donde se van a ver aplicaciones prcticas. Pero hay que
tener en cuenta que los compiladores para Microcontroladores son
especficos para estos dispositivos embebidos y no cumplen con el
Estndar ANSI C al 100 %, por lo que cuando ests programando lo
ms seguro es que te vayas dando cuenta que una funcin que en el
C estndar funciona perfectamente aqu te da un error al compilar.
Adems te irs quedando con mucho cdigo que lo has probado y
sabes que te funciona perfectamente, cuando tengas que hacer una
aplicacin prctica no tendrs la duda si puedes usar una
determinada estructura en tu programa si es posible utilizar
punteros o no y como hacerlo, porque ya lo sabrs a la vez que has
ido aprendiendo el lenguaje de programacin y no solo eso, te irs
familiarizando con las instrucciones especficas del compilador: de
que herramientas dispone, sus funciones precompiladas, su sistema
de depuracin de errores, etc.
Que herramientas voy a necesitar para realizar el curso?.
El compilador CCS seguro, vaya es de pago ya empezamos con
problemas te puedes bajar una versin de Evaluacin por 30 das
desde aqu:

http://www.ccsinfo.com/ccsfreedemo.php
Despus de rellenar el formulario te descargas el programa de
instalacin y lo instalas en tu ordenador como un programa ms de
Windows, aunque tienes que tener en cuenta que solo podrs
programar un pequeo conjunto de PIC de cada familia, otro
inconveniente es que tienes que estar conectado a Internet para que
te funcione si no te aparecer esta ventanita poco amigable:

Programacin PIC en C

Otra limitacin es que el tamao del programa no puede superar los


2K de memoria, aunque para los ejemplos que vamos a hacer aqu te
sobra. Bien ya tenemos solucionado el tema del compilador, bien sea
por que con la demo nos apaamos o porque tengo un amigo
cojonudo que me va ha prestar uno con licencia para que pueda
realizar el curso (je,je.. ).
Bien ya tengo el compilador y puedo empezar a programar y a crear
mis .HEX (para el que no lo sepa es el archivo que tenemos que
cargar en nuestro PIC para que funcione). Todo esto es muy
elemental para el que lo sabe, pero como dije al principio este curso
est pensado tambin para el que no tiene ni idea de programar
microcontroladores. As es que sigamos.
Una vez que tenemos nuestro .HEX tendremos que comprobar que
funciona realmente para ello tenemos dos opciones:
Montar nuestro circuito con todos sus componentes, programar
el PIC con un programador comercial como el PICSTART de
Microchip o con uno de los muchos que hay en Internet que
sirven perfectamente para empezar a programar estos
dispositivos.
Utilizar un programa de simulacin electrnica como Proteus
que tiene la ventaja de disponer de una extensa biblioteca de
microcontroladores PIC junto con los componentes auxiliares
que normalmente utilizan estos dispositivos: leds, pantallas
LCD, teclados, memorias, etc.

Programacin PIC en C

Bien nosotros utilizaremos la segunda opcin, aunque en una prctica


veremos como hacerlo de la primera forma.
La versin de evaluacin de Proteus te la puedes descargar desde
aqu:

http://www.labcenter.co.uk/download/prodemo_download.cfm

Claro que tiene limitaciones, sino no sera una demo, la principal es


que no podemos guardar nuestros
trabajos y la segunda es que no lleva incorporado muchas de las
libreras dinmicas necesarias
para realizar la simulacin de algunos microcontrloladores. Mira a ver
si el amigo que te dejo el compilador te puede dejar tambin una
licencia para este magnfico Simulador.

Nota: en este sitio est prohibido el mostrar facilitar enlaces a


lugares de descarga de dudosa reputacin. Lo digo tambien para que
se tenga en cuenta en el foro que prximamente estar a vuestra
disposicin y donde podremos exponer nuestras dudas experiencias
sobre este tema y sobre otros que irn saliendo.

Otra cosa que quiero aclarar es que el curso va a ser todo lo prctico
que pueda y la forma de proceder ser
la siguiente: ir mostrando uno varios ejemplos de cada tema y
posteriormente har una Explicacin de los mismos. Yo no se
vosotros pero yo cada vez que he querido aprender algo nuevo lo
primero que he hecho a sido mirar los ejemplos, despus vosotros
tendris que comprobar que lo que he dicho es cierto y que el
ejemplo compila y funciona sin errores.
Para facilitar la navegacin el prximo da presentar el ndice de los
temas que va a tratar el curso
Aunque puede que lo vaya modificando segn vallamos avanzando.

Programacin PIC en C

Bueno vamos a continuar con el ndice de nuestro curso:


Mi primer programa en C con el compilador PCW C.
Simular nuestro primer programa con proteus.
Variables y Tipos de Datos.
Constantes.
Depuracin de programas con Proteus y CCS
Funciones de Entrada / Salida serie RS232
o La funcin printf().
o Funciones getc(), getch() y getchar().
o Funciones gets() y puts().
Operadores.
Sentencias repetitivas.
o Bucle while
o Bucle for
o Bucle do-while
Sentencias condicionales
o Sentencia if
o Sentencia if-else
o Sentencia switch
Sentencias de salto.
Sentencias goto, break, continue.
Sentencia return.
Funciones.
Punteros.
Arrays.
Cadenas de caracteres.
Funciones para manipular cadenas de caracteres.
o Funcin strcyp (cadena 1, cadena 2).
o Funcin strcat (cadena 1, cadena 2).
o Funcin strlen (cadena).
o Funcin strcmp (cadena 1, cadena 2).
Arrays Multidimensionales.
Arrays de cadenas.
Punteros y Arrays.
Array de punteros.
Relacin entre Arrays y Punteros.
Aritmtica de Punteros y errores mas comunes.
Estructuras.
Estructuras y Punteros.
Paso de Estructuras como argumentos a funciones.
Uniones.
Enumeraciones.
Uso de la palabra clave typedef.
Campos de bits

Programacin PIC en C

Vamos a crear nuestro primer ejemplo paso a paso: abrimos el IDE


de nuestro compilador y seleccionamos New->Source File segn se
muestra en la figura de abajo:

Nos saldr un cuadro de dialogo de guardar de Windows, donde le


pondremos un nombre a nuestro archivo y lo guardaremos.
Despus escribimos el cdigo fuente que se muestra en la figura de
abajo y guardamos el documento:

Programacin PIC en C

Comentario del programa:


En primer lugar nos encontramos con tres directivas del
prepocesador, las identificaremos porque empiezan por el smbolo
(#):
La primera de ellas es una directiva include su funcin es
introducir un documento dentro de otro. En la posicin del
programa donde se encuentra esta directiva, se incluir el
archivo indicado. Se suele usar para incluir los archivos de
cabecera (generalmente con extensin.h). En este caso
concreto se incluye el archivo <16F877A.h>,en este archivo se
incluyen las definiciones de los registros del PIC.
#use delay (clock=4000000); directiva para el uso de retardos,
entre parntesis tenemos que poner la frecuencia de reloj que
vamos a utilizar.

Programacin PIC en C

#use rs232
(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) esta
directiva es para la comunicacin del PIC con otro dispositivo
va RS232, por ejemplo un ordenador, en ella se encuentran
definidas los prototipos de las funciones de entrada y salida
como printf().
En segundo y ltimo lugar se encuentra la funcin main. Este es el
ncleo del programa, el que va ha incluir todos los pasos a seguir
durante su ejecucin. En nuestro primer ejemplo solo contiene una
sentencia que hace una llamada a la funcin printf(), esta funcin se
encarga de mostrar un mensaje por el dispositivo de salida RS-232.
El mensaje que muestra la funcin printf es el que recibe como
parmetro (el texto entre parntesis). Dicho mensaje es delimitado
por las comillas dobles, que indican el principio y el fin de una cadena
de texto.
Bien una vez creado el archivo .c de nuestro programa tenemos que
crear un proyecto y asociarle el archivo que acabamos de crear,
tenemos dos opciones crearlo manualmente utilizar el wizard que
tiene el IDE, en este primer ejemplo utilizaremos la opcin manual.
Despus seleccionamos New ->Project Manual

Y aadimos el Ejemplo1.c que hemos creado a nuestro proyecto:


9

Programacin PIC en C

Seleccionamos la pestaa Compile y pulsamos sobre Build All para


construir todo.

10

Programacin PIC en C

Vemos que el archivo de salida no nos ha producido ningn error.


Por tanto el proyecto se ha generado correctamente.
Y si vamos a la carpeta donde habamos guardado nuestro primer
ejemplo, tenemos todos los archivos que nos ha creado el IDE:

11

Programacin PIC en C

De todos estos archivos los que mas nos interesa son los que estn
marcados en la figura de arriba. El archivo Ejemplo1.hex es el que
tenemos que utilizar para programar el PIC y el que termina con
extensin .cof lo utilizaremos para cargarlo en el simulador Proteus y
poder simular el programa paso a paso, entre otras posibilidades muy
tiles a la hora de depurar nuestro cdigo.
Bien ya tenemos nuestro primer ejemplo generado y listo para
cargarlo en nuestro simulador Proteus. Vamos a ello:
Arrancamos nuestro simulador Proteus y pasamos a colocar nuestros
dispositivos en el rea de trabajo. Empezaremos colocando el PIC,
para ello hacemos clic en el botn que pone Pick Devices segn se
muestra en la figura de abajo:

12

Programacin PIC en C

En la ventana que nos aparece en el campo Keywords escribimos el


nombre de nuestro PIC.

Una vez seleccionado hacemos doble clic sobre el para incorporarlo a


nuestro proyecto.

13

Programacin PIC en C

Bien, vamos por el segundo y ltimo elemento que necesitamos para


simular nuestro programa. Hay que tener en cuenta que el simulador
es capaz de hacer funcionar nuestro circuito sin algunos elementos
que seran necesarios si decidimos montar nuestro circuito en una
placa real (por ejemplo la alimentacin del PIC y el cristal de cuarzo).
El segundo elemento que necesitamos es un Terminal Virtual que
har las veces de monitor, para poder ver las salidas en formato
texto de nuestro PIC como si se tratar del smbolo del sistema en
un ordenador de escritorio con el Windows instalado. En la figura de
abajo se muestra donde podemos incorporar dicho instrumento.

14

Programacin PIC en C

Con esto ya tendremos los dos elementos necesarios para simular


nuestros programas, recordemos que en este curso se va a ver las
generalidades del lenguaje C aplicadas a este compilador, en el caso
de las aplicaciones prcticas que empezaremos pronto en otro
articulo tendremos que hacer un circuito independiente para cada
ejemplo ya que cada uno de ellos incorporar elementos diferentes
como: diodos Led, motores, teclados, displays, etc.
La interconexin de los dos dispositivos es muy sencilla segn se
muestra en la figura de abajo, solo hay que hacer clic con el puntero
del ratn en forma de lpiz entre los terminales que queremos
conexionar:

15

Programacin PIC en C

El pin del PIC que habamos elegido como transmisin de datos en


nuestro programa ir conectado al terminal RXD de recepcin de
datos en el Terminal Virtual y viceversa.
Bien ahora tenemos que cargar nuestro programa en el PIC para
poder simularlo, para ello hacemos doble clic sobre el PIC y nos
aparecer la ventana de la figura de abajo:

16

Programacin PIC en C

Los valores que en un principio tenemos que introducir para que


nuestra simulacin funcione son los que estn sealados en la figura
de arriba. En Program File pincharemos sobre la carpeta y
seleccionaremos el archivo con extensin .cof que se haba creado al
compilar nuestro programa, si en vez de este seleccionamos el que
tiene extensin .Hex funcionar igual pero no podremos realizar la
simulacin paso a paso. El otro valor a tener en cuenta es que la
frecuencia del reloj del PIC debe coincidir con el valor que le
habamos puesto en el programa en nuestro caso 4 MHz.
Si ahora hacemos clic sobre el botn Play se nos abrir una terminal
al estilo MSDos donde nos mostrar la salida de nuestro programa:

17

Programacin PIC en C

Ahora si le damos al botn de simulacin paso a paso podremos


simular nuestro ejemplo paso a paso.
Si en vez de ello nos sale una ventana mostrando dos advertencias
de que no se puede encontrar el cdigo fuente de nuestro ejemplo,
como se muestra en la figura de abajo.

18

Programacin PIC en C

Seguiremos los siguientes pasos:


En el men seleccionamos Source y hacemos clic sobre Define Code
Generation Tools

19

Programacin PIC en C

Nos aparecer la ventana de abajo en la que pulsaremos sobre el


botn New

Buscamos en nuestro directorio donde se ha instalado el compilador y


seleccionamos CCsc.exe tal y como se muestra en la figura de abajo:

20

Programacin PIC en C

Despus en el combo Tool seleccionamos el compilador y


configuramos el resto de parmetros tal y como se muestra en la
figura de abajo y pulsamos OK:

21

Programacin PIC en C

Ahora nos queda aadir nuestro cdigo fuente para ello vamos al
men seleccionamos Source Add/Remove Source files

Y aadimos nuestro cdigo fuente ejemplo1.c


Si ahora volvemos a simular nuestro ejemplo paso a paso nos
aparecer la ventana siguiente:
22

Programacin PIC en C

Donde podemos ver la ejecucin del programa lnea a lnea o poner


puntos de interrupcin en las partes del programa que nosotros
queramos. Saber que existe un plugin que permite integrar un visor
de proteus en el famoso simulador MPLAB. Incluir un video en la
seccin de descargas donde explica como hacerlo, aunque nosotros
seguiremos utilizando este mtodo.
Bien a partir de ahora ya podemos empezar a estudiar el lenguaje de
programacin C en este compilador como si fuera un compilador
cualquiera como Microsoft Visual C++ pero comprobando las
particularidades de este compilador. Todos los ejemplos van a seguir
el mismo procedimiento por lo que solo pondr el cdigo y la
explicacin del mismo.
Qu son las variables? pues sencillamente el poder identificar con un
nombre una o varias posiciones de memoria de la RAM de nuestro
PIC y de esta manera el poder almacenar all los datos que va a
utilizar nuestro programa.
En C para poder utilizar una variable primeramente hay que
declararla siguiendo la siguiente sintaxis:
23

Programacin PIC en C

tipo nombre_variable [=valor];

Lo que va entre corchetes es porque es opcional es decir, las


variables se pueden inicializar no al declararlas.
Ejemplo de variable declarada:
int i;
Ejemplo de variable declarada e inicializada:
int i=5;
En una misma lnea se puede declarar ms de una variable siguiendo
el siguiente formato:
tipo nombre_variable1,nombre_variable2,....;

Hay que tener en cuenta que la lnea tiene que acabar en punto y
coma.
El tipo de datos es obligatorio ponerlo y le dice al compilador cuantas
celdillas de memoria tiene que reservar para almacenar el valor de la
variable. Los tipos de datos pueden variar de un compilador a otro,
vamos a ver los tipos de datos que podemos usar con nuestro
compilador CCS.
Los tipos de datos bsicos que utiliza nuestro compilador son los
siguientes:

24

Programacin PIC en C

Sin embargo el compilador CCS tambin admite los siguientes tipos


de datos definidos en el estndar C y que son los que normalmente
se utilizan a la hora de programar:

Todos los tipos excepto float son por defecto sin signo, aunque
pueden llevar el especificador unsigned signed y su rango de
valores ser el que corresponda a su tipo bsico.
Estos son los tipos bsicos, tambin estn los tipos de datos
compuestos como Enumeraciones, Estructuras y Uniones que estn
formados por una combinacin de los bsicos y que los veremos ms
adelante.
El nombre de la variable no puede ser una palabra clave (reservada
por el compilador para realizar unas funciones determinadas y los
caracteres que podemos utilizar son las letras: a-z y A-Z ( ojo! la o
no est permitida), los nmeros: 0-9 y el smbolo de subrayado _.
Adems hay que tener en cuenta que el primer carcter no puede ser
un nmero.

Dnde se declaran las variables?


Las variables segn el lugar en que las declaremos pueden ser de dos
tipos: globales o locales.
La variables globales se declaran fuera de las funciones y
pueden ser utilizadas en cualquier parte del programa y se
destruyen al finalizar ste.
25

Programacin PIC en C

Las variables locales se declaran en la funcin en que van a ser


utilizadas. Slo existen dentro de la funcin en que se declara y
se destruye al finalizar dicha funcin. Si una funcin va a usar
argumentos (DATOS), entonces debe declarar las variables que
van a aceptar los valores de esos argumentos. Estas variables
son los parmetros formales de la funcin. Se comportan como
cualquier otra variable local de la funcin, crendose al entrar
en la funcin y destruyndose al salir. Cuando veamos el tema
de las funciones veremos ejemplos de estas variables.

Bueno ya est bien de teora vamos hacer un ejemplo donde vamos a declarar y a usar
varios tipos de variables:

Este programa generar la siguiente salida:


26

Programacin PIC en C

Comentario del programa:

El compilador utiliza 8 bits para representar los nmeros enteros sin signo con lo
cual podemos representar desde el 0 hasta el 255 que corresponde en binario al
nmero: 11111111. Por lo que al asignarle a la variable el valor 256 el
compilador no generar un error pero el dato guardado ser errneo, nos
mostrar 0 que es el siguiente valor a 255 en binario.
Para los nmeros enteros con signo tambin se utilizan 8 bits pero el ltimo bit
se reserva para el signo, con lo que se podrn representar los nmeros desde: 127 al 127.
El tipo short se utilizar para las variables de un bit y tendrn como valor 0 1.
Para los nmeros tipo long int se reservan 16 bits sin signo con lo que su rango
va de 0 a 65535
Para el tipo signed long se reservan tambin 16 bits pero se utiliza uno para el
signo, por lo que se tiene un rango que va desde -32767 a 32767.
El tipo float define un nmero de 32 bits en punto flotante. y con el podremos
representar los nmeros reales.
El tipo char se utiliza para almacenar los caracteres, utiliza 8 bits sin signo
suficientes para representar los 256 caracteres del cdigo ASCII.
Los smbolos %D, %lu, %ld, %c le indica a la funcin printf en que formato
tiene que representar el nmero. En la ayuda del compilador vienen los
diferentes especificadores que hay para los diferentes tipos de datos. A lo largo
de los siguientes ejemplos se irn mostrando algunos ms.

27

Programacin PIC en C

CONSIDERACIONES: Hay que intentar siempre utilizar el tipo de dato que menos
memoria ocupe dentro de los valores que pueda utilizar la variable. Si abusamos de los
tipos grandes para almacenar valores pequeos nos quedaremos sin memoria y en los
programas grandes es un dato que tenemos que tener en cuenta.

Nota: en los ejemplos que tengan poco cdigo fuente como este y para que el formato
de texto salga con los mismos colores que utiliza el compilador utilizar imgenes para
mostrar el cdigo y en la seccin de descargas ir incluyendo los ejemplos del curso
para que todo el que no quiera teclearlos a mano se los pueda descargar. Otra cosa no
incluir el circuito en Proteus ya que es el mismo para todos los ejemplos a excepcin
de que en algunos ejemplos pueda ir cambiando el tipo de PIC.
Antes de empezar con el tema de las constantes voy a comentar
valga la redundancia la forma de poner comentarios a nuestros
programas.
Hay dos formas de poner comentarios en C:

Poniendo doble barra (la que hay encima del 7), esta forma es
prctica para comentar una lnea.
Ejemplo:
//Este texto es un comentario.
//y este otro tambin.
la otra forma es meter el texto a comentar dentro de estos
smbolos /* mi comentario*/. La ventaja de este sistema es que
podemos comentar bloques de textos enteros.
Ejemplo:
/*Mi comentario empieza aqu.....
mas comentarios ..
y termina aqu */
El comentar nuestro cdigo es una buena costumbre que no debemos
pasar por alto, ya que si pasado un tiempo queremos volver a un
programa y modificar alguna parte de l ayuda mucho el que su
cdigo est comentado. Otra forma en la que se utilizan los
comentarios es a la hora de depurar cdigo, en vez de estar borrando
y escribiendo trozos de cdigo que no funcionan correctamente los
comentamos, de est forma el compilador no los tratar como cdigo
28

Programacin PIC en C

fuente y podremos realizar ajustes y pruebas de una manera ms


fcil. Muchas veces tambin vemos que revisando cdigo que han
hecho otras personas hay partes del cdigo que estn comentadas
esto es para hacerlo mas funcional, es decir, por poner un ejemplo, si
utilizas el PIC 16F877 des comenta esta parte y si utilizas otro PIC lo
dejas comentado, de esta manera comentando o descomentando
unas cuantas lneas podemos utilizar el programa en varias
situaciones.
Bueno, todo esto para el que tenga una idea de programacin seguro
que ya lo sabe, pero como dije al principio voy ha intentar que este
curso le sirva tambin al que no tenga ni idea de programacin
aunque, en este caso, hay que decir tambin si se es honesto, que
aprender un lenguaje de programacin al igual que aprender un
idioma nuevo supone un esfuerzo considerable y no vasta con leerse
un libro de C y decir ya soy un programador de C!, bajo mi modesta
opinin lo que hay que hacer es practicar mucho, es decir teclear
mucho cdigo compilarlo y comprobar que funciona como nosotros
queremos que lo haga, al principio cometeremos muchos errores pero
el descubrir cual es la causa del error nos servir para aprender mas
todava y sobre todo no desanimarse a la primera de cambio cuando
algo no funcione. La constancia y la perseverancia son las claves del
xito para conseguir cualquier objetivo, no solo el aprender a
programar PIC en C. Y ya est bien porque menudo rollo estoy
soltando, as que vamos a empezar con lo que era el tema de este
capitulo: las constantes.
Las constantes se refieren a valores fijos que no se pueden alterar
por medio del programa.
Pueden definirse constantes de cualquiera de los tipos de datos
simples que hemos visto.
Se declaran colocando el modificador const delante del tipo de datos.
Ejem:
const int MINIMO=10,INTERVALO=15;
Esto definir dos constantes MINIMO con el valor de 10 e INTERVALO
con el valor de 15.
Otra forma de definir constantes es usando la directiva de
compilacin #define.
29

Programacin PIC en C

Ejem.
#define MAXIMO 30
Esta orden se ejecuta de la siguiente forma: en la fase de compilacin
al ejecutar #define el compilador sustituye cada operacin de la
primera cadena de caracteres por la segunda, MAXIMO por el valor
30 adems, no se permite asignar ningn valor a esa constante.
Es decir si pusiramos:
#define MAXIMO = 30
Al compilar tendramos un error.
Nota: La declaracin #define no acaba en ";"
Tambin podemos tener en nuestro programa Constantes de cadena:
una cadena de texto es una secuencia de caracteres encerrados entre
dobles comillas. Se usa para funciones de entrada y salida estndar,
como funcin de entrada y salida de texto estamos utilizando la
funcin printf que esta definida dentro de-> #use rs232, pero ya
veremos que el compilador CCS proporciona un nmero considerable
de funciones listas para usarse y que nos sirven para comunicarnos
con el dispositivo de entrada y salida RS-232.
Hemos dicho que podemos definir constantes prcticamente de
cualquier tipo de dato, pero CCS nos permite tambin representar
esas constantes en diferentes sistemas de numeracin como
hexadecimal, binario, octal, decimal y adems definir tambin
constantes de caracteres especiales que el compilador utilizar para
realizar acciones concretas. De los sistemas de numeracin
permitidos los que ms se usan son los siguientes:

Decimal
Ejemplo: 222
Hexadecimal empiezan por 0x
30

Programacin PIC en C

Ejemplo: 0x2A
Binario empiezan por 0b
Ejemplo:
0b00001011
Este ltimo formato es muy til, por ejemplo el PIC dispone de unos
registros que sirven para configurar los puertos del PIC como
entradas de datos o salida de datos, por defecto vienen configurados
como entradas y si quiero utilizar algn pin como salida porque
quiero utilizarlo para encender un LED o lo que sea, tengo que poner
a cero dicho registro. En el formato binario se ve fcilmente que
valores se le va asignar al registro, teniendo en cuenta que los
registros empiezan por 0.
Como siempre vamos hacer un ejemplo para ver si nuestro
compilador se traga todo lo que he dicho:

31

Programacin PIC en C

Bien si todo va bien obtendremos la siguiente salida:

Comentario: Como dije en la introduccin de este curso la finalidad


es aprender a programar PIC en lenguaje C eso conlleva saber el
lenguaje C, que seguiremos viendo en esta parte del curso, pero
tambin el saber utilizar los recursos y funcionalidades que nos
ofrecen los PIC como por ejemplo saber programar sus contadores,
como enviar datos a un LCD, el utilizar los conversores A/D, etc. Para
ello voy a iniciar prximamente un segundo artculo donde
empezaremos a estudiar ejemplos prcticos de los PIC.
Una vez iniciada la parte de prcticas vamos a seguir con la teora,
pero antes he incluido este pequeo artculo sacado de un video
tutorial que encontr en Internet y que he adaptado al compilador
CCS, el video tutorial lo colocare en la seccin descargas para el que
lo quiera ver. Pues, una vez dicho esto vamos a empezar. En la
ltima prctica que hemos visto (el uso del TMR0 como contador)
vimos que el entorno de Proteus nos proporciona una ventana de
visualizacin del estado de los registro SFR de nuestro PIC , muy til
cuando estamos depurando nuestro programa, pero Proteus nos
proporciona ms ventanas para ver el estado de los registros de
nuestro PIC que podemos acceder a ellas por medio del men Debug
--> PIC-CPU cuando estamos ejecutando nuestro programa en el
modo de simulacin paso a paso cuando hemos pulsado el botn de
32

Programacin PIC en C

pausa, una vista condensada de todas esas ventanas la tenemos en


la figura de abajo:

Como vemos aparte de poder ver el estado de los registros SFR del
PIC podemos ver el estado de la memoria EPROM del PIC, El
contenido de la memoria de programa (donde se encuentra grabado
de forma permanente nuestro programa ), el estado de PILA (til
cuando se trabaja con interrupciones y funciones), otra ventana nos
muestra el estado de la memoria RAM reservada a los datos
registros de propsito general (GPR) en formato hexadecimal y otra
donde podemos ver el estado de las variables que tenemos activas en
ese momento, recordar que si utilizamos variables locales por
ejemplo dentro de una funcin, ests se destruirn al salir de la
funcin. Pero todo esto como he dicho lo tenemos cuando estamos
ejecutando nuestro programa en el modo paso a paso tenemos
nuestro programa en pausa.

33

Programacin PIC en C

Si estamos en modo Run e intentamos acceder a estas ventanas


vemos que estn deshabilitadas:

Qu otro sistema tenemos para depurar nuestros programas? Pues


bien una manera que siempre podemos utilizar es utilizar la funcin
printf como herramienta de depuracin, es decir, ponemos la funcin
printf en determinadas partes del programa donde queramos saber el
estado de una o varias variables y por medio de la terminal podemos
saber el valor que van tomando, una vez comprobado que nuestro
programa funciona como nosotros queremos borramos las funciones
printf que hayamos introducido con propsitos de depuracin.
Pero Proteus nos proporciona otro mtodo para ver el estado de las
variables cuando estamos ejecutando nuestro programa ya sea en
modo Run en modo paso, es la ventana Watch Window y podemos
acceder a ella por medio del men Debug --> Watch Windows.
Vamos a ver cmo podemos utilizarla. Para ello compilaremos el
siguiente ejemplo:
#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT,PUT,NOWDT
#use RS232(BAUD=9600, BITS=8, PARITY=N, XMIT=PIN_B4,
RCV=PIN_B5)
int x;
int y;
void main() {
x,y=0;
34

Programacin PIC en C

while(TRUE)
{
if (x<=9)
{
x++;
delay_ms(500);
//printf("x = %d.\r",x);
}
else
{
if (y<=9)
{
y++;
delay_ms(500);
//printf("y = %d.\r",y);
}
}
}
}
Es un programa que lo nico que hace es incrementar la variable X de
0 a 10 y despus hace lo mismo con la variable Y, pero es suficiente
para ver cmo utilizar la ventana Watch Windows para ver el valor
que van tomando las variables X e Y.
Primeramente compilamos el ejemplo y despus dentro del IDE del
compilador hacemos clic en el icono Symbol Map segn se muestra
en la figura de abajo:

Esto har que nos aparezca el archivo Symbol Map en modo lectura,
en este archivo podemos ver en qu posicin de memoria se
guardarn las diferentes variables que tengamos declaradas en
nuestro programa, este archivo se actualizar en cada compilacin
que hagamos.

35

Programacin PIC en C

Como vemos en la figura de arriba las variable X e Y tienen


asignadas las direcciones de memoria 0x011 y 0x012 en la
memoria RAM de propsito general (GPR), que como ya sabemos es
la que el programador dispone para almacenar los valores de sus
variables.
Bien, una vez anotadas estas direcciones volvemos al entorno de
Proteus y abrimos la ventana Watch Windows, dentro de ella
hacemos clic con el botn derecho del ratn y seleccionamos Add
Items (By Address) , segn se muestra en la figura de abajo:

36

Programacin PIC en C

Nos aparecer una nueva ventana donde iremos aadiendo las


variables con su direccin correspondiente:

Una vez aadidas las variables podemos ver el valor que van
tomando mientras ejecutamos nuestro programa en la ventana Watch
Windows, segn se muestra en la figura de abajo:

37

Programacin PIC en C

Pero tenemos an mas opcciones, por ejemplo podemos establecer


condiciones para ello hacemos clic en la variable con el botn derecho
y seleccionamos Watchpoint Condition
Nos aparecer la ventana que se muestra abajo:

Por ejemplo yo la he configurado para que cuando la variable X sea


igual a cinco se pare la simulacin, pero admite ms condiciones solo
hay que ponerse y experimentar con las diferentes opciones que
tenemos, tambin decir que podemos hacer que la ventana Watch
Windows nos muestre los registros SFR que nos interesan junto con
las variables que nosotros hemos declarado, en fin muchas
posibilidades de depuracin. El conocer estas herramientas nos
puede facilitar mucho el aprendizaje porque vemos la secuencia real
que sigue nuestro programa, que algunas veces puede que no
coincida con nuestra lgica de funcionamiento del programa.

Nota: el video tutorial lo podeis descargar desde:

Descargas --> Apuntes --> Electrnica --> Proteus --> Uso de Watch Windows en
Proteus.zip
38

Programacin PIC en C

Como siempre espero vuestros comentarios y os agradecera que las


preguntas que tengis sobre estos temas, pues las hagis
directamente en el foro que para eso est.
Aunque no hemos visto el tema de las funciones todava, pero ya que estamos
utilizando esta funcin muy a menudo, vamos a ver alguna de las posibilidades que nos
ofrece. El que tenga conocimientos del lenguaje C sabr que para utilizar esta funcin
que pertenece al estndar ANSI de C hay que incluir previamente el archivo de cabecera
#include <stdio.h>, pero esto con el compilador PCW de CCS no funciona, en este
compilador esta funcin est definida en la directiva:

#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_B1,RCV=PIN_B2)

Esto quiere decir que cada vez que queramos utilizar la funcin printf tenemos que
haber incluido previamente esta directiva, que posibilita la comunicacin del PIC con
otro dispositivo utilizando el protocolo de comunicacin serie RS232, adems de la
funcin printf esta directiva permite el uso de otras funciones para la entrada y salida de
datos serie como: getc, getchar, gets, puts y kbhit que iremos viendo poco a poco, pero
la ms importante para la salida de datos sin duda es printf, porque nos permite
formatear la salida de esos datos de la forma que nosotros queramos.

Como vemos la directiva #use RS232 admite una serie de parmetros que son los que
van entre parntesis separados por comas, estos son los siguientes:

BAUD con este parmetro establecemos la velocidad en baudios a la que


queremos que se transmitan los datos por el puerto serie, 9600 es lo normal.
BITS nmero de bits que utilizaremos en la transmisin, el estndar establece
que pueden ser 8 9, para la comunicacin con microcontroladores con 8 son
suficientes.
PARITY nos permite utilizar un bit de paridad para la comprobacin de errores,
est opcin la dejamos a No.
XMIT est opcin nos configura porque patilla del PIC saldrn los datos, est
opcin junto con la siguiente s que la tendremos que cambiar a nuestras
necesidades.
RCV nos configura porque patilla del PIC se recibirn los datos. En el ejemplo,
los datos se transmiten por el PIN RB1 y se reciben por RB2.

39

Programacin PIC en C

La forma de hacer la llamada a la funcin printf es la siguiente:

printf(Nombre Funcin, Cadena de caracteres , valores);

Como vemos la funcin printf tambin admite parmetros que podremos utilizar para
formatear el texto de salida. Vamos a ver cules son:

El primero es opcional y es el nombre de una funcin, si no lo ponemos los datos se


transmitirn va RS232 a travs de los pines que hayamos configurado en la directiva
#use RS232.
El segundo parmetro es una cadena de caracteres encerrada entre comillas dobles.
Y el tercero son datos o nombres de variables cuyo valor queremos que se muestren.
Vamos a ver todo esto con ejemplos que es como mejor se ven las cosas:

1 Ejemplo:

#include <16F877.h>
#use delay(clock=4000000)
#include <LCD.C>
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_B1,RCV=PIN_B2)
void main()
{
int i1=9;
lcd_init(); //funcin de inicializacin del LCD
//Mostramos una cadena en la terminal
printf("Esto es una cadena\r");
//Mostramos una cadena de texto junto con el valor de una variable
//en la terminal.
printf("El valor de la variable i1 es: %d",i1);
//Mostramos el valor de la variable por el LCD
printf (lcd_putc,"El valor de i1 es: %d",i1);

40

Programacin PIC en C

Comentario:
En este primer ejemplo vamos a ver el uso de la funcin printf utilizando diferentes
parmetros. Como vamos a utilizar la librera que incluye el compilador para el manejo
de un LCD tenemos que incluir la directiva:

#include <LCD.C>

Declaramos una variable i1 de tipo entero que nos va a servir para mostrar su valor en la
terminal y en un LCD.
Cuando utilicemos la librera LCD.C y antes de utilizar cualquier otra funcin incluida
en la librera tenemos que llamar a la siguiente funcin que sirve para inicializar el
LCD.

lcd_init();

En la primera llamada a la funcin printf como parmetros solo incluimos una cadena
de caracteres constante que termina en (\r), esa barra invertida junto con la r se le llama
secuencia de escape y le est diciendo al compilador que al final de la cadena introduzca
un retorno de carro (tecla enter). Las secuencias de escape se utilizan para representar
caracteres o acciones especiales.

printf("Esto es una cadena\r");

En la tabla de abajo se muestran las secuencias de escape que tenemos disponibles para
utilizar con la funcin printf:

\r

Retorno de carro

\t

Tabulador
41

Programacin PIC en C

\'

Comilla simple

\"

Comillas dobles

\\

Barra invertida

\?

Smbolo de
interrogacin

\0

Caracter nulo

\%

Smbolo Tanto por


ciento

\b

Retroceder un caracter

Vamos con la segunda llamada a la funcin:

printf("El valor de la variable i1 es: %d",i1);

En este caso tampoco est definido el primer parmetro, por tanto, al igual que en la
primera llamada a la funcin, los datos se enviaran por el puerto serie al pin que
hayamos definido en la directiva #use RS232, en esta llamada vemos que tenemos la
cadena de caracteres limitada por las comillas dobles y separado por una coma, como
tercer parmetro el nombre de la variable i1 que habamos declarado previamente. En la
cadena de caracteres vemos que aparece el carcter de % seguido de la letra d, ese es un
carcter especial para la funcin y lo que le indica a la funcin es que en esa posicin
muestre el valor de la variable i1, la d le indica a la funcin que represente ese valor en
formato de nmero entero. Podemos representar el valor de la variable en diferentes
formatos segn se muestra en la tabla de abajo:

Caracter

Cadena caracter

Entero sin signo

Entero con signo

Lu Entero largo sin signo


Ld Entero largo con signo
x

Entero Hexadecimal (minsculas)

Entero Hexadecimal (maysculas)

Lx Entero largo Hexadecimal (minsculas)


LX Entero largo Hexadecimal (maysculas)
f

Nmero real en coma flotante con truncado


42

Programacin PIC en C

Nmero real en coma flotante con redondeo

Nmero real en formato exponencial

Entero sin signo con decimales insertados.


Especifica dos nmeros para n. La 1 cifra
indica el total y la 2 el nmero de decimales

Si quisisemos mostrar el valor de ms de una variable lo haramos de la siguiente


forma:

printf("El valor i1 es: %d el de i2: %d y el de i3: %d",i1,i2,i3);

Vamos con la ltima llamada a la funcin del 1 ejemplo:

printf (lcd_putc,"El valor de i1 es: %d",i1);

En esta llamada hemos incluido el primer parmetro y hemos puesto el nombre de la


funcin lcd_putc, est funcin est definida en la librera LCD.C que trae el compilador
para ayuda del manejo de los dispositivos LCD y que hemos incluido en nuestro
programa por medio de la directiva #include <lcd.c>, vemos que la librera est
encerrada entre los smbolos de <> esto le indica al compilador que busque la librera en
el directorio en que se instalo el compilador, si copiramos esa librera en otro directorio
tendramos que indicarle la ruta completa, pero esta vez encerrada entre comillas dobles.

Ejemplo:

#include C:\Ejemplos de C\lcd.c

Pues bien ahora la funcin printf no enviar los datos al puerto serie, sino a la funcin
lcd_puct que ser la encargada de envirselos al LCD, esta funcin por defecto enva
los datos al puerto D del PIC, pero accediendo a la librera se puede modificar el puerto
fcilmente.
43

Programacin PIC en C

Aqu tenis un video demostrativo del ejemplo:

Ver vdeo

2 Ejemplo

Salida del programa:

44

Programacin PIC en C

Comentario del programa:


El especificador de formato %x indica al sistema que escriba en hexadecimal
(base 16) el valor sustituido.
El ejemplo tambin escribe el carcter 'A', apoyndose en cuatro formas distintas
de representaciones inciales. En todos los casos se almacenar el mismo valor
numrico, pero son diferentes las representaciones usadas.
El carcter (A) sale en la terminal en una lnea diferente cada vez que se
imprime, eso es debido a la secuencia de escape (\r) utilizada.
Observar que el ejemplo se ha hecho sobre el PIC 16f84 que no dispone de una
USART hardware para la comunicacin serie , pero sin embargo el programa se
ha ejecutado correctamente, eso es debido a que la comunicacin serie se ha
establecido por software por medio de las libreras implementadas en el
compilador PCW.
Vamos a continuar con las funciones disponibles en CCS para la entrada y salida de
datos a travs del puerto serie RS-232. Hasta ahora solo hemos visto que con la funcin
printf(), podemos enviar datos formateados a travs del pin que hayamos seleccionado
en la directiva:
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_D1,RCV=PIN_D2)

En este caso los datos saldrn por el pin RD1 del PIC. Pero de que funciones
disponemos para recibir datos desde fuera hacia nuestro PIC?. El que haya programado
45

Programacin PIC en C

en C echar de menos la funcin scanf() definida en la librera stdio.h y perteneciente al


estndar ANSI C. Pero desgraciadamente esa funcin tampoco est disponible en CCS.
Pero tampoco hay por qu preocuparse mucho, porque disponemos de otras. En este
caso vamos a ver las funciones: getc(), getch() y getchar(). Las tres hacen lo mismo por
lo que podemos usarlas indistintamente.

Estas funciones esperan un carcter por la patilla del PIC que hayamos definido en la
directiva #use RS232 con el parmetro RCV. En el caso del ejemplo de arriba, los datos
sern recibidos por el pin RD2 del PIC.

Pues vamos a ver nuestro primer ejemplo acerca del uso de estas funciones:

Comentario:
El ejemplo lo que hace es mostrar el valor de la tecla que pulsemos en el teclado y su
equivalente en cdigo ASCII

Vamos a explicar su funcionamiento paso a paso:

Primeramente, como siempre, incluimos por medio de la directiva #include el


archivo de cabecera del PIC que vamos a utilizar, en este caso el PIC16F877.
46

Programacin PIC en C

Por medio de #use delay le decimos al compilador la frecuencia de reloj que


vamos a utilizar en nuestro circuito.
Configuramos los parmetro de la directiva #use RS232, fijaros que
XMIT=PIN_D0 y que RCV=PIN_D1. Con lo cual los datos saldrn del PIC por
el pin RD0 y entrarn por el pin RD1.
Dentro de la funcin principal main(), escribimos lo que queremos que haga
nuestro programa. Las instrucciones siempre empezarn a ejecutarse una a una a
partir de esta funcin y de arriba hacia abajo.
Lo primero que hacemos es declarar una variable de tipo char donde
almacenaremos el valor de la tecla que pulsemos en el teclado.
Despus se nos mostrar un mensaje en la terminal invitndonos a que
introduzcamos un carcter.
printf("Introduzca un caracter :\r");

Despus se ejecutar la sentencia:


ch=getch()

Que esperar hasta que pulsemos una tecla y almacenar su valor en la variable ch.
La siguiente instruccin:
printf("El caracter %c tiene un valor ASCII decimal de %d.\r",ch,ch);

muestra el valor del carcter y su equivalente en cdigo ASCII


Despus se repite el proceso dos veces ms, pero esta vez utilizando las
funciones getc() y getchar()
Al utilizar solo la variable ch, el valor de la nueva tecla pulsada sobrescribir el valor
anterior de la variable.

La salida de nuestro programa ser el siguiente:

47

Programacin PIC en C

Bien, hay que decir que el programa finalizar al llegar a la ltima sentencia incluida en
la funcin main(). Para que el programa termine cuando nosotros queramos tenemos
que incluir como mnimo un bucle y establecer una condicin para que podamos salir de
l, vamos a ver esto con otro ejemplo:

En este ejemplo se irn mostrando en la terminal las teclas que vayamos pulsando por el
teclado hasta que pulsemos la tecla n momento en el cual finalizar el programa.
48

Programacin PIC en C

Los cdigos fuentes de los ejemplos los tenis aqu.


Un par de funciones mas que se pueden utilizar en la entrada y salida
de datos serie RS232 son las funciones gets() y puts().

gets(string): esta funcin lee los caracteres que se introducen por


el teclado hasta que encuentra un retorno de carro (tecla Enter). El
pin asignado para la lectura de los caracteres es el que hayamos
configurado en RCV. En el ejemplo de abajo el pin RD5.

puts(string): esta funcin enva la cadena de texto contenida dentro


de los parntesis al pin que hayamos configurado en el parmetro
XMIT de la directiva #use RS232, en el ejemplo de abajo el pin RD4.
Una vez enviada la cadena aade un retorno de carro.

#use RS232(BAUD=9600, BITS=8, PARITY=N, XMIT=PIN_D4,


RCV=PIN_D5)

Vamos a ver un ejemplo sencillo que utilice estas dos funciones:

49

Programacin PIC en C

Comentario
En este ejemplo se ha declarado un tipo de dato que todava no
hemos visto, un array de caracteres:

char nombre[9];

Aunque veremos los tipos de datos compuestos ms adelante,


podemos adelantar que un array es un conjunto de variable del
mismo tipo de datos. Cada una de esas variables se coloca de forma
consecutiva en la memoria RAM del PIC y se les llama elementos del
array. Los elementos del array se enumeran empezando por el 0, (es
una caracterstica del lenguaje C). En el ejemplo de arriba se ha
declarado un array de caracteres (tipo char) y el nmero mximo de
elementos que podemos almacenar en el es de 9. Sus elementos
estarn numerados del 0 al 8. Y podemos acceder a ellos de la
siguiente forma:

valor = nombre[0];

50

Programacin PIC en C

.. = ..[.];

valor = nombre[8];

El ejemplo lo nico que hace es enviar un mensaje a la terminal


dicindonos que introduzcamos nuestro nombre (puede ser tambin
una password o lo que queramos). Cuando introduzcamos el nombre
y pulsemos la tecla Enter, la cadena de caracteres ser guardada en
el array que hemos declarado previamente y luego con la primera
funcin prinf() mostramos el valor de la cadena de texto guardada en
el array, con la segunda funcin prinf() mostramos el tercer carcter
del nombre introducido (nombre[2]). Este ser la salida de nuestro
programa:

Si intentamos introducir una cadena ms larga, el valor se mostrar


en la terminal pero truncado.

Por ejemplo si intentamos introducir la cadena:

51

Programacin PIC en C

Microcontroladores PIC

La terminal nos mostrar:

Microcont

Como he dicho antes los elementos del array se almacenan en


posiciones consecutivas de la memoria RAM del PIC. Esto lo gestiona
automticamente el compilador, lo mismo que cuando haces un
programa en C en otro lenguaje de alto nivel para un PC de
escritorio el programador no est preocupado de en qu posicin de
la memoria RAM se almacenarn las variables que declara. Pero si a
pesar de ello quieres saberlo haces lo siguiente:

Despus de compilar el ejemplo, te vas al men compile > Symbol


Map y nos aparecer la ventana de abajo:

Donde vemos las posiciones de memoria donde se han mapeado


nuestras variables. Como vemos nuestro array ha ocupado las
posiciones de memoria de la 0x21 a la 0x29 de los registros GPR del
PIC (en total 9 bytes), ya que los elementos que componen el Array
son de tipo char que son de un byte (8 bits) cada uno.
52

Programacin PIC en C

Si queremos ver los valores que va tomando cada uno de los


elementos del Array en tiempo de ejecucin. Lo podemos hacer por
medio de la ventana Watch Windows en Proteus. Si no te acuerdas de
cmo se hace mralo aqu

Y obtendremos lo siguiente:

Consideraciones:
En C existe el concepto de memoria dinmica. La memoria dinmica
es aquella que se puede reservar y liberar en tiempo de ejecucin, es
decir, durante la ejecucin del programa se liberar y se asignar
memoria para optimizar los recursos de la CPU, para ello se dispone
de funciones como malloc() y free(). El compilador CCS tambin
admite este tipo de funciones, para utilizarlas debemos de incluir el
archivo de cabecera stdlibm.h, ya veremos un ejemplo sobre la
asignacin de memoria dinmica, si no utilizamos estas funciones la
reserva de memoria es esttica, es decir, si declaramos un array de
nueve elementos el compilador le reservar memoria contigua a
dicho array al compilar el programa en los registros de propsito
general (GPR). Esa memoria se reserva cuando el PIC empieza a
ejecutar su programa y permanece reservada hasta que
desconectamos el PIC. Con todo esto quiero decir que tenemos que
tener siempre claro de la memoria RAM de que disponemos, segn el
modelo de microcontrolador que utilicemos en nuestro proyecto, si no
lo sabes consulta el data sheet del PIC que ests utilizando. Por
ejemplo si en el PIC del ejemplo que hemos hecho (16f877) en vez
53

Programacin PIC en C

de un array de 9 elementos declaramos uno de 100 elementos el


compilador nos mostrar el siguiente error al compilar:

Y como ya he dicho en alguna ocasin, utiliza el tipo de datos ms pequeo posible, en


el ejemplo que he puesto he declarado un array de nueve elementos, para introducir el
nombre Antonio que tiene seis caracteres, con lo cual estoy desperdiciando dos bytes
de memoria RAM, eso en un ordenador de escritorio es insignificante pero en un
microcontrolador si que es importante y puede que nos quedemos sin memoria
suficiente para declarar todas las variables de nuestro programa.

El cdigo del ejemplo lo tenis aqu

Aunque existen algunas funciones ms para la entrada y salida de datos serie, las que
llevamos vistas hasta ahora son las ms importantes, as que el prximo da
empezaremos con los operadores, indispensables para hacer operaciones con los datos
que introduzcamos en nuestro programa.
l lenguaje C dispone de una gran cantidad de operadores que nos
sirven para operar con los datos dentro de nuestros programas, se
pueden clasificar en varios apartados: aritmticos, relacionales, de
asignacin, de manejo de un solo bit, etc. Pero lo importante no es
saber a qu grupo pertenece cada operador, sino en conocer la
operacin que se puede realizar con cada uno de ellos. Vamos a ver
los operadores que nos permite utilizar nuestro compilador CCS.

Operadores Aritmticos: permiten la realizacin de


operaciones matemticas en nuestros programas.
54

Programacin PIC en C

Operador

Descripcin

Suma

Resta

Multiplicacin

Divisin

Mdulo (Resto de una divisin entera)

++

Incrementa en uno el valor del operando

--

Decrementa en uno el valor del


operando

Operadores relacionales: compara dos operandos y devuelve


1 (verdadero) 0 (falso) segn el resultado de la expresin. Se
utilizan principalmente para elaborar condiciones en las
sentencias condicionales e iterativas que se vern ms
adelante.

Operador

Descripcin

<

Menor que

>

Mayor que

<=

Menor o igual que

>=

Mayor o igual que

==

Igual a

Distinto de

Operadores de asignacin: permiten asignar valores a las


variables. Tenemos las siguientes.

Operador
Descripcin
+=
Asignacin de suma. x+=y es lo mismo que x=x+y
-=

Asignacin de resta. x-=y es lo mismo que x=x-y

*=

Asignacin de multiplicacin. x*=y es lo mismo que x=x*y

/=

Asignacin de divisin. x/=y es lo mismo que x=x/y

55

Programacin PIC en C

%=

Asignacin de resto de divisin. x%=y es lo mismo que x=x%y

<<=

Asignacin de desplazamiento a la izquierda. x<<=y es lo mismo que


x=x<<y

>>=

Asignacin de desplazamiento a la derecha. x>>=y es lo mismo que


x=x>>y

&=

Asignacin de AND de bits. x&=y es lo mismo que x=x&y

|=

Asignacin de OR de bits. x|=y es lo mismo que x=x|y

^=

Asignacin de OR exclusivo de bits (XOR). x^=y es lo mismo que x=x^y

Operadores Lgicos: Al igual que los operadores relacionales,


stos devuelven 1 (verdadero), 0 (falso) tras la evaluacin de
sus operandos. La tabla siguiente ilustra estos operadores.

Operador
!

Descripcin
NO lgico

&&

Y lgico

||

O lgico

Operadores de manejo de bits: Estos operadores permiten


actuar sobre los operandos para modificar un solo bit, los
operandos slo pueden ser de tipo entero (incluyendo el tipo
char).

Operador

Descripcin

Negacin de bits (complemento a


1)

&

Y de bits (AND)

O de bits (OR)

O exclusivo de bits (XOR)

>>

Desplazamiento a la derecha

<<

Desplazamiento a la izquierda

56

Programacin PIC en C

Operadores para manejar punteros: En el lenguaje C est


muy difundido el uso de punteros, este compilador permite su
uso y los operadores que utiliza para ello son los siguientes:

Operador
&
Operador de direccin

Descripcin

Operador de indereccin

->

Acceder a los miembros de una estructura por medio de punteros

Los que se inician en el mundo de la programacin suelen encontrar


complicado el emplear punteros en sus programas pero, una vez que
se entiende el concepto se simplifica y optimiza mucho nuestro
cdigo. Ya dijimos que el PIC dispone de unos registros de propsito
general (GPR) que el programador utiliza para almacenar all sus
variables y poder utilizarlas a lo largo del programa, pues bien un
puntero es otra variable a la cual se le asigna la direccin del registro
memoria de otra variable.

La forma de utilizar los punteros lo veremos en profundidad ms


adelante, pero aqu tienes un pequeo ejemplo de cmo utilizarlos.

Ejemplo:

int y,z; //declaracin de las variables x e y de tipo entero:


int *x; //declaracin de la variable puntero x que guardar la
direccin de memoria de una variable de tipo entero.
x=&y; // a travs del operador de direccin (&) le asigno al puntero x
la direccin de memoria donde est guardada la variable y.
z=*x; //a travs del operador de indereccin (*) le asignamos a z el
valor de la variable cuya direccin est almacenada en la variable
puntero x.

57

Programacin PIC en C

Nota: como vemos los smbolos de direccin (&) e indereccin (*)


son los mismos que el AND en el manejo de bits (&) y el operador
aritmtico de multiplicacin, el compilador los diferencia segn los
operandos que le preceden.

Precedencia de los operadores:

Expresiones en orden descendente de precedencia


(expr)
!expr

~expr

++expr

expr++

--expr

(type)expr

*expr

&value

sizeof(type)

expr*expr

expr/expr

expr%expr

expr+expr

expr-expr

expr<<expr

expr>>expr

expr<expr

expr<=expr

expr --

expr>expr expr>=expr

expr = = expr expr!=expr


expr&expr
expr^expr
expr | expr
expr&& expr
expr || expr
expr ? expr: expr
value = expr

value+=expr value-=expr

value*=expr

value/=expr

value%=expr

value>>=expr value<<=expr value&=expr


value^=expr

value|=expr

expr,expr

Las operaciones con mayor precedencia se realizan antes que las de


menor precedencia.
Si en una operacin encontramos signos del mismo nivel de
precedencia, dicha operacin se realiza de izquierda a derecha.
Ejemplo:
a*b+c/d-e
Las operaciones se realizarn en el siguiente orden:
58

Programacin PIC en C

1.
2.
3.
4.

a*b resultado = x
c/d resultado = y
x+y resultado = z
z-e

Nota: Es aconsejable el uso de parntesis para evitar errores en la


precedencia de operadores, adems el cdigo fuente queda ms
legible.
Ejemplo:
a*(b+c)+d
En este caso el orden en realizarse las operaciones ser el siguiente:
1. b+c resultado = x
2. a*x resultado = y
3. y+d
sizeof(type)--> nos da el tamao en bytes del tipo de dato variable
que le pongamos entre los parntesis.
Para conocer bien los resultados que se obtienen al utilizar cada uno
de los operadores, lo mejor es practicar con ellos. Vamos a ver un
ejemplo donde se muestra el uso de algunos de ellos:

59

Programacin PIC en C

Comentario del programa:


En este ejemplo introducimos unos valores por el teclado del
ordenador y se los enviamos al pic via serie por el dispositivo RS-232,
luego realizaremos diferentes operaciones con ellos y mostraremos el
resultado en la Terminal, pero hay que tener en cuenta que que esos
valores que introducimos por el teclado son caracteres y por tanto no
se los podemos asignar directamente a una variable de tipo entero
para operar con ellos, primero tenemos que convertirlos. CSS nos
proporciona las siguientes funciones para ello:

60

Programacin PIC en C

- atoi(cadena) --> devuelve un valor entero de 8 bits de tamao.


- atol(cadena) --> devuelve un valor entero de 16 bits
- atoi32(cadena) --> devuelve un valor entero de 32 bits

Para saber el rango de valores admisible por cada funcin repasa los
tipos de datos

Estas funciones estn definidas en el fichero de cabecera stdlib.h, por


tanto no hay que olvidarse de incluirlo previamente por medio de la
directiva: #include <stdlib.h>.

Fijaros en la instruccin de la lnea 31 que nos da el tamao de la


variable y:

printf("El tama\xa4o de y es: %d bytes\r",sizeof(y));

\xa4 --> es la secuencia de escape para representar la letra . Esto


es porque el compilador no reconoce los caracteres en castellano.

Tabla equivalente de caracteres en castellano:

\xa0

\x82

\xa1

\xa2

\xa3

\xb5
\x90

\xd6
61

Programacin PIC en C

\xe0
\xe9

\xa4

\xa5

\xa8

La salida del programa para los valores de x=50 e y=6 es la


siguiente:

El cdigo fuente y el DSN de proteus lo tenis aqui.

Una precaucin que tenemos que tener en cuenta es que si utilizamos


valores numricos grandes y un PIC con poca memoria RAM, pronto
la agotaremos. Esto solo es un ejemplo terico del uso de operadores
aritmticos, aplicaciones prcticas puede tener muchas, depende de
lo que quieras hacer.

Un ejemplo sencillo pero prctico, lo tienes aqu.


SENTENCIAS REPETITIVAS:

62

Programacin PIC en C

Son aquellas que ejecutan un bloque de sentencias mientras se


cumpla una expresin lgica. Este bloque de sentencias que se
ejecuta repetidas veces, se denomina bucle, y cada ejecucin se
denomina iteracin.

De las diferentes sentencias repetitivas que hay vamos a empezar


con while.

La sentencia while permite la ejecucin de un bloque de sentencias si


se evala como verdadera una expresin lgica. La expresin lgica
aparece al principio del bloque de sentencias.
En la figura de abajo se muestra el Pseudocdigo, el diagrama de
flujo y la sintaxis de la sentencia while.

63

Programacin PIC en C

El Pseudocdigo es una forma informal de representar la secuencia


del programa, sin tener en cuenta la sintaxis particular del lenguaje
en que vayamos a programar y el diagrama de flujo es una
representacin grfica del Pseudocdigo.

Cuando vayamos a crear un programa el dibujar previamente un


diagrama de flujo el Pseudocdigo de la secuencia de nuestro
programa puede ayudarnos en la tarea de programacin, pero en
ningn caso es un paso obligatorio.

El bloque delimitado por las llaves puede reducirse a una sentencia, y


en este caso se suprimen las llaves.

La expresin lgica debe estar delimitada por parntesis.

Cuando el programa llega a una sentencia while, sigue los siguientes


pasos.
Evala la expresin.
Si es falsa, continua la ejecucin tras el bloque de sentencias.
Si es verdadera entra en el bloque de sentencias asociado al
while.
Ejecuta dicho bloque de sentencias, evaluando de nuevo la
expresin y actuando en consecuencia.
Si la primera evaluacin resulta falsa, el bloque de sentencias no se
ejecuta nunca.

Si la expresin es siempre cierta el bucle es infinito.

Vamos con el primer ejemplo:

64

Programacin PIC en C

Comentario
El ejemplo lo que hace es mostrar en la terminal la tabla de
multiplicar del nmero cuatro, utilizando un bucle while. Para ello
necesitamos declarar una variable auxiliar de tipo entero llamada i1,
inicializada con el valor de 1, en cada iteracin se comprueba el valor
de la variable auxiliar, mientras el valor de i1 sea <=10 la evaluacin
ser verdadera y se ejecutarn las instrucciones que hay dentro del
bloque while, dentro de ese bloque tenemos que incrementar el valor
de i1, de esta manera nos aseguramos en algn momento la salida
del bucle, cuando i1 llegue a 11 la condicin ser falsa y la secuencia
del programa saltar a la lnea 19 finalizando el programa.

La salida del programa ser el siguiente:

65

Programacin PIC en C

Si queremos que el programa este siempre ejecutndose (lo normal


en un programa para Microcontroladores), hay que colocar un bucle
infinito, mira el siguiente ejemplo:

66

Programacin PIC en C

Comentario
true es una constante booleana que equivale a 1 verdadero. Por tanto la evaluacin del
bucle siempre ser cierta y no habr manera del salir de l. El programa estar siempre
esperando a que pulses una tecla y mostrar el valor de la tecla pulsada en la terminal.
Bucle for()
En el ejemplo de la tabla de multiplicar utilizamos el bucle while para
obtener los diez valores de la tabla, y si recordis necesitbamos una
variable de control que tenamos que inicializar antes de entrar en el
bucle, comprobar el valor de la variable para la continuacin en el
bucle y la modificacin posterior de la variable de control para poder
salir del bucle en un momento determinado.

Pues bien, casi siempre que se hace algo, C proporciona


frecuentemente un modo ms compacto de hacer lo mismo.

El bucle for permite indicar estos tres elementos en un solo lugar, al


principio del bucle, facilitando as la obtencin de un cdigo
compacto, pero legible. Veamos cual es su sintaxis:

67

Programacin PIC en C

En un bucle for, el parntesis que acompaa a la palabra reservada


for generalmente contiene tres expresiones: Expresin 1; inicializa
la variable variables de control del bucle. Expresin 2; representa
la condicin de continuacin en el bucle. Expresin 3; modifica el
valor de las variables de control en cada iteracin del bucle.
Los puntos y comas que separan cada expresin son obligatorios.

Vamos a ver un ejemplo donde se muestran las diferentes


posibilidades de que disponemos cuando utilicemos el bucle for:

68

Programacin PIC en C

Comentario
1 bucle for:

indice=1, inicializa a la variable de control del bucle. La segunda


expresin, indice<=VAL_MAX, representa la condicin de
continuacin. Por ltimo, la tercera expresin, indice++, utiliza el
operador de incremento para modificar a la variable de control en
cada iteracin del bucle.
69

Programacin PIC en C

Los pasos que sigue la sentencia for son los siguientes:

1. indice es la variable de control. Se inicializa a 1


2. se testea la condicin de expresin_2.
3. se ejecutan las sentencias
4. la variable de control indice se incrementa en uno
5. si se cumple que indice<=VAL_MAX va al paso 3. Si no va al paso
6.
6. Finalizar la ejecucin cuando indice=20

2 bucle for

Bucle for con varias variables de control, las variables tienen que ir
separadas por comas. En este caso tenemos las variables x e y,
aunque podemos poner todas las que queramos, ambas variables son
inicializadas dentro de la sentencia for.

3 bucle for

Cuando el bucle for se escribe sin cuerpo sirve por ejemplo para
generar retardos, esta posibilidad la utilizaremos poco con este
compilador ya que incluye funciones especficas de retardo.

4 bucle for

El bucle for permite no incluir las expresiones 1 y 3, aunque los


puntos y comas son obligatorios ponerlos. En este caso se asemeja
mucho a un bucle while.

70

Programacin PIC en C

5 bucle for

Se puede crear un bucle infinito por medio de la expresin for(;;).


Podemos salir de un bucle infinito por medio de la sentencia break,
cuando se encuentra en cualquier lugar dentro del cuerpo de un bucle
da lugar a la terminacin inmediata de este, en el caso del ejemplo
saldremos del bucle cuando pulsemos la letra v. Las sentencias de
salto las veremos ms adelante.

La salida del programa ser la siguiente:

El cdigo fuente lo tenis aqu.

Como veis el lenguaje C posee mucha flexibilidad y se puede hacer


una misma cosa de varias formas. Segn el caso ser ms cmodo y
legible utilizar una sentencia que otra.

71

Programacin PIC en C

Como ejercicio podis hacer la tabla de multiplicar de un nmero


utilizando el bucle for.
Bucle do-while()
A diferencia de los bucles for y while, que analizan la condicin del
bucle al principio del mismo, el bucle do-while analiza la condicin al
final del bucle. Esto significa que el bucle do-while siempre se ejecuta
al menos una vez. La forma general del bucle do-while es la que se
muestra en la figura de abajo:

Vamos a ver un ejemplo:

72

Programacin PIC en C

Comentario
Este ejemplo pide un valor entre 1 y 10, ejecutndose repetidas
veces hasta que se introduce un valor entre ambos lmites. Por ltimo
el programa visualiza el valor ledo.

Este bucle se ejecutar como mnimo una vez porque el programa no


sabe cul es la condicin de continuacin hasta que se encuentra el
while del final del cuerpo del bucle. Si la condicin sigue siendo cierta
(es decir, si el valor ledo est fuera del intervalo deseado), el
programa regresa al principio del bucle do-while y lo ejecuta de
nuevo.

Fijaros en la orden if que aparece dentro del cuerpo del bucle. Esto
se permite porque las estructuras de control se pueden anidar unas
dentro de otras.

73

Programacin PIC en C

RECUERDA: En el bucle while la comprobacin de la condicin de


control del bucle se encuentra al principio, por lo que dicho bucle
puede no ejecutarse nunca; la comprobacin en el bucle do-while
est al final del bucle, por lo que al menos se ejecutar una vez.

El cdigo fuente lo tenis aqu.


If
Vamos a empezar las sentencias condicionales, con la ms simple de
todas, la sentencia if. Si se evala como cierta la expresin que hay
entre parntesis al principio de la sentencia if se ejecuta el bloque de
sentencias contenido entre las llaves y si se evala como falsa la
condicin, el programa se salta ese bloque de instrucciones. En la
figura de abajo tenis la sintaxis de esta sentencia.

74

Programacin PIC en C

Si slo hay una sentencia se pueden suprimir las llaves, ejemplo:

if (x=1)
printf(Sin llaves solo una sentencia asociada al if);

Como ejemplo de sentencias if tenis el decodificador de binario a


decimal.
Sentencia IfElse
Cuando el programa llega a una sentencia condicional del tipo If
Else, primero se evala una expresin; si se cumple (es cierta) se
ejecuta un bloque de sentencias y si es falsa se ejecuta otro bloque.

En la figura de abajo se muestra la sintaxis de esta sentencia


condicional.

75

Programacin PIC en C

Ejemplo:

Comentario
Este ejemplo visualiza en el display de ctodo comn, conectado a la
puerta B del PIC, el 0 si el interruptor conectado a RA0 est abierto
y 1 si est cerrado, para ello utiliza la sentencia if-else, dentro de
un bucle infinito para que el programa est siempre chequeando el
estado de la patilla RA0.

En este ejemplo hemos incluido una directiva nueva #use


fast_io(puerto). Esta directiva se utiliza para optimizar el cdigo
generado por el compilador cuando se utilizan funciones de manejo
de entrada y salida como input(pin) definidas ya en CCS.

76

Programacin PIC en C

Si no se incluye esta directiva el compilador tomar por defecto la


directiva #use standard_io(A), que har que cada vez que se
utilicen estas funciones se reprograme el pin correspondiente como
entrada salida, lo que har que el cdigo ASM generado tras la
compilacin sea mayor.

Podemos comprobar esto si despus de compilar nuestro ejemplo,


dentro del IDE de CCS seleccionamos Compile--> C/ASM List

Como se ve en la figura la memoria de programa (ROM) ocupa 21


palabras.

Ahora se pueden hacer las siguientes pruebas, la primera poner la


directiva #use standard_io(A), y la segunda simplemente quitar la
directiva #use fast_io(A) y no poner nada, segn se muestra en la
figura de abajo:

77

Programacin PIC en C

Volvemos a compilar y en ambos casos obtendremos lo siguiente:

78

Programacin PIC en C

En ambos casos la memoria ROM utilizada es de 24 palabras, tres


ms que cuando utilizbamos la directiva #use fast_io(A).

Otras funciones para el manejo de bits de los puertos de entrada y


salida que vienen definidas en CCS y que dependen de la directiva
#use*_io() son:

output_bit(Nombre_pin,valor) --> coloca el pin indicado a 0


1.
output_high(Nombre_pin) --> coloca el pin indicado a 1.
output_low(Nombre_pin) --> coloca el pin indicado a 0

Fijaros que no he utilizado la directiva #use fast_io(B) para el


puerto B, ya que no se utilizan funciones del compilador para el
manejo de los bits de salida. En este caso el puerto B del PIC se
controla mapeando la direccin de memoria del puerto B como una
variable ms en la RAM del PIC, por medio del identificador port_b.

79

Programacin PIC en C

Circuito del ejemplo:

El cdigo del ejemplo y el circuito en Proteus lo tenis aqu


Sentencia switch
La sentencia switch se compone de las siguientes palabras clave:
switch, case, default y break.

Lo que hace est sentencia es comparar sucesivamente el valor de


una expresin (dicha expresin tan solo puede ser de tipo entero o de
tipo carcter) con una lista de constantes enteras o de caracteres.
Cuando la expresin coincide con la constante, ejecuta las sentencias
asociadas a sta.

La estructura de la sentencia switch es la siguiente:

80

Programacin PIC en C

La sentencia break hace que el programa salte a la lnea de cdigo


siguiente a la sentencia switch. Si se omite se ejecutar el resto de
casos case hasta encontrar el prximo break.

La sentencia default se ejecuta cuando no ha habido ninguna


coincidencia. La parte default es opcional y, si no aparece, no se lleva
a cabo ninguna accin al fallar todas las pruebas y el programa
seguir a partir de la llave que cierra la sentencia switch

Consideraciones a la hora de usar esta sentencia:


81

Programacin PIC en C

En una sentencia switch No puede haber dos sentencias case


con el mismo valor de constante.
Una constante char se convierte automticamente a sus valores
enteros.
Switch difiere del if en que switch solo puede comprobar la
igualdad mientras que if puede evaluar expresiones relacionales
o lgicas. Adems cuando la comparacin se basa en variables
o se trabaja con expresiones que devuelven float deberemos
usar el if-else.
Hay que decir que la secuencia de sentencias en un case no es
un bloque (no tiene porque ir entre llaves). Por lo tanto no
podramos definir una variable local en l. Mientras que la
estructura swith global s que es un bloque.

Vamos a ver un ejemplo para ver todo esto:

82

Programacin PIC en C

Comentario

En el ejemplo introducimos un carcter numrico, lo almacenamos en


el array llamado cadena1 y por medio de la funcin atoi() lo
convertimos a un valor entero y guardamos su valor en la variable de
tipo entero num, no hay que olvidarse de incluir el archivo de
cabecera stdlib.h necesaria para la funcin atoi().

Ahora introducimos valores para ver que obtenemos a la salida.


Si introducimos un 1, coincidir con el valor de la constante
asignada al primer case, por lo cual se ejecutan las dos primeras
sentencias y el programa para de ejecutar sentencias porque se ha
encontrado con un break, despus ejecuta el ltimo printf() por estar
esta sentencia fuera de las llaves que delimitan a switch.

83

Programacin PIC en C

Fijaros en el segundo case, he omitido su break correspondiente a


posta (el compilador no da error si se quita), para que veis el
resultado cuando se introduce un 2:

Como veis en la figura de arriba se ejecutan las sentencias


pertenecientes al segundo case, pero al no encontrar la sentencia
break, ejecuta tambin la sentencia del tercer case. Esto hay que
tenerlo en cuenta para tener claro que lo que hace salir de la
sentencia switch es el break correspondiente a cada case.
Si introducimos por ejemplo un 9 al no a ver coincidencia con el
valor de ningn case, se ejecutar la sentencia perteneciente a
default.

El cdigo fuente del ejemplo lo tenis aqu.

Un ejemplo un poco ms prctico del uso de esta sentencia, lo tenis


aqu, gracias a QuijotescoXp, que ha hecho una mejora en el
decodificador binario a decimal que en su da inclu en la seccin de
prcticas, os animo a que participes en el foro aportando mejoras
ejemplos nuevos, de esta forma ayudas a que el curso vaya para
adelante, si es que realmente os interesa.

84

Programacin PIC en C

www.aquihayapuntes.com

Tutorial creado por Biblioman. Versin 1.00


http://www.aquihayapuntes.com/programacion-pic-en-c.html
Portado a PDF por Meta.
http://electronica-pic.blogspot.com
Cualquier sugerencia, duda o cualquier comentario, puedes realizarla en el
foro aqu: http://www.aquihayapuntes.com/foro
Puede haber futuras actualizaciones, mejoras y contenidos.

85

También podría gustarte