Você está na página 1de 6

Proyecto con un PIC18F4550 y XC8

Posted on 22 Agosto, 2012 by Suky


Teniendo una idea general de cmo es la estructura de un archivo fuente de C pasaremos a realizar un primer ejemplo como para llevarlo al hardware y ver su funcionamiento. Para trabajar nuestro microcontrolador necesita una fuente de reloj, que provea una seal a frecuencia constante que permita ir leyendo y ejecutando las sentencias secuencialmente. Generalmente los microcontroladores modernos ofrecen la posibilidad de recibir esta seal de reloj desde varias fuentes, cristales externos, osciladores externos u osciladores internos, pero adems permiten elevar la frecuencia de trabajo internamente (PLL). Esto permite mayor flexibilidad y adems al aumentar la frecuencia ejecutar ms instrucciones por segundo. El microcontrolador PIC18F4550 que se utiliza en este tutorial incluye un PLL que permite multiplicar la frecuencia de un cristal u oscilador externo, pero no as del oscilador interno. A tener en cuenta, los microcontroladores de gama baja de Microchip necesita 4 ciclos de reloj para ejecutar una instruccin simple, entonces tenemos que Fcy=Fosc/4. Un PIC18F4550 que puede trabajar hasta 48 MHz ejecuta como mximo 12 millones de instrucciones por segundo, o sea 12 MIPS. Para seleccionar qu tipo de fuente de reloj se utilizar y la configuracin del PLL se utilizan los bits de configuracin del microcontrolador que solo pueden ser modificados al ser programados. Adems de estas opciones los bits de configuracin permiten establecer otras caractersticas como por ejemplo, habilitar o no el reset, proteger contra lectura ciertos sectores de programa, habilitar el perro guardian, etc. Para ms detalles hay que estudiarse el datasheet del microcontrolador especfico, dado que en PICs pueden variar entre familias. Para configurar el reloj y PLL del PIC18F4550 veamos el siguiente esquema extrado del datasheet:

Vamos a fijar como frecuencia de trabajo los 48 MHz mximos que soporta el microcontrolador, para ello vamos a utilizar como fuente un cristal externo de 12 MHz. Para lograr los 48MHz es necesario habilitar el PLL, esto lo hacemos mediante los bits FOSC3:FOSC0. Para un cristal de 12 MHz se debe colocar 111x = HS oscillator, PLL enabled (HSPLL) y revisando la documentacin que provee XC8 (doc/pic18_chipinfo.html) se debe colocar FOSC=HSPLL_HS. Si observamos la figura anterior, al habilitar el PLL la frecuencia de entrada del mismo debe ser 4 MHz, y para ello se provee de un divisor de frecuencia controlado por PLLDIV, en este caso los 12 MHz los dividimos por 3, por lo tanto debemos hacer PLLDIV=3. La frecuencia de salida del PLL es de 96 MHz, los cuales sirven de fuente de clock para el mdulo USB y tambin para el microcontrolador. Pero

para el microcontrolador los 96 MHz los podemos dividir en 2, 3, 4 o 6! O sea, podemos obtener gran variedad de frecuencias. Como nos establecimos como meta obtener 48 MHz debemos hacer CPUDIV=OSC1_PLL2. En resumen en los bit de configuraciones establecemos: #pragma config FOSC=HSPLL_HS, PLLDIV=3, CPUDIV=OSC1_PLL2 Estas configuraciones seran las principales para establecer el reloj de nuestro microcontrolador pero existen dos fusibles de configuracin que otorgan otras opciones de trabajo. Tenemos IESO, que permite cambiar la fuente de clock cuando el microcontrolador est en funcionamiento y FCMEN que en caso de fallar la fuente de reloj principal realiza el cambio a la fuente de reloj interna INTRC. Dentro del datasheet hay secciones donde podemos encontrar ms detalles para el uso de estos modos, aqu solo los estableceremos como OFF: #pragma config IESO=OFF, FCMEN=OFF Como comentamos anteriormente existen otros fusibles de configuracin que dependen del microcontrolador utilizado, aqu vamos a establecerlos de la siguiente manera, los detalles los podemos encontrar en la seccin Special Feactures of the CPU/Configuration Bits. #pragma config PWRT=OFF, BOR=OFF, BORV=3, VREGEN=OFF, WDT=OFF #pragma config MCLRE=ON, XINST=OFF Hay varios ms, pero si no se configuran quedan como vienen por defecto. En MPLAB X podemos ver la configuracin en Windows/PIC Memory Views/Configuration Bit. Como primer ejemplo vamos hacer titilar un led, este ejemplo es el Hola Mundo en los microcontroladores. Para ello vamos a necesitar una funcin que cree una demora y para ello XC8 dispone de __delay_us() y __delay_ms(), para integrarlas debemos llamar a xc.h pero adems previamente definir el valor de _XTAL_FREQ. A tener en cuenta, tanto __delay_ms como __delay_us utilizan la funcin _delay(), y esta solo soporta hasta 197120 ciclos, o sea que para 48 MHz la mxima demora posible es 16.42 ms. Para el control del led debemos establecer el pin a utilizar como salida y luego escribir en el pin el valor que queramos establecer (0 o 1 lgico), para ello tenemos los registros TRIS y los registros LAT. En caso de necesitar leer el valor que tiene un pin se utilizan los registros PORT. Esto es una mejora introducida a partir de la familia PIC18, debido a que en familias anteriores para hacer operaciones sucesivas en puertos se necesitaba agregar un nop entre ellas. Si por ejemplo queremos controlar nuestro led mediante el pin B0 debemos trabajar con TRISB y LATB, XC8 para facilitarnos el desarrollo tiene definido el bit 0 de TRISB como TRISB0 o como tambin es compatible con C18 se puede acceder mediante TRISBbits.TRISB0. Los mismo para el bit 0 de LATB, LATB0 o LATBbits.LATB0. Esto lo podemos ver en el archivo cabecera pic18F4450.h que se encuentra en xc8\v1.00\include. Entonces el cdigo ejemplo seria de la siguiente forma:

/* * File: main.c * Author: Suky */ #define _XTAL_FREQ 48000000 #include <xc.h> #pragma config FOSC=HSPLL_HS, PLLDIV=3, CPUDIV=OSC1_PLL2 #pragma config IESO=OFF, FCMEN=OFF #pragma config PWRT=OFF, BOR=OFF, BORV=3, VREGEN=OFF, WDT=OFF #pragma config MCLRE=ON, XINST=OFF void main(void) { TRISB0=0; // Lo establecemos como salida while(TRUE){ // _delay(x) 197120 cycles max LATB0=0; // Apagamos led __delay_ms(10); LATB0=1; // Encendemos led __delay_ms(10); } } Nota: Tener en cuenta que la demora generada es solo de 10ms, en simulacin se podr visualizar el titilar del led pero en una implementacin real no, pronto lo mejoraremos Pero hagamos uso de los macros!!! El ejemplo quedara as: /* * File: main.c * Author: Suky */ #define _XTAL_FREQ 48000000 #include <xc.h> #pragma config FOSC=HSPLL_HS, PLLDIV=3, CPUDIV=OSC1_PLL2 #pragma config IESO=OFF, FCMEN=OFF #pragma config PWRT=OFF, BOR=OFF, BORV=3, VREGEN=OFF, WDT=OFF #pragma config MCLRE=ON, XINST=OFF #define PIN_DIR_LED TRISB0 #define PIN_LED LATB0

#define OUTPUT 0 #define INPUT 1 #define ON 1 #define OFF 0 void main(void) { PIN_DIR_LED=OUTPUT; while(TRUE){ // _delay(x) 197120 cycles max PIN_LED=OFF; __delay_ms(10); PIN_LED=ON; __delay_ms(10); } } Se dan cuenta que si quiero cambiar de pin para controlar el Led se hace mucho ms sencillo? Y eso que solo es un ejemplo muy sencillo! En este ejemplo solo implementamos la funcin principal (void main(void)) que debe estar si o si en nuestro proyecto, pues el compilador tiene una funcin que es llamada al ocurrir un reset (vector 000) la cual inicializa el puntero de la pila (Stack en ingles), las variables inicializadas, etc. y luego llama a la funcin main(). Esta funcin puede contener el cdigo para inicializar el hardware de la forma que nosotros queramos, o llamar a funciones adicionales que hagan esta tarea y luego generalmente tiene el bucle infinito. Este bucle debe estar si o si, sino al terminar de ejecutar las instrucciones el microcontrolador se resetea. Dentro del bucle tendremos lo que queremos que el microcontrolador ejecute peridicamente hasta ser reseteado. En C un bucle infinito se puede hacer de varias formas, aqu usamos la sentencia while: while(Condicion){Sentencias} Esta sentencia o estructura de control de C permite ejecutar las sentencias que contiene de forma cclica mientras la condicin sea verdadera. Tener en cuenta que primero se pregunta si la condicin es cierta y luego ejecuta las sentencias. Como la condicin en nuestro caso es TRUE (1), se ejecuta de forma infinita. Esto representado en un diagrama de flujo sera la siguiente:

Otra forma de implementarlo es usando la sentencia do-while: do{Sentencias}while(Condicion); En este caso las sentencias se ejecutan primero y luego se pregunta la condicin, por lo que las sentencias se ejecutan mnimo una vez. El hardware mnimo para poder implementar el ejemplo seria el siguiente:

Você também pode gostar