Programación del PIC16 en C
Contenido
[ocultar]- 1 Introducción
- 2 Hardware necesario
- 3 Módulo 1: Introducción al PIC16F876A
- 4 Módulo 2: Puertos de E/S digitales. Introducción al lenguaje C (I)
- 5 Módulo 3: Puerto serie. Introducción al lenguaje C (II)
- 6 Módulo 4: Temporizadores
- 7 Módulo 5: Displays de cristal líquido (LCD)
- 8 Módulo 6: Conversor analógico/digital
- 9 Módulo 7: Memoria EEPROM
- 10 Módulo 8: Control de servos
- 11 Módulo 9: Introducción a la programación en lenguaje ENSAMBLADOR
- 12 Módulo 10: Bus I2C
- 13 Módulo 11: Memoria Flash y protocolo ICSP
- 14 Repositorio
- 15 Historia
- 16 Enlaces
- 17 Autores
- 18 Licencia
- 19 Noticias
Introducción

Curso de introducción a la programación en C de los microcontroladores PIC16F87X de Microchip. Es totalmente práctico, haciéndose ejemplos desde el primer momento. El enfoque didácto es lo que los autores llamamos POE: Programación Orientada a Ejemplos ;-). En cada uno de los módulos se presentan los conocimientos teóricos mínimos necesarios y se aplican en ejemplos.
El lector aprenderá el funcionamiento de los diferentes recursos de estos micros así como la programación en lenguaje C, que se va introduciendo gradualmente con los ejemplos.
Todos los ejemplos se han probado en la Tarjeta Skypic, a la que se le añaden diferentes placas periféricas. Esta tarjeta es hardware libre, por lo que están disponibles todos sus planos.
Hardware necesario
![]() |
Tarjeta Skypic. Tarjeta Microcontroladora basada en el PIC16F876A. Se conecta por el puerto serie al PC desde donde se decargan directamente los programas. Incorpora un led y un botón para hacer pruebas, que serán usados mucho en los ejemplos de programación.
Esta tarjeta es hardware libre, por lo que están disponibles todos sus planos. |
![]() |
Tarjeta Freeleds. Tarjeta con 8 leds que se conecta a cualquiera de los puertos de la Skypic. Es muy útil para mostrar información en ellos. |
![]() |
Display LCD de 16x2 caracteres con una placa para su conexión a los puertos A y B de la Skypic |
![]() |
Servo Futaba 3003. A la Skypic se pueden conectar directamente hasta 8 servos. |
![]() |
Altavoz pequeño de 8 ohm y 0.2W |
![]() |
Potenciómetro de 10K con conector para la Skypic |
![]() |
SRF02: Emisor-receptor de ultrasonidos por bus I2C |
Módulo 1: Introducción al PIC16F876A
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Modulo1-ejemplos.zip
plantilla.c plantilla.hex Plantilla de programación para el SDCC hola_mundo.c hola_mundo.hex Programa "Hola mundo" que enciende el led de la Skypic
Módulo 2: Puertos de E/S digitales. Introducción al lenguaje C (I)
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Modulo2-ejemplos.zip
- PUERTO B
ledon.c ledon.hex Poner a 1 el bit 1 (RB1) del puerto B. Se enciende el led de la Skypic ledon2.c ledon2.hex Igual que ledon.c. Mejora de la legibilidad mediante #define salida8.c salida8.hex Ejemplo de salida de 8 bits variables1.c variables1.hex Ejemplo de declaracion de variables y su uso contador1.c contador1.hex Bucle for. Contador desde 0 hasta 128 que se muestra por los leds. Versión rápida no apreciable por ojo humano contador2.c contador2.hex Funciones en C. Contador desde 0 hasta 128 que se muestra por los leds. Versión con pausa para ver la secuencia pulsador-led.c pulsador-led.hex Ejemplo de entrada y salida digitales. Por RB1 (el led) se saca el valor negado de lo recibido por RB0 (pulsador) pulsador-led2.c pulsador-led2.hex Ejemplo de entrada y salida digitales. Por RB1 (el led) se saca el valor negado de lo recibido por RB0 (pulsador) . Mejora de la legibilidad mediante #define. contador-int1.c contador-int1.hex Detección de flancos por RB0, mediante espera activa. contador-int2.c contador-int2.hex Detección de flancos por RB0. Ejemplo mediante interrupciones. pull-ups.c pull-ups.hex Ejemplo de activación de las resistencias de pull-up. flancos1.c flancos1.hex Detección de cambio en pines RB4-RB7. Mediante espera activa. flancos2.c flancos2.hex Detección de cambio en pines RB4-RB7. Mediante interrupciones luces.c luces.hex Arrays en C. Secuencia de luces en los leds luces2.c luces2.hex Arrays en C. Operador Sizeof. Mismo ejemplo anterior, pero calculándose automáticamente el tamaño del array
- PUERTO A
RA0-on.c RA0-on.hex Poner el pin 0 (RA0) del puerto A a 1 salida6.c salida6.hex Ejemplo de salida digital de 6 bits RA0-led.c RA0-led.hex Ejemplo de entrada y salida digitales. Por RB1 (el led) se saca el valor RA0
- PUERTO C
RC0-on.c RC0-on.hex Poner el pin 0 (RC0) del puerto C a 1 C-salida8.c C-salida8.hex Ejemplo de salida digital de 8 bits RC0-led.c RC0-led.hex Ejemplo de entrada y salida digitales. Por RB1 (el led) se saca el valor RC0
Módulo 3: Puerto serie. Introducción al lenguaje C (II)
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Modulo3-ejemplos.zip
sci-conf.c sci-conf.hex Configuracion del puerto serie a 9600 baudios y 8N1. Cada vez que se recibe un dato del PC se cambia el estado del led sci-conf2.c sci-conf2.hex Mismo ejemplo anterior, pero con la parte de configuración en una función separada sci-eco.c sci-eco.hex Ejemplo de envio-recepcion de datos. Se hace eco de todo lo recibido por el puerto serie sci-eco2.c sci-eco2.hex Mismo ejemplo anterior, pero dividido en funciones sci-cad.c sci-cad.hex Envío de cadenas por el puerto serie sci-cad2.c sci-cad2.hex Envío de cadenas. Se prueba a enviar una cadena con caracteres especiales sci-menu.c sci-menu.hex Envío-recepción de datos. Ejemplo de programa interactivo. Instrucción switch. sci-error.c sci-error.hex Prueba de error en el flag de overflow. Este programa "se cuelga" sci-read2.c sci-read2.hex Nueva rutina de lectura de por el puerto serie que tiene en cuenta los errores y no se bloquea sci-int-rx.c sci-int-rx.hex Recepción de datos mediante interrupciones sci-contador-eco.c sci-contador-eco.hex Ejemplo de dos tareas "concurrentes". Una hace eco por el puerto serie mientras la otra cuenta. sci-int-tx.c sci-int-tx.hex Transmisión de datos mediante interrupciones sci-contadores.c sci-contadores.hex Ejemplo de dos tareas "concurrentes". Una envía datos constantemente mientras la otra cuenta. sci.h [--] Rutinas de manejo del puerto serie para ser usadas desde otros programas usando #include sci-test.c sci-test.hex Ejemplo de uso de sci.h libsci.c libsci.lib Módulo de comunicaciones serie. Para ser enlazado con nuestros programas libsci.h [---] Cabeceras para el módulo libsci sci-test2.c sci-test2.hex Ejemplo de uso del módulo libsci sci-test3.c sci-test3.hex Ejemplo de uso de la libreria libsci.lib sci-hex.c sci-hex.hex Conversión de números a cadenas ASCII para ser enviados a través del puerto serie
Módulo 4: Temporizadores
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Module4-ejemplos.zip
timer0-pausa1ms.c timer0-pausa1ms.hex Realizar una pausa de 1ms. Se hace parpadear el led de la Skypic timer0-pausa10ms.c timer0-pausa10ms.hex Realizar una pausa de 10ms. Se hace parpadear el led de la Skypic timer0-onda1Khz.c timer0-onda1Khz.hex Generación de una señal de 1Khz de frecuencia timer0-onda10Khz.c timer0-onda10Khz.hex Generación de una señal de 10Khz de frecuencia timer0-escala.c timer0-escala.hex Reproducción de la escala musical timer0-delay.c timer0-delay.hex Ejemplo de esperas de "larga duración". Se hace parpadear el led a la frecuencia de 1Hz (1 vez por segundo) timer0-onda10Khz-int.c timer0-onda10Khz-int.hex Generación de una onda de 10Khz mediante interrupciones timer0-organo.c timer0-organo.hex Órgano digital por el puerto serie timer0-pwm1.c timer0-pwm1.hex Generación de una señal PWM con ciclos de trabajo del 20% y 50% timer0-pwm2.c timer0-pwm2.hex Generación de una señal PWM con ciclos de trabajo del 20% y 50%. Ejemplo mejorado. timer0-pwm3-fade.c timer0-pwm3-fade.hex Generación de señales PWM de máxima resolución. Se decrementa el ciclo de trabajo gradualmente para hacer que los leds se apaguen progresivamente (efecto fade) timer0-pwm-int.c timer0-pwm-int.hex Generación de señales PWM mediante interrupciones timer0-pwm-sci.c timer0-pwm-sci.hex Ejemplo de control de motores con PWM. Mover el Skybot a diferentes velocidades
- Programas para Octave/Matlab: Modulo4-octave.zip
timer0_ticks.m Calcular el número de ticks del Temporizador 0 que tienen que transcurrir para lograr un tiempo determinado timer0_Duracion.m Calcular el tiempo real que transcurre cuando se quiere esperar un tiempo determinado timer0_TMR0.m Obtener los valores de inicialización del temporizador así como el prescaler para lograr una pausa de un valor concreto timer0_TMR0_frec.m Obtener los valores de inicialización del temporizador así como el prescaler para generar una señal cuadrada de una frecuencia determinada
Ejemplo 1: Configurar el timer0 para realizar pausas de 1ms
octave:1> timer0_TMR0(20,1000); T0INI= 100, PS2:0= 100, Div= 32, tc= 998.4 us, Error= 1.60 us T0INI= 178, PS2:0= 101, Div= 64, tc= 998.4 us, Error= 1.60 us T0INI= 217, PS2:0= 110, Div= 128, tc= 998.4 us, Error= 1.60 us T0INI= 236, PS2:0= 111, Div= 256, tc= 1024.0 us, Error= -24.00 us
- Como argumento se pasa la frecuencia del cristal (en Mhz) y el tiempo en micro-segundos. Existen 4 soluciones, según los valores usados para el prescaler (32,64,128 o 256). T0INI indica el valor con el que hay que inicializar el temporizador para que ocurra un overflow transcurrido 1ms
Ejemplo 2: Configurar el timer0 para generar una onda cuadrada de 800 Hz
octave:1> timer0_TMR0_frec(20,800); TMR0= 61, PS2:0= 011, Div= 16, Frec= 801.3 Hz, Error= -1.28 Hz TMR0= 158, PS2:0= 100, Div= 32, Frec= 797.2 Hz, Error= 2.81 Hz TMR0= 207, PS2:0= 101, Div= 64, Frec= 797.2 Hz, Error= 2.81 Hz TMR0= 232, PS2:0= 110, Div= 128, Frec= 813.8 Hz, Error= -13.80 Hz TMR0= 244, PS2:0= 111, Div= 256, Frec= 813.8 Hz, Error= -13.80 Hz
- Como argumento se pasa la frecuencia del cristal (en Mhz) y la frecuencia de la señal a generar, en Hz. Existen 5 soluciones, según los valores establecidos para el prescaler (16,32,64,128 o 256). La frecuencia obtenida no es exacta, sino que existe un error, también calculado por el script.
Módulo 5: Displays de cristal líquido (LCD)
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Modulo5-ejemplos.zip
lcd-hola.c lcd-hola.hex Ejemplo "hola mundo". Se inicializa el LCD y se imprime la cadena "HOLA!" lcd-term.c lcd-term.hex Convertir el LCD en una "maquina de escribir". Los caracteres que se envian por el puerto serie desde el PC se imprimen en el LCD lcd-menu.c lcd-menu.hex Ejemplo de prueba de los diferentes comandos del LCD. Mediante un menu de opciones que sale por el puerto serie, el usuario selecciona los comandos a probar lcd-usuario.c lcd-usuario.hex Ejemplo de como definir nuestros propios caracteres para ser impresos en el LCD
Módulo 6: Conversor analógico/digital
- Transparencias: (En línea) (PDF) ([OpenOffice])
- Ejemplos: Modulo6-ejemplos.zip
ad0-leds.c ad0-leds.hex Ejemplo de lectura del cana RA0 analógico. La muestra de 8 bits leída se envía por el puerto B para ser visualizada en los leds ad0-leds-int.c ad0-leds-int.hex Ejemplo de lectura del cana RA0 analógico. La lectura del conversor se realiza mediante interrupciones. ad0-vumetro.c ad0-vumetro.hex Ejemplo de lectura del cana RA0 analógico. La lectura se realiza mediante interrupciones. La información se muestra en los leds
Módulo 7: Memoria EEPROM
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Modulo7-ejemplos.zip
eeprom-write-byte.c eeprom-write-byte.hex Escritura de un byte en la memoria eeprom eeprom-read-byte.c eeprom-read-byte.hex Ejemplo de lectura de la memoria eeprom. Se lee el byte de la direccion 0 y se saca por los leds eeprom-write.c eeprom-write.hex Ejemplo de escritura de una tira de bytes en la eeprom eeprom-dump-sci.c eeprom-dump-sci.hex Ejemplo para volcar el contenido de la memoria eeprom por el puerto serie eeprom-write-int.c eeprom-write-int.hex Ejemplo de escritura de una tira de bytes en la eeprom. La escritura se hace por interrupciones
Módulo 8: Control de servos
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Modulo8-ejemplos.zip
servo1.c servo1.hex Movimiento de un servo. Se coloca en las posiciones -90, 0 y 90 servo8.c servo8.hex Posicionamiento de 8 servos. Se mueven los servos 0 y 1. El resto se dejan en la posición de 0 grados servo8-int.c servo8-int.hex Posicionamiento de 8 servos mediante interrupciones servos-sci.c servos-sci.hex El usuario puede establecer la posición de los 8 servos mediante comandos ASCII por el puerto serie
Módulo 9: Introducción a la programación en lenguaje ENSAMBLADOR
- Transparencias: (En línea) (PDF) (OpenOffice)
- Ejemplos: Modulo9-ejemplos.zip
plantilla.asm plantilla.hex Plantilla ejemplo para programar los PICs en ensamblador ledon.asm ledon.hex Ejemplo "Hola mundo" para encender el led conecado a RB1 ledon2.asm ledon2.hex Mismo ejemplo que ledon.asm, pero contiene el codigo de arranque necesario para cargarlo con el Bootloader outputb.asm outputb.hex Enviar un VALOR al puerto B pulsador.asm pulsador.hex Ejemplo de comprobación de bits. Leer el estado del pulsador. Cuando se aprieta se enciende el led ledp.asm ledp.hex Bucles. Hacer parpadear el led (bit RB1) sci-eco.asm sci-eco.hex Se hace eco de todo lo recibido por el puerto serie sci-int1.asm sci-int1.hex Interrupciones. Prueba de la interrupcion de recepcion del SCI sci-int2.asm sci-int2.hex Mismo ejemplo anterior, pero guardando el contexto al producirse la interrupción y recuperándolo al final sdcc-asm.c sdcc-asm.hex Ejemplo de invocación de instrucciones en ensamblador desde un programa en C. Se hace parpadear el led
Módulo 10: Bus I2C
- Transparencias: (En línea) (PDF)
- Ejemplos: Modulo10-ejemplos.zip
I2C_esclavo.c I2C_esclavo.hex Ejemplo de esclavo por el I2C. La Skypic esclava se convierte en un puerto serie remoto, de manera que el maestro puede enviar información al PC a través de este esclavo. Además, el maestro puede cambiar el estado del LED del esclavo y leer su pulsador I2C_master.c I2C_master.hex Ejemplo de Maestro por el I2C. Se usa junto con el ejemplo anterior. La Skypic se convierte en un maestro que accede a la Skypic esclava para cambiar el estado de su led, enviar información por su puerto serie y leer su pulsador srf02.c srf02.hex Ejemplo de utilización del sensor de distancia SRF02, conectado por el I2C a una Skypic. El programa permite acceder a todos los servicios ofrecidos por el sensor desde el puerto serie del PC distancia.c distancia.hex Ejemplo de utilización del sensor de distancia SRF02, conectado por el I2C a una Skypic. La distancia se lee constantemente y se envía por el puerto serie brujula.c brujula.hex Ejemplo de manejo de una brújula por I2C. El programa permite acceder a todos los servicios ofrecidos por la brújula desde el puerto serie del PC LCD_sensores.c LCD_sensores.c Ejemplo de uso de múltiples sensores por I2C. Se leen el sensor de distancia y la brújula y se muestran los resultados en un LCD conectado también por I2C
Módulo 11: Memoria Flash y protocolo ICSP
- Transparencias: No hay. La información está en los ejemplos
- Ejemplos: Modulo11-ejemplos.zip
flash-write-word.c flash-write-word.hex Ejemplo de escritura de una palabra en la flash del PIC flash-read-word.c flash-read-word.hex Ejemplo de lectura de la memoria flash. Se lee una palabra y se envia por el sci flash-dump.c flash-dump.hex Volcar el contenido de la flash del PIC por el puerto serie icsp-dump.c icsp-dump.hex Volcar un bloque de memoria flash de otro PIC, por ICSP. Los datos se envian por el puerto serie icsp-ledp.c icsp-ledp.hex Ejemplo de grabación de un programa por el icsp. El PIC "grabador" graba el programa de parpadear el led en otro pic. ¡¡¡Un PIC que graba a otro PIC!!!!! icsp-ledp-ok.c icsp-ledp-ok.hex Grabación de un programa por ICSP. Versión MEJORADA. Además de grabarse el programa ledp en otro Pic, se realiza su VERIFICACION y la grabación de la palabra de configuración. icsp-virus1.c icsp-virus1.hex Programa que se CLONA A SI MISMO. ¡¡UN VIRUS!!. Se hace un duplicado de la memoria flash del PIC original en el PIC destino. Ahora el pic destino, a su vez, se puede clonar en otro pic, infectándolo ;-) icsp-virus2.c icsp-virus2.hex VIRUS. Mismo ejemplo anterior, pero que realiza juegos con las luces en una tarjeta Freeleds conectada al puerto C, para ver a simple vista la idea de clonación.
Repositorio
- Repositorio SVN: http://svn.iearobotics.com/Curso_pic/
Para obtener la última versión teclear:
svn co http://svn.iearobotics.com/Curso_pic/
Historia
- Jun/2009: Creado como una de las partes del Curso de Microcontroladores PIC: Arquitectura, recursos y programación, impartido en esa misma fecha a personal de la Administración pública
Enlaces
Autores
Licencia
![]() |
Noticias
- 16/Sep/2009: Añadido módulo 11. Primera versión del curso publicada :-)
- 15/Sep/2009: Añadidos módulos 8, 9 y 10
- 14/Sep/2009: Añadidos módulos 4, 5, 6 y 7
- 13/Sep/2009: Añadido módulo 3
- 12/Sep/2009: Añadido módulo 2
- 10/Sep/2009: Comenzada esta página. Añadido módulo 1