PIC16F87X
# PIC16F87X

Los PIC16F87X forman una subfamilia de microcontroladores PIC (Peripheral Interface Controller) de gama media de 8 bits, fabricados por Microchip Technology Inc..

Cuentan con memoria de programa de tipo EEPROM Flash mejorada, lo que permite programarlos fácilmente usando un dispositivo programador de PIC. Esta característica facilita sustancialmente el diseño de proyectos, minimizando el tiempo empleado en programar los microcontroladores (µC).

Esta subfamilia consta de los siguientes modelos que varían de acuerdo a prestaciones, cantidad de terminales y encapsulados:

* PIC16F870
* PIC16F871
* PIC16F872
* PIC16F873A
* PIC16F874A
* PIC16F876A
* PIC16F877A

La "A" final de los modelos PIC16F873A, PIC16F874A, PIC16F876A y PIC16F877A indica que estos modelos cuentan con módulos de comparación analógicos.

El hecho de que se clasifiquen como microcontroladores (MCU) de 8 bits hace referencia a la longitud de los datos que manejan las instrucciones, y que se corresponde con el tamaño del bus de datos y el de los registros de la CPU.

Se trata de versiones mejoradas del caballo de batalla PIC16F84, muy empleado en proyectos sencillos, de educación y de entrenamiento.

## Características principales

Las características principales de estos dispositivos son:

* CPU de arquitectura RISC (Reduced Instruction Set Computer).
* Set de 35 instrucciones.
* Frecuencia de reloj de hasta 20MHz (ciclo de instrucción de 200ns).
* Todas las instrucciones se ejecutan en un único ciclo de instrucción, excepto las de salto.
* Hasta 8K x 14 palabras de Memoria de Programa FLASH (ver tabla a continuación).
* Hasta 368 x 8 bytes de Memoria de Datos tipo RAM (ver tabla a continuación).
* Hasta 256 x 8 bytes de Memoria de Datos tipo EEPROM (ver tabla a continuación).
* Hasta 15 fuentes de Interrupción posibles.
* 8 niveles de profundidad en la Pila hardware.
* Modo de bajo consumo (Sleep).
* Tipo de oscilador seleccionable (RC, HS, XT, LP y externo).
* Rango de voltaje de operación desde 2,0V a 5,5V.
* Conversor Analógico/Digital de 10 bits multicanal.
* 3 Temporizadores.
* Watchdog Timer o Perro Guardián.
* 2 módulos de captura/comparación/PWM.
* Comunicaciones por interfaz USART (Universal Synchronous Asynchronous Receiver Transmitter).
* Puerto Paralelo Esclavo de 8 bits (PSP).
* Puerto Serie Síncrono (SSP) con SPI e I²C.

### Detalles según modelo

| Modelo | Memoria de programa Flash (palabras de 14 bits) | Memoria de datos SRAM (bytes) | Memoria de datos EEPROM (bytes) | Líneas de E/S | Canales A/D | PWM | MSSP | MSSP | USART | Comparadores |
| - | - | - | - | - | - | - | - | - | - | - |
| Modelo | Memoria de programa Flash (palabras de 14 bits) | Memoria de datos SRAM (bytes) | Memoria de datos EEPROM (bytes) | Líneas de E/S | Canales A/D | PWM | SPI | I²C Maestro | USART | Comparadores |
| PIC16F870 | 2048 | 128 | 64 | 22 | 5 | 1 | No | No | Sí | No |
| PIC16F871 | 2048 | 128 | 64 | 33 | 8 | 1 | No | No | Sí | No |
| PIC16F872 | 2048 | 128 | 64 | 22 | 5 | 1 | Sí | Sí | No | No |
| PIC16F873A | 4096 | 192 | 128 | 22 | 5 | 2 | Sí | Sí | Sí | Sí (2) |
| PIC16F874A | 4096 | 192 | 128 | 33 | 8 | 2 | Sí | Sí | Sí | Sí (2) |
| PIC16F876A | 8192 | 368 | 256 | 22 | 5 | 2 | Sí | Sí | Sí | Sí (2) |
| PIC16F877A | 8192 | 368 | 256 | 33 | 8 | 2 | Sí | Sí | Sí | Sí (2) |

## Tipos de encapsulado y número de terminales

Microchip Technology Inc. fabrica estos microcontroladores en encapsulados PDIP y SPDIP, SOIC, SSOP, PLCC, QFP y QFN.

Los dispositivos PIC16F870, PIC16F872, PIC16F873A y PIC16F876A se fabrican en encapsulados de 28 pines en formatos PDIP, SOIC, SSOP y QFN, mientras que los dispositivos PIC16F871, PIC16F874A y PIC16F877A se fabrican en encapsulados de 40 pines para formato PDIP, y en encapsulados de 44 pines para formatos PLCC, QFP y QFN.

En los encapsulados de 28 pines no está implementado el Puerto Paralelo Esclavo (PSP).

Muchas de los pines o terminales de estos dispositivos, como suele ocurrir en la mayoría de microcontroladores, tienen más de una función (multiplexación), dependiendo de cómo se configuren internamente por software.

Los terminales VDD (tensión) y VSS (masa) sirven únicamente para alimentar al dispositivo.

## Estructura interna

Estos microcontroladores tienen la memoria de programa y la memoria de datos separadas, lo que se conoce como arquitectura Harvard. Esta configuración interna permite entre otras cosas acceder a las instrucciones de programa y a los datos simultáneamente a través de buses diferentes, lo que mejora notablemente la velocidad de proceso de estos dispositivos.

## Circuitería externa auxiliar

Para que el microcontrolador sea capaz de funcionar en cualquier proyecto, se necesita al menos la siguiente circuitería externa:

* La alimentación.
* El reloj (oscilador).

También, y de manera opcional:

* El circuito de reinicio.

### La alimentación

Los dispositivos de la familia PIC16F87X admiten un amplio rango de tensiones de alimentación, que va de 2,0 V a 5,5 V. La tensión a la cual se alimenten determinará la frecuencia máxima de trabajo.

La potencia máxima disipada es de 1 W y se calcula mediante la siguiente fórmula:

$\,\!P_{disipada}=V_{DD}(I_{DD}-\Sigma I_{OH})+\Sigma [(V_{DD}-V_{OH})I_{OH}]+\Sigma (V_{OL}I_{OL})$

donde:

* $V_{DD}$ es la tensión suministrada por la fuente de alimentación.
* $I_{OH}$ es la corriente suministrada por las salidas del PIC en estado alto.
* $I_{OL}$ es la corriente absorbida por las salidas del PIC en estado bajo.
* $V_{OH}$ es la tensión entregada por los terminales en estado alto.
* $V_{OL}$ es la tensión presente en los terminales en estado bajo.

### El reloj

El reloj u oscilador se utiliza para generar la base de tiempo del microcontrolador. Para la conexión del oscilador se emplean los terminales OSC1 y OSC2 del dispositivo.

Los microcontroladores PIC16F87X emplean por cada ciclo de instrucción cuatro ciclos de reloj. Esto significa que por ejemplo, si el microcontrolador debe ejecutar un programa de 1000 instrucciones con un reloj de 10 MHz (periodo de reloj de 100 ns), el tiempo total que empleará para ejecutar todo el programa (asumiendo que todas las instrucciones fueran de un ciclo de instrucción) será de:

$T={1000*4 \over {10*10^{6}}}=400\mu s$

La serie PIC16F87X puede trabajar a una frecuencia de reloj máxima de 20 MHz. Esto quiere decir que, a esta frecuencia, el tiempo necesario para ejecutar las instrucciones de un ciclo de instrucción es de 200 ns, y de 400 ns para las de dos ciclos de instrucción (instrucciones de salto).

La señal de reloj puede generarse mediante una red resistencia-condensador, un cristal de cuarzo piezoeléctrico o un resonador cerámico, aunque empleando cristales de cuarzo se consiguen frecuencias de oscilación muy exactas, lo cual es útil para calcular tiempos de ejecución, temporizaciones precisas, etc.

Estos microcontroladores permiten escoger entre cinco tipos distintos de osciladores:

* LP (Low Power): reloj de bajo consumo, estable, con frecuencia de oscilación de hasta 200 kHz.
* XT (Xtal, Crystal): estable, frecuencia de oscilación de hasta 4 MHz.
* HS (High Speed): estable, frecuencia de oscilación de hasta 20 MHz.
* RC (Resistor/Condensador): frecuencia de oscilación dependiente de resistencia, condensador, voltaje de alimentación y temperatura de trabajo. Es el tipo más económico, pero también el más inestable.
* Externo: cuando la señal de reloj es externa, generada por otro circuito.

Los modos LP, XT y HS suponen la conexión de un cristal de cuarzo o resonador cerámico entre las patitas OSC1/CLKIN y OSC2/CLKOUT del dispositivo, mientras que el modo RC y Externo solo ocupan la patita OSC1/CLKIN.

### El circuito de reinicio

El terminal MCLR (Master Clear) debe estar a valor lógico alto para que el dispositivo funcione normalmente, esto es, sin irse a reinicio. Con un valor lógico bajo el dispositivo se reinicia, comenzando la ejecución desde el principio del programa que tenga cargado en memoria.

Lo más práctico, para facilitar el hecho de poder realizar un reinicio manual, es utilizar un pulsador (pulsador de reinicio), similar al que se puede encontrar en la mayoría de ordenadores. El fabricante recomienda que se intercale una resistencia de 50 a 100 ohmios entre el pulsador y la patita MCLR, para evitar posibles corrientes inducidas de más de 80 mA que podrían bloquear el dispositivo cuando este se lleva a masa (reinicio).

Debido a que el pulsador no produce una respuesta instantánea, producto de los rebotes de éste (transitorio), se generan una serie de pulsos hasta quedar estabilizado en su estado permanente. Para evitar esto se puede usar un condensador instalado en paralelo con la entrada MCLR (filtro pasa bajo).

También resulta muy efectivo el uso de un filtro pasa alto para hacer la señal de reinicio independiente del tiempo en que se presiona el pulsador. Inmediatamente después de pulsar el pulsador el μC se reinicia, sin tener en cuenta cuánto tiempo se mantiene presionado dicho pulsador.

Estas técnicas de reinicio son muy efectivas, pero no son las únicas. Existe infinidad de circuitos y posibilidades para provocar el reinicio externo en los microcontroladores, adecuándose cada solución a la necesidad o al criterio de diseño del circuito y su función específica.

## Memoria interna

Existen tres bloques bien diferenciados de memoria. Estos son:

* Memoria de programa EEPROM Flash: es el lugar físico donde se guarda el programa de usuario. Es de tipo no volátil.
* Memoria de datos SRAM: es el lugar físico donde se guardan datos. Es de tipo volátil.
* Memoria de datos EEPROM: es el lugar físico donde se guardan datos. Es de tipo no volátil.

### Memoria de datos SRAM

Esta memoria es de tipo volátil, lo que significa que no conserva su contenido después de un apagado de alimentación.

En esta memoria se encuentran los registros de funciones especiales (SFR) y los registros de propósito general (GPR), y está particionada en cuatro bancos (0, 1, 2 y 3), seleccionables independientemente. El banco 0 es el banco seleccionado por defecto cuando se alimenta al microcontrolador.

## Registros de funciones especiales (SFR)

Todos los microcontroladores cuentan con registros internos que permiten controlar y supervisar las funciones y recursos disponibles del dispositivo.

Los registros de los microcontroladores PIC se encuentran en un espacio especial de la memoria de datos, el SFR (Special Function Registers). En los dispositivos PIC16F87X estos registros son de 8 bits, la mayoría de lectura y escritura. Se puede acceder a dichos bits de manera individual, o bien a todo el registro a la vez.

Determinados pares de registros tienen funciones especiales para las cuales se pueden considerar unidos en un único registro de 16 bits, aunque físicamente siguen estando separados.

### El registro STATUS

El registro de estado (STATUS) es uno de los más importantes y empleados en el microcontrolador.

Proporciona información acerca del resultado de operaciones aritméticas, operaciones lógicas y causa de reinicios, además de permitir la selección del banco de memoria de datos.

## El registro W

El registro de trabajo W (Working Register) es un registro relevante especial de 8 bits que participa en la mayoría de instrucciones. A diferencia de los SFR, se encuentra dentro de la misma CPU, y puede ser accedido tanto para lectura como para escritura..

## Set de instrucciones y sintaxis

Los PIC16F87X son microcontroladores RISC. Esto se refleja en que tienen un repertorio reducido de 35 instrucciones ortogonales (prácticamente todas las instrucciones pueden utilizar cualquier operando), éstas son rápidas y todas tienen una longitud fija de 14 bits.

Las instrucciones se pueden clasificar en:

* Instrucciones de carga.
* Instrucciones de bits.
* Instrucciones aritméticas.
* Instrucciones lógicas.
* Instrucciones de salto.
* Instrucciones de manejo de subrutinas.
* Instrucciones especiales.

### Tabla resumen de instrucciones

| Sintaxis | Descripción | Ciclos de Instrucción |
| - | - | - |
| Instrucciones de carga |||
| CLRF f | Borra el contenido del registro f | 1 |
| CLRW | Borra el contenido del registro W | 1 |
| MOVF f,d | Mueve el contenido del registro f | 1 |
| MOVWF f | Mueve el contenido del registro W al registro f | 1 |
| MOVLW k | Guarda en el registro W el valor k | 1 |
| Instrucciones de bit |||
| BCF f,b | Pone en "0" el bit b del registro f | 1 |
| BSF f,b | Pone en "1" el bit b del registro f | 1 |
| Instrucciones aritméticas |||
| ADDLW k | Suma el valor k al registro W | 1 |
| ADDWF f,d | Suma el contenido del registro W con el de f | 1 |
| DECF f,d | Decrementa en una unidad el contenido del registro f | 1 |
| INCF f,d | Incrementa en una unidad el contenido del registro f | 1 |
| SUBLW k | Resta el valor k al registro W | 1 |
| SUBWF f,d | Resta el contenido del registro W al registro f | 1 |
| Instrucciones lógicas |||
| ANDLW k | Realiza la operación lógica AND entre el valor k y el registro W | 1 |
| ANDWF f,d | Realiza la operación lógica AND entre el contenido del registro W y el de f | 1 |
| COMF f,d | Niega el valor del registro f | 1 |
| IORLW k | Realiza la operación lógica OR entre el valor k y el registro W | 1 |
| IORWF f,d | Realiza la operación lógica OR entre el contenido del registro W y el de f | 1 |
| RLF f,d | Rota el contenido del registro f hacia la izquierda a través del carry bit | 1 |
| RRF f,d | Rota el contenido del registro f hacia la derecha a través del carry bit | 1 |
| SWAPF f,d | Intercambia los cuatro primeros bits con los cuatro últimos del registro f | 1 |
| XORLW | Realiza la operación lógica XOR entre el valor k y el registro W | 1 |
| XORWF f,d | Realiza la operación lógica XOR entre el contenido del registro W con el de f | 1 |
| Instrucciones de salto |||
| BTFSC f,b | Lee el bit b del registro f y salta la instrucción siguiente si está en “0” | 1 (2 si salta) |
| BTFSS f,b | Lee el bit b del registro f y salta la instrucción siguiente si está en “1” | 1 (2 si salta) |
| DECFSZ f,d | Decrementa en una unidad el contenido del registro f y salta la instrucción siguiente si es cero | 1 (2 si salta) |
| INCFSZ f,d | Incrementa en una unidad el contenido del registro f y salta la instrucción siguiente si es cero | 1 (2 si salta) |
| GOTO k | Salto incondicional a la etiqueta k | 2 |
| Instrucciones de manejo de subrutinas |||
| CALL k | Llamada a la subrutina k | 2 |
| RETFIE | Retorno de una interrupción | 2 |
| RETLW | Retorno de una subrutina con el valor k en el registro W | 2 |
| RETURN | Retorno de una subrutina | 2 |
| Instrucciones especiales |||
| CLRWDT | Borra el temporizador del Watchdog | 1 |
| NOP | No realiza ninguna operación (pero consume tiempo de ejecución) | 1 |
| SLEEP | Se pone el PIC en estado de reposo (dormido) | 1 |

En todas las instrucciones donde aparece una d como operando:

* Si d = 0, el resultado de la operación se guarda en W.
* Si d = 1, el resultado de la operación se guarda en el registro f. Es el valor por defecto.

## Registro de configuración

Estos microcontroladores cuentan con un registro especial llamado palabra de configuración (Configuration Word) de 14 bits, que se encuentra en la dirección 2007h de la memoria de programa.

Este registro debe escribirse durante el proceso de grabación del microcontrolador ya que no puede ser modificado durante el tiempo de ejecución de un programa.

Su función es especificar ciertas características de funcionamiento del microcontrolador, como son:

* Protección de memoria de programa.
* Uso del modo de depuración en circuito.
* Permiso de escritura en memoria Flash.
* Protección de memoria EEPROM de datos.
* Uso de programación en modo de bajo voltaje.
* Uso de reinicio por caída de tensión.
* Uso del temporizador de conexión de alimentación.
* Uso del Watchdog.
* Tipo de oscilador empleado.

Existen dos formas de configurar estos bits: una de ellas es desde MPLAB, mediante la opción Configuration bits del menú configure. La otra es mediante la directiva _ _CONFIG dentro del programa ensamblador.

## El conversor analógico-digital

El conversor analógico-digital (ADC en inglés) que llevan incorporados los microcontroladores de la subfamilia PIC16F87X es de 10 bits. Su funcionamiento es bastante simple, comparado con los conversores A/D R2R, los de resistencia ponderada, etc.

El número de canales de conversión disponibles depende del modelo de dispositivo. Así, los modelos PIC16F874A y PIC16F877A vienen equipados con 8 canales, mientras que los modelos PIC16F873A y PIC16F876A vienen equipados con 5 canales.

La técnica que utilizan estos dispositivos para la conversión es la de “incremento y comparación”. Consiste en usar un registro auxiliar cuyo valor se compara con la entrada analógica. Si es menor se incrementa el registro y se vuelve a comparar. Así hasta que el valor del registro sea lo más aproximado posible (pero sin pasarse) a la entrada analógica.

El rango de voltaje aceptado para la conversión de la señal analógica es de 0 V a 5 V. Si se tiene que trabajar con una señal de mayor voltaje, basta con poner a la entrada del conversor un divisor de tensión correctamente calculado o bien trabajar con alguna tensión de referencia externa al μC.

La resolución de la conversión es función de la tensión de referencia externa (en caso de que la hubiere) y viene dada por:

$Res={{V_{ref+}-V_{ref-}} \over 1024}$

Si no existe referencia externa, el microcontrolador toma como valores de referencia Vref+ = VDD y Vref- = GND (valores de alimentación del dispositivo).

Por ejemplo, si la tensión de referencia positiva (Vref+) es de 5 V y la tensión de referencia negativa (Vref-) es de 0 V, la resolución es de 4,8 mV por cada bit. Una vez realizada la conversión, se obtienen un valor binario 0000000000 para 0 V y un valor binario 1111111111 para 5 V.

### Controlando el conversor A/D

Los registros asociados al conversor A/D son:

* ADRESH (completo)
* ADRESL (completo)
* ADCON0 (completo)
* ADCON1 (completo)

Como la resolución del convertidor A/D es de 10 bits y los registros del µC son de 8 bits, se utilizan dos registros, ADRESL y ADRESH (AD Result Low y AD Result High), de forma concatenada. Es decir, los 8 bits de ADRESL y 2 bits de ADRESH.

Los registros ADCON0 y ADCON1 permiten controlar, configurar y poner en marcha al conversor.

Los bits 6 y 7 del registro ADCON0 sirven para ajustar la frecuencia del oscilador del conversor, que está ligada directamente con la frecuencia de oscilación del μC. Los bits 3,4 y 5 sirven para elegir el canal de conversión. El bit 2 sirve para iniciar la conversión. Debe ponerse en nivel lógico alto (1) para comenzar el proceso de conversión. Automáticamente, este bit pasará a nivel lógico bajo (0) cuando la conversión haya finalizado. El bit 1 no se usa. El bit 0 sirve para activar el módulo de conversión. Si este bit está a nivel lógico bajo, el módulo de conversión estará deshabilitado.

El registro ADCON1 es el encargado de definir qué patita del µC usaremos como entrada analógica. Esto es muy útil cuando, por ejemplo, se usa un mismo terminal del µC como salida/entrada digital y en un determinado momento se quiere que ese mismo terminal lea un voltaje analógico externo. Este registro también es el responsable de la selección de la “justificación” del resultado de la conversión (bit 7) y de configurar cual/es serán los terminales donde aplicaremos la tensión de referencia en caso de necesitarla.

### Conversión Terminada

El tiempo que le toma al μC realizar la conversión se denomina $T_{AD}$ y nunca debe ser menor que 1,6 μs para la familia 16F87X. el tiempo $T_{AD}$ es configurado por software según la relación $T_{AD}=kT_{OSC}$ donde K es el divisor de la frecuencia del conversor. Por ejemplo, si trabajamos con $T_{OSC}$ = 1μs y en los bits 7 y 6 del registro ADCON0 ponemos 00, quedará: $T_{AD}=2T_{OSC}=2*1\mu s=2\mu s$ lo cual está dentro del rango permitido.

Una vez terminada la conversión, el resultado se almacena en los registros ADRESH y ADRESL según estén configurados en el bit 7 del registro ADCON1. La "justificación" a la derecha o izquierda es sencilla de comprender; se trata de guardar el resultado de 10 bits en dos registros de 8 bit’s c/u, o sea que se elegirá si se quieren los 8 primeros bits en el ADRESL y los dos restantes en el ADRESH o viceversa.

Generalmente la elección de la justificación está directamente emparentada con la resolución que queremos leer, es decir, si se quiere conectar un potenciómetro y según la tensión aumentar o disminuir el tiempo de parpadeo de un led, se puede justificar a la izquierda y leer como resultado de la conversión solo los 8 bits del ADRESH y descartar o despreciar los dos bits de menor peso significativo que se guardarán en el ADRESL.

### Pasos necesarios para la conversión A/D

A modo de algoritmo los pasos necesarios para una correcta utilización del módulo A/D son los siguientes:

* Configurar el módulo A/D:
   * Terminales de entrada analógica y de referencia.
   * Seleccionar el canal adecuado.
   * Seleccionar la velocidad de conversión.
   * Prender el conversor: Setear el bit 0 del registro ADCON0
* Empezar la conversión: Setear el bit 1 del registro ADCON0
* Esperar que el bit 2 del registro ADCON0 se ponga a 0
* Leer el resultado en los registros ADRESH:ADRESL

En estos pasos no se tiene en cuenta que se pueden necesitar más de una conversión por distintos canales o bien que se realicen varias conversiones y luego tomar un promedio. Esta última técnica es muy usada cuando las variaciones de tensión son rápidas y promediando tres o cuatro conversiones se tiene así el resultado, hasta que se realice una segunda conversión.

## Temporizadores

Esta familia de microcontroladores tiene dos tipos de temporizadores: TMR0 y TMR1, y TMR2. Son registros de 8 bits que se encargarán de acumular eventos, de modo que al pasar del valor 0xFF a 0x00, se pondrá en 1 la bandera de desbordamiento de TIMER0 o TIMER1 dependiendo el caso. Al habilitar las interrupciones por el microcontrolador, en este momento se dará una interrupción.

El registro TMR0 o TMR1 podrá incrementarse cada 2, 4, 8, 16, 32, 64, 128 o 256 ciclos de reloj, de modo que conociendo la frecuencia a la que está trabajando el microcontrolador, se puede tener un temporizador. La bandera de desbordamiento se activará según la siguiente expresión:

$T_{TXIF}=(T)(PRE)(256-ValorInicialTMRX)$

Donde:

T: periodo de oscilación del microcontrolador.

PRE: predivisor

ValorInicialTMRX: valor de inicio del registro TMR0 o TMR1

El valor del predivisor se seleccionará configurando los tres bits menos significativos del registro OPTION_REG, donde se tendrán las siguientes opciones:n las siguientes posibilidades:

| PRE | PS2 | PS1 | PS0 |
| - | - | - | - |
| 2 | 0 | 0 | 0 |
| 4 | 0 | 0 | 1 |
| 8 | 0 | 1 | 0 |
| 16 | 0 | 1 | 1 |
| 32 | 1 | 0 | 0 |
| 64 | 1 | 0 | 1 |
| 128 | 1 | 1 | 0 |
| 256 | 1 | 1 | 1 |

## Acerca de la programación de los dispositivos

La familia de los PIC16F87X cuenta con un conjunto reducido de 35 instrucciones, lo que facilita enormemente su memorización. La mayoría de estas instrucciones se ejecutan en un solo ciclo de instrucción, mientras que aquellas instrucciones que realizan saltos de ejecución lo hacen en dos ciclos de instrucción. Cada una de estas instrucciones se codifica en una palabra de 14 bits única e inequívoca, que conforman en conjunto lo que se conoce como código máquina del dispositivo.

Aunque podría emplearse directamente este código máquina para programar el dispositivo (ya fuera en formato binario o en hexadecimal), resultaría demasiado lento y complicado. Por esta razón, cada una de las instrucciones se representa de manera equivalente con un nemónico, que es más fácil de recordar y de interpretar por el programador. A este tipo de lenguaje de programación se le llama lenguaje ensamblador.

Actualmente, para la programación de microcontroladores puede emplearse tanto el lenguaje ensamblador como lenguajes de más alto nivel, tipo C o Pascal, empleando el compilador adecuado.

Los microcontroladores tienen un espacio de memoria que varía según el modelo y este espacio de memoria es limitado. Hay que tener en cuenta que a cada instrucción escrita en lenguaje de alto nivel le corresponderán por lo general varias instrucciones en lenguaje ensamblador, lo que significa que un programa escrito en lenguaje de alto nivel ocupa más espacio de memoria que uno escrito en lenguaje ensamblador. Por este motivo, la elección de uno u otro tipo de lenguaje a la hora de programar deberá hacerse teniendo en cuenta el espacio de memoria disponible.

En caso de utilizar un lenguaje de alto nivel, siempre se requerirá compilar el programa terminado para obtener el archivo hexadecimal (lenguaje máquina) con el cual se programará el microcontrolador.

La programación física del dispositivo se hará normalmente mediante un programador, capaz de grabar el programa de usuario en la memoria del microcontrolador.

## Ejemplo sencillo: encender y apagar un LED

El ejemplo propuesto ilustra cómo conectar un LED por medio de una resistencia limitadora de corriente a un terminal de salida de un PIC16F873, para que éste se encienda al presionar un pulsador y se apague al soltarlo.

### Circuito eléctrico

El circuito completo se debe alimentar a 5 V. Se utiliza un cristal de cuarzo de 10 MHz con condensadores de 27 nF como circuito de reloj y un circuito de reset.

Se agrega un pulsador conectado a la patita RA0 (entrada) y un LED con su resistencia limitadora conectado a la patita RB7 (salida).

### Programa

Para crear el programa que se grabará en el PIC se puede usar MPLAB, que es el entorno de desarrollo gratuito ofrecido por el fabricante Microchip Technology Inc.

Básicamente este sencillo ejemplo se puede modelar con el siguiente pseudocódigo:

**Ensamblador**

Empleando MPLAB, se genera el programa en lenguaje ensamblador a partir del pseudocódigo anterior. El archivo generado deberá tener la extensión ".asm":

El símbolo ; permite escribir comentarios en el programa.

Inicio, Comienzo, Apaga y Enciende son etiquetas que ayudan a identificar una dirección de memoria del programa. Estas se reemplazan por la dirección de memoria correspondiente.

En el programa se pueden observar las directivas comentadas, instrucciones, literales, configuración de registros, etc.

**Lenguaje máquina**

Al compilar el archivo ".asm" creado se obtienen varios archivos. Uno de ellos, con extensión ".hex", es el que se grabará en el PIC, y contiene todas las instrucciones traducidas al lenguaje máquina del microcontrolador.

El archivo ".hex" obtenido es el siguiente:

