Aprendiendo Aprogramar PIC Con CCS

download Aprendiendo Aprogramar PIC Con CCS

of 58

Transcript of Aprendiendo Aprogramar PIC Con CCS

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    1/58

    Aprendiendo a programar

    Microcontroladores PIC en

    Lenguaje C con CCS

    Los compiladores de lenguaje C hoy son ampliamenteutilizados para la creacin de programas paramicrocontroladores PIC. El compilador que mejor soluciona lasnecesidades del programador enmascarando el hardware ysimplificando la implementacin de una aplicacin es el

    fabricado por la compaa CCS.Hasta hace unos 5 aos los programas se seguan escribiendo en lenguaje Assembler,

    pero gracias a que los compiladores de lenguaje C se mejoraron, en cuanto a su relacinde compresin, y los microcontroladores ampliaron su capacidad de memoria, hoy enda prcticamente el 99% de las aplicaciones para microcontroladores se realiza enlenguaje C (tambin existe el compilador para lenguaje BASIC y PASCAL, sinembargo los compiladores de lenguaje C son los mas usados por sus prestaciones).Hoy cuando tenemos que sentarnos a trabajar con un microcontrolador el desarrolladorse encuentra ante una gran oferta de compiladores en mercado, y surge la pregunta:Cul elijo?

    Sin duda alguna el compilador mas completo para microcontroladores PIC es eldesarrollado por la firma CCS inc.(Custom Computer Services. Inc), el cual es muy

    popular en Amrica Latina por la gran documentacin que existe sobre el mismo.En esta seccin aportaremos nuestro granito de arena, ensendoles a trabajar con elmismo en el entorno de desarrollo Integrado de Microchip MPLAB.

    Aprendiendo a crear nuestro Primer ProyectoComo creemos que la enseanza es un proceso dinmico, progresivo y divertido,utilizaremos la metodologa de ir introduciendo conceptos en la medida que los

    necesitamos y sobre la marcha.Nuestro primer paso ser aprender a crear un proyecto en MPLAB IDE para elToolsuite (herramienta de compilacin) CCS.Antes que nada debemos tener Instalado el MPLAB el cual lo poedemos descargargratuitamente desde la propia compaa MICROCHIP: www.microchip.com/mplabAtencin: Al momento de escribir esta primer nota, el MPLABX versin 1.00 NO

    BETAtiene problemas el editor del mismo indicando las funciones embebidas

    como NO DECLARADAS, por tanto NO ACONSEJAMOS POR AHORA

    INSTALAR DICHO ENTORNO HASTA QUE EL PROBLEMA NO SEA

    SUBSANADO, por tal motivo recomendamos descargar :

    LA VERSION CORRIENTE DE MPLAB IDE 8.83

    Una vez descargado el MPLAB IDE 8.83 o similar, instalarlo en modo CUSTOM y yhabilitar el toolsuite del compilador CCS.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    2/58

    En la siguiente figura podemos apreciar la habilitacin referida en el prrafo anterior:

    Una vez finalizada la instalacin tenemos que instalar el compilador CCS. Puedebajarse desde la misma WEB de la compaa CCS: http://www.ccsinfo.com/Una versin demo limitada o recurrir a las versiones del compilador CCS que secomparten en TARINGA: www.taringa.net, en este caso una vez instalado elcompilador debemos copiar los archivos .CRG que vienen en la versin compartida yque debern pegarse dentro de la carpeta que genera el compilador al instalarse y que sellama PICC. El Windows nos advierte que es archivos ya existen y si queremosreemplazarlos, a lo cual accederemos con la opcin aceptar.Para aquellos que van a optar por las versiones compartidas de Maringa, busquen unade las ultimas versiones, por ejemplo la 4.114 o la 4.124. No aconsejamos anteriores porlos problema que tienen cada una y que han ido solucionados en estas.

    Ahora que ya tenemos el MPLAB IDE, y el compilador instalados, realizaremos nuestroprimer proyecto:

    * Disparemos el MPLAB y vayamos a la solapa PROJECT:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    3/58

    * Hagamos clic k con el Mouse sobre el item PROJECT WIZARD y se desplegarla ventana de bienbenida:

    Ahora pulsamos en botn [Siguiente] y aparecer la siguiente ventana para queseleccionemos el microcontrolador con el cual vamos a trabajar:

    Nosotros seleccionamos el PIC16F887, pero usted puede seleccionar el que tenga.Nuevamente luego de pulsar el botn [Siguiente] le aparecer la siguiente ventanadonde cargaremos el Toolsuite, es decir la herramienta o conjunto de herramientasde programacin. Nosotros seleccionaremos el Toolsuite de CCS, para lo cualdeber usted accionar el botn del control desplegable y picar con el Mouse sobre

    el compilador CCS:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    4/58

    Algunas veces, segn la versin de Windows instalada, Windows no encuentra laruta de acceso al compilador, lo cual genera que el toolsuite seleccionado aparezcacon una cruz roja por delante, lo que se puede corregir simplemente buscando el

    archivo del compilador manualmente mediante el botn [Browse]

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    5/58

    El tercer paso es seleccionar la carpeta donde almacenaremos nuestro proyecto y loy le ponemos un nombre al mismo. Nosotros creamos en el escritorio (desktop) unacarpeta MPLAB_CCS para almacenar en ella los proyectos que haremos. Dentro dedicha carpeta creamos una capeta llamada ProyectoInicial. De esta forma la rutatotal es:

    C:\Users\andres\Desktop\MPLAB_CCS\ProyectoInicial\ProyectoInicial

    Ahora pulsamos nuevamente el botn [Siguiente] y se desplegar la ventana delcuarto paso mediante la cual podemos adjuntar a nuestro proyecto archivos pre-armados, lo cual es muy til para ahorrar tiempo de escritura de cdigo, sin embargoen nuestro primer proyecto no utilizaremos esta opcin, por lo cual pasaremos lamisma por alto :

    y pulsaremos siguiente, lo cual nos llevar al final de la creacin de nuestroproyecto con el mtodo asistido (WIZARD) que tiene el MPLAB

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    6/58

    En esta ltima pantalla se nos indica un resumen de cmo se crear el proyecto. Siuno lo desea puede volver hacia atrs para modificar algn paso. Si todo estacorrecto podemos pulsar simplemente el botn de [finalizar].

    Y volveremos al espacio de trabajo principal con la ventana del worksapce (espaciode trabajo) ya desplegada con las carpetas que forman parte del proyecto:

    De esta forma ya hemos creado nuestro primer proyecto al cual le insertaremos

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    7/58

    Creando Nuestro Primer CdigoYa que hemos aprendido a crear nuestro primer proyecto, escribiremos nuestro primercdigo, el cual adicionaremos a nuestro proyecto. Para ello nos moveremos con elMouse 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 nuestroprograma.Por ser este nuestro primer programa, simplemente haremos titilar un LED con untiempo de flashing de 500ms. La idea es introducirnos de a poco, y muchas veces querercomenzar con un cdigo demasiado elaborado es complejo.

    #include

    #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 Cnativo) 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. Enesta cabecera encontraremos instrucciones dirigidas al compilador y no al

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    8/58

    microcontrolador, dichas instrucciones se denominan directivas.Las directivas sediferencian 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

    #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 nos permite decirle al compilador para quemicrocontrolador hemos escrito el cdigo.Seguidamente con la directiva #use delay(crystal=4000000) le indicamos aque frecuencia esta funcionando nuestro oscilador.

    El orden de las directivas es crucial ya que siempre primero debemosindicarle al compilador cual es el PIC que estamos usando y luego cual esla frecuencia del oscilador. Posteriormente podemos agregar el resto dedirectivas. Si esto no se respeta podemos tener errores en el proceso decompilacin sobre todo cuando usamos alguna funcin propiacompilador (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 lafrecuencia que le indicamos. As esta directiva nos permite activar multiplicadores ydivisores internos, o accionar los osciladores internos cuando el microcontrolador lostrae; por ejemplo:

    #use delay(crystal=4000000, clock=16000000)

    Le indica al compilador que tenemos un cristal externo de 4Mhz, y que la frecuenciaque 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 esel siguiente:

    #use delay(internal=8000000, clock=16000000)

    Sin embargo esta directiva debe usarse con precaucin ya que el clock que definimosnunca debe sobrepasar la mxima velocidad de procesamiento del PIC que se estusando. Este parmetro se denomina MIPS (Millones de Instrucciones por Segundo) yse obtiene dividiendo la frecuencia de entrada por cuatro.

    MIPS = fosc/4

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    9/58

    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 uncuelgue del mismo, el Brown Out Detect, que resetea el microcontrolador ante un fallode 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 entreversiones del compilador o tipos de microcontroladores.En lneas generales podemos decir que anteponiendo la palabra NO al fusible deconfiguracin (as se llama al seteo de las propiedades), se le informa al compilador queel fusible en cuestin est desactivado, mientras que colocando solo el nombreactivamos la propiedad.Por otra parte para activar o desactivar los distintos fusibles se puede realizar en variaslneas (como en el ejemplo) o se pueden activar y desactivar en una sola lnea separandocada fusible con comas:

    #fuse NOWDT,HS,NOPUT,NOLVP,NOMCLR,NOPROTECT,NOBROWNOUT

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

    Finalizada la cabecera, contina el cdigo, que es el que se traducir en instrucciones almicrocontrolador luego del proceso de compilacin. En nuestro caso nuestro cdigo es

    bastante sencillo:

    void main(void)

    { //abrimos la funcin principalsetup_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 querealizan una operacin determinada, como lo hacen las rutinas, sin embargo lasfunciones 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 locontrario 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, nitampoco puede devolver uno. Por lo tanto observe que va acompaada por dos palabras

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    10/58

    voidlo 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 hemosusado todas las funciones embebidas (incluidas dentro) del compilador para simplificarla escritura del cdigo y que nos ahorran mucho tiempo.Debe observarse que cada lnea la hemos decalado (separado del origen) por medio delTABULADOR; esto es una buena prctica para poder advertir a simple vista cualessentencias 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 lospuertos 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 puestos van a trabajar como analgicos yque puertos van a trabajar como digitales. La funcin configura los bits PCFG oANSEL 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 decabecera del procesador (16f887.h).Es importante resaltar que las etiquetas siempre van en mayusculas, mientras que lasinstrucciones se escriben en minscula.

    Es muy importante que se respete el orden mayscula-minscula pues elcompilador es sensible a ello. Si escribimos una instruccin conmayscula, 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: whileEl while es una instruccin condicional la cual determina la ejecucin de una o masinstrucciones 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 sesimboliza con el nmero 1; por el contrario, si la condicin no se cumple, es falsa y sesimboliza con el nmero 0.En un while, lo que este dentro del bloque del mismo, se ejecutar, siempre que lacondicin de verdadera, caso contrario no se ejecutar ninguna sentencia que seencuentre dentro del while.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    11/58

    En nuestro caso hemos forzado la condicin 1, con lo cual el while se ejecutareternamente. 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 casoes el RB0, al cual CCS lo denomina dentro del archivo de cabecera delmicrocontrolador como PIN_B0.Este formato si bien parece en principio raro porque no se adapta al usado en el datasheet, es prctico para los programadores NO ELECTRNICOS, y es el que haadoptado 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 enmilisegundos. Tambin existe el delay_us que nos permite crear un delay demicrosegundos.La exactitud de la funcin delay depende de que hayamos definido correctamente lafrecuencia de clock.

    Compilando nuestro primer cdigoYa hemos terminado de escribir nuestro primer cdigo, ahora tenemos que convertirloen hexadecimal para grabarlo dentro del microcontrolador. Este proceso se denominacompilacin.El programador de microcontroladores, cualquiera sea el que estemos usando, necesitaque le carguemos el cdigo a programar dentro del microcontrolador en formatohexadecimal, l lee un archivo en formato HEX de INTEL, el cual tiene una estructurainterna que Microchip adapt a su necesidad.El compilador CCS es un compilador denominado de 2 pasos ya que en el primer

    paso traduce el programa escrito en lenguaje C al lenguaje Assembler y luego en un

    segundo paso, traduce este archivo al hexadecimal.Como consecuencia de todo el proceso de traduccin o como se lo llama tcnicamentecompilacin, CCS genera una serie de archivos:

    xxxxx.ERR : contiene los errores del proceso de compilacinxxxxx.HEX: contiene el codigo en hexadecimal, este es usado por el programadorxxxxx.LST: contiene un listado del proceso de ensambladoxxxxx.STA: contiene cuanta memoria RAM, ROM y STACK esta usando el programaxxxxx.TRE: contiene un rbol de las llamadas a funciones, es visible en el IDE de CCSxxxxx.SYM: contiene la localizacin de cada registro y variable usada en la RAMxxxxx.ESYM: solo es visible en el IDE de CCS y contiene informacin para el mismo.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    12/58

    En la siguiente figura podemos ver un ejemplo del resultado del proceso decompilacin:

    Grabado nuestro cdigo en el PICUna vez compilado nuestro cdigo, ahora lo cargaremos en nuestro microcontrolador;

    para ello iremos a la solapa programmer, all haremos clic con el Mouse sobre la solapaselect Programmer y se desplegar un men. Sobre dicho men haremos clic sobre eltem PICkit 2:

    Esto activar los controles del PICkit2 programmer, los cuales aparecern como una

    nueva barra de herramientas:

    En dicho men tenemos los conos para: programar el microcontrolador, leer elcontenido de la memoria de programa del microcontrolador, leer el contenido de lamemoria EEPROM de datos del microcontrolador, verificar el contenido de la memoriade programa del microcontrolador, borrar el microcontrolador, verificar si la memoriade programa del microcontrolador esta vaca, sacar el reset del ICSP y arrancar el

    programa, poner el RESET del ICSP y detener el programa y finalmente, con el cono

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    13/58

    del lapicito, como se le dice en la jerga de los programadores, establecer unacomunicacin con el microcontrolador.Observe que si se ha establecido la comunicacin sin problemas deber aparecer elsiguiente mensaje en la ventana de salida :

    Initializing PICkit 2 version 0.0.3.63Found PICkit 2 - Operating System Version 2.32.0

    PICkit 2 Unit ID = OlHoss

    Target power detected ( 4.70V)

    PIC16F887 found (Rev 0x2)

    PICkit 2 Ready

    En la primera lnea nos indica la versin del firmware que esta grabada dentro delmicrocontrolador de nuestro pickit2, seguidamente nos indica el ID grabado dentro delPICkit 2. A continuacin nos indica cual es el valor de VCC ledo sobre la placa deaplicaciones, el microcontrolador que tenemos instalado ya que lee su cdigo derevisin interna, y finalmente nos indica que el PICkit 2 est listo para operar.

    Por tanto, ahora que esta todo listo, programaremos el microcontrolador pulsando elcono respectivo dentro de las herramientas del programador:

    Accionado el control se inicia el proceso de programacin, siempre que todo estrealmente bien conectado:

    Durante la programacin se irn desplegando distintos mensajes en la ventana de salidadel PICkit 2:

    Programming Target (20/02/2012 20:00:56)

    PIC16F887 found (Rev 0x2)

    Erasing Target

    Programming Program Memory (0x0 - 0x4F)

    Verifying Program Memory (0x0 - 0x4F)

    Programming Configuration Memory

    Verifying Configuration Memory

    PICkit 2 Ready

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    14/58

    Aprendiendo el ABC del

    Lenguaje C

    Se dice que el lenguaje C es un lenguaje de nivel medio. Larazn de esta indicacin est en que en C se pueden crearprogramas que manipulan la mquina casi como lo hace ellenguaje Ensamblador, pero utilizando una sintaxis que seasemeja ms a los lenguajes de alto nivel. De los lenguajes dealto nivel toma las estructuras de control que permitenprogramar de forma estructurada.

    Al tener caractersticas de los lenguajes de bajo nivel se puede tomar el control absolutodel microcontrolador. Adems tiene atajos que gustan mucho a los programadores altener una sintaxis menos restrictiva que lenguajes como Pascal por ejemplo, lo que leconvierte en el lenguaje idneo para crear cualquier tipo de aplicacin.Sus caractersticas bsicas son:

    Es un lenguaje estructurado y modular. Lo que facilita su compresin y escritura Es un lenguaje que incorpora manejo de estructuras de bajo nivel (punteros,

    bits), lo que le acerca a los lenguajes de segunda generacin Permite utilizar estructuras de datos complejas (arrays, pilas, colas, textos,...) Es un lenguaje compilado

    Permite crear todo tipo de aplicaciones

    Cual es estructura de un programa en Lenguaje C?Un programa en C consta de una o ms funciones, las cuales estn compuestas dediversas sentencias o instrucciones.Una sentencia indica una accin a realizar por parte del programa. Una funcin no esms que (por ahora) un nombre con el que englobamos a las sentencias que posee a finde poder invocarlas mediante dicho nombre.La idea es:

    parmetros nombreDeFuncin(parmetros){

    Sentencias;

    }

    Los smbolos {y }indican el inicio y el final de la funcin. Esos smbolos permitendelimitar bloques en el cdigo.El nombre de la funcin puede ser invocado desde otras sentencias simplemente

    poniendo como sentencia el nombre de la funcin.Como a veces las funciones se almacenan en archivos externos, necesitamos incluir esosarchivos en nuestro cdigo mediante una sentencia especial #include, que en

    realidad es una directiva de preprocesador. Una directiva de preprocesador es unainstruccin para el compilador con el que trabajamos.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    15/58

    El uso es:

    #include

    La directiva #includepermite indicar un archivo de cabecera en el que estar

    incluida la funcin que utilizamos. En el lenguaje C estndar los archivos de cabeceratienen extensin h. Los archivos de cabecera son los que permiten utilizar funcionesexternas (o libreras) en nuestro programa.Una de las libreras ms utilizadas en los programas, es la que contiene las etiquetas detodos los registros de funciones especiales del MCU PIC que hayamos seteado en el

    proyecto. En el caso de CCS esta librera est disponible en la cabecera 16Fxxx.hEn todos los lenguajes de programacin, el primer programa a realizar es el famoso

    Hola mundo, un programa que escribe este texto en pantalla. En el mundo de losmicrocontroladores PIC, este programa se traduce en hacer titilar un led. De esta formaen CCS el cdigo de este programa es:

    #include #use delay(crystal=12000000)//

    #fuses HS,NOWDT,NOLVP,NODEBUG,NOBROWNOUT,NOPLLEN,CPUDIV1,PUT,MCLR

    #define LED1 PIN_B4

    void main(void)

    {

    setup_adc_ports(NO_ANALOGS);

    while(1)

    {

    output_high(LED1);

    delay_ms(500);

    output_low(LED1);

    delay_ms(500);

    }}

    Cules son los elementos de un programa en C?

    Los programas en C se basan en sentencias las cuales siempre se incluyen dentro de unafuncin. En el caso de crear un programa ejecutable, esas sentencias estn dentro de lafuncin main. A est funcin le antecede y precede la palabra void.Ahora bien al escribir sentencias hay que tener en cuenta las siguientes normas:

    (1) Toda sentencia en C termina con el smbolo "punto y coma" (;)

    (2) Los bloques de sentencia empiezan y terminan delimitados con el smbolo de llave({ y }). As { significa inicio y } significa fin

    (3) En C hay distincin entre maysculas y minsculas. No es lo mismo main queMAIN. Todas las palabras claves de C estn en minsculas. Los nombres que pongamosnosotros tambin conviene ponerles en minsculas ya que el cdigo es mucho mslegible as.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    16/58

    Qu es un comentario?Se trata de texto que es ignorado por el compilador al traducir el cdigo. Esas lneas seutilizan para documentar el programa.Esta labor de documentacin es fundamental. De otro modo el cdigo se convierte enilegible incluso para el programador que lo dise. Tan importante como saber escribirsentencias es utilizar los comentarios. Todava es ms importante cuando el cdigo va aser tratado por otras personas, de otro modo una persona que modifique el cdigo deotra lo tendra muy complicado.En C los comentarios se delimitan entre los smbolos /* y */ para los bloque y // para laslineas

    // Esto es un comentario usado para las lneas/* Esto es un comentario el compilador har caso omiso de este texto*/

    Qu debemos considerar como importante en C?C no es un lenguaje dcil para enfrentarlo intuitivamente por primera vez; se requiereun mnimo conocimiento de sus fundamentos antes de poner las manos sobre el teclado.En este aspecto es particularmente importante comprender los diferentes tipos de datosy las reglas que rigen su operacin.La idea directriz de C es la definicin de procedimientos (funciones), que en principiodevuelven un valor. Lo que para nosotros es - conceptualmente - el programa principal,tambin es en C una funcin (la ms externa).Incidentalmente, su valor es devuelto al sistema operativo como cdigo de conclusindel programa.Ante todo, C est diseado con vistas a la compatibilidad. En este sentido, todas lasdefiniciones que puedan hacerse no sern concretas, pues son adaptables de acuerdo conla implementacin. Un entero, por ejemplo, es una entidad con ciertas caractersticasgenerales, pero su implementacin diferir en distintos equipos.C maneja los datos en forma de variables y constantes, conceptos con los quesupondremos que el lector est familiarizado. Las variables, simbolizadas mediantedatos alfanumricos (cuyas reglas de construccin trataremos ms adelante), presentancaractersticas que ser muy importante considerar:

    Tipo de dato: cada variable (tambin las constantes) est caracterizada por eltipo de dato que representa.

    Visibilidad: en un programa C, cada variable tiene un rango de visibilidad(procedimientos en los que es reconocida), que depende de cmo se la hayadeclarado.

    Existencia: relacionado con la anterior caracterstica, es posible que el contenidode una variable perdure, o que se pierda, por ejemplo, al terminarse un

    procedimiento.

    Cul es el grupo de caracteres de C?C emplea dos conjuntos de caracteres:

    El primero de ellos incluye todos los caracteres que tienen algn significadopara el compilador.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    17/58

    El segundo incluye todos los caracteres representables.

    C acepta slo ciertos caracteres como significativos. Sin embargo, otros caracterespueden formar parte de expresiones literales (constantes literales, nombres de archivo,etc.) que no sern analizadas por C.

    Los caracteres a los que C asigna especial significado se pueden clasificar enalfanumricos y signos especiales. Los caracteres alfanumricos incluyen las letras(alfabeto ingls, de A a Z), maysculas y minsculas, los dgitos, y el guin bajo(underscore: _).En todos los casos, las maysculas son consideradas distintas de las minsculas. Todacadena alfanumrica con significacin en C est compuesta exclusivamente por estoscaracteres.Los signos especiales son los listados a continuacin. Ellos se emplean comodelimitadores, operadores, o signos especiales.

    Maysculas: A - Z Signo ms +

    Minsculas: a - z Signo menos -Dgitos: 0 9 Parntesis izquierdo (Guin bajo: _ Parntesis derecho )Coma , Corchete izquierdo [Punto . Corchete derecho ]Punto y coma ; Llave izquierda {Dos puntos : Llave derecha {Signo de interrogacin ? Signo Mayor >Signo de admiracin ! Signo Menor Mayor que>= Mayor igual que< Menor que

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    20/58

    Qu son los operadores lgicos?Estos operadores se usan para establecer una relacin lgica entre 2 comparaciones,

    generalmente se usan dentro de las estructuras condicionales que luego veremos.

    OPERADOR ACCIN&& And|| Or! Not

    La operacin lgica no se realiza a nivel bit entre los operandos, sino que establece unarelacin entre condiciones comparativas en las que participan los operandos, ejemplo(condicin 1) && (condicin 2) establece que si se cumple la condicin 1 y la condicin2.

    En C, cualquier valor distinto de 0 es VERDADERO. FALSO es 0 (cero).

    Cmo declaramos una variable en Lenguaje C?En C siempre se deben declarar las variables. La declaracin consiste en un tipo de dato,seguido por el nombre de la variable y el punto y coma:

    int a;

    int b,c,d;

    int a = 10;

    Los tres casos son definiciones correctas de variables, en el ltimo adems de declararla variable se le asigna un valor inicial.En caso de existir una expresin con variables de diferentes tipos, el resultado obtenidoes del tipo de operando de mayor precisin.Todos los char se convierten a int.Todos los float se convierten a double.(hay que tener en cuenta que el tipo char es enrealidad un int de menor precisin).

    Cmo convertimos un tipo de una variable en otra?A veces es til, o necesario, realizar conversiones explcitas para obligar que unaexpresin sea de un cierto tipo.La forma general de esta conversin en C es:(tipo) expresin;

    siendo tipo, el tipo de datos al que se convertir la expresin.

    NOTA: Esta conversin de tipos, (tambin llamada CAST), permite convertirexpresiones no variables, esto es, si tengo una variable x de tipo int y le aplico (float)xlo que se convierte es el resultado, en caso que yo asigne esta operacin a otra variable,

    pero no se convierte la variable x a float.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    21/58

    Supongamos que hacemos un programa que divide 10 por 3, uno sabe que el resultadoser flotante: 3.333, y como 10 y 3 son enteros uno escribira:

    int a=10, b=3;

    float r;

    r=a/b;printf(El resultado es %f, r);

    Pero se encontrara que el resultado no es el deseado, esto ocurre porque en C ladivisin entre enteros da como resultado un entero y en la realidad no siempre es as,(slo en el caso que b sea divisor de a). Pero cambiando el clculo de la divisin por:

    r=(float)a/b;

    As se garantiza que el resultado ser flotante.

    Cmo definimos una constante numrica?Las constantes se definen en diferentes formatos dependiendo del prefijo:0x (hexadecimal), 0 (octal), 0b (binario).

    Cmo definimos una constante de caracteres (string)?Las variables almacenadas en memoria de programa suelen ser cadenas de caracteres.Este tipo de variable se define como: const rom char[]Tambin se pueden declarar tablas de caracteres.

    Ejemplo:

    rom const char tabla[][20] = { "string 1", "string 2",

    "string 3", "string 4" };

    Tabla es una variable que contiene 80 caracteres en memoria de programa, ya que estcompuesta de 4 cadenas de 20 caracteres cada una.Para copiar una cadena de caracteres que se encuentra situada en la memoria de

    programa (ROM) en la memoria de datos (RAM), debemos usar una rutina o funcinestndar de C denominada str2ramVeamos un ejemplo de copia de una cadena en ram a otra en rom:

    void str2ram(static char *dest, static char rom *src){while ((*dest++ = *src++) != '\0');

    Que es la funcin printf()?Es una funcin que est incluida en el archivo de cabecera stdio.h y se utilizan paraenviar informacin por la USART del microcontrolador.El nmero de parmetros pasados puede variar, dependiendo de la cantidad de variablesa mostrar. El primer parmetro indica, por un lado, los caracteres que se mostrarn por

    pantalla y adems los formatos que definen como se vern los argumentos, el resto delos parmetros son las variables a enviar por la USART.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    22/58

    Ejemplo:

    int a=100, b=50;

    printf(%i es mayor que %i\r, a, b);

    Si conectamos a la USART de nuestro PIC un MAX232 y lo enlazamos al puerto COMde la PC, podremos ver la informacin con el programa Hypeterminal de Windows, queen este caso nos mostrar en la pantalla de la PC:

    100 es mayor que 50

    Los formatos ms utilizados con printf() son:

    CODIGO FORMATO%c Un solo carcter

    %d Decimal (un entero)%i Un entero%f Punto decimal flotante%e Notacin cientfica%o Octal%x Hexadecimal%u Entero sin signo%s Cadena de caracteres%% Imprime un signo %%p Direccin de un puntero

    Los formatos pueden tener modificadores para especificar el ancho del campo, elnmero de lugares decimales y el indicador de alineacin a la izquierda.Ejemplos:

    %05d, un entero de 5 dgitos de ancho; rellenar con ceros. Alineado a la derecha.%10.4f, un real de 10 dgitos de ancho, con 4 decimales. Alineado a la derecha.%-10.2f, un real de 10 dgitos de ancho, con 2 decimales. Alineado a la izquierda.

    En la funcin printf() tambin se pueden encontrar caracteres de escape que permitenintercalar algn carcter especial en la cadena.

    Ejemplo

    printf(\nHola mundo.\n);

    Aqu antes de imprimir el texto Hola mundo, \n obliga a un salto de lnea - retorno decarro, (ENTER) dentro del Programa Hyperterminal, ya que estos caracteres especialessolo pueden sen entendidos y vistos por los programas emuladores de terminales.

    Caracteres de escape mas usados:CDIGO DESCRIPCIN

    \n Salto de lnea retorno de carro (ENTER)\t Tabulado horizontal

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    23/58

    \v Tabulado vertical\r Retorno de carro.\b Backspace.\f Alimentacin de pgina.

    Para usar la funcin printf() debemos previamente en la cabecera habercolocado la directiva #use RS232 ( parmetros), la cual debe encontrarsesiempre despus de la directiva #use delay. Esta directiva se usa paraindicarle al compilador datos esenciales como ser: el BAUD RATE, lospines de la comunicacin, el nmero de bits de la comunicacin, si se usala USART del PIC o se emula por software, etc. Un ejemplo de la directivapara un PIC16F887 que usa su USART sera la siguiente:

    #use RS232(BAUD=9600, BITS=8, PARITY=N, XMIT=PIN_C6, RCV=PIN_C7)

    Un ejemplo de cdigo completo es el siguiente programa en el cual transmitimos un

    hola mundo por la USART, y dicho mensaje podr ser recibido por el programaHypeterminal de Windows:

    #include

    #fuses INTRC_IO,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP

    #use delay(clock=4000000)

    #use RS232(BAUD=9600, BITS=8, PARITY=N, XMIT=PIN_C6, RCV=PIN_C7)

    void main(void)

    {

    setup_adc_ports(NO_ANALOGS); //Selecciona terminales

    while(1)// ciclo for infinito

    {

    printf("Hola Mundo\r",temperatura);// imprimo por USART

    delay_ms(100);// delay

    }

    }

    Cules son las estructuras bsicas de C?Estas estructuras son las que le dan inteligencia al programa permitiendo que elmicrocontrolador haga algo a partir de una condicin que es evaluada

    Sentencia if:Forma general:if (condicin)

    sentencia1;

    else

    sentencia2;

    Si la condicin es verdadera (se cumple), se ejecuta la sentencia1, de lo contrario lasentencia2. (esta estructura suena de la siguiente forma: si la (condicin) se cumple, seejecuta la sentencia1, sino, se ejecuta la sentenca2.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    24/58

    Tambin se pueden escalonar los if:

    if (condicin)

    Sentencia1;

    else if (condicin)

    Sentencia2;

    elseSentencia3;

    Y anidar:

    if (x)

    if (a

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    25/58

    Ejemplo:La sentencia switch se usa en general para seleccionar menes de opciones, en estesegmento de cdigo lo que se explora es justamente el valor de la opcin seleccionada,y segn la misma ser la operacin realizada:

    switch(opcion)

    {

    case 1:

    re = valor*valor;

    printf(El cuadrado de %i es %i\n, valor, res);

    break;

    case 2:

    re = valor*valor*valor;

    printf(El cubo de %i es %i\n, valor, res);

    break;

    case 3:

    res = valor % 2;

    if (res)

    prinf(El nmero %i es impar\n, valor);

    else

    printf(El nmero %i es par\n, valor);

    break;

    default:

    printf(Opcin erronea);

    }

    La variable opcion contiene el valor del men seleccionado por el usuario. En cada caselo que se explora es si la variable ha adquirido ese valor.

    Los bucles o ciclos iterativos

    El bucle for:Esta sentencia nos permite repetir una o varias sentencias una cantidad de vecesdeterminada por 3 parmetros.

    Forma general del for:Para una sola sentencia .

    for(inicializacin; condicin; incremento)

    sentencia;

    Para un bloque de sentencias (recordemos que el bloque queda definido por las llaves.

    for(inicializacin; condicin; incremento)

    {

    sentencias;

    }

    El siguiente ejemplo muestra los primeros 100 nmeros enteros:

    #include #fuses INTRC_IO,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP

    #use delay(clock=4000000)

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    26/58

    #use RS232(BAUD=9600, BITS=8, PARITY=N, XMIT=PIN_C6, RCV=PIN_C7)

    void main(void)

    {

    setup_adc_ports(NO_ANALOGS); //Selecciona terminales

    while(1)// ciclo for infinito

    {

    for(i=1; i=1; i - -)

    printf(%d, i);

    Se pueden evaluar ms de una variable:

    int i, j;

    for(i=1, j=100; i0; i++, j - -)

    printf(i = %d, j= %d\n, i, j);

    El siguiente bucle no termina nunca, (bucle infinito):

    for( ; ; )

    Debemos recordar que si la cantidad de sentencias, (equivalencias, operacionesaritmticas, llamadas a funciones, etc.), pertenecientes al bucle son ms de una, estasdeben ir entre { }.

    El bucle while:El bucle while permite ejecutar una o mas sentencias en tanto se cumpla una condicin.Si la condicin deja de cumplirse, se dejan de ejecutar la o las instrucciones y se saledel bloque while para continuar procesando las instrucciones que se encuentran despusdel mismo

    while (condicin)

    sentencia;

    while (condicin)

    {

    sentencia1;

    sentencia2;

    sentencia3;

    sentencia4;

    .

    .

    Senttencia_n;

    }

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    27/58

    Ejemplo:char salir;

    salir = n;

    while (salir != n)

    {

    printf(Estoy dentro del mientras\n);

    getc(%c, &salir);}

    printf(\nYa sal);

    El bucle tambin puede estar vaco. El siguiente ejemplo funcionar hasta que se pulsela letra A:

    while ((letra = getc()) != A);

    El bucle do while:La diferencia que existe con el while, es que en el bucle do while por lo menos una

    vez, el programa ejecuta las sentencias del bucle, (hasta llegar a la sentencia while), yluego decide si contina iterando, siempre que se cumpla la condicin examinada por elwhile.La forma general del bucle es:

    do

    {

    sentencia;

    } while (condicin);

    Operaciones A Nivel De Bits, (Bitwise):El lenguaje c proporciona la posibilidad de manipular los bits de un byte, realizandooperaciones lgicas y de desplazamiento. En el caso de las operaciones lgicas, estasgeneralmente son usadas para crear mascaras que fuercen a que ciertos bits sean puestosen 1 o en 0.Los operadores a nivel de bits son los siguientes:

    OPERADOR ACCIN& AND entre bits| OR entre bits

    ^ XOR entre bits, (or exclusivo).~ NOT , (si es 1 pasa a ser 0 y viceversa)> Desplazamiento a derecha

    Ejemplos de los operadores son los siguientes:

    var > n = se desplaza n bits a la derecha.

    1 & 1 = 1

    1 | 0 = 1, 0 | 1 = 1 y 1 | 1 = 1

    1 ^ 0 = 1 y 0 ^ 1 = 1

    ~1 = 0 y ~0 = 1

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    28/58

    De forma general conviene tener siempre presente estos resultados

    X & 1 = X , X & 0 = 0

    X | 1 = 1 , X | 0 = X

    X ^ 1 = ~X , X ^ 0 = X

    Estructuras De Datos:

    Arrays:Un array es una coleccin de elementos de un mismo tipo, que se referencian usando unnombre de variable comn. En C, el array ocupa posiciones de memoria contiguas. Ladireccin ms baja corresponde al primer elemento y la ms alta al ltimo. Para accedera un elemento especfico se usan ndices.

    Arrays unidimensionales:

    Forma general de declararlos:

    tipo nombre-variable[tamao];

    Ejemplo:

    int numeros[10];

    Es un arreglo de 10 elemento enteros, donde el primero es numeros[0]y el ltimonumeros[9].Guardemos en este array los nmeros dgitos, (0 al 9):

    for(i=0; i

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    29/58

    Ejemplos:

    int numeros[10] = {1,2,3,4,5,6,7,8,9,10};

    char cadena[6] = hola;

    char cadena[5] = {h, o, l, a, \0};

    Cadenas (Strings):En C no existe un tipo de datos especfico para declarar cadenas, en su lugar la idea decadena surge de un array de caracteres que siempre termina con el carcter nulo, (\0) ycuya posicin debe contemplarse al dimensionar el array.Para guardar una cadena de 10 caracteres:

    char cadena[11];

    Cuando se introduce una constante de cadena, (encerrada entre dobles comillas), no esnecesario terminar con el carcter nulo, ya que el C lo crea automticamente.

    Ejemplo: El segmento del siguiente programa que muestra una cadena introducidadesde el teclado usando el Hyperterminal y la USART del Microcontrolador:

    char cadena[100];

    printf(Ingrese cadena, de hasta 100 caracteres\n);

    gets(cadena);

    printf(Usted ingres: %s, cadena);

    Para que es la sentencia #define?Esta sentencia permite declarar constantes y es muy usada para definir valores queusaremos dentro del programa

    #define VREF 5 //define la tensin de referencia

    #define ADCBITS 1024.0 // define la resolucin del ADC

    Que son los Punteros?La memoria de un Microcontrolador se representa habitualmente mediante direccionesexpresadas en valores hexadecimales. Una variable, por ejemplo x, es una direccin dememoria donde se guarda algn valor. En los lenguajes de programacin uno usaidentificadores, (nombres simblicos), para reservar lugares de la memoria necesarios

    para almacenar datos que permitan realizar operaciones. Estos lugares son tan amplioscomo el tipo de dato en que fue declarada la variable, esto es:Si declaro una variable x de tipo entera, (int), estara reservando 2 bytes en memoria, sideclaro una de tipo char sera 1 byte, etc.Un puntero es una variable de algn tipo que permite guardar una direccin dememoria, esto permite, indirectamente, acceder al contenido de esa direccin.Un puntero se declara de forma general de la siguiente manera:

    tipo *nombre-variable;

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    30/58

    Ejemplo :

    int *p;

    char *q;

    Veamos un pequeo segmento de programa que ilustre las cualidades de los punteros:

    int *p; (1)

    int x = 5; (2)

    p = &x; (3)

    printf(El valor de x es: %d\n, x); (4)

    printf(p apunta a x, entonces en x hay: %d, *p); (5)

    Este ejemplo dar como resultado la visualizacin del contenido de la variable x, o sea5, dos veces.Veamos lnea por lnea:

    En (1) se declara un variable puntero, p, a los enterosEn (2) una variable x entera con el valor inicial de 5.

    En (3) se almacena en el puntero, p, la direccin de memoria de x; el operador &permite ver la direccin de memoria de una variable.

    Luego en (4) se muestra el contenido de x.

    Como en (3) se guard la direccin de x en p, ste, que es un puntero, tienen la cualidadde ver el contenido de esa direccin de forma indirecta por medio del operador *.

    Esto es lo que se hace en (5), ver el contenido de x, pero desde el puntero, ya que ltiene almacenada la direccin de memoria de x. Por eso se visualiza dos veces elcontenido de x.

    Assembler embebidoSe puede insertar cdigo en assembler mediante #asm y #endasm.Dentro de un bloque en assembler no se deben usar:

    Las directivas del ensamblador.

    las etiquetas deben acabar con : No se soporta direccionamiento indirecto. La constantes se especifican como en lenguaje C.

    Ejemplo:

    #asm //codigo en Assembler

    MOVLW 10 // Movemos decimal al contador

    MOVWF count, 0

    inicio: //etiqueta

    NOP

    NOP

    DECFSZ count, 1, 0 //decrementamos el contador

    BRA inicio

    salir:

    #endasm //salimos del bloque assembler

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    31/58

    Qu son las estructuras?Una estructura es un conjunto de variables de diferentes tipos referenciadas bajo elmismo nombre.

    Ejemplo:struct Reloj

    {

    char hora;

    char minuto;

    char segundo;

    }

    De esta forma se define una estructura llamada reloj, ahora hay que declarar unavariable de este tipo:

    struct Reloj Time;

    En este caso la variable e es de tipo empleado y se pueden acceder a los camposmiembros de la estructura de la siguiente forma:

    Time.hora

    Time.minuto

    Time.segundo

    Las estructuras son muy usadas para crear campos de BITS que nos permitan usar deforma individual cada uno de los BITS de los registros de funciones especiales.

    Que son las funciones?

    Las funciones son porciones de cdigo que facilitan la claridad de desarrollo delprograma. Son similares a las subrutinas, con la diferencia que podemos pasarlesvalores para que precesen y nos pueden devolver el resultado de dichos procesamiento.Todas las funciones retornan un valor y pueden recibir parmetros.La estructura general de un funcin en C es la siguiente:

    Tipo_de_retorno nombre_funcin (tipo param1, ..., tipo paramn)

    {

    sentencias

    return(valor_de_retorno);

    }

    Los posibles tipos de retorno son los tipos de datos ya vistos: (int, float, void, char,etc).Para crear una funcin en C, primero hay que declarar el prototipo de la misma antes dela funcin main()y luego de la llave final del programa se define la funcin.

    Ejemplo:La siguiente funcin suma dos valores y retorna un resultado:

    int suma(int x, int y)

    {

    return x+y;

    }

    Se retorna de una funcin cuando se llega a la sentencia return o cuando se encuentra lallave de cierre de la funcin.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    32/58

    Cuando lo que se desea escribir es un procedimiento que, por ejemplo, realice un delayo muestre un texto por LCD o cargue una arreglo, o sea, que no devuelva ningn valorse escribe como tipo de retorno void,( que significa tipo vaco).

    Alcance de las variables:

    Variable global:Conocida por todas las funciones. Se puede utilizar en cualquier punto del programa. Sedeclara fuera del main.

    Variable local:Se declara apenas abrir una llave en el cdigo, cuando la llave se cierra esta variabledesaparece.

    Variable declarada en los parmetros formales de unafuncin:Tiene el mismo comportamiento de las variables locales.

    Paso De Parmetros a las funciones:

    Paso por valor:Cuando se pasa un parmetro por valor a una funcin, la misma hace copias de lasvariables y utiliza las copias para hacer las operaciones. No se alteran los valoresoriginales, ya que cualquier cambio ocurre sobre las copias que desaparecen al terminarla funcin.

    Ejemplo:delay_ms(100); // llamamos a la funcin

    En este ejemplo llamamos a la funcin delay_msy le pasamos el valor 100, el cual seencuentra dentro del parntesis.

    Paso por referencia:Cuando el objetivo de la funcin es modificar el contenido de la variable pasada como

    parmetro, debe conocer la direccin de memoria de la misma. Para ellose le anteponea la variable el operador &, puesto que se le est pasando la direccin de memoria de lavariable

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    33/58

    Ejemplo:

    void calcula_voltaje (int val, float &voltaje)//funcion que calcula el

    voltaje

    {

    voltaje=(val*v_max)/escala;

    }

    En el ejemplo de la funcin observamos el apuntador & que apunta a la variable voltaje,de esta forma le pasamos el valor de la variable a la posicin que la misma ocupa.

    ATENCIN: Los arrays, (entindase tambin cadenas),siempre se pasan por referencia y no hace falta anteponerleel smbolo &, pues como habamos dicho el nombre de unarray es un puntero al primer elemento del mismo.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    34/58

    Programando PIC con CCS

    A partir de aqu comenzaremos a usar lo aprendido en los

    captulos anteriores. La nica forma de asimilar e incorporarnuevo conocimiento, es poner en prctica lo que se aprende.Iremos desde lo simple a lo complejo, desde el encendido deun LED hasta el control por PC de nuestra aplicacin o circuitoelectrnico.

    Para trabajar podemos usar un protoboard, sin embargo no soy muy amigo de este tipode herramientas ya que es fcil encontrarse con falsos contactos y crear verdaderasmaraas de cables. Es preferible construir un circuito elemental que tenga todos los

    perifricos que veremos o en su defecto adquirir ya la placa armada. Si bien el adquirir

    algo armado nos quita el sabor del hgalo usted mismo, nos permite ganar tiempo.Otra herramienta que se puede usar es el PROTEUS, sin embargo la virtualizacin deun circuito no nos permite afrontar las problemticas reales, como son los rebotes, ruidoelectromagntico, etc.Yo presentar el esquema de una placa ideal y aconsejar la compra de un modelo, sinembargo queda en el lector el tomar estas ideas u optar por las opciones anteriores quetambin son vlidas, lo importante es aprender.

    Caractersticas de los Microcontroladores PIC Lnea

    Media Mejorada PIC16F1XXXMicrochip es una compaa en constante evolucin y renovacin, y por ende ao trasao presenta nuevos microcontroladores al mercado y nuevas mejoras en susarquitecturas tpicas. Hasta el ao 2010, los ncleos de los procesadores de Microchip

    podan dividirse en 6 familias: PIC Linea Base (PIC10F,PIC12F5X y PIC16F5X) PIC Lnea Media (PIC16F y PIC12F) PIC18F dsPIC30F/33F PIC24F/24H

    PIC32De todas estas familias, las ms antiguas son los PIC Lnea Base y PIC Lnea Media,concebidos para ser programados en Lenguaje Assembler, con lo cual las limitacionesde su arquitectura, tambin limitan la cantidad de cdigo que se puede escribir enLenguaje C dentro del microcontrolador. Es por ello que a partir de la creacin de lafamilia PIC18F y desde all en adelante, todos los microcontroladores se concibieron

    para trabajar en Lenguaje C.Sin embargo el mercado de los microcontroladores PIC Lnea Media es muy amplio y

    para estos usuario Microchip mejor el ncleo de estos MCU, desarrollando una nuevageneracin , a la cual ha bautizado como PIC Lnea Media Mejorada, los cuales se

    identifican por su cdigo inicial: PIC16F1xxx o PIC12F1xxx.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    35/58

    Esta renovacin de los viejos ncleos PIC16F introduce todas las mejoras que hanadquirido los PIC18F con el Tiempo.Dichas caractersticas son las siguientes:

    Memoria de Programa hasta 32K instrucciones Memoria de Datos hasta 2K Mejora de Perifricos (USART, CCP, PWM ,Puertos I/O) Insercin de nuevos Perifricos Modos de muy bajo consumo Mejoras en el Oscilador Interno con un PLL x 4 Ampliacin del Set de Instrucciones Ampliacin del STACK a 16 niveles

    Salvado automtico de contexto Control del STACK por medio del usuario Mejora del registro FSR y creacin de 2 (FSR0 y FSR1)

    Todas estas nuevas caractersticas hacen de estos PIC los sucesores indiscutibles de lavieja familia PIC16F con la posibilidad de migracin a PIC18F menos abrupta.Para iniciar en nuestro curso, trabajaremos con el PIC16F1939, el cual reemplazatcitamente a los viejos PIC16F877A y con menor costo.

    El nuevo PIC16F1939Este microcontrolador, forma parte de la familia PIC16F193X, la cual esta constituida

    por los siguientes dispositivos:

    PIC16F1933 (equivalente a un PIC16F873A) PIC16F1934(equivalente a un PIC16F874A) PIC16F1936(equivalente a un PIC16F876A) PIC16F1937(equivalente a un PIC16F877A) PIC16F1938(equivalente a un PIC16F876A pero con mas memoria)

    PIC16F1939(equivalente a un PIC16F877A pero con mas memoria)Todos ellos de costo inferior a los PIC16F87X equivalentes y mayores prestaciones.En el mercado nacional podemos conseguir este microcontrolador en los dos Partners deMicrochip: MCElectronics y ELEMON.El PIC16F1939 es el ms caro de la familia, sin embargo es ms econmico que suantecesor el PIC16F877A. Con esta poltica Microchip pretende seducir a susconsumidores para que abandonen sus aplicaciones emplazadas con las viejas unidadesPIC16F y migren a los PIC16F1XXX .Cuando migramos un desarrollo emplazado con PIC16F877A a un PIC16F1939 no sologanamos en el costo sino que al mismo tiempo tenemos el doble de memoria de

    programa y mucha ms memoria de datos, lo cual nos permitir ampliar nuestra

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    36/58

    aplicacin. En la siguiente figura vemos las caractersticas ms destacables de estasunidades.

    El PIN-OUT del PIC es el siguiente:

    El ABC del Hardware elemental del PICComencemos por decir que el Microcontrolador por ser una mquina secuencial,necesita para funcionar de un generador de pulsos de onda cuadrada, a los cuales sedenominan pulsos de clock. Dichos pulsos pueden ser generados de 3 formas diferentes:

    Usando un Oscilador de Onda Cuadrada Externo (EC) Usando un resonador, Cristal de cuarzo o red RC colocada en OSC1 y OSC2 Usando el Oscilador interno del Microcontrolador.

    En los nuevos PIC16F1939, el mdulo generador de clock presenta la siguientearquitectura interna:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    37/58

    Las fuentes generadoras del clock para alimentar la CPU y los Perifricos pueden serdistintas:Si usamos un cristal o un resonador externo, este lo podemos conectar entre los

    terminales OSC1 y OSC2. En caso de usar cristales, estos deben ser configurados en losbits de configuracin como HS, XT o LP, segn el rango de frecuencias donde trabajen.Para esto Microchip nos da una tablita de referencia:

    En estos casos el hardware se realizar no solo conectando el respectivo cristal entre losterminales, sino tambin 2 capacitores del tipo cermico, preferentemente NP0 respectoa masa, para estabilizar la frecuencia, y eliminar armnicos indeseados.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    38/58

    Los nuevos PIC incorporan un juego de 3 osciladores internos, denominadosHFINTOSC de 16MHz, MFINTOSC de 500KHz y LFINTOSC de 31KHz. De estos

    por medio de un divisor de frecuencia programable, podemos obtener distintasfrecuencias para excitar a la CPU y los perifricos. E incluso es posible derivar la salidadel divisor de 8 MHz , para pasarla por el PLL y de esta forma tener 32 MHz defrecuencia de clock. En esta modalidad la CPU puede alcanzar su velocidad mxima de

    procesamiento para estos micros; 8 MIPS (8 Millones de Instrucciones Por Segundo).Esta opcin del PLL no solo la activamos para el oscilador interno sino tambin para loscristales externos, sin embargo debe cuidarse de no superar los 32Mhz internos al CPU.

    Otra de las opciones internas que tiene este microcontrolador es la posibilidad de activarel BROWOUT RESET, el cual resetear el microcontrolador en caso de detectar unavariacin de la tensin de alimentacin del microcontrolador.

    Adems en los nuevos PIC es posible conmutar el oscilador en el momento de arranque,para ello existe un fusible de configuracin mediante llamado IESO el cual habilita laconmutacin o no.La conmutacin de la fuente del oscilador se usa por lo general cuando se quiere ahorrarenerga, por ejemplo, se arranca en el modo de cristal externo de alta velocidad, y luegose pasa al oscilador interno de baja frecuencia.En este caso el sistema utiliza un bit denominado SCS (System Clock Select ), el cual seencuentra dentro de un registro interno que controla al oscilador y que se denomina

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    39/58

    OSCCON. Este bit permite realizar la conmutacin por software desde el osciladorexterno al interno y viceversa.Por lo general, excepto que se este diseando una aplicacin donde se debe ahorrar almximo los recursos de energa, la opcin del IESO no se utiliza.Otro recurso novedoso es el detector de la falla del oscilador primario o externo FSCM

    (Fail-Safe Clock Monitor). Este modulo, cuando se activa, monitorea el osciladorprimario (LP, XT,HS, EC, RC y el Oscilador del Timer1). Para ello compara esteoscilador con la seal de clock de 31Khz del LFINTOSC. Si el oscilador externo llegasea perder pulsos de clock, esto ser detectado por el FSCM, lo cual activar una

    bandera indicadora denominada OSFIF (Oscilador Fail Interrupt Flag), la cual si seencuentra debidamente habilitada por medio del bit OSFIE, generar una interrupcin,mediante la cual se puede conmutar hacia el oscilador interno usando el bit SCSmencionado anteriormente y pasar a trabajar con el oscilador interno HFINTOSCseteado en algn valor de frecuencia por medio del divisor de frecuencia programable.

    Todas estas caractersticas pueden ser habilitadas o no, mediante el correcto seteo de losfusibles de configuracin usando la directiva #FUSES.Dentro de la carpeta PICC del compilador encontraremos una carpeta denominadaDEVICES, dentro de la cual encontraremos los archivos de cabecera que contienentodas las etiquetas para manejar los microcontroladores PIC de forma sencilla yconfigurar todas las opciones vistas. Existe un archivo de cabecera por cada micro:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    40/58

    Dentro de este archivo podemos ver el conjunto de etiquetas que nos permiten setearestas opciones parra configurar los fusibles de configuracin desde el cdigo, usando ladirectiva #FUSES:

    Estas etiquetas pueden cambian entre microcontroladores porque no todos tienen lasmismas opciones de configuracin, de hecho algunas de las que mencionamos son

    exclusivas de los PIC16F1XXX y PIC18F, mientras que en los PIC16F convencionalesno se encontrarn. Por ello es buena prctica que a nuestros proyectos le adjuntemos elarchivo de cabecera de nuestro microcontrolador, a modo de consulta:

    Para asimilar estos conceptos vamos a aplicarlos en un proyecto inicial, el cual consistee leer 3 pulsadores y accionar 3 leds.En este caso configuraremos las opciones de los fusibles de configuracin de lasiguiente manera:

    Oscilador: Usaremos el Interno a una frecuencia de 4 MHz

    FSCM: No lo usaremos pues trabajamos con oscilador interno IESO: tampoco lo usaremos por la misma razn que el anterior

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    41/58

    WatchDog Timer: Lo desactivado ya que es una aplicacin no comercial Power Up Timer: Lo activaremos para asegurar un arranque estable STVREN: no lo usaremos pues al ser sencilla la aplicacin no es posible que se

    desbode el STACK DEBUG: no lo usaremos pues no vamos a depurar cdigo BROUNOUT: no lo usaremos pues no es una aplicacin comercial VCAP: no lo usaremos pues no trabajamos con teclados MTOUCH PROTECT: no lo usaremos pues no necesitamos proteger el cdigo CPD: tampoco necesitamos proteger los datos en EEPROM pues no la usaremos WRT: tampoco usaremos la proteccin contra escritura de la memoria FLASH

    de programa pues esta opcin se usa por lo general en los modos de autoprogramacin cuado el microcontrolador viene equipado con un pequeofirmware llamado BOOTLOADER.

    En estas condiciones (las cuales usamos usualmente cuando realizamos proyectos NOCOMERCIALES, y que usaremos para todos los proyectos del libro), los fusibles de

    configuracin se setearn mediante la directiva #FUSES de la siguiente forma:#include //archivo de cabecera del PIC usado

    #FUSES INTRC_IO //Oscilador Interno y tanto RA6 como RA7 son I/O

    #FUSES NOCLKOUT //No sale el clock interno hacia afuera

    #FUSES NOWDT //Watch Dog Timer apagado

    #FUSES PUT //Power Up Timer activado

    #FUSES NOBROWNOUT //Reset ante variaciones de VCC desactivado

    #FUSES NOIESO //Switch del oscilador en el encendido apagado

    #FUSES NOFCMEN //detector de falla del oscilador principal apagado

    #FUSES NOSTVREN //reset por desborde del stack desactivado

    #FUSES NOLVP //Programacin en baja tensin desactivada

    #FUSES NOPROTECT //Proteccin contra lectura de la FLASH desactivada

    #FUSES NOCPD //Proteccin de la EEPROM desactivada

    #FUSES NOVCAP //Regulador de voltaje para el MTOUCH apagado

    Para hacer ms comprensible el cdigo desde el punto de vista del programador,crearemos una serie de etiquetas para el manejo de los puertos de entrada/salida :

    #define LED1 PIN_B0 //PORTB RB0

    #define LED2 PIN_B1 //PORTB RB1

    #define LED3 PIN_B2 //PORTB RB2

    #define SW1 PIN_A0 //PORTA RA0

    #define SW2 PIN_A1 //PORTA RA1

    #define SW3 PIN_A2 //PORTA RA2

    El compilador CCS, es un compilador orientado a los programadores, ms que a loselectrnicos, y por tal motivo tiende a ser ms amigable la arquitectura y manejo delmismo al usuario. Por tal motivo a la hora de nombrar los puertos del microcontrolador,dentro del archivo de cabecera 16F1939.h ha llamado a los mismos no por el nombreque figuran en el dataste, sino por el seudnimo PIN_XY donde X es la letra del puertoal que pertenecen por ejemplo A,B,C,D,etc, y la letra Y representa el nmero del bit.

    Los Puertos de entrada/salida (PORTS I/O) son usados para controlar el entorno delmicrocontrolador. El PIC16F1939 cuenta con un total de 36 puertos. Estos si bien secontrolan de forma independiente, se agrupan en arreglos de 8 bits. De esta formanuestro PIC tiene 5 grupos denominados PORTA (8bits), PORTB (8bits), PORTC

    (8bits) , PORTD (8bits) y PORTE (4 bits). Cada puerto de forma independiente se

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    42/58

    denomina RXY, donde X es la letra del grupo al cual pertenece e Y es el nmero deorden, el cual puede ser desde 0 (menor peso) a 7 (el de mayor peso).Todos los puertos son bi-direccionales, es decir que pueden ser programados paratrabajar como puerto de entrada o salida. La direccin de los puertos esta controlada porunos registros denominados TRISX, donde X es la letra que corresponde al PORT que

    controlan:

    Segn el estado lgico que se cargue en un bit del registro TRIS, el PORT

    correspondiente trabajar como entrada o salida (1= Entrada, 0=Salida).Los puertos tiene la capacidad de entregar como mximo una corriente de 25ma. Yreconocen el estado lgico como la lgica TTL, es decir que cualquier tensin porencima de los 2,5V es reconocida como 1 lgico, y por debajo de 0,8V como un cero.Por otra parte entregan una tensin 1 lgico como los CMOS, la cual llega a VCC.

    En los microcontroladores PIC la mayora de los puertos estn multiplexados con otrasfunciones, como ser puertos de comunicaciones, entradas para el conversor analgico,entradas a comparadores de voltaje, salidas PWM, etc.Cuando un PIC arranca su operacin, la inicia con sus capacidades analgicas activas,esto significa que aquellas entradas que se conectan al conversor analgico digital o alos comparadores, o como en el caso del PIC16F1939, las entradas MTOUCH.Es por esta razn que el usuario debe configurar dichas entradas como analgicas odigitales antes de usarlas. Para ello existe saciado a cada PORT, un registro denominadoANSELA para el PORTA, ANSELB para el PORTB, ANSELE para el PORTE yANSELD para el PORTD. Para que un puerto determinado funcione como digital, alANSEL correspondiente hay que ponerlo en estado lgico 1.

    Para simplificar el manejo de los puertos CCS tiene una serie de funciones embebidas,es decir que estn incorporadas en el mismo compilador, y que no se necesita agregarningn archivo de cabecera para usarlas.

    Estas son:output_high(PIN_XY); //pone en uno un pin determinado

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    43/58

    output_low(PIN_XY); //pone en cero un pin determinado

    output_bit(PIN_XY,estado); //pone en cero o uno un pin determinado

    output_X(valor); //saca un valor de 8 bits por un puerto determinado

    input(PIN_XY); //lee el estado de un pin y nos devuelve el mismo

    input_X(); //lee el estado de un puerto completo y devuelve el mismo

    A continuacin haremos uso de estas funciones, las cuales se encargan adems deconfigurar el puerto como salida o entrada.Adems de estas funciones se incorpora una funcin mediante la cual se puede setearque pines funcionaran como analgicos o no, la misma se denomina:

    setup_adc_ports(pines analgicos) //setea que puertos son analogicos

    Para nuestro caso como no usaremos los puertos analgicos, le pasaremos a esta funcinla etiqueta NO_ANALOGS, como figura en el archivo de cabecera 16F1939.h:

    De esta forma nuestra configuracin de puertos analgicos y digitales quedar de lasiguiente forma:

    setup_adc_ports(NO_ANALOGS); //configuramos los puertos como digitales

    Lo que nos queda simplemente es el cdigo, el cual estar incluido dentro de un bucleinfinito, realizado mediante un while(TRUE), ya que esa ser la tarea que eternamentedeber realizar el microcontrolador.

    La tarea es sencilla: nuestra CPU solo debe ver que pulsador (SW) se accion yconforme a ello encender un LED determinado. Para cubrir este objetivo usaremos lasfunciones para control I/O embebidas y las estructuras condicionales IF://bucle principal

    while(TRUE){

    if(input(SW1)) //chequeamos si SW1=1

    output_high(LED1); //si si, encendemos LED1

    else //sino

    output_low(LED1); //apagamos LED1

    if(input(SW2)) //chequeamos si SW2=1

    output_high(LED2); //si si, encendemos LED2

    else //sinooutput_low(LED2); //apagamos LED2

    if(input(SW3)) //chequeamos si SW3=1

    output_high(LED3); //si si, encendemos LED3

    else //sino

    output_low(LED3); //apagamos LED3

    }

    En el siguiente listado mostramos el programa completo:

    #include

    #fuses INTRC_IO,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOCLKOUT

    #fuses NOIESO,NOFCMEN,NOWRT,NOVCAP,NOSTVREN,NODEBUG,NOLVP

    #use delay(internal,clock=4000000)

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    44/58

    #define LED1 PIN_B0 //PORTB RB0

    #define LED2 PIN_B1 //PORTB RB1

    #define LED3 PIN_B2 //PORTB RB2

    #define SW1 PIN_A0 //PORTA RA0

    #define SW2 PIN_A1 //PORTA RA1

    #define SW3 PIN_A2 //PORTA RA2

    void main(void)

    {

    setup_oscillator(OSC_4MHZ|OSC_INTRC|OSC_PLL_OFF);

    setup_adc_ports(NO_ANALOGS);

    while (TRUE)

    {

    if(input(SW1)) //chequeamos si SW1=1

    output_high(LED1); //si si, encendemos LED1

    else //sino

    output_low(LED1); //apagamos LED1

    if(input(SW2)) //chequeamos si SW2=1

    output_high(LED2); //si si, encendemos LED2

    else //sino

    output_low(LED2); //apagamos LED2

    if(input(SW3)) //chequeamos si SW3=1

    output_high(LED3);//si si, encendemos LED3

    else //sino

    output_low(LED3); //apagamos LED3

    }

    }Observe que en el listado hemos seteado los fusibles de configuracin en 2 lineas,aunque tambin podra haberse realizado todo en una.

    El circuito que utilizaremos para hacer funcionar nuestro cdigo, lo presentamos en lasiguiente figura:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    45/58

    En el circuito es bastante sencillo:

    Los resistores R4,R5 y R6 son resistores de PULL DOWN; R1,R2 y R3 limitanla corriente instantnea que se genera al accionar los pulsadores SW1,SW2 y SW3.Los LEDs estan polarizados a unos 10ma aprox. por medio de los resistores R7,R8 yR9. Finalmente el pin MCLR se encuentra conectado a VCC por medio del resistor dePULL UP R10.El circuito no necesita de ningn cristal externo ya que se usa el oscilador interno.La aplicacin puede alimentarse desde una batera de 9V o una fuente equivalenteusando el siguiente circuito regulador:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    46/58

    El esquemtico lo hemos realizado con el Proteus, y es por esta razn que debemosadvertirles que los pines de alimentacin NO FIGURAN EN EL CIRCUITO, ya quePROTEUS da por sentado que el tcnico ya sabe como alimentarlo.Dichos pines, para los encapsulados de 40 terminales son VCC:11 y 32, GND:12 y 31Para poder programar nuestro cdigo dentro del microcontrolador, prepararemos en elextremo del circuito impreso un conector de tira de pines (5 postes) para realizar la

    conexin ICSP segn el siguiente esquema:

    Como esta conexin ser un estndar en nuestros circuitos ya que es una forma muyprctica de programar nuestro programa de aplicaciones sobre el PCB sin retirar elmicrocontrolador del mismo. El lector podr observar, luego con el uso, la velocidadque adquiere la depuracin de un cdigo.

    Hagamos un driver para un motorAprovechando ya los primeros conocimientos, los pondremos en prctica sobre unaaplicacin real, disearemos el control de un motor de corriente continua de 12V hasta 1A, del tipo usado en muchas aplicaciones pequeas. El sistema de control nos permitiractivar el arranque y la parada del motor as como cambiar su direccin.Para el circuito usaremos el PIC16F1939 que estamos estudiando, ademsnecesitaremos un L293D, el cual es un driver para motores de corriente continua dehasta 1 Amper, unos pulsadores y unos LEDs para hacer la sealizacin.El circuito lo implementaremos sobre una placa del tipo pertinax multiperforada paso2.54mm, muy comunes actualmente, y generalmente usadas para la implementacin decircuitos experimentales.

    El circuito podemos verlo a continuacin:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    47/58

    La secuencia de nuestro programa ser muy simple; leer los pulsadores y en funcin delpulsador que accionemos, cambiaremos la funcin del dispositivo.Las funciones de la aplicacin estarn controladas por 2 Flags (banderas) internos, loscuales se implementan mediante la creacin de 2 variables de 1 bit, y a las quellamaremos FLAG_RUN y FLAG_FWRW.La aplicacin estar constituida por 2 rutinas o funciones del tipo void-void, que leernel estado de los pulsadores (ScanKey) y controlaran el funcionamiento del motor(MotorControl).Para implementar el programa usaremos las funciones embebidas estudiadasanteriormente y los recursos del lenguaje C tambin estudiados en los apartadosanteriores.El listado del programa con su respectivo comentario lo presentamos aqu:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    48/58

    //archivo de cabecera del procesador

    #include

    //seteamos la frecuencia del delay

    #use delay(internal, clock=4000000)

    //fusibles de configuracin#fuses INTRC_IO //oscilador Interno con Puertos IO

    #fuses NOPROTECT//sin proteccin de cdigo

    #fuses PUT//Power Up Timer activado

    #fuses NOBROWNOUT//Sin Brown Out

    #fuses NOWDT//sin WDT

    #fuses MCLR//master clear

    #fuses NOCLKOUT//no sale la frecuencia del clock

    #fuses NOIESO//cambio de clock desactivado

    #fuses NOFCMEN//sin monitor de falla de clock

    #fuses NOWRT//sin proteccin contra escritura

    #fuses NOVCAP//regulador para el MTOUCH desactivado

    #fuses NOSTVREN//reset por desborde del stack desactivado

    #fuses NOLVP//programacin en bajo voltaje desactivado

    //definiciones de etiquetas

    #define BTN1 PIN_A0

    #define BTN2 PIN_A1

    #define RUN PIN_B0

    #define FW PIN_B1

    #define RW PIN_B2

    //funciones prototipo

    void ScanKey(void);

    void MotorControl(void);

    //variables globales

    short FlagRUN=0;

    short FlagFWRW=0;

    //programa principal

    void main(void)

    {

    // Configuramos el oscilador interno

    setup_oscillator(OSC_4MHZ|OSC_PLL_OFF|OSC_INTRC);

    // Configuramos los puertos analgicos como digitales

    setup_adc_ports(NO_ANALOGS);

    // Bucle principal

    while(true){

    ScanKey(); //llamada a la funcin de lectura de los

    pulsadores

    MotorControl();//llamada a la funcin de control del motor

    }

    }

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    49/58

    //Rutinas auxiliares:

    void ScanKey(void)

    {

    if(input(BTN1)) //lee el estado del pulsador

    { //si el mismo est accionadoFlagRUN=!FlagRUN;//cambia el estado de FlagRUN

    MotorControl();//llamada a la funcin que controla el motor

    delay_ms(2);//espera para evitar leer el rebote al oprimir

    while(input(BTN1));//re-lectura espera que se suelte

    delay_ms(2);//espera para evitar leer el rebote al soltar

    }

    if(input(BTN2)) //lee el estado del pulsador

    { //si el mismo est accionado

    FlagFWRW=!FlagFWRW;//cambia el estado de FlagFWRW

    MotorControl();//llamada a la funcin que controla el motor

    delay_ms(2);//espera para evitar leer el rebote al oprimer

    while(input(BTN2));//re-lectura espera que se suelte

    delay_ms(2);//espera para evitar leer el rebote al soltar

    }

    }

    void MotorControl(void)

    {

    if(FlagRun==1)// FlagRUN=1 ?

    output_high(RUN);//habilita el motor

    else

    {

    output_low(RUN);//sino desactiva el L293

    output_low(FW);//apagamos FW y RW

    output_low(RW);

    }

    if(FlagRun==1)// FlagRUN=1 ?

    {

    if(FlagFWRW==1)// FlagFWRW=1?

    {

    output_low(RW); //apaga RW

    delay_ms(50); //espera un tiempo

    output_high(FW);//enciende FW

    }

    else // Sino

    {

    output_low(FW);//apaga FW

    delay_ms(50); //espera un tiempo

    output_high(RW);//enciende RW

    }

    }

    }

    El programa est realizado usando un algoritmo denominado multitarea cooperativa,ya que el main esta constituido por llamadas a funciones sucesivas, donde cada funcinrealiza una tarea determinada y cooperan entre s para generar como resultado finalla aplicacin requerida.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    50/58

    Aprendamos a Manejar un LCD alfanumricoEn nuestra anterior nota aplicamos nuestros primeros conocimientos para hacer un

    pequeo control de un motor de corriente continua.Hoy aprenderemos a manejar un LCD inteligente alfanumrico.El trmino inteligente deviene de que el LCD trae un controlador propio el cual se

    encarga de posicionar el mensaje, donde le decimos, y adems realiza el barrido de lainformacin a presentar en el display de forma autnoma. Para nosotros el LCD es un

    perifrico ms con el cual podemos comunicarnos.Este tipo de display fue desarrollado por la firma HITACHI a mediado de los 80,cuando desarroll un controlador para los mismos al cual bautiz con el cdigoHD77480, el cual tuvo tal repercusin en mercado que se transform en un estndar yactualmente otras compaas, como SAMSUNG fabrican controladores de similarescaractersticas (KS0066 o el S6A0069 entre otros).El controlador se encarga de todo, nosotros debemos conectar el display, inicializarlo yluego enviarle los mensajes que queremos en formato ASCII y los comando que ledigan donde posicionar el mensaje, en caso de no enviarle un comando de

    posicionamiento, el colocar el mensaje a partir de la ltima posicin donde seencuentra el cursor.

    El PIN-OUTEl LCD como se transform en casi un estndar de mercado, posee un PIN-OUT querespetan todos los fabricantes de LCD alfanumericos:

    Estos display se pueden conectar usando una interfaz de 8 cables para el bis de datos, otan solo 4. Por otra parte el bus de control puede contener las 3 lneas: RS, E y R/W; otan solo 2: RS y E, la lnea R/W en este caso es conectada directamente a masa.Como en los microcontroladores siempre tratamos de ahorrar puertos I/O, lasconexiones siempre se realizan con un bus de datos de 4 lneas, y el bus de control se

    puede realizar implementando 2 o 3 lneas, dependiendo si queremos manejar latransferencia de datos de forma inteligente, consultando el estado del LCD antes detransferir un dato, o por el mtodo de Fuerza Bruta, en el cual NO SE USA R/W,conectando este pin directamente a masa. En este caso entre dato y dato se espera un

    tiempo de unos 2 a 5 ms.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    51/58

    La conexin de 8 bits se usaba en la poca de la programacin ASSEMBLER, ya queera ms sencilla la rutina de manejo del LCD. Sin embargo como casi todos losdesarrollos actualmente se realizan con interfaces de 4 bits, la conexin de 8 bits en busde datos ha sido descartada.

    DRIVER PARA EL LCDEn la actualidad realmente es un placer trabajar con un LCD alfanumrico, ya que CCSha desarrollado una librera para el manejo del mismo, la cual es instalada en el mismo

    proceso de instalacin y que encontraremos dentro de la carpeta de CCS, en la carpetaDRIVERS:

    C:\Archivos de programa\PICC\Drivers

    La librera se denomina lcd.cDentro de la misma encontraremos los #define para que fijemos la conexin:

    #define LCD_ENABLE_PIN PIN_E0

    #define LCD_RS_PIN PIN_E1

    #define LCD_RW_PIN PIN_E2

    #define LCD_DATA4 PIN_D4

    #define LCD_DATA5 PIN_D5

    #define LCD_DATA6 PIN_D6

    #define LCD_DATA7 PIN_D7

    Los tres primeros #define nos permiten indicarle al compilador que pines del micro seusaran en la conexin del bus de control del LCD, los siguientes nos permiten definirque pin de que puerto se usar como puerto de datos.

    Una vez configurada la conexin, las funciones a usar generalmente sern:

    lcd_init(); //inicialza el LCD, se debe colocar al principio

    lcd_gotoxy();//posiciona el cursor segn las coordenadas

    //que se le pasen a la funcin x: determina la

    //posicin dentro de la linea

    //y: determina la linea

    lcd_putc();// nos permite escribir caracteres al LCD

    En el siguiente ejemplo veremos funcionar el LCD con su librera.

    A continuacin realizamos un contador ASCENDENTE/DESCENDENTE programabley para mostrar el estado de cuenta usaremos un LCD de 2 filas (renglones) por 16caracteres , el cual es uno de los mas difundos en mercado.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    52/58

    La tensin de alimentacin del LCD es de 5V.El pulsador nos permite indicarle al contador si cuenta en forma ascendente odescendente. El pulsador RESET nos permite resetear el microcontrolador y por tanto

    reiniciar el contador. Los pulsos a contar se aplican a RA4, y los diodos D1 y D2

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    53/58

    forman un circuito de enclavamiento de entrada, evitando que la seal de entrada excedalos 5V respecto a masa.El listado del programa es el siguiente:

    #include

    #device adc=10

    #fuses

    INTRC_IO,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOCLKOUT,NOIESO

    #fuses NOFCMEN,NOWRT,NOVCAP,PLL_SW,STVREN,NODEBUG,NOLVP

    #use delay(clock=4000000)

    //posicionamos LCD

    #define LCD_ENABLE_PIN PIN_D6 ////

    #define LCD_RS_PIN PIN_D4 ////

    #define LCD_RW_PIN PIN_D5 ////

    #define LCD_DATA4 PIN_D0 ////

    #define LCD_DATA5 PIN_D1 ////

    #define LCD_DATA6 PIN_D2 ////

    #define LCD_DATA7 PIN_D3

    //libreria LCD

    #include

    //prototipo de funciones

    void Lee_teclado(void);

    void Lee_pulso(void);

    void PrintLCD(void);

    //variables globales

    signed long contador=0;//variable contador

    short Flag=0;//indicador de modo de cuenta

    void main(void)

    {

    setup_oscillator(OSC_INTRC|OSC_4MHZ|OSC_PLL_OFF);//configuramos eloscilador

    setup_adc_ports(NO_ANALOGS);//desactivamos los canales analogicos

    del ADC

    setup_lcd(LCD_DISABLED);//desactivamos el driver de LCD interno

    lcd_init();//inicializamos el LCD

    while(TRUE)

    {

    lee_teclado();//leemos el teclado

    Lee_pulso();//leemos si ingresaron pulsos

    PrintLCD();//inprimimos en el LCD

    }

    }

    void Lee_teclado(void)

    {

    if(input(PIN_A0))//test si se pulso el cambio de modo de cuenta

    {

    Flag=!Flag; //cambiamos de estado el flag que controla el

    modo de cuenta

    delay_ms(2); //antirebote de entrada

    while(input(PIN_A0));//enclavamiento si el usuario sigue

    pulsando

    delay_ms(2);//anti rebote de salida

    }

    }

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    54/58

    void Lee_pulso(void)

    {

    if(input(PIN_A4))//ingreso un pulso

    {

    if(Flag==1)//que estado tiene el flag

    {

    contador=contador+1;//si Flag=1 incrementa el contadorif(contador>9999) //verificamos el final de cuenta superior

    contador=0;

    }

    else

    {

    contador=contador-1;//si Flag=0 decrementa el contador

    if(contador

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    55/58

    Programando los

    Perifricos con el

    compilador CCS

    Los Microcontroladores PIC son los reyes del sistema decontrol embebido, son la mejor representacin de los mismosya que integran una gran cantidad de perifricos como serADC, USART, Timers, PWM, Modulos de Captura,Comparadores Analgicos, Drivers para LCDs, Sensado de

    Teclado Capacitivo (MTOUCH), Interfaces I2C y SPI,Generadores de Frecuencia lineales, Sensores de Temperatura(TIM), Interfaz USB y ETHERNET, CAN y PWM trifsicos etc.

    Aprendamos el ABC del conversor A/DEl Conversor A/D que integran los PIC16F1939 es de 10 bits, y este pude ser utilizado

    para medir cualquier variacin analgica que se encuentre entre 0 y 5V mximo.En el PIC16F1939 tenemos 14 canales de conversin es decir que podemos acceder alconversor por 14 pines distintos.En la siguiente figura podemos ver su diagrama en bloques:

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    56/58

    Adems de los 14 canales (AN0-AN13) el conversor tambin pude acceder al sensor detemperatura interno que tiene integrado (Temp Sens) mediante el cual se puede medir aque temperatura se encuentra el propio chip, el conversor DAC y y VFR o generador devoltaje de referencia interno. Todo mediante un multiplexor que se encuentra a laentrada del ADC, el cual es controlado por los bits selectores del canal CHS0 a CHS4.La tensin de referencia del ADC pude ser interna o externa segn sea seleccionado.Para encender el conversor debe ponerse en uno el bit ADON y para iniciar el procesode conversin se usa el bit GO/DONE (el usuario activa el bit GO/DONE, y al finalizarla conversin automticamente el ADC apaga el bit GO/DONE).El resultado en 10 bits se almacena en dos registros denominados ADRESH y ADRESL

    (ADRESH contiene los bits de mayor peso y ADRESL los de menor peso). El resultadose puede ajustar a la derecha o a la izquierda segn como se haya seteado con el bitADFM que controla el formato.

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    57/58

    El clock para excitar el ADC se obtiene por divisin de la frecuencia de procesamientode la CPU, denominada FCY (FCY=OSC/4), o puede provenir de su propio osciladorRC.

    Usemos CCS para controlar el ADCCCS tiene una librera muy sencilla para el manejo del A/D, la cual esta formada por elconjunto de las siguientes 4 funciones embebidas:

    setup_adc_ports(etiquetas); //setea pines funcionaran analogicos

    setup_adc(etiquetas);//setae oscilador del adc

    set_adc_channel(Nro Canal);//setea el canal a medir

    variable=read_adc();//lee el valor del conversor y lo almacena

    Como se puede apreciar es bastante sencillo el manejo del conversor, para metabolizarlo que acabamos de aprender veremos una aplicacin donde realizamos un voltmetro

    de 0 a 5 Volt. A continuacin exponemos el cdigo:

    #include

    #device adc=10 //defiimos el resultado del adc, en 10 bits

    #fuses INTRC_IO,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,NOBROWNOUT

    #fuses NOFCMEN,NOWRT,NOVCAP,PLL_SW,STVREN,NODEBUG,NOLVP,NOCLKOUT

    #use delay(internal=4000000)

    #include "flex_lcd.c"

    void lee_adc(void);

    void muestra(void);

    float convervolt(long valor);

    #define VREF 5.0

    #define RESOLUCION 1024.0

    long valor_adc=0; //variable de 16 bits OJO INT es igual a CHAR es

    decir 8 bit

    void main(void)

    {

    setup_adc_ports(sAN0|VSS_VDD);//configure AN0 como analog y el

    resto

    //digital con referencia interna

    setup_adc(ADC_CLOCK_INTERNAL);//configuro la velocidad del ADC

    output_b(0);//inicializa el PORTB

    lcd_init();//INICIA EL lcd

  • 7/21/2019 Aprendiendo Aprogramar PIC Con CCS

    58/58

    while(TRUE)

    {

    lee_adc();

    muestra();

    }

    }

    void muestra(void)

    {

    float voltaje;

    lcd_gotoxy(1,1);//posiciona el cursor en la posicion 1, linea 1

    printf(lcd_putc,"ADC con CCS");//escribimos en el lcd

    voltaje=convervolt(valor_adc);

    lcd_gotoxy(1,2);//posiciona el cursor en la posicion 1, linea 2

    //escribimos el valor del adc en decimal y como voltaje

    printf(lcd_putc,"AN0=%04Lu->V=%1.2f",valor_adc,voltaje);

    }

    void lee_adc(void)

    {

    set_adc_channel(0);//selecciono el canal a leer (canal0)

    //enciendo el conversor y leeo el valor

    valor_adc=read_adc(ADC_START_AND_READ);

    }

    float convervolt(long valor)

    {

    float volt;

    volt=(float)((VREF/RESOLUCION)*valor);

    return volt;

    }

    La tensin de entrada se aplica con un potencimetro, de 10K como mximo, a laentrada AN0. Luego de convertida es mostrada en el LCD como su valor crudo y suequivalente en tensin, para marcar la correspondencia entre los valores.

    Autor: Andrs Ral Bruno Saravia

    Empresa: RTC-Argentina (centro regional de entrenamiento oficial de Microchip)

    Lugar y Fecha: Buenos Aires Argentina. 23 de Abril del ao 2012-12-11

    Queda autorizada la copia y distribucin gratuita del presente material