Sei sulla pagina 1di 6

Aprendiendo a programar Microcontroladores PIC en Lenguaje C con CCS

Los compiladores de lenguaje C hoy son ampliamente utilizados para la creacin de programas con microcontroladores PIC. El compilador que mejor soluciona las necesidades del programador enmascarando el hardware y simplificando la implementacin de una aplicacin es el fabricado por la compaa CCS. Por Andrs Ral Bruno Saravia

Entrega N 2.
En nuestra entrega anterior aprendimos a crear un proyecto dentro del MPLAB para escribir nuestro primer cdigo en lenguaje C, hoy crearemos nuestro primer cdigo y aprenderemos la funcin que cumplen sus elementos principales .

Creando Nuestro Primer Cdigo


Ya que hemos aprendido a crear nuestro primer proyecto, escribiremos nuestro primer cdigo, el cual adicionaremos a nuestro proyecto. Para ello nos moveremos con el Mouse hasta el cono de New File y haremos clic sobre el mismo:

Y se desplegar una nueva ventana en la cual escribiremos el cdigo de nuestro programa. Por ser este nuestro primer programa, simplemente haremos titilar un LED con un tiempo de flashing de 500ms. La idea es introducirnos de a poco, y muchas veces querer comenzar con un cdigo demasiado elaborado es complejo.
#include<16f887.h> #use delay(osc=4000000) //configura fusibles de configuracin #fuses XT //Oscilador a cristal standar #fuses NOWDT //sin WatchDog Timer #fuses NOPROTECT //sin proteccion de memoria de programa #fuses NOPUT //sin PowerUp Timer #fuses NOBROWNOUT //sin brownout #fuses NOLVP //sin programacin en baja tensin //rutina principal void main(void) { //abrimos la funcin principal Setup_adc_ports(NO_ANALOGS);//configuramos los puertos digitales while(1) //creamos un bucle infinito { //abrimos el bucle output_high(PIN_B0); //prendemos RB0 delay_ms(500); //esperamos 500 ms output_low(PIN_B0); //borramos RB0 delay_ms(500); //esperamos 500 ms } //cerramos el bucle //cerramos la funcin principal

Este cdigo lo hemos escrito en lo que se conoce en la jerga tcnica como codigo en C nativo ya que usamos las funciones de control de entrada / salida de CCS El cdigo inicia siempre en lo que se conoce como cabecera, es decir el principio. En esta cabecera encontraremos instrucciones dirigidas al compilador y no al microcontrolador, dichas instrucciones se denominan directivas. Las directivas se diferencian de las instrucciones en que: Siempre se encuentran en la cabecera del programa Todas comienzan con el smbolo del numeral #

En nuestro caso estas son las directivas:


#include<16f887.h> #use delay(crystal=4000000) //configura fusibles de configuracin #fuses XT //Oscilador a cristal standar #fuses NOWDT //sin WatchDog Timer #fuses NOPROTECT //sin proteccion de memoria de programa #fuses NOPUT //sin PowerUp Timer #fuses NOBROWNOUT //sin brownout #fuses NOLVP //sin programacin en baja tensin

La directiva : #include<16f887.h> nos permite decirle al compilador para que microcontrolador hemos escrito el cdigo.

Seguidamente con la directiva #use delay(crystal=4000000) le indicamos a que frecuencia esta funcionando nuestro oscilador. El orden de las directivas es crucial ya que siempre primero debemos indicarle al compilador cual es el PIC que estamos usando y luego cual es la frecuencia del oscilador. Posteriormente podemos agregar el resto de directivas. Si esto no se respeta podemos tener errores en el proceso de compilacin sobre todo cuando usamos alguna funcin propia del compilador (llamadas funciones embebidas) para manejar algn perifrico, y que la misma necesita saber la frecuencia del oscilador. La directiva puede tener distintas formas ya que amolda la configuracin interna a la frecuencia que le indicamos. As esta directiva nos permite activar multiplicadores y divisores internos, o accionar los osciladores internos cuando el microcontrolador los trae; por ejemplo:
#use delay(crystal=4000000, clock=16000000)

Le indica al compilador que tenemos un cristal externo de 4Mhz, y que la frecuencia que llega a la CPU es de 16Mhz, por lo tanto el compilador configurar correctamente el PLL de la CPU para alcanzar los 32Mhz. Otro ejemplo pero usando el reloj interno es el siguiente:
#use delay(internal=8000000, clock=16000000)

Sin embargo esta directiva debe usarse con precaucin ya que el clock que definimos nunca debe sobrepasar la mxima velocidad de procesamiento del PIC que se est usando. Este parmetro se denomina MIPS (Millones de Instrucciones por Segundo) y se obtiene dividiendo la frecuencia de entrada por cuatro.
MIPS = fosc/4

La directiva #fuse xx nos permite activar o desactivar las caractersticas del nucleo, como ser el circuito de Watch Dog Timer, que reseta al microcontrolador ante un cuelgue del mismo, el Brown Out Detect, que resetea el microcontrolador ante un fallo de la alimentacin, el tipo de oscilador, etc. Las etiquetas usadas para activar o desactivar la propiedad, estn incluidas en el archivo de cabecera y deben ser consultadas siempre, ya que las mismas suelen cambiar entre versiones del compilador o tipos de microcontroladores. En lneas generales podemos decir que anteponiendo la palabra NO al fusible de configuracin (as se llama al seteo de las propiedades), se le informa al compilador que el fusible en cuestin est desactivado, mientras que colocando solo el nombre activamos la propiedad. Por otra parte para activar o desactivar los distintos fusibles se puede realizar en varias lneas (como en el ejemplo) o se pueden activar y desactivar en una sola lnea separando cada fusible con comas:
#fuse NOWDT,HS,NOPUT,NOLVP,NOMCLR,NOPROTECT,NOBROWNOUT

La cabecera adems puede incorporar redefinicin de nombres de pines, definicin de variables y constantes. Y prototipo de funciones. Esto ser visto en nuestras prximas lecciones.

Finalizada la cabecera, contina el cdigo, que es el que se traducir en instrucciones al microcontrolador luego del proceso de compilacin. En nuestro caso nuestro cdigo es bastante sencillo:
void main(void) { //abrimos la funcin principal setup_adc_ports(NO_ANALOGS);//configuramos los puertos digitales while(1) //creamos un bucle infinito { //abrimos el bucle output_high(PIN_B0); //prendemos RB0 delay_ms(500); //esperamos 500 ms output_low(PIN_B0); //borramos RB0 delay_ms(500); //esperamos 500 ms } //cerramos el bucle //cerramos la funcin principal

Todo programa siempre inicia en una rutina principal. En el lenguaje C las rutinas se denominan funciones. Las funciones son un conjunto de sentencias u ordenes que realizan una operacin determinada, como lo hacen las rutinas, sin embargo las funciones tiene una caracterstica extra; a ellas se les puede pasar valores de variables para que las procesen, y son capaces de devolvernos los resultados de dichos procesos. Bsicamente actan como las funciones matemticas. Todo programa C siempre inicia en la funcin principal, la cual se denomina main. Dicho nombre no puede ser distinto, todo programa debe tener una funcin main, de lo contrario el compilador nos indicar un error. La funcin encierra una serie de sentencias, las cuales forman el bloque de dicha funcin. Dicho bloque inicia con una llave { y finaliza con otra llave } . Entre estas dos llaves se encuentran las sentencias y las estructuras lgicas. La funcin main es una funcin especial ya que no puede recibir ningn valor, ni tampoco puede devolver uno. Por lo tanto observe que va acompaada por dos palabras void lo cual en el lenguaje C significa vaco; es decir que no devuelve ningn valor (primer void) ni puede recibir ningn valor, (segundo void, el cual esta encerrado entre parntesis).
void main(void) { Nuestro cdigo }

Nuestro cdigo lo hemos escrito en formato CCS nativo. Esto significa que hemos usado todas las funciones embebidas (incluidas dentro) del compilador para simplificar la escritura del cdigo y que nos ahorran mucho tiempo. Debe observarse que cada lnea la hemos decalado (separado del origen) por medio del TABULADOR; esto es una buena prctica para poder advertir a simple vista cuales sentencias son las que estas anidadas dentro de cada bloque del programa principal. La primera lnea o sentencia le indica al compilador que debe desactivar todos los puertos analgicos del PIC y que debe configurarlos como puertos digitales:
setup_adc_ports(NO_ANALOGS);

Usamos la funcin embebida setup_adc_ports, la cual esta embebida en el compilador, y que se encarga bsicamente de setear que puertos van a trabajar como analgicos y que puertos van a trabajar como digitales. La funcin configura los bits PCFG o ANSEL dependiendo con que PIC estemos trabajando y lo realiza de forma automtica. Observe que hemos escrito entre parntesis NO_ANALOGS lo cual le dice al compilador que no hay puertos analgicos. Esta etiqueta la obtenemos del archivo de cabecera del procesador (16f887.h). Es importante resaltar que las etiquetas siempre van en mayusculas, mientras que las instrucciones se escriben en minscula. Es muy importante que se respete el orden mayscula-minscula pues el compilador es sensible a ello. Si escribimos una instruccin con mayscula, NO LA IDENTIFICAR. Debe observarse tambin que las sentencias siempre terminan con un punto y coma. La siguiente sentencia de nuestro cdigo es una instruccin estructural: while El while es una instruccin condicional la cual determina la ejecucin de una o mas instrucciones en tanto y en cuanto se cumpla una condicin, la cual se encierra entre parntesis. En programacin, si una condicin se cumple, se dice que es verdadera, y esto se simboliza con el nmero 1; por el contrario, si la condicin no se cumple, es falsa y se simboliza con el nmero 0. En un while, lo que este dentro del bloque del mismo, se ejecutar, siempre que la condicin de verdadera, caso contrario no se ejecutar ninguna sentencia que se encuentre dentro del while. En nuestro caso hemos forzado la condicin 1, con lo cual el while se ejecutar eternamente. Es decir que las sentencias encerradas dentro del bloque while (limitado por las llaves{}), se ejecutaran por siempre. Observe que dentro del while usamos tambin funciones embebidas:
output_high(PIN_B0); output_low(PIN_B0);

Estas son funciones de salida de datos, se encargan de poner en uno o en cero un puerto, el cual la misma funcin se encarga de configurar como salida, no debe hacerlo el programador. Entre parntesis le indicamos el PIN a encender o apagar. En nuestro caso es el RB0, al cual CCS lo denomina dentro del archivo de cabecera del microcontrolador como PIN_B0. Este formato si bien parece en principio raro porque no se adapta al usado en el data sheet, es prctico para los programadores NO ELECTRNICOS, y es el que ha adoptado CCS. Por ejemplo el RA0 CCS lo llama PIN_A0, y al RC6, PIN_C6, y as sucesivamente. Otra de las sentencias usadas es
delay_ms(500);

La cual es una funcin de tiempo que nos permite crear un tiempo de espera en milisegundos. Tambin existe el delay_us que nos permite crear un delay de microsegundos. La exactitud de la funcin delay depende de que hayamos definido correctamente la frecuencia de clock. De esta forma hemos hecho falshear un LED en nuestro primer cdigo. Bueno, esto es todo por ahora , en las prximas entregas iremos descubriendo paso a paso las utilidades de la programacin en lenguaje C y del entorno CCS. Continuar ......