lunes, 30 de enero de 2012

Programacion de PIC con SDCC

Voy a ir creando una serie de post para introducirse en la programación de microcontroladores pic con el compilador SDCC. Yo utilizo un PIC18F2550, pero estos ejemplos aplican en general a toda la linea de PIC18, principalmente a PIC18F2455, PIC18F2550, PIC18F4455, PIC18F4550. Con ciertas modificaciones también sirve a modo de ejemplo para los PIC16. La idea de estos post es ampliar el contenido didáctico disponible sobre este compilador, que no hay mucho material a modo de ejemplo y además tener esto como un referencia personal. SDCC es una herramienta libre, y esta disponible tanto para Windows como Linux.
Suponiendo que ya tenemos instalado el SDCC, y algún IDE, o no, empezamos con el clásico “Hola Mundo” electrónico, en el que simplemente haremos apagar y prender un led.
En este primer ejemplo se contempla el modo de setear los bits de configuración del PIC, y la utilización de la librería delay que esta incluida en el compilador.
El circuito es el siguiente:
Circuito led blinking

Notese la ausencia de oscilador, esto se debe a que haremos uso del oscilador interno del PIC.

Bits de configuración

Para configurar los bits de configuración(o también llamado fuses-fusibles) se usan las siguientes directivas del compilador“__code” y “__at”, es necesario mirar el header del pic a programar para poder ver como están nombrados los registros y sus bits Como así también el datasheet para tener una buena idea de las configuraciones. Por ejemplo si se quiere modificar el registro CONFIG1H, y se pretende que los bits queden seteados de la siguiente manera: Oscilador Switchover deshabilitado, Fail safe Clock deshabilitado, Habilitado el oscilador interno con CLOK en RA6, la sintaxis requerida es:
static __code char __ar(__CONFIG1H) config1= _OSC_INTOSC__INTOSC_CLK0_RA6___USB_EC_1H & _FCMEN_OFF_1H & _IESO_OFF_1H

Es algo similar a como se hace en asm.

Conociendo esto ya es posible pasar a nuestro primer programa:


//Definiciones para hacer mas legible el codigo
#define LED_TRIS TRISBbits.TRISB0
#define LED_PIN PORTBbits.RB0

//Agrego la librería de los pic para cargar configuraciones y variables y se agrega la librería delay provista por el compilador.
#include "pic18fregs.h"
#include "delay.h"

static __code char __at __CONFIG1H conf1 = _OSC_INTOSC__INTOSC_CLK0_RA6___USB_EC_1H; // Activo oscilador interno
static __code char __at __CONFIG4L conf2 = _LVP_OFF_4L; // Desabilito LVP
static __code char __at __CONFIG2H conf3 = _WDT_DISABLED_CONTROLLED_2H; // Desabilito WDT

//Programa principal
void main(){
OSCCON = 0b11110011; //Configuro oscilador int en 8MHZ
LED_TRIS = 0; //Configuro como salida
while(1){
LED_PIN = 1;
delay1mtcy(1);
LED_PIN = 0;
delay1mtcy(1);
}
}



El programa esta bastante comentado, no hay mucho que agregar, los define al inicio simplifican el código, y no generan código maquina extra. Los include para agregar librerías, como se hace normalmente en c. Se configuran los bits de interés. En el programa se configuran otros registros mas. Como ser el registro para el control del oscilador, en este caso se trabaja a 8MHz, y a través del registro TRISB se configura el bit correspondiente al led, como salida. En los define al inicio se adopto el pin RB1. Para generar los delay se recurrió a la librería "delay.h" que se incluye con el compilador, dicha librería integra funciones para generar retardos de una cierta cantidad de ciclos de reloj. Mirando en el archivo delay.h se puede encontrar lo siguiente( lo he traducido):
/*
* La familia de funciones delayNNtcy realizan un
* retardo de NN ciclos. Los posibles valores de NN:
* 10 10*n ciclos de retraso
* 100 100*n ciclos de retraso
* 1k 1000*n ciclos de retraso
* 10k 10000*n ciclos de retraso
* 100k 100000*n ciclos de retraso
* 1m 1000000*n ciclos de retraso
*/
La formula para saber cuantos ciclos de retrasos necesitamos para generar un retardo de n seg es:[latex]N=n\frac{FOSC}{4}[/latex]
Suponiendo que tenemos un reloj del sistema de 8MHz, y queremos un retardo de 8 segundos necesitaremos 16 millones de ciclos.
Podríamos entonces usar la función de 1m de la siguiente forma:
delay1mtcy(16);

Por ultimo nos queda compilar nuestro programa y obtener el hex a grabar en el pic. Con SDCC solo obtendremos un archivo que contiene el código en asm, pero si dispones de gpasm(es dentro de la suite gputils) podemos generar el hex. El comando básico para la compilación es : sdcc -mpic16 -p18f2550 "%f" --use-non-free

-mpic16 es para indicar la familia del pic,
-p18f2550 es para indicar el dispositivo
y por ultimo --use-non-free es para indicar que use librerías que no son libres, esto es necesario porque por problemas de licencias con Microchip, los archivos header de los diferentes pics no son libres,

La familia del pic(en SDCC) depende de la longitud de la palabra de instrucción, asi para los PIC18 una instrucción es una palabra de 16bits, en cambio para los PIC16 es de 14bits. Por lo que en SDCC tenemos dos familias, llamadas mpic16 y mpic14
Comparte este articulo
  • Comparte con Facebook
  • Comparte con Twitter
  • Comparte con Google+
  • Comparte con Stumble Upon
  • Comparte con Evernote
  • Comparte con Blogger
  • Comparte con Email
  • Comparte con Yahoo Messenger
  • More...

7 comentarios:

  1. [...] hardware es el mismo que en el ejemplo del “Hola mundo”. Y este es el codigo: [...]

    ResponderEliminar
  2. muy buen post, gracias por compartirlo ahorita mismo me pongo a probarlo con el 2550
    aunque se lo voy a tener que quitar a mi programador clon ;)

    ResponderEliminar
    Respuestas
    1. gracias me alegro que te sirva.
      Pero recuerda que vas a necesitar otro programador, porque sino no podras pasarle el programa, ni volver a tener tu clon andando.
      Suerte.

      Eliminar
  3. hermano me sirvió de mucho tu post, pero me gustaría que me pudieras ayudar en un error que tengo al compilar
    el cual es este:
    /usr/bin/../share/sdcc/include/pic16/pic18fregs.h:138:26: error: pic18f2550.h: No such file or directory


    y no se porque razón me sale :D

    ResponderEliminar
    Respuestas
    1. Buenas, le dijiste al compilador que use las librerias no libres? se hace con el argumento --use-non-free
      Saludos!

      Eliminar
  4. No funciono me tiro varios errores los envío:

    MacBook-Pro-de-Luis-2:Uno_sdcc osbox68$ sdcc -mpic16 -p18f2550 "uno_sdcc.c" --use-non-free

    WARNING: The target device seems to support XINST and no #pragma config XINST=OFF was found.

    The code generated by SDCC does probably not work when XINST is enabled (possibly by default).

    Please make sure to disable XINST.

    (If the target does not actually support XINST, please report this as a bug in SDCC.)

    uno_sdcc.c:9: error 20: Undefined identifier '_OSC_INTOSC__INTOSC_CLK0_RA6___USB_EC_1H'

    uno_sdcc.c:9: error 2: Initializer element is not constant

    INFO: changing configuration word at 0x300006 from 0xfb to 0xbb due to pic16devices.txt

    uno_sdcc.c:11: error 20: Undefined identifier '_WDT_DISABLED_CONTROLLED_2H'

    uno_sdcc.c:11: error 2: Initializer element is not constant

    MacBook-Pro-de-Luis-2:Uno_sdcc osbox68$

    ResponderEliminar