1. Programación en C de PICs empleando
herramientas libres
Matias De la Puente
mfpuente.ar@gmail.com
10 de mayo de 2009
1. Introducción
Los microcontroladores PIC programados en ensamblador logran una eje-
cución óptima del programa cargado en su memoria, pero muchas veces la
tarea de realizar y mantener un programa de grandes dimensiones en en-
samblador se hace difícil. Sobre todo cuando ha pasado un tiempo sin ver el
programa. Esta es la principal ventaja de C, un lenguaje de programación
de mas alto nivel que ensamblador. Un programa realizado en C puede no
ser mas rápido que uno realizado en ensamblador pero facilita la realización
y mantenimiento de un programa de grandes dimensiones. Además el código
fuente realizado en C es fácilmente portado a distintos modelos de PICs rea-
lizando únicamente pequeñas modicaciones relacionadas a la arquitectura
del microcontrolador.
Este articulo muestra el empleo del compilador libre sdcc[4] para com-
pilar programas en C, como así también el empleo del programador de PICs
libre picp[3] para cargar el programa compilado en la memoria del PIC.
Para leer este articulo solo es necesario que el lector presente mínimos
conocimientos del lenguaje C y de la linea de comandos.
1
2. 2. Primer programa
El listado 1 simplemente hará oscilar un led conectado al pin RA0 de un
microcontrolador PIC16f84A.
1 #include pic16f84a.h
2
3 void delay ()
4 {
5 int i, j;
6 for (i=0; i4; i++)
7 for (j=0; j 250; j++)
8 ;
9 }
10
11 void main ()
12 {
13 TRISA = 0x00;
14
15 while (1)
16 {
17 RA0 = 1;
18 delay ();
19 RA1 = 0;
20 delay ();
21 }
22 }
Listing 1: Primer programa - pic01.c
Este código puede ser escrito con cualquier editor de texto como ser:
vim, nano, gedit, leafpad, mousepad, kate hasta inclusive puede escribirse
empleando openoce o abiword pero guardando el documento como texto
plano.
2.1. Explicación del código
La primera linea del programa incluye al código fuente el archivo de
cabecera pic16f84a.h, el cual dene todos los registros del microcontrolador
incluyendo los registros de conguración.
La función delay (linea 3) realiza un retardo aproximado de 1 segundo
si el microcontrolador presenta un ciclo de instrucción de 1 ms.
La función main (linea 11) es la primera función que ejecuta por defecto
el microcontrolador (y de cualquier programa en C). La primera instrucción
a ejecutar es TRISA = 0x00, la cual congura como salida al puerto A. El
bucle de la linea 15 se ejecutará mientras el microcontrolador se encuentre
encendido, ya que la condición (1) siempre será positiva, a este bucle se lo
denomina bucle innito. Las lineas 17 y 19 colocan en 1 y 0, respectivamente,
2
3. el bit 0 del puerto A. Las lineas 18 y 20 llaman a la función delay para
realizar el retardo denido.
De esta manera al colocar un led en el pin RA0 del microcontrolador,
este oscilará a una frecuencia de 0.5 Hz aproximadamente.
2.2. Compilación del programa
La compilación del programa se realiza con el siguiente comando:
$ sdcc -mpic14 -p16f84a pic01.c
La opción -mpic14 le indica al compilador que genere código en en-
samblador para microcontroladores con instrucciones de 14 bits (16F84A,
16F628A, 16F876A, etc). Para microcontroladores con instrucciones de 16
bits se debe emplear la opción -mpic16. La siguiente opción, -p16f84a, in-
dica al compilador el modelo de microcontrolador a emplear y debe coincidir
con el modelo del archivo de cabecera incluido en el código fuente. La ultima
opción indica el o los archivo de código fuente a compilar.
Este compilador genera a partir del archivo de código fuente en C distin-
tos archivos, los mas importantes son:
pic01.asm contiene el código ensamblador generado por sdcc.
pic01.hex contiene el código binario listo para ser grabado en la memoria
del microcontrolador.
El archivo pic01.hex, junto con otros más, no son generados directamente
por sdcc sino que son generados por gpasm y gplink del paquete gputils[1].
El compilador sdcc genera el código ensamblador a partir del código en C
y automáticamente ejecuta gpasm y gplink para generar el archivo .hex a
partir del código ensamblador. Se le puede indicar a sdcc que utilice las
herramientas de Microchip[2] mpasm y mplink solamente agregando a sdcc
la opción -mplab-comp.
El compilador sdcc soporta un gran numero de microcontrolador de 14
y 16 bits. Para obtener una lista de los microcontroladores de 14 bits sopor-
tados por el compilador solo hay que ejecutar el siguiente comando
$ sdcc -mpic14 -phelp pic01.c
Para este ejemplo se empleó el archivo pic01.c pero puede ser cualquier
otro inclusive uno vacío. Para obtener una lista de los microcontroladores
de 16 bits soportados por el compilador simplemente hay que reemplazar la
opción -mpic14 por -mpic16.
2.3. Acerca de los registros
Como se menciono anteriormente, los registros del microcontrolador se
encuentran denidos dentro del archivo de cabecera incluido en el código
3
4. fuente. No hace falta abrir este archivo de cabecera para saber como están
denidos todos los registros del microcontrolador ya que el nombre de registro
es el mismo empleado dentro de la hoja de datos del microcontrolador. Por
ejemplo, si queremos modicar el valor del registro INTCON del PIC16F84A
elegido simplemente hay que introducir la linea INTCON = 0x00; en el código
fuente, para este ejemplo se modico por el valor 0x00 pero puede ser el que
uno desee.
Cabe mencionar que los microcontroladores de 14 bits presentan regis-
tros en diferentes bancos de memoria. En ensamblador el desarrollador debía
seleccionar el banco de memoria en donde se encontraba el registro a mo-
dicar. En C no hace falta realizar esta tarea ya que el mismo compilador
genera el código para elegir el banco correspondiente antes de modica el
registro. En los microcontroladores de 16 bits lo bancos de memoria fueron
eliminados y no hace falta realizar esta tarea, mejorando el rendimiento del
programa.
Ahora bien, a veces es necesario modica solamente un bit de un registro,
esto puede ser fácilmente realizado ya que también se encuentran denidos
los bits de cada registro. La nomenclatura empleada para realizar esta tarea
es diferente entre un microcontrolador de 14 bits y uno de 16 bits. Para un
microcontrolador de 14 bits se emplea esta nomenclatura:
nombre del registro _bits.nombre del bit
Por ejemplo, se desea habilitar las interrupciones globales de PIC16F84A,
para eso hay que poner en 1 el bit GIE del registro INTCON, simplemente
agregamos al código fuente la linea INTCON_bits.GIE = 1;. Para un micro-
controlador de 16 bits la nomenclatura es similar, la única diferencia es que
no presenta el guión bajo entre nombre del registro y bits. En este caso para
habilitar las interrupciones globales del microcontrolador se emplearía esta
linea de código: INTCONbits.GIE = 1;.
Un caso a tener en cuenta es el de los microcontroladores de 16 bits
ya que no se requiere incluir el archivo de cabecera según el modelo a pro-
gramar. Esto es, solamente hace falta incluir al código fuente el archivo de
cabecera pic18fregs.h y a través de la opción -p18fxxxx se elige el modelo
a programar.
3. Grabación del programa en la memoria del mi-
crocontrolador
Para grabar el programa en la memoria del microcontrolador se emplea
picp. Este comando se comunica con el programador1 PICSTART Plus de
1
Para evitar confusiones el programador es el dispositivo capaz de guardar un programa
en la memoria del microcontrolador. Para hacer referencia a la persona que escribe el
programa se empleara desarrollador
4
5. Microchip para grabar los microcontroladores.
3.1. Grabar el programa
La grabación del programa en la memoria del microcontrolador se realiza
simplemente empleando los siguientes instrucciones:
$ picp /dev/ttyS0 16f84a -ef
$ picp /dev/ttyS0 16f84a -bp -wp pic01.hex
El primer comando limpieza (erase) toda la memoria ash del microcon-
trolador. La segunda opción realiza un blanqueado (blank) de la memoria de
programa para luego grabar el programa compilado con sdcc.
La primera opción /dev/ttyS0 es el puerto serie en donde se encuentra
conectado el programador (COM1, COM2, etc. para usuarios de Windows). La
segunda opción 16f84a indica el modelo de microcontrolador a colocado
en el programador. Se puede obtener una lista completa de los dispositivo
soportados empleando picp -d. La opción -ef especica que se limpie la
memoria ash del microcontrolador. La opción -bp blanquea la memoria de
programa del microcontrolador. Por ultimo, la opción -wp pic01.hex escribe
en la memoria de programa el archivo pic01.hex.
3.2. Lectura de la memoria del microcontrolador
Con picp también es posible leer la memoria del microcontrolador, siem-
pre y cuando el microcontrolador no este protegido contra lectura. El co-
mando a emplear es similar a escribir el programa:
$ picp /dev/ttyS0 16f84a -rp temp.hex
Aquí, la opción -rp temp.hex lee la memoria de programa del microcon-
trolador y la almacena en temp.hex.
3.3. Lectura y escritura de los bits de conguración
Para leer y escribir los bits de conguración del microcontrolador se em-
plean las opciones -rc y -wc respectivamente. La lectura de los bits de con-
guración se realiza con:
$ picp /dev/ttyS0 16f84a -rc
La escritura de los bits de conguración se realiza con:
$ picp /dev/ttyS0 16f84a -wc 0x3FF9
El microcontrolador es congurado con la palabra
2 0x3FF9. Esto es, sin
protección de código, temporizador de arranque desactivado, temporizador
watchdog desactivado y oscilador de tipo XT. Para mas información el lector
puede referirse al manual del microcontrolador.
2
Dato de 16 bits
5
6. 3.3.1. Denir los bits de conguración desde el programa
Los bits de conguración pueden ser denidos desde el mismo programa
en C. Para ello sdcc ofrece un par de palabras reservadas
3 que hacen posible
esta tarea, las palabras reservadas son code y at y se emplean como se observa
en el listado 2.
code char at 0x2007 CONFIG = 0x3FF9;
Listing 2: Denición de los byte de conguración
Esta linea de código es agregada al programa principal luego de las di-
rectivas #include. De esta manera cuando el programa sea grabado en la
memoria del microcontrolador también lo harán los bits de conguración.
Una vez mas el lector debe referirse al manual del microcontrolador a
usar para obtener la o las direcciones y valores de los bits de conguración.
4. Conclusión
La programación de un microcontrolador empleando el lenguaje C a pro-
bado durante años ser la forma mas eciente de desarrollar un programa para
microcontroladores, por supuesto que no se genera un código ensamblador
óptimo pero el código hecho en C puede ser mantenido en forma mas sencilla
que uno en ensamblador. Además pensar la solución al problema en código
en C es aun mas fácil que pensarla en ensamblador.
Este articulo ha demostrado que el desarrollo de un programa en C y el
grabado del mismo en la memoria del microcontrolador ha sido sencilla de
realizar. Las herramientas a utilizar son de fácil acceso y bien documentadas.
Un editor de texto y comandos fueron solamente necesarios para escribir
el programa y grabarlo al microcontrolador, esto prueba que no hacen falta
complejas aplicaciones grácas para realizar este trabajo. Por supuesto que
puede incorporarse dentro del editor de texto un par de botones en la barra de
herramienta para que haga en forma automática la compilación y el grabado
del programa.
Referencias
[1] GNU PIC Utilities. http://gputils.sourceforge.net/.
[2] Microchip. http://www.microchip.com/.
[3] PIC Programmer. http://home.pacbell.net/theposts/picmicro/.
[4] Small Device C Compiler. http://sdcc.sourceforge.net.
3
Como if, while, etc.
6