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:
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