Propuesta para la programación básica del Temporizador 1 del microcontrolador PIC18F2550 con el compilador SDCC Por: I.I.E. Miguel Montiel Martínez montiel.martinez@gmail.com Resumen Este articulo trata sobre la programación esencial del temporizador/contador 1 de un microcontrolador PIC18F2550, a través de la utilización del lenguaje de alto nivel C, con el compilador libre SDCC. Como primer punto es mostrada una guía gráfica de los pasos que componen a la propuesta del autor, enseguida, se aborda de forma directa la definición del tiempo de retardo deseado, así como la determinación de los valores de precarga, con estos valores iniciales obtenidos, se mencionan de forma explícita, los registros que serán afectados en la programación del tiempo de retardo. Como cuarto punto, se proponen funciones para compilador SDCC que generan el retardo calculado, llevando como consecuencia natural la generación de un producto, el código fuente, mismo que se muestra en el quinto apartado, como punto final se obtiene un resultado simulado por software, que confirma los cálculos previamente realizados. Palabras clave: PIC18F2550, Temporizador,SDCC. Introducción En el artículo Propuesta de la configuración básica del Temporizador 1 del microcontrolador PIC18F2550, se aborda la parte teórica para la determinación de un valor de precarga, a fin de obtener un retardo de tiempo. Es por medio del compilador para dispositivos pequeños de C, denominado SDCC (de sus siglás en inglés) que se usa el valor de precarga para generar este retardo de tiempo, el cual es visible, a través de cambios de potencial eléctrico en una terminal de salida, elegida por el programador, a través de la configuración del hardware del microcontrolador, para generar un firmware. A partir de la inserción de firmware en el microcontrolador, se puede verificar los resultados obtenidos, mediante la técnica de simulación con el software de Labcenter Electronics Proteus, en su versión de demostración con la herramienta de osciloscopio(Labcenter Electronics, 2011). De esta forma, al programar un sistema embebido basado en microcontrolador, mediante el uso de aplicaciones de software libre, no solo se tiene la oportunidad de únicamente aprender, sino que además de compartir de forma libre el conocimiento (Bañobre & Alvarellos, 2010). 1. Propuesta de método para la programación del temporización Los elementos que conforman la programación de la temporización generada se representan en la Ilustración 1: Pasos para la programación de un retardo con el temporizador 1 Definición del tiempo de retardo Requerido y requerimientos Desarrollo del código fuente principal Cálculo de valor de PRECARGA Compilación del Código Fuente Asignación de valores a registros asociados con el Temporizador 1 Formación de las funciones requeridas Descarga del .HEX generado al microcontrolador Ilustración 1: Pasos para la programación de un retardo con el temporizador 1 2. Definición del tiempo de retardo y establecimiento de la precarga Para configurar el Temporizador 1, el programador tuvo que haber definido, la frecuencia de reloj usada por el sistema, la división de frecuencia deseada y el valor de precarga inicial de temporización. Como ejemplo de lo anterior, a continuación, se presenta la configuración requerida para un microcontrolador que trabaja con un oscilador de cristal a 20MHz, configurado para que internamente, por medio de un elemento de hardware denominado PLL, incremente la frecuencia de reloj de sistema a 48MHz, y con esto sea obtenido un retardo de 1.57 ms (Jung, 2010; RedPIC, 2010). T1INI PRECARGA=65536− Divisor 1 2 4 8 F osc ⋅Tiempo DESEADO 4⋅divisor Tmin 0.0833333 0.1666667 0.3333333 0.6666667 Tmax 5461.33 10922.67 21845.33 43690.67 (1) Tiempo microsegundos microsegundos microsegundos microsegundos Tabla 1: Tiempos estimados para una frecuencia de 48MHz Con los datos presentados, al ser sustituidos en la ecuación (1), se obtiene que el valor de precarga para el temporizador 1, la resolución se presenta en la ecuación (2) 48MHz ⋅1.57 ms 4⋅1 T1INI =46696 T1INI =65536− (2) Nótese que se ha escogido un divisor de frecuencia por 1, esta decisión es con base en la tabla 3 de la sección 4. Cálculo del tiempo de retardo, en el artículo Propuesta de la configuración básica del Temporizador 1 del microcontrolador PIC18F2550, ya que en la fila 1, se puede verificar que el valor máximo de tiempo generado por este divisor es de 5.4 ms aproximadamente, siendo éste mas adecuado, que el calculado en el segundo renglón, y la razón de esto es porque, el “tick” o duración del pulso de menor tiempo, es mayor en el segundo caso que en el primero,de esta manera, se genera así la pérdida de resolución en el tiempo deseado. 3. Definición de valores en registros implicados A partir del valor de precarga, se hace necesario establecer los valores adecuados a establecer en cada registro implicado en la configuración del Temporizador 1. Nombre INTCON Bit 7 Bit 6 GIE/GIEH Bit 5 PEIE/GIEL Bit 4 TMR0IE Bit 3 INT0IE Bit 2 RBIE Bit 1 TMR0IF Bit 0 INT0IF RBIF PIR1 - ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF PIE1 - ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE TMR1L Valores a cargar en el registro menos significativo del temporizador TMR1H T1CON IPR1 Valores a cargar en el registro más significativo del temporizador RD16 T1RUN T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON - ADIP RCIP TXIP SSPIP CCP1IP TMR2IP TMR1IP Tabla 2: Registros asociados al Temporizador 1 Siguiendo el orden de los registros mostrados en la Tabla 2: Registros asociados al Temporizador 1, los valores asociados al Temporizador 1, los valores a asignar, son los que se muestran a continuación en Tabla 3: Valores de registros asociados al Temporizador 1: INTCON 0 X X X X X X X No se habilitan interrupciones globales PIR1 X X X X X X X 0 Es limpiada la bandera de interrupción del temporizador 1 PIE1 X X X X X X X 0 No se habilita la interrupción por desborde del temporizador 1 TMR1L X X X X X X X X Aún no se carga el registro TMR1H X X X X X X X X Aún no se carga el registro T1CON 1 0 0 0 0 0 0 0 • • • • • • IPR1 La fuente de señal para el Temporizador 1 proviene del reloj principal. No se habilita el Temporizador 1 como oscilador. El divisor de frecuencia es por uno. Inicialmente no se da señal de inicio al Temporizador. El temporizador recibe y entrega 16 bits. El temporizador se usa en modo corrida libre. X X X X X X X 0 No se habilita la interrupción del periférico Temporizador 1 Tabla 3: Valores de registros asociados al Temporizador 1 4. Propuesta de funciones para la programación retardo de tiempo En primer lugar debemos generar una función que permita inicializar tanto al temporizador, como a los pines de entrada – salida del microcontrolador, esta función recibe el nombre de init_board() y se muestra a continuación: void init_board(void) { ADCON1=0x7; // PORTA usado como E/S digital TRISAbits.TRISA4=0; // salida para temporizador 1 //Etapa de configuración del Temporizador 1 T1CONbits.TMR1CS=0; //Fuente de TMR1CS -> interna fosc/4 T1CONbits.NOT_T1SYNC=0; T1CONbits.T1OSCEN=0; //No habilitamos temporizador 1 como oscilador T1CONbits.T1CKPS0=0; T1CONbits.T1CKPS1=0; //divisor de frecuencias en 1:1 } El proceso para la generación del retardo se resume en el monitoreo del estado de la bandera TMR1IF, mientras ésta sea 0, el Temporizador aún no ha llegado al estado de desborde, cuando ocurre el cruce por cero, la bandera TMR1IF pasa a estado ALTO, haciendo que el ciclo se interrumpa, enseguida, debe ser apagada la bandera TMR1ON, con el objetivo de detener al Temporizador y limpiar nuevamente la bandera de interrupción del Temporizador. La siguiente función muestra el proceso para generar el retardo que se desea: void pausa_1_57ms(void) { TMR1H = T1INIH; //Carga la parte alta del temporizador 1 TMR1L = T1INIL; //Carga la parte baja del temporizador 1 T1CONbits.TMR1ON=1; //Arranca el temporizador 0 while(PIR1bits.TMR1IF == 0); //Esperar hasta que TMR1IF sea uno T1CONbits.TMR1ON=0; //Detener el temporizador 0 PIR1bits.T1MR1IF = 0; //Limpia la bandera TMR1IF para un nuevo ciclo } El valor obtenido para T1INI, es un entero decimal, pero debe transformarse a un número en hexadecimal y dividirlo en dos bytes, con el fin de realizar la precarga de los registros TMR1H y TMR1L. //definiciones -- El número deseado es el 46696 = 0xB668 y debe transformarse a // hexadecimal #define T1INIL 0x68 //parte baja de precarga #define T1INIH 0xB6 //parte alta de precarga #define TESTIGO LATAbits.LATA4 //bit de salida 5. Producto: Código Fuente Finalmente, el código fuente que se muestra a continuación, configura cada uno de los elementos mencionados anteriormente, generando así el retardo teórico deseado para encender y apagar un led conectado en el PIN RA4 cada 3.14ms, es decir a una frecuencia de 318.47Hz /* ----------------------------------------------------------------------- */ /* Plantilla generada por Piklab */ /* ----------------------------------------------------------------------- */ /** Timer1EnciendeLed.c Este programa configura como salida el puerto RA4 y lo coloca en estado alto después de un tiempo definido por el TMR1. Copyright (C) <2011> <Miguel Montiel Martinez> montiel.martinez@gmail.com Este programa es software libre: usted puede redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General GNU publicada por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o (a su elección) cualquier versión posterior. Este programa se distribuye con la esperanza de que sea útil, pero SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública General GNU para obtener una información más detallada. Debería haber recibido una copia de la Licencia Pública General GNU junto a este programa. En caso contrario, consulte <http://www.gnu.org/licenses/>. */ #include <pic18f2550.h> /* Bits de configuración: adapte los parámetros a su necesidad */ code char at __CONFIG1L CONFIG1L = _USBPLL_CLOCK_SRC_FROM_96MHZ_PLL_2_1L & _CPUDIV__OSC1_OSC2_SRC___1__96MHZ_PLL_SRC___2__1L & _PLLDIV_DIVIDE_BY_5__20MHZ_INPUT__1L; code char at __CONFIG1H CONFIG1H = _OSC_HS__HS_PLL__USB_HS_1H & _FCMEN_ON_1H & _IESO_ON_1H; code char at __CONFIG2L CONFIG2L = _PUT_ON_2L & _BODEN_ON_2L & _BODENV_2_0V_2L & _VREGEN_OFF_2L; code char at __CONFIG2H CONFIG2H = _WDT_DISABLED_CONTROLLED_2H & _WDTPS_1_32768_2H; code char at __CONFIG3H CONFIG3H = _CCP2MUX_RC1_3H & _PBADEN_PORTB_4_0__CONFIGURED_AS_DIGITAL_I_O_ON_RESET_3H & _LPT1OSC_OFF_3H & _MCLRE_MCLR_ON_RE3_OFF_3H; code char at __CONFIG4L CONFIG4L = _STVR_ON_4L & _LVP_OFF_4L & _ENHCPU_OFF_4L & _BACKBUG_OFF_4L; code char at __CONFIG5L _CP_3_OFF_5L; code char at __CONFIG5H code char at __CONFIG6L _WRT_3_OFF_6L; code char at __CONFIG6H code char at __CONFIG7L _EBTR_3_OFF_7L; code char at __CONFIG7H CONFIG5L = _CP_0_OFF_5L & _CP_1_OFF_5L & _CP_2_OFF_5L & CONFIG5H = _CPB_OFF_5H; CONFIG6L = _WRT_0_OFF_6L & _WRT_1_OFF_6L & _WRT_2_OFF_6L & CONFIG6H = _WRTC_OFF_6H & _WRTB_OFF_6H; CONFIG7L = _EBTR_0_OFF_7L & _EBTR_1_OFF_7L & _EBTR_2_OFF_7L & CONFIG7H = _EBTRB_OFF_7H; //definiciones -- El número deseado es el 46696 = 0xB668 y debe transformarse a // hexadecimal #define T1INIL 0x68 //parte baja de precarga #define T1INIH 0xB6 //parte alta de precarga #define TESTIGO LATAbits.LATA4 //bit de salid //Prototipos void init_board(void); void pausa_1_57ms(void); //Sección de interrupciones /*Para este fuente no se requiere de interrupciones*/ //Código fuente principal void main() { init_board(); while(1) { pausa_1_57ms(); TESTIGO = 1; pausa_1_57ms(); TESTIGO = 0; } } void init_board(void) { ADCON1=0x7; // PORTA usado como E/S digital TRISAbits.TRISA4=0; // salida para temporizador 1 //Etapa de configuración del Temporizador 1 T1CONbits.TMR1CS=0; //Fuente de TMR1CS -> interna fosc/4 T1CONbits.NOT_T1SYNC=0; T1CONbits.T1OSCEN=0; //No habilitamos temporizador 1 como oscilador T1CONbits.T1CKPS0=0; T1CONbits.T1CKPS1=0; //divisor de frecuencias en 1:1 } void pausa_1_57ms(void) { TMR1H = T1INIH; //Carga la parte alta del temporizador 1 TMR1L = T1INIL; //Carga la parte baja del temporizador 1 T1CONbits.TMR1ON=1; //Arranca el temporizador 0 while(PIR1bits.TMR1IF == 0); //Esperar hasta que TMR1IF sea uno T1CONbits.TMR1ON=0; //Detener el temporizador 0 PIR1bits.TMR1IF = 0; //Limpia la bandera TMR1IF para un nuevo ciclo } 6. Resultados Después de compilar con éxito el programa mostrado anteriormente con el software Piklab (Dutta et al., 2010; Gómez & Torres, 2004; Hadacek & Gibaud, 2010; Montiel, 2010a), se realiza una prueba de simulación con el software ISIS Proteus, propietaria de Labcenter Electronics (Breijo, 2008; Montiel, 2010b, 2010c), donde al colocar el microcontrolador PIC18F2550 con un osciloscopio virtual, el cual tiene el cursor de tiempo activado y con bases de tiempo en 0.5 ms/div y en 100µs/div, se verifica que los valores calculados, son idénticos a los valores mostrados en la Ilustración 2: Tren de pulsos en RA4, y en Ilustración 3: Aproximación del tren de pulsos en RA4 respectivamente. Ilustración 2: Tren de pulsos en RA4 Ilustración 3: Aproximación del tren de pulsos en RA4 7. Conclusiones En este trabajo se presentó, la configuración básica para programar un tiempo determinado en un microcontrolador PIC18F2550 utilizando el compilador SDCC. Entre las características que podemos destacar tenemos, el uso de un registro de 16 bits segmentado en dos de 8 bits, programación basada en los datos que nos presenta directamente la hoja de datos del microcontrolador, identificación de ecuaciones que permiten el cálculo del retardo de tiempo y un excelente desempeño mostrado en el simulador especilizado en electrónica analógica, digital y sistemas empotrados ISIS Proteus, cuya propietaria es Labcenter Electronics. Finalmente, se puede concluir que, a través de la ecuación (1) de la sección 2. Definición del tiempo de retardo y establecimiento de la precarga , en conjunto con el compilador de fuente abierta SDCC, es posible generar tiempos muy exactos y suficientemente confiables. 8. Referencias Bañobre, D., & Alvarellos, F. (2010). Software Libre (spanish audio). software Libre. España. Recuperado a partir de http://www.youtube.com/watch? v=FvLJ2JotttM&feature=youtube_gdata_player Breijo, E. G. (2008). Compilador C CCS y Simulador PROTEUS para Microcontroladores PIC (1o ed.). Alfaomega - Marcombo. Dutta, S., Luois-VERN, J., Vigor, K., Knol, J., Dattalo, S., Bongers, K., Held, B., et al. (2010). SDCC. SourceForge. Recuperado a partir de http://sdcc.sourceforge.net/ Gómez, J. G., & Torres, A. P. . (2004). Herramientas hardware y software para el desarrollo de aplicaciones con Microcontroladores PIC bajo plataformas GNU/Linux. Hadacek, N., & Gibaud, A. (2010). Piklab. SourceForge. Recuperado a partir de http://piklab.sourceforge.net/devel.php Jung, E. (2010, Julio 22). Default config for PIC18F4550 20 Mhz (48 Mhz) | MoP. MoP. Recuperado Agosto 11, 2011, a partir de http://junif.hu/mop/programok/default_config Labcenter Electronics. (2011). Labcenter Electronics - Downloads. Labcenter Electronics ... the home of PROTEUS. Recuperado Septiembre 21, 2011, a partir de http://www.labcenter.com/download/prodemo_download.cfm#professional Montiel, M. (2010a). Herramientas Libres para la programación de Microcontroladores PIC. Instituto Tecnológico Superior de Teziutlán Sitio web. Recuperado Agosto 11, 2011, a a partir de http://www.itsteziutlan.edu.mx/index.php? option=com_content&view=article&id=597:herramientas-libres-para-la-programacion-demicrocontroladores-pic&catid=27:artlos&Itemid=288 Montiel, M. (2010b, Junio 29). proteus - Piklab PIC18F2550 sdcc y proteus en Ubuntu 10.04. PIc Linux Foro de debate y recursos compartidos. Recuperado Agosto 11, 2011, b a partir de http://pic-linux.foroactivo.net/t299-piklab-pic18f2550-sdcc-y-proteus-en-ubuntu-1004? highlight=proteus Montiel, M. (2010c). PiklabSdccProteusUbuntu. Teziutlán, Puebla. Recuperado a partir de http://www.youtube.com/watch?v=9meSBYETG9s&feature=youtube_gdata_player RedPIC. (2010, Agosto 7). Consiguiendo 4 Mhz para los 48 Mhz necesarios en los PIC’s con USB 2.0. PicManía by RedRaven. Recuperado Agosto 11, 2011, a partir de http://picmania.garciacuervo.net/conceptos.php#USB4Mhz This document is licensed under the Attribution-ShareAlike 2.5 Mexico license, available at http://creativecommons.org/licenses/by-sa/2.5/mx/.