Ingeniería inversa de MCU

Desbloqueo de microcontroladores - MikaTech

Nuestros valores y objetivos

Sobre MikaTech

El tiempo pasó rápido: desde el día en que realizamos nuestro primer proyecto de ingeniería inversa de MCU 8051 en 1998, hasta el día en que fundamos nuestro laboratorio de ingeniería inversa de un millón de dólares en 2012, transcurrieron 14 años. Ahora iniciamos nuestro nuevo negocio de desarrollo de sistemas visuales integrados; esperamos poder servir otros 10 años más.

firma Peter Lee Cofundador y CEO

Arquitectura y programación de MCU 8051 para ingeniería inversa 3

Capítulo 5: Lenguaje ensamblador

Introducción

Los ingenieros orientados al hardware tuvieron que hacer concesiones si querían seguir siendo competitivos en el desarrollo embebido. A diferencia de los circuitos electrónicos ordinarios que solo requieren cableado y fuente de alimentación para funcionar, los microcontroladores requieren además una programación personalizada para llevar a cabo las tareas definidas. Afortunadamente, las arquitecturas de microcontroladores no han avanzado hasta el punto de requerir diversos lenguajes de alto nivel; casi todas las familias de microcontroladores solo entienden de forma nativa el lenguaje de máquina. Esta estandarización trae grandes beneficios. La desventaja es que el lenguaje de máquina, consistente puramente en ceros y unos binarios, es ininteligible para los desarrolladores humanos y solo descifrable por expertos especializados en diseño de hardware. Para cerrar la brecha de comunicación entre el hardware del microcontrolador y los programadores humanos, se creó el lenguaje ensamblador — el primer lenguaje de programación de bajo nivel legible por humanos.

El ensamblador resolvió el desafío de memorizar los códigos de operación binarios crudos de las instrucciones de hardware, sin embargo introdujo una nueva barrera que complicó el flujo de trabajo tanto para los desarrolladores como para el hardware del microcontrolador. Este nuevo obstáculo se resolvió utilizando dos herramientas clave: un programa de software ensamblador basado en PC y un dispositivo de programación de hardware dedicado conocido como programador de chips.

El software ensamblador acepta mnemónicos de ensamblador legibles por humanos y los traduce de manera confiable a un archivo de salida ejecutable binario. La etapa de compilación que convierte el código fuente de ensamblador en código de máquina es crítica, ya que el archivo HEX resultante es un flujo de valores binarios que solo el hardware del microcontrolador puede interpretar. El código fuente de ensamblador crudo no puede ejecutarse directamente en un microcontrolador a menos que este archivo HEX compilado se programe en la memoria de programa del dispositivo. Aquí es donde entra en juego el componente final del flujo de trabajo de desarrollo, el programador de chips. Es un dispositivo de hardware compacto que se conecta a una PC de escritorio a través de un puerto de comunicación estándar y cuenta con un zócalo para montar el chip del microcontrolador objetivo para la programación de firmware.

5.1 Elementos del lenguaje ensamblador

El lenguaje ensamblador sigue reglas estructurales similares a los lenguajes humanos naturales, con palabras reservadas, reglas de formato estrictas y sintaxis estandarizada. Los cuatro bloques fundamentales centrales del código fuente de ensamblador se listan a continuación:

  • Etiquetas
  • Mnemónicos de instrucciones
  • Directivas del ensamblador
  • Líneas de comentario
Elementos del ensamblador

Sintaxis del lenguaje ensamblador

Se deben seguir reglas de formato estrictas (llamadas colectivamente sintaxis) al escribir código fuente de ensamblador para garantizar una compilación sin errores en código de máquina HEX ejecutable. Las reglas de sintaxis obligatorias se limitan a los siguientes requisitos:

  • Una sola línea de código fuente de ensamblador puede contener un máximo de 255 caracteres ASCII;
  • Toda línea compilable debe comenzar con una etiqueta, un mnemónico de instrucción o una directiva del ensamblador;
  • Todo el texto que aparece después de un punto y coma ";" en cualquier línea se trata como un comentario legible por humanos y es completamente ignorado por el ensamblador durante la compilación;
  • Todos los componentes distintos en una sola línea (etiquetas, instrucciones, operandos, directivas) deben estar separados por al menos un carácter de espacio en blanco. La tecla TAB del teclado se usa ampliamente en lugar de espacios simples para alinear ordenadamente etiquetas, mnemónicos y directivas en columnas verticales consistentes para una mejor legibilidad del código.

Literales numéricos

Excluyendo el sistema de numeración octal obsoleto, el lenguaje ensamblador admite valores numéricos escritos en tres formatos de base distintos:

Números decimales

Si no se especifica un sufijo de base, el ensamblador interpreta todos los literales numéricos como valores decimales. La notación decimal usa los dígitos del 0 al 9. Dado que el almacenamiento del microcontrolador asigna un máximo de dos bytes para el almacenamiento numérico general, el valor decimal más grande representable dentro del código de ensamblador es 65535. La letra de sufijo "D" puede añadirse para marcar explícitamente un valor como decimal, por ejemplo: 1234D.

Números hexadecimales

La notación hexadecimal es el formato más utilizado para la programación embebida. El sistema de base hexadecimal usa dieciséis símbolos únicos: los dígitos 0–9 y las letras A–F. El valor hexadecimal máximo de dos bytes es FFFF, que es equivalente al valor decimal 65535. Para diferenciar los literales hexadecimales de los valores decimales, se añade la letra de sufijo "h" (mayúscula o minúscula) al número, como 54h.

Números binarios

Los literales binarios se usan con frecuencia cuando los estados de bits individuales de los registros de la CPU necesitan definirse explícitamente, ya que cada dígito binario corresponde directamente a una posición de bit de hardware. La notación binaria solo usa los dígitos 0 y 1. El literal binario máximo de dos bytes es 1111111111111111. La letra de sufijo "b" (mayúscula o minúscula) se añade para distinguir los valores binarios de otros formatos numéricos, por ejemplo: 01100101B.

Operadores

Muchas directivas condicionales del ensamblador y operandos de instrucciones aceptan expresiones matemáticas y lógicas en lugar de valores estáticos fijos. A continuación se muestra un bloque condicional de ejemplo:

IF (VERSION>1)
   LCALL Table_2
   USING VERSION+1
ENDIF
   ...

El ensamblador puede evaluar expresiones matemáticas y lógicas constantes durante la compilación e incrustar los valores calculados resultantes en el código de máquina final. El conjunto completo de operadores admitidos se lista en la tabla siguiente:

Símbolo del operador Descripción de la operación Expresión de ejemplo Resultado evaluado
+ Suma 10+5 15
- Resta 25-17 8
* Multiplicación 7*4 28
/ División entera (trunca el resto) 7/4 1
MOD Módulo (resto de la división) 7 MOD 4 3
SHR Desplazamiento bit a bit a la derecha 1000B SHR 2 0010B
SHL Desplazamiento bit a bit a la izquierda 1010B SHL 2 101000B
NOT NO lógico bit a bit (complemento a 1) NOT 1 1111111111111110B
AND Y lógico bit a bit 1101B AND 0101B 0101B
OR O lógico bit a bit 1101B OR 0101B 1101B
XOR O exclusiva bit a bit 1101B XOR 0101B 1000B
LOW Extraer los 8 bits inferiores de un valor de 16 bits LOW(0AADDH) 0DDH
HIGH Extraer los 8 bits superiores de un valor de 16 bits HIGH(0AADDH) 0AAH
EQ, = Comparación de igualdad 7 EQ 4 o 7=4 0 (Falso)
NE,<> Comparación de desigualdad 7 NE 4 o 7<>4 0FFFFH (Verdadero)
GT, > Comparación mayor que 7 GT 4 o 7>4 0FFFFH (Verdadero)
GE, >= Mayor que o igual a 7 GE 4 o 7>=4 0FFFFH (Verdadero)
LT, < Comparación menor que 7 LT 4 o 7<4 0 (Falso)
LE,<= Menor que o igual a 7 LE 4 o 7<=4 0 (Falso)

Símbolos definidos por el usuario

Se pueden asignar nombres simbólicos personalizados a registros de CPU, valores constantes, direcciones de memoria y puntos de entrada de subrutinas dentro del código de ensamblador, simplificando drásticamente la legibilidad y el mantenimiento del código fuente. Por ejemplo, si el pin GPIO P0.3 se conecta a un pulsador físico que desencadena una detención completa del proceso (botón STOP), la lógica del código se vuelve mucho más intuitiva si la dirección de bit P0.3 se aliasa con el símbolo descriptivo "pushbutton_STOP". Similar a otros lenguajes de programación, reglas de nomenclatura estrictas gobiernan los símbolos personalizados válidos:

  • Los caracteres de símbolos válidos incluyen letras latinas mayúsculas y minúsculas (A-Z, a-z), dígitos decimales (0–9) y dos símbolos especiales: el guion bajo "_" y el signo de interrogación "?". El lenguaje ensamblador es completamente insensible a mayúsculas y minúsculas para los nombres de símbolos.

Los dos símbolos mostrados a continuación son tratados como idénticos por el ensamblador:

Serial_Port_Buffer
SERIAL_PORT_BUFFER
  • Para evitar la ambigüedad con los literales numéricos, todo símbolo válido debe comenzar con una letra alfabética, un guion bajo o un signo de interrogación; los dígitos numéricos no pueden usarse como primer carácter.
  • Un nombre de símbolo puede contener hasta 255 caracteres en total, pero el ensamblador solo evalúa los primeros 32 caracteres para distinguir identificadores únicos. El ejemplo siguiente demuestra este comportamiento: los dos primeros símbolos se marcan como definiciones duplicadas (error de compilación), mientras que el tercero y el cuarto se reconocen como identificadores distintos:
START_ADDRESS_OF_TABLE_AND_CONSTANTS_1
START_ADDRESS_OF_TABLE_AND_CONSTANTS_2
TABLE_OF_CONSTANTS_1_START_ADDRESS
TABLE_OF_CONSTANTC_2_START_ADDRESS
  • Ciertas palabras clave reservadas no pueden usarse como nombres de símbolos personalizados, ya que son mnemónicos de instrucciones centrales predefinidos, directivas del ensamblador o identificadores de registros de hardware integrados. Por ejemplo, un usuario no puede definir un símbolo llamado "A" o "DPTR", ya que estos nombres corresponden a registros nativos de la CPU.

La lista completa de palabras clave reservadas que están prohibidas como símbolos personalizados se proporciona en la tabla siguiente:

A AB ACALL ADD
ADDC AJMP AND ANL
AR0 AR1 AR2 AR3
AR4 AR5 AR6 AR7
BIT BSEG C CALL
CJNE CLR CODE CPL
CSEG DA DATA DB
DBIT DEC DIV DJNZ
DPTR DS DSEG DW
END EQ EQU GE
GT HIGH IDATA INC
ISEG JB JBC JC
JMP JNB JNC JNZ
JZ LCALL LE LJMP
LOW LT MOD MOV
MOVC MOVX MUL NE
NOP NOT OR ORG
ORL PC POP PUSH
R0 R1 R2 R3
R4 R5 R6 R7
RET RETI RL RLC
RR RRC SET SETB
SHL SHR SJMP SUBB
SWAP USING XCH XCHD
XDATA XOR XRL XSEG

Etiquetas

Una etiqueta es un tipo especializado de símbolo que representa un alias legible por humanos para una dirección de memoria física en la ROM de programa o la RAM de datos. Las etiquetas siempre se colocan al inicio mismo de una línea de código fuente. Las instrucciones de salto, bifurcación y llamada a subrutina serían extremadamente engorrosas de escribir y mantener sin etiquetas. El flujo de trabajo estándar de uso de etiquetas es sencillo:

  • Asignar una etiqueta con nombre descriptivo a la primera línea de una subrutina o al destino objetivo de una instrucción de salto;
  • Referenciar el nombre de la etiqueta directamente dentro de las instrucciones de salto y llamada a subrutina en lugar de ingresar manualmente direcciones numéricas crudas de memoria de 16 bits.

Durante la compilación, el ensamblador resuelve automáticamente cada etiqueta a su dirección de memoria absoluta correspondiente y sustituye el valor numérico en el código de máquina compilado.

Directivas del ensamblador

A diferencia de los mnemónicos de instrucciones de CPU que se compilan en código de máquina ejecutable almacenado dentro de la memoria de programa del microcontrolador, las directivas del ensamblador son comandos nativos interpretados únicamente por el software del ensamblador y no tienen impacto en el comportamiento en tiempo de ejecución del hardware del microcontrolador. Algunas directivas son obligatorias para cada proyecto de ensamblador válido, mientras que otras existen puramente para simplificar los flujos de trabajo de desarrollo o acelerar los procesos de compilación.
Las directivas ocupan la misma columna vertical reservada para los mnemónicos de instrucciones en el código fuente, y una sola línea de fuente solo puede contener una directiva del ensamblador.

Directiva EQU

La directiva EQU vincula un valor numérico constante fijo a un nombre de símbolo personalizado para su reutilización en todo el archivo fuente. Ejemplo de uso:

MAXIMUM EQU 99

Después de esta definición, cada aparición del símbolo "MAXIMUM" dentro del código fuente será reemplazada con el valor literal 99 durante la compilación. Cada símbolo solo puede definirse una vez usando EQU, por lo que las declaraciones EQU casi siempre se colocan en la parte superior del archivo de ensamblador para la configuración global de constantes.

Directiva SET

La directiva SET también mapea un valor numérico a un alias simbólico. Su distinción clave de EQU es que SET permite la redefinición repetida del mismo símbolo múltiples veces en todo el archivo fuente:

SPEED SET 45
SPEED SET 46
SPEED SET 57

Directiva BIT

La directiva BIT asigna un nombre de símbolo personalizado a una ubicación de memoria direccionable por bits específica, donde la dirección de bit objetivo debe caer dentro del rango 0–255. Definiciones de muestra:

TRANSMIT BIT PSW.7 ;Assign alias "TRANSMIT" to bit 7 of the PSW status register
OUTPUT BIT 6 ;Assign alias "OUTPUT" to bit address 06h
RELAY BIT 81 ;Assign alias "RELAY" to bit address 81h (corresponds to Port 0 pin 1)

Directiva CODE

La directiva CODE vincula un símbolo personalizado a una dirección fija de memoria de programa. Dado que el espacio máximo de direcciones de la memoria de programa estándar del 8051 es de 64KB, las direcciones válidas van de 0 a 65535. Ejemplo:

RESET CODE 0 ;Assign alias "RESET" to program memory location 00h
TABLE CODE 1024 ;Assign alias "TABLE" to program memory address 1024 decimal (0400h)

Directiva DATA

La directiva DATA adjunta un alias simbólico a una dirección dentro de la RAM interna directamente accesible del microcontrolador, con valores de dirección válidos que abarcan 0–255. Puede reasignar nombres legibles a cualquier SFR estándar o registro RAM de propósito general:

TEMP12 DATA 32 ;Name RAM address 32 as "TEMP12"
STATUS_R DATA 0D0h ;Rename the PSW special function register to "STATUS_R"

Directiva IDATA

La directiva IDATA crea alias simbólicos para las ubicaciones de RAM accedidas mediante direccionamiento indirecto a través de los registros puntero R0 o R1:

TEMP22 IDATA 32 ;Alias the RAM location pointed to by register at address 32 as "TEMP22"
TEMP33 IDATA T_ADR ;Alias the RAM location pointed to by register T_ADR as "TEMP33"

Directiva XDATA

La directiva XDATA asigna nombres simbólicos a las ubicaciones de memoria dentro de la RAM de datos externa, que admite direccionamiento completo de 16 bits hasta 65535. Ejemplo:

TABLE_1 XDATA 2048 ;Alias external RAM address 2048 decimal as "TABLE_1"

Directiva ORG

La directiva ORG establece el desplazamiento de memoria inicial para todo el código subsiguiente compilado o las definiciones de datos dentro del segmento activo. Ejemplo:

BEGINNING ORG 100
          ...
          ...
          ORG 1000h
TABLE     ...
          ...

Este fragmento de código coloca el programa principal comenzando en el desplazamiento de memoria 100 decimal, mientras que el bloque de datos de la tabla de consulta se ancla en la dirección 1000 hexadecimal.

Directiva USING

La directiva USING selecciona cuál de los cuatro bancos de registros de propósito general de la CPU (R0–R7) se utilizará para la lógica de código subsiguiente:

USING 0 ;Select Register Bank 0 (R0-R7 mapped to RAM addresses 0–7)
USING 1 ;Select Register Bank 1 (R0-R7 mapped to RAM addresses 8–15)
USING 2 ;Select Register Bank 2 (R0-R7 mapped to RAM addresses 16–23)
USING 3 ;Select Register Bank 3 (R0-R7 mapped to RAM addresses 24–31)

Directiva END

La directiva END marca la terminación absoluta del archivo fuente de ensamblador. El ensamblador detiene todo el procesamiento de compilación inmediatamente al encontrar este token. Ejemplo:

...
END ;Marks the end of the entire assembly source program

Directivas de selección de segmentos

Cinco directivas dedicadas controlan la selección entre los cinco tipos distintos de segmentos de memoria disponibles en los microcontroladores 8051 estándar:

CSEG ;Activates the program code memory segment for executable instructions
BSEG ;Activates the bit-addressable internal RAM segment
DSEG ;Activates the directly addressable general-purpose internal RAM segment
ISEG ;Activates the indirectly addressable internal RAM segment (accessed via R0/R1 pointers)
XSEG ;Activates the external data RAM segment

El segmento de código CSEG está habilitado por defecto cuando el ensamblador se inicializa y permanece activo hasta que se declara una directiva de segmento alternativa. Cada segmento de memoria mantiene su propio contador de direcciones independiente, que se reinicia a cero cada vez que el ensamblador reinicia la compilación. El desplazamiento inicial del contador de direcciones de un segmento puede establecerse manualmente añadiendo un especificador AT seguido de un valor numérico, una expresión aritmética o un símbolo predefinido. Ejemplo:

DSEG       ;Switch to directly addressed internal RAM segment
BSEG AT 32 ;Select bit-addressable RAM with segment counter offset starting at bit 32

El símbolo de dólar "$" representa el valor actual del contador de direcciones para el segmento activo. A continuación se proporcionan dos ejemplos prácticos de uso:

Ejemplo 1:

JNB FLAG,$ ;Infinite loop that repeats this jump instruction until FLAG bit is cleared

Ejemplo 2:

MESSAGE DB 'ALARM turn off engine'
LENGTH EQU $-MESSAGE-1

Estas dos líneas calculan el recuento exacto de caracteres de la cadena ASCII "ALARM turn off engine" almacenada en la dirección etiquetada MESSAGE.

Directiva DS

La directiva DS reserva un bloque contiguo de espacio de memoria de tamaño de byte dentro del segmento de datos DSEG, ISEG o XSEG actualmente activo. A continuación se muestran dos ejemplos de uso:

Ejemplo 1:

DSEG     ;Select direct-access internal RAM segment
DS 32         ;Advance segment address counter by 32 bytes
SP_BUFF DS 16 ;Reserve 16-byte contiguous block for serial port receive buffer
IO_BUFF DS 8  ;Reserve 8-byte contiguous block for general I/O data buffer

Ejemplo 2:

ORG 100       ;Set starting address offset to 100 decimal
DS 8          ;Reserve 8 empty consecutive bytes
LAB ......... ;Program logic begins at memory address 108

Directiva DBIT

La directiva DBIT asigna un bloque de almacenamiento de bits contiguo dentro del segmento de RAM direccionable por bits BSEG activo, con el tamaño de asignación especificado como un recuento de bits crudo:

BSEG ;Activate bit-addressable RAM segment
IO_MAP DBIT 32 ;Reserve the first 32 bit positions for I/O status flags

Directiva DB

La directiva DB almacena valores de byte estáticos o cadenas de caracteres ASCII directamente en el segmento de memoria de programa CSEG activo. Los múltiples literales numéricos se separan con comas, y las cadenas de texto ASCII deben estar encerradas entre comillas simples. Esta directiva solo puede usarse mientras el segmento de código CSEG esté activo:

CSEG
DB 22,33,'Alarm',44

Si una etiqueta precede a una declaración DB, la dirección de la etiqueta apuntará al primer elemento de datos definido (el valor 22 en este ejemplo).

Directiva DW

La directiva DW funciona de manera similar a DB, pero almacena palabras completas de dos bytes de 16 bits en la memoria de programa. El byte de orden alto de cada valor de palabra se escribe primero en la memoria, seguido del byte de orden bajo.

Directivas condicionales IF, ELSE, ENDIF

Estas tres directivas crean bloques de compilación condicional dentro del código fuente de ensamblador. Cada bloque condicional se abre con una declaración IF y termina con ENDIF, con lógica ELSE opcional que separa las rutas de código mutuamente excluyentes. La expresión matemática/lógica encerrada entre paréntesis después de IF determina qué secciones del código fuente se compilan en el binario final:

  • Si la expresión condicional se evalúa como verdadera (valor distinto de cero), todas las líneas de fuente entre IF y la siguiente directiva ELSE o ENDIF se compilan en código de máquina;
  • Si la expresión condicional se evalúa como falsa (valor cero), todas las líneas entre IF y ELSE se omiten durante la compilación, y el ensamblador reanuda el procesamiento de las líneas después de ELSE o ENDIF.

Ejemplo 1:

IF (VERSION>3)
   LCALL Table_2
   LCALL Addition
ENDIF
   ...

Si el valor de la constante VERSION es mayor que 3 (condición verdadera), las dos llamadas a subrutina a Table_2 y Addition se compilan en la imagen final del firmware. Si VERSION es menor o igual que 3 (condición falsa), estas dos instrucciones se descartan por completo durante la compilación.

Ejemplo 2:

Si el símbolo Model es igual a 1, las dos instrucciones inmediatamente posteriores a IF se compilan, y todo el código entre ELSE y ENDIF se ignora. Si Model es igual a 0, las instrucciones del bloque IF se omiten, y solo el código bajo ELSE se ensambla en código de máquina.

IF (Model)
   MOV R0,#BUFFER
   MOV A,@R0
ELSE
   MOV R0,#EXT_BUFFER
   MOVX A,@R0
ENDIF
   ...

Directivas de control del ensamblador

Las directivas de control comienzan con un signo de dólar "$". Configuran el comportamiento del ensamblador durante la compilación, incluida la inclusión de archivos fuente externos, las rutas de destino del archivo HEX de salida y las reglas de formato para el archivo de listado de compilación legible por humanos. Existen muchas directivas de control, pero solo las más comúnmente utilizadas se cubren a continuación:

Directiva $INCLUDE

Esta directiva instruye al ensamblador a cargar y analizar un archivo fuente de ensamblador externo durante el proceso de compilación:

$INCLUDE(TABLE.ASM)

Directiva $MOD8253

La directiva $MOD8253 referencia un archivo de encabezado predefinido que contiene todos los nombres de los registros de funciones especiales (SFR) y sus direcciones de memoria correspondientes para la variante del microcontrolador 8253. Con esta directiva habilitada, los desarrolladores pueden referenciar los registros por sus nombres legibles por humanos en lugar de direcciones numéricas crudas. Si esta directiva se omite, cada SFR utilizado en el proyecto debe declararse manualmente con su dirección de memoria exacta al inicio del archivo fuente.

 

Capítulo 6 : Ejemplos

Descripción general

Este capítulo entrega el conocimiento fundamental central del hardware del microcontrolador requerido para el despliegue práctico con manos en la obra. Los lectores no encontrarán lógica de programa excesivamente compleja ni esquemas de circuito avanzados con diseños optimizados de vanguardia dentro de esta sección. En su lugar, los siguientes ejemplos prácticos demuestran que la programación embebida no es ni una habilidad exclusiva ni un oficio dependiente del talento — es simplemente el proceso de ensamblar lógica funcional modular mediante sintaxis de instrucciones estandarizada. Puede estar seguro, el diseño de hardware y el desarrollo iterativo giran en torno a un flujo de trabajo central consistente: "probar, ajustar, iterar". Naturalmente, la complejidad del proyecto escala con la experiencia; la misma lógica de componentes tipo rompecabezas se aplica tanto a los prototipos de aficionados como al desarrollo profesional de arquitectura de grado industrial...

Si bien estas demostraciones introductorias se centran puramente en el funcionamiento funcional fundamental, cada plataforma de hardware embebido conlleva una capa de riesgo de seguridad subyacente a menudo subestimada que rara vez se cubre en los tutoriales para principiantes. El microcontrolador central (MCU) que ejecuta estas rutinas de control simples puede integrarse posteriormente en productos comerciales finales, donde salvaguardar el código fuente ejecutable contra el acceso no autorizado se convierte en una prioridad de diseño vital. Muchos ingenieros novatos creen erróneamente que el mecanismo de fusible de bit de bloqueo integrado puede bloquear por completo el acceso externo de lectura a la memoria flash interna, sin embargo esta suposición no es universalmente confiable. En escenarios de amenaza del mundo real, los actores malintencionados pueden desplegar flujos de trabajo de decapsulación de chips para exponer las capas desnudas del troquel de silicio y realizar micro-sondeo directo de los fusibles de hardware que controlan la seguridad. Una vez que se elimina el encapsulado, los adversarios pueden extraer un volcado completo de memoria de todas las regiones de almacenamiento del programa, completando la extracción total de firmware sin credenciales de autenticación válidas. El conjunto de chips EEPROM a bordo, que comúnmente almacena parámetros de calibración de fábrica y claves de seguridad criptográficas, enfrenta una vulnerabilidad idéntica a tales intrusiones físicas de hardware. Ciertos actores de amenaza utilizan equipos de laboratorio de haz de iones enfocado (FIB) para modificar selectivamente circuitos de fusibles individuales y forzar un desbloqueo permanente de las zonas de memoria marcadas como protegidas. Otros atacantes aprovechan las metodologías de análisis de canal lateral para leer gradualmente binarios de programa completos sin activar ningún circuito de detección de manipulación de hardware. En el peor escenario de explotación, un volcado completo de las particiones de memoria flash y EEPROM permite a los atacantes fabricar réplicas de hardware idénticas, produciendo clones de dispositivos totalmente funcionales que erosionan por completo el valor de la propiedad intelectual propietaria. Por esta razón, incluso mientras se aprende la lógica básica de entrada/salida digital y las subrutinas de control de temporización, los desarrolladores deben reconocer que pines de chip y registros centrales idénticos pueden ser explotados durante campañas maliciosas de ingeniería inversa. Recuperar un dispositivo embebido inutilizado y bloqueado ocasionalmente requiere eludir las protecciones de bloqueo de seguridad mediante la inyección de fluctuaciones de tensión — una técnica legítima de reparación de hardware que simultáneamente crea un punto de entrada de ataque viable. El dominio de la lógica operativa subyacente del bit de bloqueo es una competencia obligatoria tanto para los desarrolladores de firmware embebido como para los analistas dedicados de seguridad de hardware. Un gran volumen de dispositivos embebidos comerciales ha sufrido violaciones completas de propiedad intelectual debido a fusibles de seguridad configurados incorrectamente, dejando el código ejecutable completamente expuesto a la recuperación externa. Una lectura directa de los bytes de memoria de configuración del chip puede exponer todas las configuraciones de política de seguridad, guiando a los actores de amenaza directamente al vector de explotación más débil. Incluso la simple demostración del temporizador watchdog cubierta más adelante puede reutilizarse para implementar lógica de detección de manipulación de hardware. En la práctica real de ingeniería, los diseñadores deben equilibrar la funcionalidad del hardware con las salvaguardas anti-intrusión, asegurando que la extracción no autorizada de firmware permanezca técnica y financieramente impráctica. Las demostraciones prácticas subsiguientes ilustran flujos de trabajo elementales de operación de hardware, sin embargo muestran implícitamente cómo los periféricos centrales del MCU, incluidos temporizadores, controladores de interrupción e interfaces de comunicación serie, pueden reutilizarse para implementar contramedidas robustas de endurecimiento de seguridad. Como ilustración, utilizar módulos de temporizador para generar desplazamientos de temporización aleatorizados puede mitigar los ataques de canal lateral basados en temporización dirigidos al volcado de datos secretos confidenciales. Adicionalmente, la lógica de transmisión serie UART puede envolverse con protocolos de cifrado ligero para bloquear la captura de datos crudos durante intentos no autorizados de lectura. Los circuitos de display LED multiplexado, aunque aparentemente triviales, construyen conciencia crítica de la sensibilidad precisa de temporización — una habilidad fundacional requerida para implementar secuencias seguras de arranque autenticado. El ejemplo de almacenamiento de datos EEPROM cubre directamente los flujos de trabajo de recuperación de datos persistentes, un concepto técnico que se extiende a la retención segura de claves criptográficas a largo plazo. En última instancia, cada línea de código de firmware embebido debe redactarse bajo la suposición de que los actores hostiles pueden eventualmente ganar acceso físico completo al hardware objetivo. El mecanismo de fusible de bloqueo de seguridad meramente sirve como una barrera defensiva primaria; la protección integral de hardware se basa en salvaguardas multicapa que hacen que la decapsulación de chips y el sondeo de silicio sean económicamente inviables para los actores de amenaza. Este capítulo establece una conciencia de seguridad de línea base a pesar de no profundizar en tácticas especializadas de explotación de ingeniería inversa. Con este doble enfoque en la operación funcional y la seguridad embebida, pasamos a revisar los esquemas fundamentales de cableado del microcontrolador y los componentes periféricos de hardware de soporte.

6.1 Cableado básico de hardware

Esquema de cableado básico - Circuito de fuente de alimentación

Como se visualiza en el esquema anterior, tres dominios de señal obligatorios deben cablearse correctamente para garantizar la operación estable del microcontrolador:

  • Riel de fuente de alimentación regulada;
  • Entrada de señal de reinicio de hardware; y
  • Señal de reloj del oscilador de referencia externo.

Estos constituyen topologías de circuito extremadamente mínimas, sin embargo la complejidad del hardware aumenta drásticamente para los equipos encargados de regular maquinaria industrial de alto costo o de sostener flujos de trabajo operativos críticos para la seguridad. No obstante, este diseño de circuito simplificado es suficiente para fines de aprendizaje introductorio...

Circuito de fuente de alimentación regulada

Si bien esta variante de microcontrolador admite múltiples niveles de tensión de alimentación de entrada, no hay razón práctica para introducir riesgos de falla innecesarios probando condiciones marginales de operación de tensión. Una fuente CC estándar de 5V sigue siendo el estándar industrial más ampliamente adoptado. El diagrama esquemático mostrado implementa el regulador lineal positivo de tres terminales LM7805 de bajo costo, entregando una tensión de salida estable consistente y suficiente capacidad de corriente pico de 1A para alimentar el núcleo del microcontrolador más todo el hardware periférico auxiliar conectado.

Circuito de señal de reinicio de hardware

Para una inicialización confiable del microcontrolador, se debe afirmar una señal de lógica baja (0V) en el pin de reinicio RS. El pulsador momentáneo que vincula el pin de reinicio RS al riel de alimentación VCC no es hardware estrictamente obligatorio, sin embargo se incluye en casi todas las placas de prototipo. Este pulsador permite una reinicialización forzada controlada si la ejecución del firmware entra en un estado de falla inestable. Llevar el pin RS a 5V alto desencadena un reinicio completo del chip, reiniciando la ejecución del programa desde la dirección del vector de entrada del firmware.

Circuito del oscilador de reloj

Aunque el microcontrolador integra un oscilador RC interno, la operación estable determinista requiere un cristal de cuarzo externo emparejado con dos capacitores de carga correspondientes para fijar la frecuencia de reloj de operación central, que define directamente el rendimiento de ejecución de instrucciones del chip.

Esquema del circuito oscilador de reloj

Naturalmente, esta topología de oscilador de cristal no es universalmente aplicable, y existen múltiples soluciones alternativas de generación de reloj. Una configuración alternativa obtiene una señal de reloj de referencia de un módulo oscilador externo dedicado enrutado a través de un buffer lógico inversor, como se muestra en el diagrama izquierdo.

6.2 Componentes periféricos auxiliares

A pesar de representar hardware de computación compacto de vanguardia, un microcontrolador independiente no cumple ninguna función práctica sin hardware periférico auxiliar interfazado. Dicho simplemente, los cambios de nivel de tensión en los pines de entrada/salida del chip no tienen significado funcional a menos que se utilicen para impulsar operaciones definidas: conmutar cargas encendido/apagado, desplazamiento de datos, representación de estado visual en pantalla, y más.

Interruptores y pulsadores táctiles

Ningún componente periférico es más simple que los interruptores mecánicos y los pulsadores momentáneos; ofrecen el método más directo de detectar transiciones de estado de tensión en los pines de entrada del microcontrolador.

Interruptores mecánicos y pulsadores táctiles

La implementación en el mundo real introduce complejidad imprevista derivada del rebote de contacto mecánico, una falla generalizada inherente a todo hardware de conmutación mecánica. Cuando las superficies de contacto metálicas chocan, el momento físico y la elasticidad del material generan pulsos eléctricos rápidos repetidos en lugar de una transición de tensión limpia única entre 0V y el riel de alimentación completo. Este comportamiento oscilante se origina en pequeñas imperfecciones de superficie, acumulación de contaminación por polvo y vibración mecánica. La duración del rebote — medida en microsegundos o milisegundos — pasa desapercibida para la percepción humana, sin embargo se registra de manera confiable como múltiples eventos de entrada discretos por la lógica digital de alta velocidad del microcontrolador. Si una señal cruda de pulsador alimenta directamente una rutina de firmware de conteo de pulsos, ocurrirán tasas de error de conteo cercanas al 100% sin acondicionamiento de señal.

Filtro de rebote RC

La estrategia de mitigación más rentable para el rebote de contacto es un circuito pasivo de filtro RC de paso bajo que suprime las transiciones rápidas de tensión. Dado que las características de temporización del rebote varían entre modelos de interruptores, los valores de resistencias y capacitores carecen de especificaciones estándar rígidas, sin embargo los valores de componentes ilustrados en el diagrama ofrecen un rendimiento consistente para la mayoría de los casos de uso comunes.

Las aplicaciones que requieren estabilidad absoluta de la señal de entrada exigen contramedidas de hardware más robustas. Un circuito de flip-flop RS modifica el estado lógico de salida de la señal solo una vez ante la transición de contacto inicial, ignorando por completo los pulsos de rebote subsiguientes. Si bien esta solución de hardware requiere un componente de interruptor SPDT de mayor costo, elimina los artefactos de rebote por completo y admite la detección de pulsos de entrada extremadamente cortos que los filtros RC pasivos enmascararían, ya que no se utilizan capacitores de almacenamiento de carga en la ruta de señal.

Circuito de rebote de hardware con flip-flop RS

Más allá de las topologías de filtrado de hardware, existe una implementación ligera de rebote por software. Cuando el firmware detecta una transición de estado del pin de entrada, vuelve a verificar el nivel lógico del pin después de un período de retardo fijo. Una lectura de estado consistente confirma una actuación intencional del interruptor en lugar de ruido de rebote transitorio. Este enfoque de software conlleva costo de componentes adicional cero, suprime los artefactos de interferencia electromagnética y opera de manera confiable con contactos mecánicos desgastados de baja calidad. Su limitación principal coincide con los circuitos de filtro RC: los pulsos de entrada más cortos que el intervalo de retardo programado no pueden ser capturados por la lógica del firmware.

Módulos de aislamiento optoacoplador

Circuitos de aislamiento con optoacopladores

Los optoacopladores son componentes de aislamiento estándar de la industria utilizados para aislar galvánicamente la circuitería del microcontrolador de entornos eléctricos externos peligrosos de alta corriente o alta tensión. Los paquetes de optoacopladores típicos integran una, dos o cuatro fuentes emisoras de luz LED en el lado de entrada, emparejadas con una cantidad igual de dispositivos semiconductores sensibles a la luz en la etapa de salida: fototransistores, fototiristores o fototriacs. La funcionalidad central se basa en un canal de transmisión óptica no conductivo para transferir señales digitales entre dominios de circuito aislados manteniendo una separación eléctrica completa. Este rendimiento de aislamiento solo es efectivo cuando el lado LED de entrada y el lado fotodetector de salida reciben rieles de alimentación independientes. Esta separación protege por completo al microcontrolador y al hardware periférico de precisión sensible de transitorios de alta tensión destructivos y ruido electromagnético, dos causas raíz principales de daño permanente de hardware y comportamiento operativo inestable en los sistemas embebidos. Los optoacopladores de salida con fototransistor representan la variante más ampliamente desplegada. Para los paquetes de optoacopladores con un pin de base expuesto (pin 6), el terminal de base puede dejarse desconectado. Una red opcional de resistor-capacitor mostrada mediante cableado discontinuo en el esquema atenúa el ruido de alta frecuencia filtrando señales de pulso transitorio ultracortas.

Relés electromecánicos

Esquema del circuito de accionamiento de relés

Un relé constituye un interruptor mecánico accionado eléctricamente controlado por un circuito de lógica de baja potencia secundario. Los relés se interconectan con los pines de salida del microcontrolador para conmutar hardware de carga de alta potencia, incluidos motores CC, transformadores de CA, elementos calefactores, iluminación incandescente y conjuntos de antenas. Estas cargas de alta potencia casi siempre están físicamente separadas de los componentes de lógica de baja tensión sensibles de la PCB principal. Existen múltiples factores de forma de relés, sin embargo todos operan mediante principios idénticos de actuación electromagnética: energizar una bobina de cobre interna genera un campo magnético que conmuta mecánicamente uno o múltiples conjuntos de pares de contactos conductivos. Idéntico a los optoacopladores, los relés ofrecen aislamiento galvánico completo sin una ruta de conducción eléctrica directa entre la lógica de control de entrada y los circuitos de carga de salida. La mayoría de las variantes de relés estándar exigen tensión y corriente elevadas para energizar el devanado de la bobina, aunque los relés de señal en miniatura pueden ser impulsados directamente por la baja capacidad de suministro de corriente de los pines de salida del microcontrolador.

El esquema ilustrado se dirige a la arquitectura del microcontrolador 8051. Un transistor de par Darlington amplifica la corriente de accionamiento para energizar la bobina del relé, un trabajo obligatorio para los estados de salida lógico alto, donde el pin del microcontrolador opera como una entrada de alta impedancia con capacidad mínima de suministro de corriente, violando las pautas estándar de diseño de circuitos de accionamiento pero requerido para las características eléctricas de esta arquitectura específica.

Diagrama básico de cableado del microcontrolador con relé

Un diodo de rueda libre con polarización inversa se cablea en paralelo con el devanado de la bobina del relé para suprimir los transitorios destructivos de retorno inductivo de alta tensión generados cuando el flujo de corriente de la bobina se termina abruptamente. Este diodo de sujeción absorbe el pico de tensión inductiva para proteger los componentes semiconductores circundantes del daño por ruptura.

Diodos emisores de luz (LED)

Los diodos emisores de luz sirven como componentes indicadores de estado visual en todos los sistemas de hardware electrónico, fabricados en diversos factores de forma físicos, colores de emisión y tamaños de paquete. Su costo unitario ultrabajo, consumo de potencia mínimo y circuitería de accionamiento simplificada han desplazado a las lámparas indicadoras incandescentes heredadas en casi todas las aplicaciones modernas. El comportamiento eléctrico refleja los diodos de unión PN estándar, con la propiedad única de emisión de luz visible cuando la corriente con polarización directa fluye a través de la unión semiconductora.

Esquema del circuito de diodo emisor de luz (LED)

La limitación de corriente es un requisito crítico de diseño; la corriente directa no regulada degradará y destruirá permanentemente la unión del LED. Debe incluirse un resistor limitador de corriente en serie en cada circuito de accionamiento de LED. El cálculo del valor de resistencia requerido depende de la caída de tensión directa del LED, un parámetro determinado por el material semiconductor y la longitud de onda/color de emisión objetivo. Las especificaciones eléctricas estándar de las variantes de LED comúnmente desplegadas se tabulan a continuación. Existen tres clasificaciones principales de LED: los LED Estándar alcanzan el brillo nominal completo a 20mA de corriente directa; los LED de Baja Corriente ofrecen luminosidad equivalente a una décima parte de este consumo de corriente; los LED Super Brillantes producen una salida luminosa significativamente mayor que los factores de forma estándar bajo condiciones idénticas de corriente de accionamiento.

Color de emisión Clasificación del dispositivo Corriente de operación nominal Id (mA) Corriente máxima absoluta If (mA) Caída de tensión directa Ud (V)
Infrarrojo - 30 50 1.4
Rojo Estándar 20 30 1.7
Rojo Super Brillante 20 30 1.85
Rojo Baja Corriente 2 30 1.7
Naranja - 10 30 2.0
Verde Baja Corriente 2 20 2.1
Amarillo - 20 30 2.1
Azul - 20 30 4.5
Blanco - 25 35 4.4
Cableado de accionamiento LED de baja corriente

La familia de microcontroladores 8051 suministra corriente limitada de sumidero/fuente en los pines de E/S de propósito general, con pines que operan como sumideros de corriente de lado bajo cuando se llevan al nivel lógico 0V. Por esta razón, los LED de baja corriente se cablean con los terminales de cátodo conectados directamente a los pines de salida del microcontrolador, como se ilustra en el diagrama esquemático derecho.

Módulos de display LED de segmentos

Un módulo de display LED de segmentos integra múltiples diodos LED discretos encapsulados dentro de una única carcasa de plástico unificada. Existen numerosas variantes de display, que incorporan docenas de segmentos LED individuales para representar símbolos alfanuméricos y dígitos numéricos.

Disposición física del display LED de 7 segmentos

El display de 7 segmentos constituye la variante más ampliamente desplegada, construida a partir de ocho elementos LED independientes: siete segmentos de luz rectangulares dispuestos para formar los contornos de los dígitos numéricos, más un octavo segmento dedicado de punto decimal. Para simplificar el cableado de PCB, todos los ánodos o cátodos de los segmentos se conectan a un terminal común compartido, creando dos topologías principales de display: variantes de ánodo común y cátodo común. Los segmentos se etiquetan secuencialmente de A a G, con una designación adicional dp para el punto decimal, coincidiendo con el etiquetado mostrado en el diagrama izquierdo. Cada segmento LED requiere su propio resistor limitador de corriente en serie durante el cableado de hardware, ya que cada segmento opera como un elemento emisor de luz independiente.

El cableado directo de displays LED de múltiples dígitos al hardware del microcontrolador consume grandes cantidades de recursos limitados de pines de E/S, una restricción crítica de hardware particularmente cuando se requieren lecturas numéricas de múltiples dígitos. La limitación de recursos se vuelve inmediatamente evidente al implementar una lectura numérica dual de seis dígitos, que teóricamente demandaría 96 pines de salida dedicados si se cableara sin multiplexación. La solución estándar de la industria a esta restricción de hardware es la multiplexación de displays, aprovechando una ilusión óptica de persistencia de visión idéntica a los principios de proyección de películas cinematográficas. Solo un banco de segmentos de dígito está energizado en cualquier ciclo de reloj dado, sin embargo la conmutación secuencial rápida entre posiciones de dígito crea la percepción visual de que todos los dígitos numéricos se iluminan simultáneamente.

Diagrama de cableado del display multiplexado de 7 segmentos

La lógica de operación del esquema anterior es la siguiente: Primero, se afirma un valor de byte de datos correspondiente al dígito de unidades en un puerto del microcontrolador, mientras que el transistor T1 se habilita simultáneamente para activar el banco de display de unidades. Después de un breve intervalo de retardo fijo, el transistor T1 se desenergiza, el valor de byte de decenas se transmite al registro del puerto, y el transistor T2 habilita el banco de display de decenas. Esta secuencia de activación secuencial cicla continuamente a altas tasas de refresco a través de todas las posiciones de dígito y sus transistores de accionamiento correspondientes.

La naturaleza fundamental del microcontrolador como un dispositivo de computación binaria que interpreta exclusivamente lógica 0 y lógica 1 se vuelve completamente evidente durante los flujos de trabajo de representación de dígitos. El MCU no tiene comprensión nativa inherente de los valores posicionales decimales (unidades, decenas, centenas) o de las formas de glifos numéricos estándar legibles por humanos. Todos los valores de display objetivo deben someterse a un preprocesamiento estandarizado como se describe a continuación:

Primero, un valor entero de múltiples dígitos se descompone en valores posicionales aislados de unidades, decenas y centenas mediante subrutinas de firmware dedicadas. Cada valor de dígito individual extraído se almacena dentro de bytes de registro de 8 bits individuales. La representación de glifos de dígitos se logra mediante lógica de traducción de máscara de bits, que re-mapea los valores numéricos binarios crudos en patrones únicos de activación de segmentos mediante procesamiento de subrutina ligero. Como ejemplo ilustrativo, el valor binario crudo 0000 1000 (que representa el dígito decimal 8) se traduce en un patrón de máscara de segmentos que energiza los siete segmentos principales del display dejando el segmento de punto decimal apagado. Si el cableado del puerto del microcontrolador mapea el bit 0 al segmento A, el bit 1 al segmento B, el bit 2 al segmento C, y así sucesivamente, la tabla de consulta de máscaras de bits estandarizada para cada dígito decimal aparece como se muestra a continuación.

Tabla de referencia de máscaras de bits del display de 7 segmentos
Dígito numérico a representar Mapeo de bits de los segmentos del display
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0

Más allá de los numerales decimales del 0 al 9, un subconjunto de caracteres del alfabeto latino puede representarse mediante valores de máscara de bits ajustados: A mayúscula, C, E, J, F, U, H, L; b minúscula, c, d, o, r, t.
Para el hardware de display de cátodo común, todos los valores de lógica 1 y lógica 0 dentro de la tabla de consulta deben invertirse, y se requieren transistores bipolares NPN como componentes de conmutación de accionamiento de dígitos.

Módulos de pantalla de cristal líquido (LCD)

Los módulos LCD dedicados están construidos específicamente para la interconexión directa con microcontroladores y no pueden ser impulsados de forma nativa por circuitos integrados de lógica estándar genéricos. Estos módulos representan cadenas de texto personalizables en hardware de panel de cristal líquido compacto.

Hardware del módulo LCD de caracteres HD44780

La variante de módulo analizada dentro de este material logra una adopción generalizada en el mundo real debido a su bajo costo unitario y su conjunto integral de características, construido alrededor del chip controlador integrado HD44780 de Hitachi. Este panel estándar admite dos filas de display independientes con dieciséis posiciones de caracteres por fila, representando conjuntos completos de caracteres del alfabeto latino, símbolos del alfabeto griego, signos de puntuación, operadores matemáticos y glifos suplementarios. Los símbolos gráficos personalizados definidos por el usuario de 5×8 píxeles también pueden almacenarse y mostrarse. La funcionalidad nativa adicional incluye desplazamiento automático de texto izquierda/derecha, indicadores de cursor visibles configurables y hardware de retroiluminación LED integrado.

Definición del pinout externo del LCD

Una fila de pines de encabezado recorre un borde de la placa de circuito impreso del LCD para facilitar las conexiones de cableado con el microcontrolador. El módulo base incorpora catorce pines de señal numerados; las variantes con hardware de retroiluminación integrado añaden dos pines de alimentación suplementarios para un total de dieciséis. Las especificaciones funcionales completas de los pines se listan dentro de la tabla siguiente:

Propósito de la señal Número de pin Etiqueta de señal Estado de nivel lógico Descripción funcional
Referencia de tierra 1 Vss - Riel de tierra del sistema 0V
Fuente de alimentación principal 2 Vdd - Tensión de alimentación lógica +5V
Ajuste de contraste 3 Vee - Rango de tensión 0V a Vdd para la sintonización del contraste LCD
Señales de control de operación 4 RS 0
1
Los pines D0–D7 se interpretan como palabras de comando del controlador
Los pines D0–D7 se interpretan como bytes de datos de caracteres de display
5 R/W 0
1
Operación de escritura: el MCU transmite datos al módulo LCD
Operación de lectura: el módulo LCD emite estado/datos al MCU
6 E 0
1
Flanco descendente 1→0
Acceso al registro LCD deshabilitado
Estado operativo en espera
Fijar los valores de comando/datos en el núcleo del controlador LCD
Líneas de bus de datos y comandos 7 D0 0/1 Bit de datos 0 (bit menos significativo)
8 D1 0/1 Bit de datos 1
9 D2 0/1 Bit de datos 2
10 D3 0/1 Bit de datos 3
11 D4 0/1 Bit de datos 4
12 D5 0/1 Bit de datos 5
13 D6 0/1 Bit de datos 6
14 D7 0/1 Bit de datos 7 (bit más significativo)

Disposición de píxeles del panel LCD

Disposición de la matriz de píxeles de puntos de caracteres LCD

El hardware del panel de display LCD consiste en dos filas de caracteres independientes, cada una con dieciséis posiciones de caracteres individuales. Cada celda de carácter se implementa como una rejilla de píxeles de matriz de puntos de 5×8 u opcionalmente 5×11; este material de referencia se centra exclusivamente en la variante estándar de la industria de matriz de caracteres de 5×8.

Los niveles de contraste del display dependen de la tensión del riel de alimentación y de la configuración de display de fila única/doble. Por esta razón, se aplica una señal de tensión variable entre 0V y Vdd al pin de sintonización de contraste Vee, típicamente controlada mediante un potenciómetro trimmer. Muchos módulos LCD integran hardware de retroiluminación LED de color (emisión azul o verde). Al utilizar la funcionalidad de retroiluminación, debe cablearse un resistor limitador de corriente en serie con uno de los pines de alimentación de retroiluminación, siguiendo reglas de diseño de accionamiento idénticas aplicadas a los componentes LED discretos.

Diagrama de cableado de alimentación de retroiluminación LCD

Si no se representa ningún carácter de texto o todos los glifos mostrados aparecen tenues después del encendido, el primer paso de solución de problemas es calibrar el potenciómetro de ajuste de contraste para verificar la sintonización de tensión adecuada. Este procedimiento idéntico de solución de problemas se aplica si el modo operativo del display (representación de fila única / doble) se reconfigura en plena operación.

Arquitectura de partición de memoria interna del LCD

El controlador LCD integra tres particiones de memoria dedicadas distintas:

  • DDRAM: Memoria de Acceso Aleatorio de Datos de Display;
  • CGRAM: Memoria de Acceso Aleatorio del Generador de Caracteres; y
  • CGROM: Memoria de Solo Lectura del Generador de Caracteres.

Partición de RAM de datos de display DDRAM

El almacenamiento DDRAM contiene los valores de byte de caracteres ASCII programados para la representación en pantalla, con capacidad suficiente para almacenar ochenta bytes de caracteres totales. Las direcciones de memoria individuales mapean directamente a las posiciones discretas de celdas de caracteres en el panel LCD físico.

Mapa de direccionamiento de la memoria DDRAM LCD

La lógica operativa central es sencilla: configurar el controlador LCD para incrementar automáticamente las direcciones de memoria (desplazamiento de texto hacia la derecha), luego definir la dirección de memoria inicial para la cadena de texto objetivo (por ejemplo, la dirección hexadecimal 00).

Después de completar este paso de configuración, todos los bytes de caracteres transmitidos sobre el bus de datos D0–D7 se representan secuencialmente de izquierda a derecha en el orden de lectura estándar. Con la dirección base establecida en 00 hex, la representación de texto se inicia en la celda de carácter más a la izquierda de la fila superior del display. Si se transmiten más de dieciséis bytes de caracteres, todos los datos excedentes permanecen almacenados dentro de la memoria DRAM, sin embargo solo las dieciséis posiciones iniciales permanecen visibles en pantalla. Debe emitirse un comando dedicado de desplazamiento de display para desplazar los datos de caracteres ocultos hacia la ventana visible del panel. Funcionalmente, el panel LCD actúa como un visor fijo que se desliza horizontalmente sobre los contenidos de memoria DRAM estacionarios, creando el efecto visual de texto en desplazamiento a través de la superficie de la pantalla.

Cuando el indicador de cursor está habilitado, se representa en la posición de dirección DRAM actualmente activa. Después de escribir un byte de carácter en la dirección activa, el controlador incrementa automáticamente la dirección objetivo a la posición de celda de carácter subsiguiente.
Como memoria de acceso aleatorio volátil, todos los datos almacenados en DRAM se borran permanentemente al desconectar la fuente de alimentación.

Partición ROM del generador de caracteres CGROM

El banco de memoria de solo lectura CGROM almacena la tabla de consulta de glifos estándar precargada de fábrica que contiene cada símbolo de carácter soportado de forma nativa por el panel LCD, con cada glifo único asignado a una dirección de memoria estática fija.

Mapa de caracteres ASCII CGROM LCD

Los desplazamientos de dirección de memoria CGROM corresponden directamente a los valores de codificación ASCII estándar de caracteres. Cuando el firmware activo ejecuta una instrucción para transmitir el carácter 'P' al bus de datos LCD, el valor de byte binario 0101 0000 se afirma en las líneas de datos D0–D7. Este valor binario coincide con la codificación ASCII de la 'P' mayúscula, que el controlador LCD utiliza para indexar el banco de memoria CGROM y representar el glifo correspondiente almacenado en la dirección 0101 0000. Esta regla de mapeo se aplica universalmente a los caracteres del alfabeto latino mayúsculos y minúsculos, sin embargo no se aplica directamente a los dígitos numéricos decimales.

Como es visible en el diagrama de mapa de caracteres anterior, todos los desplazamientos de dirección de los dígitos decimales se desplazan hacia arriba por un valor de desplazamiento base de 48 relativo a su valor numérico: el dígito 0 mapea a la dirección 48, el dígito 1 mapea a la dirección 49, el dígito 2 mapea a la dirección 50, y así sucesivamente. En consecuencia, la lógica del firmware debe añadir la constante decimal 48 a cada byte de dígito numérico antes de la transmisión sobre el bus de datos LCD para una representación precisa de glifos.

Desde las arquitecturas informáticas tempranas hasta el hardware embebido moderno, los sistemas de procesamiento digital solo interpretan valores numéricos binarios y no pueden reconocer de forma nativa los caracteres alfabéticos legibles por humanos. Todos los datos intercambiados entre un microcontrolador y el hardware periférico externo existen en formato binario, incluso cuando los operadores humanos los interpretan visualmente como caracteres de texto; un teclado estándar sirve como una ilustración clara del mundo real de este principio. Cada carácter imprimible mapea a un patrón de bits binario fijo único. La codificación ASCII es un conjunto de caracteres estandarizado construido alrededor del alfabeto latino, definiendo una correlación directa uno a uno entre los símbolos gráficos imprimibles y sus representaciones numéricas binarias correspondientes.

Partición de RAM de caracteres personalizados CGRAM

Además de los glifos CGROM predefinidos de fábrica, el controlador LCD admite la representación de símbolos gráficos personalizados completamente definidos por el usuario dimensionados a la rejilla de caracteres de 5×8 píxeles mediante una partición de memoria CGRAM volátil dedicada de 64 bytes.

Los registros de memoria CGRAM tienen 8 bits de ancho, aunque solo se utilizan las cinco posiciones de bits menos significativas para el almacenamiento del patrón de píxeles. Un bit lógico alto (1) dentro de cada registro corresponde a un punto de píxel iluminado, mientras que ocho ubicaciones de memoria de registro secuenciales almacenan colectivamente el patrón de píxeles completo de un único glifo de carácter personalizado. El diagrama siguiente ilustra claramente este principio de mapeo de memoria:

Disposición de memoria de caracteres personalizados CGRAM LCD

Los patrones de glifos personalizados se inicializan típicamente al inicio del programa de firmware escribiendo patrones de bits lógicos 0 y 1 secuenciales en los registros de memoria CGRAM para construir la forma de la obra de arte de píxeles objetivo. Para representar en pantalla un glifo personalizado preconfigurado, el firmware solo necesita transmitir el valor de dirección base CGRAM correspondiente al controlador LCD. Tenga en cuenta que la primera columna de la tabla de consulta de caracteres CGROM no referencia direcciones estáticas CGROM sino que apunta a los índices de glifos CGRAM personalizados. Dentro de la lógica de ejemplo de esta referencia, transmitir el valor de índice 0 representa el primer glifo personalizado, el valor de índice 1 representa el segundo glifo personalizado, y así sucesivamente.

Referencia fundamental del conjunto de comandos del controlador LCD

Todos los bytes transmitidos al módulo LCD sobre el bus de datos D0–D7 se interpretan como códigos de operación de comando del controlador o bytes de datos de caracteres de display, determinados enteramente por el estado lógico del pin de selección de registro RS:

RS = 1 — Los bits del bus de datos D0–D7 representan valores de byte de caracteres ASCII dirigidos a la representación en pantalla. El controlador LCD indexa el mapa de glifos CGROM utilizando este valor de byte y representa el símbolo correspondiente en la posición de dirección DDRAM activa. La dirección DDRAM objetivo está preconfigurada antes de transmitir el byte de carácter o se incrementa automáticamente después de cada operación de escritura de carácter completada.

RS = 0 — Los bits del bus de datos D0–D7 representan códigos de operación del controlador estandarizados que configuran los modos operativos globales del display. Una tabla completa de todos los códigos de comando LCD reconocidos se lista a continuación:

Nombre del comando RS RW D7 D6 D5 D4 D3 D2 D1 D0 Tiempo de ejecución requerido
Limpiar el buffer completo del display 0 0 0 0 0 0 0 0 0 1 1.64ms
Retorno del cursor a la posición de inicio 0 0 0 0 0 0 0 0 1 No importa 1.64ms
Configuración de parámetros del modo de entrada 0 0 0 0 0 0 0 1 I/D S 40μs
Control de alimentación del display y el cursor 0 0 0 0 0 0 1 D U B 40μs
Comando de desplazamiento del cursor / display 0 0 0 0 0 1 D/C R/L No importa No importa 40μs
Conjunto de funciones de la interfaz de hardware 0 0 0 0 1 DL N F No importa No importa 40μs
Escribir la dirección base CGRAM objetivo 0 0 0 1 Desplazamiento de dirección CGRAM de 6 bits 40μs
Escribir la dirección base DDRAM objetivo 0 0 1 Desplazamiento de dirección DDRAM de 7 bits 40μs
Leer la bandera de ocupado (BF) y la dirección DDRAM actual 0 1 BF Dirección DDRAM activa de 7 bits N/A
Escribir byte de datos a CGRAM / DDRAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40μs
Leer byte de datos de CGRAM / DDRAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40μs
I/D 1 = Automatic address increment (+1)         R/L 1 = Shift display contents right
    0 = Automatic address decrement (-1)             0 = Shift display contents left
    
S 1 = Global display scrolling enabled           DL 1 = 8-bit parallel data bus interface
  0 = Global display scrolling disabled             0 = 4-bit split nibble data bus interface
  
D 1 = LCD panel display power active             N 1 = Dual-row character display mode
  0 = LCD panel display power disabled              0 = Single-row character display mode
  
U 1 = Blinking cursor indicator active           F 1 = 5×10 dot character glyph format
  0 = Static cursor indicator disabled              0 = 5×7 dot character glyph format
 
B 1 = Cursor blink animation enabled             D/C 1 = Shift full display buffer
  0 = Cursor blink animation disabled               0 = Shift only cursor position

Explicación del bit de estado de la bandera de ocupado

En relación con el pipeline de ejecución de instrucciones de alta velocidad del microcontrolador, el hardware del controlador LCD opera a velocidades de procesamiento drásticamente más bajas. Se implementó una bandera de señal de estado dedicada para señalar cuándo el controlador completa la ejecución de un comando pendiente y acepta nuevos bytes de datos de entrada. Esta señal de bandera de ocupado es legible a través del pin del bus de datos D7. Cuando el bit BF se limpia a lógico bajo (BF=0), el módulo LCD finaliza todo el procesamiento previo y está listo para recibir nuevos bytes de comando o datos de caracteres.

Topologías de cableado de la interfaz de hardware LCD

Existen dos estándares de cableado distintos para interconectar un módulo LCD con un microcontrolador: modo de bus completo de 8 bits y modo de bus de nibble dividido de 4 bits. El modo operativo objetivo se configura durante las rutinas de inicialización del firmware ejecutadas inmediatamente después del reinicio por encendido. El modo de 8 bits transmite bytes de datos completos de 8 bits a través del bus de datos completo D0–D7 siguiendo la lógica cubierta en las secciones anteriores. La motivación principal de diseño para implementar el modo de bus de 4 bits es la conservación de los pines de E/S de propósito general limitados del microcontrolador; solo se utilizan las cuatro líneas de datos de orden alto D4–D7 para la comunicación, mientras que D0–D3 pueden permanecer desconectadas. Cada byte de datos completo de 8 bits se divide en dos ciclos de transmisión secuenciales: los cuatro bits de nibble de orden alto se transmiten primero sobre D4–D7, seguidos de los cuatro bits de nibble de orden bajo. La secuencia de inicialización configura el controlador LCD para analizar y recombinar correctamente estas transmisiones de nibble divididas. Las operaciones de lectura de datos del módulo LCD rara vez se requieren, ya que el flujo de datos es predominantemente unidireccional del MCU al hardware LCD. Esto habilita una optimización común de ahorro de pines: conectar permanentemente el pin de control de lectura/escritura R/W a tierra. Esta modificación de hardware reduce el recuento requerido de pines de E/S en uno, sin embargo conlleva una compensación funcional: la bandera de estado de ocupado no puede sondearse, eliminando la capacidad de leer cualquier dato almacenado dentro de las particiones de memoria interna del LCD.

Esquema de cableado del microcontrolador LCD de 4 bits

Existe una solución de software sencilla para compensar el sondeo deshabilitado de la bandera de ocupado. Después de transmitir cualquier comando o byte de carácter al módulo LCD, el firmware debe insertar un intervalo de retardo fijo para permitir al controlador tiempo de procesamiento suficiente. Dado que la operación de comando LCD individual más lenta consume un máximo de aproximadamente 1.64ms, un retardo de software estandarizado de 2ms garantiza de manera confiable la finalización completa del comando antes de los ciclos de transmisión subsiguientes.

Secuencia de inicialización por encendido del LCD

El controlador LCD ejecuta automáticamente una secuencia de reinicio interna inmediatamente después de que se aplica la tensión de alimentación, consumiendo aproximadamente 15ms para completarse. Después de este retardo de inicialización, el módulo entra en una configuración operativa predeterminada definida como se lista a continuación:

  1. Todo el buffer de memoria del display limpio a glifos en blanco
  2. Configuración de interfaz de hardware predeterminada
    • DL = 1: comunicación de bus de datos paralelo de 8 bits habilitada
    • N = 0: modo de representación de texto de fila única activo
    • F = 0: formato de glifo de carácter de matriz de puntos 5×8 seleccionado
  3. Estados visuales predeterminados del display y el cursor
    • D = 0: salida del panel LCD principal deshabilitada
    • U = 0: indicador de cursor visible deshabilitado
    • B = 0: animación de parpadeo del cursor deshabilitada
  4. Modos predeterminados de escritura de entrada de caracteres
    • I/D = 1: incremento automático de la dirección DDRAM después de cada escritura de carácter
    • S = 0: desplazamiento automático global de texto deshabilitado

La secuencia automática de reinicio por encendido opera de manera confiable bajo condiciones ideales de fuente de alimentación en la mayoría de los diseños de hardware de prototipo, sin embargo la inicialización estable consistente no puede garantizarse universalmente. Si la tensión del riel de alimentación no alcanza los 5V nominales completos dentro de una ventana de encendido de 10ms, el controlador LCD entra en un estado operativo errático indefinido. Si el circuito de fuente de alimentación no puede satisfacer este requisito de rampa de tensión rápida, o si la operación de hardware consistente absoluta es obligatoria, debe ejecutarse una secuencia de inicialización de firmware manual. Esta secuencia de inicialización desencadena un reinicio secundario completo del controlador interno para restaurar una operación estable predecible.

Consulte el diagrama siguiente para el procedimiento de inicialización estandarizado de bus de 8 bits:

Capítulo 6 : Ejemplos

Introducción

El propósito de este capítulo es proporcionar información básica sobre los microcontroladores que uno necesita conocer para poder utilizarlos con éxito en la práctica. Es por esto que este capítulo no contiene ningún programa súper interesante o esquema de dispositivo con soluciones sorprendentes. En su lugar, los siguientes ejemplos son una mejor prueba de que escribir programas no es ni un privilegio ni una cuestión de talento, sino la capacidad de simplemente unir las piezas del rompecabezas usando directivas. Puede estar seguro de que el diseño y desarrollo de dispositivos consiste principalmente en el siguiente método “probar-corregir-repetir”. Por supuesto, cuanto más estás en ello, más complicado se vuelve, ya que las piezas del rompecabezas son unidas tanto por niños como por arquitectos de primera clase...

Si bien estos ejemplos se centran en los fundamentos funcionales, todo sistema embebido también conlleva una capa oculta de preocupaciones de seguridad que a menudo se pasa por alto en los textos introductorios. El **microcontrolador** (MCU) que ejecuta estos programas simples podría desplegarse posteriormente en un producto donde proteger el **código** del acceso no autorizado se vuelve crítico. Muchos desarrolladores asumen que la función **lockbit** es suficiente para prevenir una **lectura** de la memoria **flash** interna, pero este no es siempre el caso. En realidad, los atacantes pueden emplear técnicas de **decapsulación** para exponer el silicio y sondear directamente los **fusibles** que controlan el estado de **bloqueo**. Una vez que el chip está abierto, pueden intentar **volcar** toda la memoria del programa, realizando efectivamente una **extracción de firmware** sin necesidad jamás de una contraseña. La **EEPROM**, que a menudo almacena constantes de calibración o claves de seguridad, es igualmente vulnerable a tales ataques físicos. Algunos adversarios usan herramientas de haz de iones enfocado (FIB) para alterar **fusibles** individuales y forzar un **desbloqueo** de las regiones protegidas. Otros se basan en ataques de canal lateral para **leer** lentamente el **código** sin disparar ninguna detección de manipulación. En el peor de los casos, un **volcado** exitoso tanto de **flash** como de **EEPROM** permite a un atacante **duplicar** todo el dispositivo, creando clones perfectos que socavan la propiedad intelectual. Por lo tanto, incluso al aprender rutinas básicas de E/S y temporización, uno debe ser consciente de que los mismos pines y registros podrían ser explotados en un esfuerzo de **ingeniería inversa**. La **recuperación** de un sistema inutilizado a veces requiere eludir el **bloqueo** mediante una fluctuación, que es una técnica de reparación legítima pero también un vector de ataque potencial. Comprender el mecanismo subyacente de **lockbit** es crucial tanto para desarrolladores como para investigadores de seguridad. Muchos productos comerciales han sido comprometidos porque sus **fusibles** no se configuraron correctamente, dejando el **código** expuesto. Una simple **lectura** de los bytes de configuración puede revelar las configuraciones de seguridad, guiando a un atacante al eslabón más débil. Incluso el humilde ejemplo del temporizador watchdog mostrado más adelante puede reutilizarse para detectar intentos de manipulación. En la práctica, los ingenieros deben equilibrar la funcionalidad con la protección, asegurando que la **extracción de firmware** no sea trivial. Los ejemplos que siguen ilustran operaciones básicas, pero también demuestran implícitamente cómo los recursos de un MCU — temporizadores, interrupciones, comunicación serie — pueden ser cooptados para el endurecimiento de seguridad. Por ejemplo, usar un temporizador para generar retardos aleatorios puede frustrar los ataques de temporización dirigidos a **volcar** secretos. Adicionalmente, las rutinas UART pueden cifrarse para prevenir la captura durante los intentos de **lectura**. La multiplexación del display LED, aunque mundana, enseña sobre la sensibilidad de temporización, que es esencial para implementar secuencias de arranque seguras. El ejemplo de manejo de EEPROM toca directamente la **recuperación** de datos persistentes, un concepto que se extiende al almacenamiento seguro de claves criptográficas. En última instancia, cada línea de **código** debe escribirse con la suposición de que un adversario podría eventualmente ganar acceso físico. El **bloqueo** es meramente una primera línea de defensa; la seguridad verdadera requiere un enfoque multicapa que haga la **decapsulación** y el sondeo económicamente inviables. Este capítulo sienta las bases para tal conciencia, incluso si no discute explícitamente estrategias de **ingeniería inversa**. Con esta mentalidad, ahora procedemos a las conexiones y componentes fundamentales.

6.1 Conexión básica

Conexión básica - Fuente de alimentación

Como se ve en la figura anterior, para permitir que el microcontrolador opere correctamente es necesario proporcionar:

  • Fuente de alimentación:
  • Señal de reinicio: y
  • Señal de reloj.

Claramente, se trata de circuitos muy simples, pero no siempre tiene que ser así. Si el dispositivo objetivo se usa para controlar máquinas costosas o mantener funciones vitales, todo se vuelve cada vez más complicado. Sin embargo, esta solución es suficiente por el momento...

Fuente de alimentación

Aunque este microcontrolador puede operar a diferentes tensiones de alimentación, ¿por qué probar la “ley de Murphy”?! Se usa más comúnmente una CC de 5V. El circuito, mostrado en la figura, usa un regulador positivo integrado de tres terminales barato LM7805, y proporciona estabilidad de tensión de alta calidad y suficiente corriente para permitir que el microcontrolador y la electrónica periférica operen normalmente (suficiente corriente en este caso significa 1Amp).

Señal de reinicio

Para que el microcontrolador pueda operar correctamente, debe aplicarse un 0 lógico (0V) al pin de reinicio RS. El botón pulsador que conecta el pin de reinicio RS a la alimentación VCC no es necesario. Sin embargo, casi siempre se proporciona porque permite el retorno seguro del microcontrolador a las condiciones normales de operación si algo sale mal. Se lleva 5V a este pin, el microcontrolador se reinicia y el programa comienza la ejecución desde el principio.

Señal de reloj

Aunque el microcontrolador tiene un oscilador incorporado, no puede operar sin dos capacitores externos y un cristal de cuarzo que estabilizan su operación y determinan su frecuencia (velocidad de operación del microcontrolador).

Señal de reloj

Por supuesto, no siempre es posible aplicar esta solución, por lo que siempre hay alternativas. Una de ellas es proporcionar la señal de reloj desde una fuente especial a través de un inversor. Vea la figura de la izquierda.

6.2 Componentes adicionales

Independientemente del hecho de que el microcontrolador sea un producto de tecnología moderna, no sirve de nada sin estar conectado a componentes adicionales. Dicho simplemente, la aparición de tensión en sus pines no significa nada si no se usa para realizar ciertas operaciones (encender/apagar algo, desplazar, mostrar etc.).

Interruptores y botones pulsadores

No hay dispositivos más simples que los interruptores y los botones pulsadores. Esta es la forma más simple de detectar la aparición de una tensión en el pin de entrada del microcontrolador.

Interruptores y pulsadores

Sin embargo, no es tan simple en la práctica... Se trata del rebote de contacto, un problema común con los interruptores mecánicos. Cuando los contactos chocan entre sí, su momento y elasticidad actúan juntos para causar rebote. El resultado es una corriente eléctrica pulsada rápidamente en lugar de una transición limpia de cero a corriente completa. Ocurre principalmente debido a vibraciones, pequeñas asperezas y suciedad entre los contactos. Este efecto suele ser imperceptible al usar estos componentes en la vida cotidiana porque el rebote ocurre demasiado rápido. En otras palabras, todo este proceso no dura mucho (unos pocos micro o milisegundos), pero es lo suficientemente largo como para ser registrado por el microcontrolador. Al usar solo un botón pulsador como contador de pulsos, ¡ocurren errores en casi el 100% de los casos!

Rebote RC

La solución más simple a este problema es conectar un circuito RC simple para suprimir los cambios rápidos de tensión. Dado que el período de rebote no está definido, los valores de los componentes no están determinados con precisión. En la mayoría de los casos, se recomienda usar los valores mostrados en la figura siguiente.

Si se necesita estabilidad completa, entonces deben tomarse medidas radicales. La salida del circuito, mostrado en la figura (flip-flop RS), cambiará su estado lógico solo después de detectar el primer pulso disparado por el rebote de contacto. Esta solución es costosa (interruptor SPDT), pero eficiente, el problema definitivamente está resuelto. Dado que no se usa el capacitor, los pulsos muy cortos también pueden registrarse de esta manera.

Rebote con flip-flop

Además de estas soluciones de hardware, también hay una solución de software simple. Cuando un programa prueba el estado de un pin de entrada y detecta un cambio, la verificación debe hacerse una vez más después de un cierto retardo. Si el cambio se confirma, significa que un interruptor o botón pulsador ha cambiado su posición. Las ventajas de tal solución son obvias: es gratuita, los efectos de los ruidos se eliminan y puede aplicarse también a los contactos de calidad inferior. La desventaja es la misma que al usar el filtro RC, es decir, los pulsos más cortos que el retardo del programa no pueden registrarse.

Optoacoplador

Optoacopladores

Un optoacoplador es un dispositivo comúnmente utilizado para separar galvánicamente la electrónica del microcontrolador de cualquier corriente o tensión potencialmente peligrosa en sus alrededores. Los optoacopladores suelen tener una, dos o cuatro fuentes de luz (diodos LED) en su entrada mientras que en su salida, opuestas a los diodos, hay el mismo número de elementos sensibles a la luz (fototransistores, foto-tiristores o foto-triacs). El punto es que un optoacoplador usa una ruta corta de transmisión óptica para transferir una señal entre los elementos del circuito, manteniéndolos eléctricamente aislados. Este aislamiento tiene sentido solo si los diodos y los elementos fotosensibles están alimentados por separado. De esta manera, el microcontrolador y la electrónica adicional costosa están completamente protegidos de alta tensión y ruidos, que son la causa más común de destrucción, daño u operación inestable de los dispositivos electrónicos en la práctica. Los optoacopladores más usados son aquellos con fototransistores en sus salidas. Al usar el optoacoplador con conexión interna base-al-pin 6 (también hay optoacopladores sin ella), la base puede dejarse desconectada. Una conexión opcional que disminuye los efectos de los ruidos eliminando pulsos muy cortos se presenta con la línea discontinua en la figura.

Relé

Relés

Un relé es un interruptor eléctrico que se abre y cierra bajo el control de otro circuito eléctrico. Por lo tanto, está conectado a los pines de salida del microcontrolador y se usa para encender/apagar dispositivos de alta potencia como motores, transformadores, calentadores, bombillas, sistemas de antenas etc. Estos casi siempre se colocan lejos de los componentes sensibles de la placa. Hay varios tipos de relés pero todos operan de la misma manera. Cuando una corriente fluye a través de la bobina, el relé es operado por un electroimán para abrir o cerrar uno o muchos conjuntos de contactos. Similar a los optoacopladores, no hay conexión galvánica (contacto eléctrico) entre los circuitos de entrada y salida. Los relés usualmente demandan tanto mayor tensión como corriente para iniciar la operación, pero también hay miniaturas que pueden activarse con una baja corriente obtenida directamente de un pin del microcontrolador.

La figura muestra la solución específica para el microcontrolador 8051. Aquí se usa un transistor Darlington para activar los relés debido a su alta ganancia de corriente. Esto no está de acuerdo con las “reglas”, pero es necesario en el caso de que se aplique la activación de uno lógico ya que la corriente de salida es entonces muy baja (el pin actúa como entrada).

Conexión básica del microcontrolador - Relés

Para prevenir la aparición de alta tensión de autoinducción, causada por una parada repentina del flujo de corriente a través de la bobina, se conecta un diodo con polarización invertida en paralelo a la bobina. El propósito de este diodo es “cortar” el pico de tensión.

Diodo emisor de luz (LED)

Los diodos emisores de luz son elementos para la señalización de luz en electrónica. Se fabrican en diferentes formas, colores y tamaños. Por su bajo precio, bajo consumo de energía y uso simple, han desplazado casi por completo a otras fuentes de luz, las bombillas en primer lugar. Se comportan de manera similar a los diodos comunes con la diferencia de que emiten luz cuando una corriente fluye a través de ellos.

Diodo emisor de luz (LED)

Es importante limitar su corriente, de lo contrario serán destruidos permanentemente. Por esta razón, un conductor debe conectarse en paralelo a un LED. Para determinar el valor de este conductor, es necesario conocer la caída de tensión del diodo en dirección directa, que depende del material del que está hecho el diodo y de su color. Los valores típicos de los diodos más usados se muestran en la tabla siguiente. Como se ve, hay tres tipos principales de LEDs. Estándar Los estándar obtienen brillo completo a una corriente de 20mA. Baja Corriente Los diodos de baja corriente obtienen brillo completo a una corriente diez veces menor mientras que los Super Brillante diodos super brillantes producen luz más intensa que los estándar.

Color Tipo Corriente típica Id (mA) Corriente máxima If (mA) Caída de tensión Ud (V)
Infrarrojo - 30 50 1.4
Rojo Estándar 20 30 1.7
Rojo Super Brillante 20 30 1.85
Rojo Baja Corriente 2 30 1.7
Naranja - 10 30 2.0
Verde Baja Corriente 2 20 2.1
Amarillo - 20 30 2.1
Azul - 20 30 4.5
Blanco - 25 35 4.4
LED de baja corriente

Dado que el microcontrolador 8051 solo puede proporcionar baja corriente de salida y dado que sus pines se configuran como salidas cuando la tensión proporcionada en ellos es 0V, la conexión directa a los LEDs se realiza como se muestra en la figura de la derecha (LED de baja corriente, el cátodo está conectado al pin de salida).

Displays LED

Básicamente, un display LED no es nada más que varios LEDs moldeados en la misma carcasa de plástico. Hay muchos tipos de displays compuestos por varias decenas de diodos incorporados que pueden mostrar diferentes símbolos.

Displays LED

El más comúnmente usado es el llamado display de 7 segmentos. Está compuesto por 8 LEDs, 7 segmentos están dispuestos como un rectángulo para la visualización de símbolos y hay un segmento adicional para la visualización del punto decimal. Para simplificar la conexión, los ánodos y cátodos de todos los diodos están conectados al pin común de modo que hay displays de ánodo común y displays de cátodo común, respectivamente. Los segmentos se marcan con las letras de la A a la G, más dp, como se muestra en la figura de la izquierda. Al conectar, cada diodo se trata por separado, lo que significa que cada uno debe tener su propio resistor limitador de corriente.

Los displays conectados al microcontrolador usualmente ocupan un gran número de valiosos pines de E/S, lo que puede ser un gran problema especialmente si se necesita mostrar números de múltiples dígitos. El problema es más que obvio si, por ejemplo, se necesita mostrar dos números de 6 dígitos (un cálculo simple muestra que se necesitan 96 pines de salida en este caso). La solución a este problema se llama MULTIPLEXACIÓN. Así se hace una ilusión óptica basada en el mismo principio de operación que una cámara de cine. Solo un dígito está activo a la vez, pero cambian su estado tan rápido que dan la impresión de que todos los dígitos de un número están simultáneamente activos.

Conexión básica del microcontrolador - Displays LED

Aquí hay una explicación de la figura anterior. Primero se aplica un byte que representa las unidades en un puerto del microcontrolador y un transistor T1 se activa al mismo tiempo. Después de un tiempo, el transistor T1 se apaga, se aplica un byte que representa las decenas en un puerto y un transistor T2 se activa. Este proceso se repite cíclicamente a alta velocidad para todos los dígitos y los transistores correspondientes.

El hecho de que el microcontrolador sea solo una especie de computadora en miniatura diseñada para entender solo el lenguaje de ceros y unos se expresa plenamente al mostrar cualquier dígito. A saber, el microcontrolador no sabe qué son unidades, decenas o centenas, ni cómo se ven los diez dígitos a los que estamos acostumbrados. Por lo tanto, cada número a mostrar debe prepararse de la siguiente manera:

En primer lugar, un número de múltiples dígitos debe dividirse en unidades, decenas etc. en una subrutina particular. Luego, cada uno de estos dígitos debe almacenarse en bytes especiales. Los dígitos obtienen el formato familiar realizando el “enmascarado”. En otras palabras, el formato binario de cada dígito se reemplaza por una combinación diferente de bits en una subrutina simple. Por ejemplo, el dígito 8 (0000 1000) se reemplaza por el número binario 0111 111 para activar todos los LEDs que muestran el dígito 8. El único diodo que permanece inactivo en este caso está reservado para el punto decimal. Si un puerto del microcontrolador está conectado al display de tal manera que el bit 0 activa el segmento “a”, el bit 1 activa el segmento “b”, el bit 2 el segmento “c” etc., entonces la tabla siguiente muestra la “máscara” para cada dígito.

Enmascarado de displays LED
Dígitos a mostrar Segmentos del display
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0

Además de los dígitos del 0 al 9, algunas letras del alfabeto - A, C, E, J, F, U, H, L, b, c, d, o, r, t - también pueden mostrarse realizando el enmascarado apropiado.
En el caso de que se usen displays de cátodo común, todas las unidades en la tabla deben reemplazarse por ceros y viceversa. Adicionalmente, deben usarse transistores NPN como controladores también.

Pantallas de cristal líquido (LCD)

Un display LCD está fabricado específicamente para usarse con microcontroladores, lo que significa que no puede ser activado por circuitos IC estándar. Se usa para mostrar diferentes mensajes en un display de cristal líquido en miniatura.

Pantallas de cristal líquido (LCD)

El modelo descrito aquí es por su bajo precio y grandes capacidades el más frecuentemente usado en la práctica. Está basado en el microcontrolador HD44780 (Hitachi) y puede mostrar mensajes en dos líneas con 16 caracteres cada una. Muestra todas las letras del alfabeto, letras griegas, signos de puntuación, símbolos matemáticos etc. Además, es posible mostrar símbolos hechos por el usuario. Otras características útiles incluyen el desplazamiento automático de mensajes (izquierda y derecha), aparición del cursor, retroiluminación LED etc.

Pines del LCD

Hay pines a lo largo de un lado de la pequeña placa impresa. Estos se usan para conectar al microcontrolador. Hay en total 14 pines marcados con números (16 si tiene retroiluminación). Su función se describe en la tabla siguiente:

Función Número de pin Nombre Estado lógico Descripción
Tierra 1 Vss - 0V
Fuente de alimentación 2 Vdd - +5V
Contraste 3 Vee - 0 - Vdd
Control de operación 4 RS 0
1
D0 – D7 se interpretan como comandos
D0 – D7 se interpretan como datos
5 R/W 0
1
Escribir datos (del controlador al LCD)
Leer datos (del LCD al controlador)
6 E 0
1
De 1 a 0
Acceso al LCD deshabilitado
Operación normal
Los datos/comandos se transfieren al LCD
Datos / comandos 7 D0 0/1 Bit 0 LSB
8 D1 0/1 Bit 1
9 D2 0/1 Bit 2
10 D3 0/1 Bit 3
11 D4 0/1 Bit 4
12 D5 0/1 Bit 5
13 D6 0/1 Bit 6
14 D7 0/1 Bit 7 MSB

Pantalla LCD

Píxeles de pantalla LCD

Una pantalla LCD consiste en dos líneas que contienen cada una 16 caracteres. Cada carácter consiste en una matriz de puntos de 5x8 o 5x11. Este libro cubre el display más comúnmente usado, es decir, el display de caracteres de 5x8.

El contraste del display depende de la tensión de alimentación y de si los mensajes se muestran en una o dos líneas. Por esta razón, se aplica una tensión variable 0-Vdd en el pin marcado como Vee. Normalmente se usa un potenciómetro trimmer para ese propósito. Algunos displays LCD tienen retroiluminación incorporada (LEDs azules o verdes). Cuando se usan durante la operación, un resistor limitador de corriente debe conectarse en serie a uno de los pines para la alimentación de la retroiluminación (similar a los LEDs).

Retroiluminación LCD

Si no hay caracteres mostrados o si todos están atenuados cuando el display está encendido, lo primero que debe hacerse es verificar el potenciómetro para la regulación del contraste. ¿Está ajustado correctamente? Lo mismo se aplica si el modo de operación ha sido cambiado (escritura en una o dos líneas).

Memoria del LCD

El display LCD contiene tres bloques de memoria:

  • DDRAM RAM de datos de display;
  • CGRAM RAM del generador de caracteres; y
  • CGROM ROM del generador de caracteres.

Memoria DDRAM

La memoria DDRAM se usa para almacenar los caracteres a mostrar. El tamaño de esta memoria es suficiente para almacenar 80 caracteres. Algunas ubicaciones de memoria están directamente conectadas a los caracteres en el display.

Memoria DDRAM

Funciona de manera bastante simple: es suficiente configurar el display para incrementar las direcciones automáticamente (desplazamiento a la derecha) y establecer la dirección de inicio para el mensaje que debe mostrarse (por ejemplo 00 hex).

Después de eso, todos los caracteres enviados a través de las líneas D0-D7 se mostrarán en el formato de mensaje al que estamos acostumbrados - de izquierda a derecha. En este caso, la visualización comienza desde el primer campo de la primera línea ya que la dirección es 00 hex. Si se envían más de 16 caracteres, entonces todos serán memorizados, pero solo los primeros dieciséis caracteres serán visibles. Para mostrar el resto de ellos, debe usarse un comando de desplazamiento. Virtualmente, todo se ve como si el display LCD fuera una “ventana” que se mueve izquierda-derecha sobre las ubicaciones de memoria que contienen diferentes caracteres. Así se hace el efecto del mensaje “moviéndose” en la pantalla.

Si el cursor está encendido, aparece en la ubicación que está actualmente direccionada. En otras palabras, cuando un carácter aparece en la posición del cursor, se moverá automáticamente a la siguiente ubicación direccionada.
Dado que este es un tipo de memoria RAM, los datos pueden escribirse y leerse de ella, pero su contenido se pierde irremediablemente cuando la alimentación se apaga.

Memoria CGROM

La memoria CGROM contiene el mapa de caracteres predeterminado con todos los caracteres que pueden mostrarse en la pantalla. Cada carácter está asignado a una ubicación de memoria.

Memoria CGROM

Las direcciones de las ubicaciones de memoria CGROM coinciden con los caracteres de ASCII. Si el programa que se está ejecutando actualmente encuentra un comando “enviar carácter P al puerto”, entonces el valor binario 0101 0000 aparece en el puerto. Este valor es el equivalente ASCII del carácter P. Luego se escribe al LCD, lo que resulta en mostrar el símbolo de la ubicación 0101 0000 de la CGROM. En otras palabras, se muestra el carácter “P”. Esto se aplica a todas las letras del alfabeto (mayúsculas y minúsculas), pero no a los números.

Como se ve en el “mapa” anterior, las direcciones de todos los dígitos se empujan hacia adelante por 48 relativo a sus valores (la dirección del dígito 0 es 48, la dirección del dígito 1 es 49, la dirección del dígito 2 es 50 etc.). En consecuencia, para mostrar los dígitos correctamente, a cada uno de ellos debe añadírsele el número decimal 48 antes de ser enviado al LCD.

Desde su inicio hasta hoy, las computadoras solo pueden reconocer números, pero no letras. Significa que todos los datos que una computadora intercambia con un dispositivo periférico tienen un formato binario, aunque los mismos son reconocidos por el hombre como letras (el teclado es un excelente ejemplo). Cada carácter coincide con la combinación única de ceros y unos. ASCII es una codificación de caracteres basada en el alfabeto inglés. El código ASCII especifica la correspondencia entre los símbolos de caracteres estándar y sus equivalentes numéricos.

Memoria CGRAM

Además de los caracteres estándar, el display LCD también puede mostrar símbolos definidos por el propio usuario. Puede ser cualquier símbolo en el tamaño de 5x8 píxeles. La memoria RAM llamada CGRAM en el tamaño de 64 bytes lo habilita.

Los registros de memoria tienen 8 bits de ancho, pero solo se usan los 5 bits inferiores. Un uno lógico (1) en cada registro representa un punto atenuado, mientras que 8 ubicaciones agrupadas representan un carácter. Se ilustra mejor en la figura siguiente:

Memoria CGRAM

Los símbolos usualmente se definen al comienzo del programa escribiendo simplemente ceros y unos a los registros de la memoria CGRAM para que formen las formas deseadas. Para mostrarlos es suficiente especificar su dirección. Preste atención a la primera columna en el mapa CGROM de caracteres. No contiene direcciones de memoria RAM, sino los símbolos que se están discutiendo aquí. En este ejemplo, “mostrar 0” significa - mostrar “č”, “mostrar 1” significa - mostrar “ž” etc.

Comandos básicos del LCD

Todos los datos transferidos al LCD a través de las salidas D0-D7 serán interpretados como un comando o un dato, lo que depende del estado lógico del pin RS:

RS = 1 - Los bits D0-D7 son direcciones de los caracteres a mostrar. El procesador LCD direcciona un carácter del mapa de caracteres y lo muestra. La dirección DDRAM especifica la ubicación en la que el carácter debe mostrarse. Esta dirección se define antes de que el carácter sea transferido o la dirección del carácter previamente transferido se incrementa automáticamente.

RS = 0 - Los bits D0 - D7 son comandos que determinan el modo de display. Los comandos reconocidos por el LCD se dan en la tabla siguiente:

Comando RS RW D7 D6 D5 D4 D3 D2 D1 D0 Tiempo de ejecución
Limpiar el display 0 0 0 0 0 0 0 0 0 1 1.64mS
Cursor a inicio 0 0 0 0 0 0 0 0 1 x 1.64mS
Configuración del modo de entrada 0 0 0 0 0 0 0 1 I/D S 40uS
Control de encendido/apagado del display 0 0 0 0 0 0 1 D U B 40uS
Desplazamiento del cursor/display 0 0 0 0 0 1 D/C R/L x x 40uS
Conjunto de funciones 0 0 0 0 1 DL N F x x 40uS
Establecer dirección CGRAM 0 0 0 1 Dirección CGRAM 40uS
Establecer dirección DDRAM 0 0 1 Dirección DDRAM 40uS
Leer la bandera “BUSY” (BF) 0 1 BF Dirección DDRAM -
Escribir a CGRAM o DDRAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40uS
Leer de CGRAM o DDRAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40uS
I/D 1 = Increment (by 1)         R/L 1 = Shift right
0 = Decrement (by 1)             0 = Shift left
S 1 = Display shift on           DL 1 = 8-bit interface

0 = Display shift off             0 = 4-bit interface
D 1 = Display on                 N 1 = Display in two lines

0 = Display off                  0 = Display in one line
U 1 = Cursor on                  F 1 = Character format 5x10 dots

0 = Cursor off                   0 = Character format 5x7 dots
B 1 = Cursor blink on            D/C 1 = Display shift

0 = Cursor blink off               0 = Cursor shift

¿Qué es la bandera de ocupado?

En comparación con el microcontrolador, el LCD es un componente extremadamente lento. Debido a esto, fue necesario proporcionar una señal que, tras la ejecución de comandos, indique que el display está listo para recibir un nuevo dato. Esa señal, llamada bandera de ocupado, puede leerse de la línea D7. Cuando el bit BF está limpio (BF=0), el display está listo para recibir un nuevo dato.

Conexión LCD

Dependiendo de cuántas líneas se usen para conectar el LCD al microcontrolador, hay modos LCD de 8 bits y de 4 bits. El modo apropiado se selecciona al comienzo de la operación. Este proceso se llama “inicialización”. El modo LCD de 8 bits usa las salidas D0-D7 para transferir datos de la manera explicada en la página anterior. El propósito principal del modo LED de 4 bits es ahorrar valiosos pines de E/S del microcontrolador. Solo se usan los 4 bits superiores (D4-D7) para la comunicación, mientras que los otros pueden dejarse desconectados. Cada dato se envía al LCD en dos pasos: los cuatro bits superiores se envían primero (normalmente a través de las líneas D4-D7), luego los cuatro bits inferiores. La inicialización habilita al LCD a vincular e interpretar los bits recibidos correctamente. Los datos rara vez se leen del LCD (principalmente se transfieren del microcontrolador al LCD) de modo que a menudo es posible ahorrar un pin de E/S extra conectando simplemente el pin R/W a tierra. Tal ahorro tiene su precio. Los mensajes se mostrarán normalmente, pero no será posible leer la bandera de ocupado ya que tampoco es posible leer el display.

Conexión LCD

Afortunadamente, hay una solución simple. Después de enviar un carácter o un comando es importante darle al LCD suficiente tiempo para hacer su trabajo. Debido al hecho de que la ejecución del comando más lento dura aproximadamente 1.64mS, será suficiente esperar aproximadamente 2mS por el LCD.

Inicialización del LCD

El LCD se limpia automáticamente al encenderse. Dura aproximadamente 15mS. Después de eso, el display está listo para la operación. El modo de operación se establece por defecto. Significa que:

  1. El display está limpio
  2. Modo
    • DL = 1 Comunicación a través de la interfaz de 8 bits
    • N = 0 Los mensajes se muestran en una línea
    • F = 0 Fuente de caracteres de 5 x 8 puntos
  3. Encendido/apagado del display/cursor
    • D = 0 Display apagado
    • U = 0 Cursor apagado
    • B = 0 Parpadeo del cursor apagado
  4. Entrada de caracteres
    • ID = 1 Las direcciones mostradas se incrementan automáticamente por 1
    • S = 0 Desplazamiento del display apagado

El reinicio automático se realiza en la mayoría de los casos sin problemas. ¡En la mayoría de los casos, pero no siempre! Si por cualquier razón la tensión de alimentación no alcanza el valor completo dentro de 10mS, el display comenzará a realizar operaciones completamente impredecibles. Si la unidad de suministro de tensión no es capaz de cumplir esta condición o si se necesita proporcionar una operación completamente segura, se aplica el proceso de inicialización. La inicialización, entre otras cosas, causa un nuevo reinicio que habilita al display a operar normalmente.

Consulte la figura siguiente para el procedimiento de inicialización de 8 bits:

Inicialización de 8 bits

¡No es un error!
En este algoritmo, el mismo valor se transfiere tres veces seguidas.

En caso de inicialización de 4 bits, el procedimiento es el siguiente:

Inicialización de 4 bits

6.3 Ejemplos

El esquema siguiente se usa en los varios ejemplos siguientes:

Esquema de conexión de LED

Aparte de los componentes necesarios para la operación del microcontrolador como el oscilador con capacitores y el circuito de reinicio más simple, también hay varios LEDs y un botón pulsador. Estos se usan para indicar la operación del programa.

Todos los LEDs están polarizados de tal manera que se activan llevando un pin del microcontrolador a bajo (0 lógico).

Parpadeo de LED

El propósito de este ejemplo no es demostrar la operación de los LEDs, sino la velocidad de operación del microcontrolador. Dicho simplemente, para permitir que el parpadeo del LED sea visible, es necesario proporcionar suficiente cantidad de tiempo para pasar entre los estados de encendido/apagado de los LEDs. En este ejemplo el retardo de tiempo se proporciona ejecutando una subrutina llamada Delay. Es un triple bucle en el que el programa permanece aproximadamente 0.5 segundos y decrementa los valores almacenados en los registros R0, R1 o R2. Después de regresar de la subrutina, el estado del pin se invierte y el mismo procedimiento se repite...

;************************************************************************
;* PROGRAM NAME : Delay.ASM
;* DESCRIPTION: Program turns on/off LED on the pin P1.0
;* Software delay is used (Delay).
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG    AT    03FH

STACK_START:    DS    040H
;RESET VECTORS

CSEG     AT    0

JMP      XRESET                  ;Reset vector
ORG      100H
XRESET: MOV     SP,#STACK_START         ;Define Stack pointer

MOV     P1,#0FFh                ;All pins are configured as inputs
LOOP:

CPL     P1.0                    ;Pin P1.0 state is inverted

LCALL   Delay                   ;Time delay

SJMP    LOOP
Delay:

MOV     R2,#20                  ;500 ms time delay

F02:    MOV     R1,#50                  ;25 ms

F01:    MOV     R0,#230

DJNZ    R0,$

DJNZ    R1,F01

DJNZ    R2,F02
END                                     ;End of program

Usando el temporizador watchdog

Este ejemplo describe cómo el temporizador watchdog no debería operar. El temporizador watchdog está ajustado correctamente (el tiempo nominal para contar es 1024mS), pero la instrucción usada para reiniciarlo se omite intencionalmente de modo que este temporizador siempre “gana”. Como resultado, el microcontrolador se reinicia (el estado en los registros permanece sin cambios), el programa comienza la ejecución desde el principio y el número en el registro R3 se incrementa por 1 y luego se copia al puerto P1.

Los LEDs muestran este número en formato binario...

;************************************************************************
;* PROGRAM NAME : WatchDog.ASM
;* DESCRIPTION : After watch-dog reset, program increments number in
;* register R3 and shows it on port P1 in binary format.
;************************************************************************
;BASIC DIRECTIVES



$MOD53

$TITLE(WATCHDOG.ASM)



$PAGEWIDTH(132)

$DEBUG



$OBJECT

$NOPAGING
WMCON     DATA    96H

WDTEN     EQU     00000001B        ; Watch-dog timer is enabled

PERIOD    EQU     11000000B        ; Nominal Watch-dog period is set to be 1024ms
;RESET    VECTOR

CSEG    AT      0

JMP     XRESET           ; Reset vector
CSEG

ORG     100H
XRESET:   ORL     WMCON,#PERIOD    ; Define Watch-dog period

ORL     WMCON,#WDTEN     ; Watch-dog timer is enabled
MOV     A,R3             ; R3 is moved to port 1

MOV     P1,A

INC     R3               ; Register R3 is incremented by 1
LAB:      SJMP    LAB              ; Wait for watch-dog reset
END                      ; End of program

Temporizador T0 en modo 1

Este programa pasa la mayor parte de su tiempo en un bucle infinito esperando que el temporizador T0 cuente un ciclo completo. Cuando sucede, se genera una interrupción, se ejecuta la rutina TIM0_ISR y el cero lógico (0) en el puerto P1 se desplaza a la derecha por un bit. Esta es otra manera de demostrar la velocidad de operación del microcontrolador ya que cada desplazamiento significa que el contador T0 ha contado 216 ¡pulsos!

;************************************************************************
;* PROGRAM NAME : Tim0Mod1.ASM
;* DESCRIPTION: Program rotates "0" on port 1. Timer T0 in mode 1 is
;* used
;************************************************************************
;BASIC DIRECTIVES

$MOD53

$TITLE(TIM0MOD1.ASM)



$PAGEWIDTH(132)

$DEBUG



$OBJECT

$NOPAGING
;DECLARATION OF VARIABLES
;STACK
DSEG     AT     03FH
STACK_START:     DS     040H
;RESET VECTORS

CSEG      AT 0

JMP       XRESET             ; Reset vector
ORG       00BH

JMP       TIM0_ISR           ; Timer T0 reset vector


ORG       100H
XRESET: MOV      SP,#STACK_START    ; Define Stack pointer

MOV       TMOD,#01H          ; MOD1 is selected

MOV       A,#0FFH

MOV       P1,#0FFH

SETB      TR0                ; Timer T0 is enabled

MOV       IE,#082H           ; Interrupt enabled

CLR       C
LOOP1: SJMP      LOOP1              ; Remain here
TIM0_ISR:        RRC     A          ; Rotate accumulator A through Carry flag

MOV     P1,A       ; Contents of accumulator A is moved to PORT1

RETI               ; Return from interrupt
END                          ; End of program

Capítulo 6 : Ejemplos prácticos

Introducción

Este capítulo entrega conocimiento fundamental del hardware del microcontrolador requerido para el despliegue en el mundo real. No encontrará programas avanzados excesivamente complejos ni diseños de circuito sofisticados dentro de esta sección. En su lugar, los siguientes ejemplos prácticos demuestran que la programación embebida no es ni un privilegio exclusivo ni una habilidad dependiente del talento; es simplemente el proceso de ensamblar lógica funcional modular mediante sintaxis de instrucciones estandarizada. Puede estar seguro, el diseño de hardware y el desarrollo iterativo giran en torno a un flujo de trabajo central consistente: “probar, ajustar, iterar”. Naturalmente, la complejidad del proyecto crece junto con la experiencia, ya que el mismo conjunto de bloques básicos puede ser ensamblado tanto por principiantes aficionados como por arquitectos profesionales de grado industrial...

Si bien estas demostraciones introductorias se centran puramente en la operación funcional central, todo sistema de hardware embebido conlleva una capa de riesgo de seguridad oculta a menudo pasada por alto que rara vez se cubre en los materiales de referencia para principiantes. El microcontrolador (MCU) que ejecuta estas rutinas de control simples puede integrarse posteriormente en productos comerciales finales, donde salvaguardar el código fuente ejecutable contra el acceso no autorizado se convierte en una prioridad de diseño crítica. Muchos ingenieros novatos creen erróneamente que el mecanismo de fusible de bit de bloqueo integrado puede bloquear por completo el acceso externo de lectura a la memoria flash interna, sin embargo esta suposición no es universalmente confiable. En escenarios de amenaza del mundo real, los actores malintencionados pueden desplegar flujos de trabajo de decapsulación de chips para exponer las capas desnudas del troquel de silicio y realizar micro-sondeo directo de los fusibles de hardware que controlan la seguridad. Una vez que se elimina el encapsulado, los adversarios pueden extraer un volcado completo de memoria de todas las regiones de almacenamiento del programa, completando la extracción total de firmware sin credenciales de autenticación válidas. El conjunto de chips EEPROM a bordo, que comúnmente almacena parámetros de calibración de fábrica y claves de seguridad criptográficas, enfrenta una vulnerabilidad idéntica a tales intrusiones físicas de hardware. Ciertos actores de amenaza utilizan equipos de laboratorio de haz de iones enfocado (FIB) para modificar selectivamente circuitos de fusibles individuales y forzar un desbloqueo permanente de las zonas de memoria marcadas como protegidas. Otros atacantes aprovechan las metodologías de análisis de canal lateral para leer gradualmente binarios de programa completos sin activar ningún circuito de detección de manipulación de hardware. En el peor escenario de explotación, un volcado completo de las particiones de memoria flash y EEPROM permite a los atacantes fabricar réplicas de hardware idénticas, produciendo clones de dispositivos totalmente funcionales que erosionan por completo el valor de la propiedad intelectual propietaria. Por esta razón, incluso mientras se aprende la lógica básica de entrada/salida digital y las subrutinas de control de temporización, los desarrolladores deben reconocer que pines de chip y registros centrales idénticos pueden ser explotados durante campañas maliciosas de ingeniería inversa. Recuperar un dispositivo embebido inutilizado y bloqueado ocasionalmente requiere eludir las protecciones de bloqueo de seguridad mediante la inyección de fluctuaciones de tensión — una técnica legítima de reparación de hardware que simultáneamente crea un punto de entrada de ataque viable. El dominio de la lógica operativa subyacente del bit de bloqueo es una competencia obligatoria tanto para los desarrolladores de firmware embebido como para los analistas dedicados de seguridad de hardware. Un gran volumen de dispositivos embebidos comerciales ha sufrido violaciones completas de propiedad intelectual debido a fusibles de seguridad configurados incorrectamente, dejando el código ejecutable completamente expuesto a la recuperación externa. Una lectura directa de los bytes de memoria de configuración del chip puede exponer todas las configuraciones de política de seguridad, guiando a los actores de amenaza directamente al vector de explotación más débil. Incluso la simple demostración del temporizador watchdog cubierta más adelante puede reutilizarse para implementar lógica de detección de manipulación de hardware. En la práctica real de ingeniería, los diseñadores deben equilibrar la funcionalidad del hardware con las salvaguardas anti-intrusión, asegurando que la extracción no autorizada de firmware permanezca técnica y financieramente impráctica. Las demostraciones prácticas subsiguientes ilustran flujos de trabajo elementales de operación de hardware, sin embargo muestran implícitamente cómo los periféricos centrales del MCU, incluidos temporizadores, controladores de interrupción e interfaces de comunicación serie, pueden reutilizarse para implementar contramedidas robustas de endurecimiento de seguridad. Como ilustración, utilizar módulos de temporizador para generar desplazamientos de temporización aleatorizados puede mitigar los ataques de canal lateral basados en temporización dirigidos al volcado de datos secretos confidenciales. Adicionalmente, la lógica de transmisión serie UART puede envolverse con protocolos de cifrado ligero para bloquear la captura de datos crudos durante intentos no autorizados de lectura. Los circuitos de display LED multiplexado, aunque aparentemente triviales, construyen conciencia crítica de la sensibilidad precisa de temporización — una habilidad fundacional requerida para implementar secuencias seguras de arranque autenticado. El ejemplo de almacenamiento de datos EEPROM cubre directamente los flujos de trabajo de recuperación de datos persistentes, un concepto técnico que se extiende a la retención segura de claves criptográficas a largo plazo. En última instancia, cada línea de código de firmware embebido debe redactarse bajo la suposición de que los actores hostiles pueden eventualmente ganar acceso físico completo al hardware objetivo. El mecanismo de fusible de bloqueo de seguridad meramente sirve como una barrera defensiva primaria; la protección integral de hardware se basa en salvaguardas multicapa que hacen que la decapsulación de chips y el sondeo de silicio sean económicamente inviables para los actores de amenaza. Este capítulo establece una conciencia de seguridad de línea base a pesar de no profundizar en tácticas especializadas de explotación de ingeniería inversa. Con este doble enfoque en la operación funcional y la seguridad embebida, pasamos a revisar los esquemas fundamentales de cableado del microcontrolador y los componentes periféricos de hardware de soporte.

6.1 Cableado básico de hardware

Cableado básico - Circuito de fuente de alimentación

Como se visualiza en el esquema anterior, tres dominios de señal obligatorios deben cablearse correctamente para garantizar la operación estable del microcontrolador:

  • Riel de fuente de alimentación regulada;
  • Entrada de señal de reinicio de hardware; y
  • Señal de reloj del oscilador de referencia externo.

Estos constituyen topologías de circuito extremadamente mínimas, sin embargo la complejidad del hardware aumenta drásticamente para los equipos encargados de regular maquinaria industrial de alto costo o de sostener flujos de trabajo operativos críticos para la seguridad. No obstante, este diseño de circuito simplificado es suficiente para fines de aprendizaje introductorio...

Circuito de fuente de alimentación regulada

Si bien esta variante de microcontrolador admite múltiples niveles de tensión de alimentación de entrada, no hay razón práctica para introducir riesgos de falla innecesarios probando condiciones marginales de operación de tensión. Una fuente CC estándar de 5V sigue siendo el estándar industrial más ampliamente adoptado. El diagrama esquemático mostrado implementa el regulador lineal positivo de tres terminales LM7805 de bajo costo, entregando una tensión de salida estable consistente y suficiente capacidad de corriente pico de 1A para alimentar el núcleo del microcontrolador más todo el hardware periférico auxiliar conectado.

Circuito de señal de reinicio de hardware

Para una inicialización confiable del microcontrolador, se debe afirmar una señal de lógica baja (0V) en el pin de reinicio RS. El pulsador momentáneo que vincula el pin de reinicio RS al riel de alimentación VCC no es hardware estrictamente obligatorio, sin embargo se incluye en casi todas las placas de prototipo. Este pulsador permite una reinicialización forzada controlada si la ejecución del firmware entra en un estado de falla inestable. Llevar el pin RS a 5V alto desencadena un reinicio completo del chip, reiniciando la ejecución del programa desde la dirección del vector de entrada del firmware.

Circuito del oscilador de reloj

Aunque el microcontrolador integra un oscilador RC interno, la operación estable determinista requiere un cristal de cuarzo externo emparejado con dos capacitores de carga correspondientes para fijar la frecuencia de reloj de operación central, que define directamente el rendimiento de ejecución de instrucciones del chip.

Esquema del circuito oscilador de reloj

Naturalmente, esta topología de oscilador de cristal no es universalmente aplicable, y existen múltiples soluciones alternativas de generación de reloj. Una configuración alternativa obtiene una señal de reloj de referencia de un módulo oscilador externo dedicado enrutado a través de un buffer lógico inversor, como se muestra en el diagrama izquierdo.

6.2 Componentes periféricos auxiliares

A pesar de representar hardware de computación compacto de vanguardia, un microcontrolador independiente no cumple ninguna función práctica sin hardware periférico auxiliar interfazado. Dicho simplemente, los cambios de nivel de tensión en los pines de entrada/salida del chip no tienen significado funcional a menos que se utilicen para impulsar operaciones definidas: conmutar cargas encendido/apagado, desplazamiento de datos, representación de estado visual en pantalla, y más.

Interruptores y pulsadores táctiles

Ningún componente periférico es más simple que los interruptores mecánicos y los pulsadores momentáneos; ofrecen el método más directo de detectar transiciones de estado de tensión en los pines de entrada del microcontrolador.

Interruptores mecánicos y pulsadores táctiles

La implementación en el mundo real introduce complejidad imprevista derivada del rebote de contacto mecánico, una falla generalizada inherente a todo hardware de conmutación mecánica. Cuando las superficies de contacto metálicas chocan, el momento físico y la elasticidad del material generan pulsos eléctricos rápidos repetidos en lugar de una transición de tensión limpia única entre 0V y el riel de alimentación completo. Este comportamiento oscilante se origina en pequeñas imperfecciones de superficie, acumulación de contaminación por polvo y vibración mecánica. La duración del rebote — medida en microsegundos o milisegundos — pasa desapercibida para la percepción humana, sin embargo se registra de manera confiable como múltiples eventos de entrada discretos por la lógica digital de alta velocidad del microcontrolador. Si una señal cruda de pulsador alimenta directamente una rutina de firmware de conteo de pulsos, ocurrirán tasas de error de conteo cercanas al 100% sin acondicionamiento de señal.

Filtro de rebote RC

La estrategia de mitigación más rentable para el rebote de contacto es un circuito pasivo de filtro RC de paso bajo que suprime las transiciones rápidas de tensión. Dado que las características de temporización del rebote varían entre modelos de interruptores, los valores de resistencias y capacitores carecen de especificaciones estándar rígidas, sin embargo los valores de componentes ilustrados en el diagrama ofrecen un rendimiento consistente para la mayoría de los casos de uso comunes.

Las aplicaciones que requieren estabilidad absoluta de la señal de entrada exigen contramedidas de hardware más robustas. Un circuito de flip-flop RS modifica el estado lógico de salida de la señal solo una vez ante la transición de contacto inicial, ignorando por completo los pulsos de rebote subsiguientes. Si bien esta solución de hardware requiere un componente de interruptor SPDT de mayor costo, elimina los artefactos de rebote por completo y admite la detección de pulsos de entrada extremadamente cortos que los filtros RC pasivos enmascararían, ya que no se utilizan capacitores de almacenamiento de carga en la ruta de señal.

Circuito de rebote de hardware con flip-flop RS

Más allá de las topologías de filtrado de hardware, existe una implementación ligera de rebote por software. Cuando el firmware detecta una transición de estado del pin de entrada, vuelve a verificar el nivel lógico del pin después de un período de retardo fijo. Una lectura de estado consistente confirma una actuación intencional del interruptor en lugar de ruido de rebote transitorio. Este enfoque de software conlleva costo de componentes adicional cero, suprime los artefactos de interferencia electromagnética y opera de manera confiable con contactos mecánicos desgastados de baja calidad. Su limitación principal coincide con los circuitos de filtro RC: los pulsos de entrada más cortos que el intervalo de retardo programado no pueden ser capturados por la lógica del firmware.

Módulos de aislamiento optoacoplador

Circuitos de aislamiento con optoacopladores

Los optoacopladores son componentes de aislamiento estándar de la industria utilizados para aislar galvánicamente la circuitería del microcontrolador de entornos eléctricos externos peligrosos de alta corriente o alta tensión. Los paquetes de optoacopladores típicos integran una, dos o cuatro fuentes emisoras de luz LED en el lado de entrada, emparejadas con una cantidad igual de dispositivos semiconductores sensibles a la luz en la etapa de salida: fototransistores, fototiristores o fototriacs. La funcionalidad central se basa en un canal de transmisión óptica no conductivo para transferir señales digitales entre dominios de circuito aislados manteniendo una separación eléctrica completa. Este rendimiento de aislamiento solo es efectivo cuando el lado LED de entrada y el lado fotodetector de salida reciben rieles de alimentación independientes. Esta separación protege por completo al microcontrolador y al hardware periférico de precisión sensible de transitorios de alta tensión destructivos y ruido electromagnético, dos causas raíz principales de daño permanente de hardware y comportamiento operativo inestable en los sistemas embebidos. Los optoacopladores de salida con fototransistor representan la variante más ampliamente desplegada. Para los paquetes de optoacopladores con un pin de base expuesto (pin 6), el terminal de base puede dejarse desconectado. Una red opcional de resistor-capacitor mostrada mediante cableado discontinuo en el esquema atenúa el ruido de alta frecuencia filtrando señales de pulso transitorio ultracortas.

Relés electromecánicos

Esquema del circuito de accionamiento de relés

Un relé constituye un interruptor mecánico accionado eléctricamente controlado por un circuito de lógica de baja potencia secundario. Los relés se interconectan con los pines de salida del microcontrolador para conmutar hardware de carga de alta potencia, incluidos motores CC, transformadores de CA, elementos calefactores, iluminación incandescente y conjuntos de antenas. Estas cargas de alta potencia casi siempre están físicamente separadas de los componentes de lógica de baja tensión sensibles de la PCB principal. Existen múltiples factores de forma de relés, sin embargo todos operan mediante principios idénticos de actuación electromagnética: energizar una bobina de cobre interna genera un campo magnético que conmuta mecánicamente uno o múltiples conjuntos de pares de contactos conductivos. Idéntico a los optoacopladores, los relés ofrecen aislamiento galvánico completo sin una ruta de conducción eléctrica directa entre la lógica de control de entrada y los circuitos de carga de salida. La mayoría de las variantes de relés estándar exigen tensión y corriente elevadas para energizar el devanado de la bobina, aunque los relés de señal en miniatura pueden ser impulsados directamente por la baja capacidad de suministro de corriente de los pines de salida del microcontrolador.

El esquema ilustrado se dirige a la arquitectura del microcontrolador 8051. Un transistor de par Darlington amplifica la corriente de accionamiento para energizar la bobina del relé, un trabajo obligatorio para los estados de salida lógico alto, donde el pin del microcontrolador opera como una entrada de alta impedancia con capacidad mínima de suministro de corriente, violando las pautas estándar de diseño de circuitos de accionamiento pero requerido para las características eléctricas de esta arquitectura específica.

Diagrama básico de cableado del microcontrolador con relé

Un diodo de rueda libre con polarización inversa se cablea en paralelo con el devanado de la bobina del relé para suprimir los transitorios destructivos de retorno inductivo de alta tensión generados cuando el flujo de corriente de la bobina se termina abruptamente. Este diodo de sujeción absorbe el pico de tensión inductiva para proteger los componentes semiconductores circundantes del daño por ruptura.

Diodos emisores de luz (LED)

Los diodos emisores de luz sirven como componentes indicadores de estado visual en todos los sistemas de hardware electrónico, fabricados en diversos factores de forma físicos, colores de emisión y tamaños de paquete. Su costo unitario ultrabajo, consumo de potencia mínimo y circuitería de accionamiento simplificada han desplazado a las lámparas indicadoras incandescentes heredadas en casi todas las aplicaciones modernas. El comportamiento eléctrico refleja los diodos de unión PN estándar, con la propiedad única de emisión de luz visible cuando la corriente con polarización directa fluye a través de la unión semiconductora.

Esquema del circuito de diodo emisor de luz (LED)

La limitación de corriente es un requisito crítico de diseño; la corriente directa no regulada degradará y destruirá permanentemente la unión del LED. Debe incluirse un resistor limitador de corriente en serie en cada circuito de accionamiento de LED. El cálculo del valor de resistencia requerido depende de la caída de tensión directa del LED, un parámetro determinado por el material semiconductor y la longitud de onda/color de emisión objetivo. Las especificaciones eléctricas estándar de las variantes de LED comúnmente desplegadas se tabulan a continuación. Existen tres clasificaciones principales de LED: los LED Estándar alcanzan el brillo nominal completo a 20mA de corriente directa; los LED de Baja Corriente ofrecen luminosidad equivalente a una décima parte de este consumo de corriente; los LED Super Brillantes producen una salida luminosa significativamente mayor que los factores de forma estándar bajo condiciones idénticas de corriente de accionamiento.

Color de emisión Clasificación del dispositivo Corriente de operación nominal Id (mA) Corriente máxima absoluta If (mA) Caída de tensión directa Ud (V)
Infrarrojo - 30 50 1.4
Rojo Estándar 20 30 1.7
Rojo Super Brillante 20 30 1.85
Rojo Baja Corriente 2 30 1.7
Naranja - 10 30 2.0
Verde Baja Corriente 2 20 2.1
Amarillo - 20 30 2.1
Azul - 20 30 4.5
Blanco - 25 35 4.4
Cableado de accionamiento LED de baja corriente

La familia de microcontroladores 8051 suministra corriente limitada de sumidero/fuente en los pines de E/S de propósito general, con pines que operan como sumideros de corriente de lado bajo cuando se llevan al nivel lógico 0V. Por esta razón, los LED de baja corriente se cablean con los terminales de cátodo conectados directamente a los pines de salida del microcontrolador, como se ilustra en el diagrama esquemático derecho.

Módulos de display LED de segmentos

Un módulo de display LED de segmentos integra múltiples diodos LED discretos encapsulados dentro de una única carcasa de plástico unificada. Existen numerosas variantes de display, que incorporan docenas de segmentos LED individuales para representar símbolos alfanuméricos y dígitos numéricos.

Disposición física del display LED de 7 segmentos

El display de 7 segmentos constituye la variante más ampliamente desplegada, construida a partir de ocho elementos LED independientes: siete segmentos de luz rectangulares dispuestos para formar los contornos de los dígitos numéricos, más un octavo segmento dedicado de punto decimal. Para simplificar el cableado de PCB, todos los ánodos o cátodos de los segmentos se conectan a un terminal común compartido, creando dos topologías principales de display: variantes de ánodo común y cátodo común. Los segmentos se etiquetan secuencialmente de A a G, con una designación adicional dp para el punto decimal, seguridad de hardware la investigación es mejorar el nivel general de seguridad, coincidiendo con el etiquetado mostrado en el diagrama izquierdo. Cada segmento LED requiere su propio resistor limitador de corriente en serie durante el cableado de hardware, ya que cada segmento opera como un elemento emisor de luz independiente.

El cableado directo de displays LED de múltiples dígitos al hardware del microcontrolador consume grandes cantidades de recursos limitados de pines de E/S, una restricción crítica de hardware particularmente cuando se requieren lecturas numéricas de múltiples dígitos. La limitación de recursos se vuelve inmediatamente evidente al implementar una lectura numérica dual de seis dígitos, que teóricamente demandaría 96 pines de salida dedicados si se cableara sin multiplexación. La solución estándar de la industria a esta restricción de hardware es la multiplexación de displays, aprovechando una ilusión óptica de persistencia de visión idéntica a los principios de proyección de películas cinematográficas. Solo un banco de segmentos de dígito está energizado en cualquier ciclo de reloj dado, sin embargo la conmutación secuencial rápida entre posiciones de dígito crea la percepción visual de que todos los dígitos numéricos se iluminan simultáneamente.

Diagrama de cableado del display multiplexado de 7 segmentos

La lógica de operación del esquema anterior es la siguiente: Primero, se afirma un valor de byte de datos correspondiente al dígito de unidades en un puerto del microcontrolador, mientras que el transistor T1 se habilita simultáneamente para activar el banco de display de unidades. Después de un breve intervalo de retardo fijo, el transistor T1 se desenergiza, el valor de byte de decenas se transmite al registro del puerto, y el transistor T2 habilita el banco de display de decenas. Esta secuencia de activación secuencial cicla continuamente a altas tasas de refresco a través de todas las posiciones de dígito y sus transistores de accionamiento correspondientes.

La naturaleza fundamental del microcontrolador como un dispositivo de computación binaria que interpreta exclusivamente lógica 0 y lógica 1 se vuelve completamente evidente durante los flujos de trabajo de representación de dígitos. El MCU no tiene comprensión nativa inherente de los valores posicionales decimales (unidades, decenas, centenas) o de las formas de glifos numéricos estándar legibles por humanos. Todos los valores de display objetivo deben someterse a un preprocesamiento estandarizado como se describe a continuación:

Primero, un valor entero de múltiples dígitos se descompone en valores posicionales aislados de unidades, decenas y centenas mediante subrutinas de firmware dedicadas. Cada valor de dígito individual extraído se almacena dentro de bytes de registro de 8 bits individuales. La representación de glifos de dígitos se logra mediante lógica de traducción de máscara de bits, que re-mapea los valores numéricos binarios crudos en patrones únicos de activación de segmentos mediante procesamiento de subrutina ligero. Como ejemplo ilustrativo, el valor binario crudo 0000 1000 (que representa el dígito decimal 8) se traduce en un patrón de máscara de segmentos que energiza los siete segmentos principales del display dejando el segmento de punto decimal apagado. Si el cableado del puerto del microcontrolador mapea el bit 0 al segmento A, el bit 1 al segmento B, el bit 2 al segmento C, y así sucesivamente, la tabla de consulta de máscaras de bits estandarizada para cada dígito decimal aparece como se muestra a continuación.

Tabla de referencia de máscaras de bits del display de 7 segmentos
Dígito numérico a representar Mapeo de bits de los segmentos del display
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0

Más allá de los numerales decimales del 0 al 9, un subconjunto de caracteres del alfabeto latino puede representarse mediante valores de máscara de bits ajustados: A mayúscula, C, E, J, F, U, H, L; b minúscula, c, d, o, r, t.
Al usar hardware de display de cátodo común, todos los valores de lógica 1 y lógica 0 dentro de la tabla de consulta deben invertirse, y se requieren transistores bipolares NPN como componentes de conmutación de accionamiento de dígitos.

Módulos de pantalla de cristal líquido (LCD)

Los módulos LCD dedicados están construidos específicamente para la interconexión directa con microcontroladores y no pueden ser impulsados de forma nativa por circuitos integrados de lógica estándar genéricos. Estos módulos representan cadenas de texto personalizables en hardware de panel de cristal líquido compacto.

Hardware del módulo LCD de caracteres HD44780

La variante de módulo analizada dentro de este material logra una adopción generalizada en el mundo real debido a su bajo costo unitario y su conjunto integral de características, construido alrededor del chip controlador integrado HD44780 de Hitachi. Este panel estándar admite dos filas de display independientes con dieciséis posiciones de caracteres por fila, representando conjuntos completos de caracteres del alfabeto latino, símbolos del alfabeto griego, signos de puntuación, operadores matemáticos y glifos suplementarios. Los símbolos gráficos personalizados definidos por el usuario de 5×8 píxeles también pueden almacenarse y mostrarse. La funcionalidad nativa adicional incluye desplazamiento automático de texto izquierda/derecha, indicadores de cursor visibles configurables y hardware de retroiluminación LED integrado.

Definición del pinout externo del LCD

Una fila de pines de encabezado recorre un borde de la placa de circuito impreso del LCD para facilitar las conexiones de cableado con el microcontrolador. El módulo base incorpora catorce pines de señal numerados; las variantes con hardware de retroiluminación integrado añaden dos pines de alimentación suplementarios para un total de dieciséis. Las especificaciones funcionales completas de los pines se listan dentro de la tabla siguiente:

Propósito de la señal Número de pin Etiqueta de señal Estado de nivel lógico Descripción funcional
Referencia de tierra 1 Vss - Riel de tierra del sistema 0V
Fuente de alimentación principal 2 Vdd - Tensión de alimentación lógica +5V
Ajuste de contraste 3 Vee - Rango de tensión 0V a Vdd para la sintonización del contraste LCD
Señales de control de operación 4 RS 0
1
Los pines D0–D7 se interpretan como palabras de comando del controlador
Los pines D0–D7 se interpretan como bytes de datos de caracteres de display
5 R/W 0
1
Operación de escritura: el MCU transmite datos al módulo LCD
Operación de lectura: el módulo LCD emite estado/datos al MCU
6 E 0
1
Flanco descendente 1→0
Acceso al registro LCD deshabilitado
Estado operativo en espera
Fijar los valores de comando/datos en el núcleo del controlador LCD
Líneas de bus de datos y comandos 7 D0 0/1 Bit de datos 0 (bit menos significativo)
8 D1 0/1 Bit de datos 1
9 D2 0/1 Bit de datos 2
10 D3 0/1 Bit de datos 3
11 D4 0/1 Bit de datos 4
12 D5 0/1 Bit de datos 5
13 D6 0/1 Bit de datos 6
14 D7 0/1 Bit de datos 7 (bit más significativo)

Disposición de píxeles del panel LCD

Disposición de la matriz de píxeles de puntos de caracteres LCD

El hardware del panel de display LCD consiste en dos filas de caracteres independientes, cada una con dieciséis posiciones de caracteres individuales. Cada celda de carácter se implementa como una rejilla de píxeles de matriz de puntos de 5×8 u opcionalmente 5×11; este material de referencia se centra exclusivamente en la variante estándar de la industria de matriz de caracteres de 5×8.

Los niveles de contraste del display dependen de la tensión del riel de alimentación y de la configuración de display de fila única/doble. Por esta razón, se aplica una señal de tensión variable entre 0V y Vdd al pin de sintonización de contraste Vee, típicamente controlada mediante un potenciómetro trimmer. Muchos módulos LCD integran hardware de retroiluminación LED de color (emisión azul o verde). Al utilizar la funcionalidad de retroiluminación, debe cablearse un resistor limitador de corriente en serie con uno de los pines de alimentación de retroiluminación, siguiendo reglas de diseño de accionamiento idénticas aplicadas a los componentes LED discretos.

Diagrama de cableado de alimentación de retroiluminación LCD

Si no se representa ningún carácter de texto o todos los glifos mostrados aparecen tenues después del encendido, el primer paso de solución de problemas es calibrar el potenciómetro de ajuste de contraste para verificar la sintonización de tensión adecuada. Este procedimiento idéntico de solución de problemas se aplica si el modo operativo del display (representación de fila única / doble) se reconfigura en plena operación.

Arquitectura de partición de memoria interna del LCD

El controlador LCD integra tres particiones de memoria dedicadas distintas:

  • DDRAM: Memoria de Acceso Aleatorio de Datos de Display;
  • CGRAM: Memoria de Acceso Aleatorio del Generador de Caracteres; y
  • CGROM: Memoria de Solo Lectura del Generador de Caracteres.

Partición de RAM de datos de display DDRAM

El almacenamiento DDRAM contiene los valores de byte de caracteres ASCII programados para la representación en pantalla, con capacidad suficiente para almacenar ochenta bytes de caracteres totales. Las direcciones de memoria individuales mapean directamente a las posiciones discretas de celdas de caracteres en el panel LCD físico.

Mapa de direccionamiento de la memoria DDRAM LCD

La lógica operativa central es sencilla: configurar el controlador LCD para incrementar automáticamente las direcciones de memoria (desplazamiento de texto hacia la derecha), luego definir la dirección de memoria inicial para la cadena de texto objetivo (por ejemplo, la dirección hexadecimal 00).

Después de completar este paso de configuración, todos los bytes de caracteres transmitidos sobre el bus de datos D0–D7 se representan secuencialmente de izquierda a derecha en el orden de lectura estándar. Con la dirección base establecida en 00 hex, la representación de texto se inicia en la celda de carácter más a la izquierda de la fila superior del display. Si se transmiten más de dieciséis bytes de caracteres, todos los datos excedentes permanecen almacenados dentro de la memoria DRAM, sin embargo solo las dieciséis posiciones iniciales permanecen visibles en pantalla. Debe emitirse un comando dedicado de desplazamiento de display para desplazar los datos de caracteres ocultos hacia la ventana visible del panel. Funcionalmente, el panel LCD actúa como un visor fijo que se desliza horizontalmente sobre los contenidos de memoria DRAM estacionarios, creando el efecto visual de texto en desplazamiento a través de la superficie de la pantalla.

Cuando el indicador de cursor está habilitado, se representa en la posición de dirección DRAM actualmente activa. Después de escribir un byte de carácter en la dirección activa, el controlador incrementa automáticamente la dirección objetivo a la posición de celda de carácter subsiguiente.
Como memoria de acceso aleatorio volátil, todos los datos almacenados en DRAM se borran permanentemente al desconectar la fuente de alimentación.

Partición ROM del generador de caracteres CGROM

El banco de memoria de solo lectura CGROM almacena la tabla de consulta de glifos estándar precargada de fábrica que contiene cada símbolo de carácter soportado de forma nativa por el panel LCD, con cada glifo único asignado a una dirección de memoria estática fija.

Mapa de caracteres ASCII CGROM LCD

Los desplazamientos de dirección de memoria CGROM corresponden directamente a los valores de codificación ASCII estándar de caracteres. Cuando el firmware activo ejecuta una instrucción para transmitir el carácter 'P' al bus de datos LCD, el valor de byte binario 0101 0000 se afirma en las líneas de datos D0–D7. Este valor binario coincide con la codificación ASCII de la 'P' mayúscula, que el controlador LCD utiliza para indexar el banco de memoria CGROM y representar el glifo correspondiente almacenado en la dirección 0101 0000. Esta regla de mapeo se aplica universalmente a los caracteres del alfabeto latino mayúsculos y minúsculos, sin embargo no se aplica directamente a los dígitos numéricos decimales.

Como es visible en el diagrama de mapa de caracteres anterior, todos los desplazamientos de dirección de los dígitos decimales se desplazan hacia arriba por un valor de desplazamiento base de 48 relativo a su valor numérico: el dígito 0 mapea a la dirección 48, el dígito 1 mapea a la dirección 49, el dígito 2 mapea a la dirección 50, y así sucesivamente. En consecuencia, la lógica del firmware debe añadir la constante decimal 48 a cada byte de dígito numérico antes de la transmisión sobre el bus de datos LCD para una representación precisa de glifos.

Desde las arquitecturas informáticas tempranas hasta el hardware embebido moderno, los sistemas de procesamiento digital solo interpretan valores numéricos binarios y no pueden reconocer de forma nativa los caracteres alfabéticos legibles por humanos. Todos los datos intercambiados entre un microcontrolador y el hardware periférico externo existen en formato binario, incluso cuando los operadores humanos los interpretan visualmente como caracteres de texto; un teclado estándar sirve como una ilustración clara del mundo real de este principio. Cada carácter imprimible mapea a un patrón de bits binario fijo único. La codificación ASCII es un conjunto de caracteres estandarizado construido alrededor del alfabeto latino, definiendo una correlación directa uno a uno entre los símbolos gráficos imprimibles y sus representaciones numéricas binarias correspondientes.

Partición de RAM de caracteres personalizados CGRAM

Además de los glifos CGROM predefinidos de fábrica, el controlador LCD admite la representación de símbolos gráficos personalizados completamente definidos por el usuario dimensionados a la rejilla de caracteres de 5×8 píxeles mediante una partición de memoria CGRAM volátil dedicada de 64 bytes.

Los registros de memoria CGRAM tienen 8 bits de ancho, aunque solo se utilizan las cinco posiciones de bits menos significativas para el almacenamiento del patrón de píxeles. Un bit lógico alto (1) dentro de cada registro corresponde a un punto de píxel iluminado, mientras que ocho ubicaciones de memoria de registro secuenciales almacenan colectivamente el patrón de píxeles completo de un único glifo de carácter personalizado. El diagrama siguiente ilustra claramente este principio de mapeo de memoria:

Disposición de memoria de caracteres personalizados CGRAM LCD

Los patrones de glifos personalizados se inicializan típicamente al inicio del programa de firmware escribiendo patrones de bits lógicos 0 y 1 secuenciales en los registros de memoria CGRAM para construir la forma de la obra de arte de píxeles objetivo. Para representar en pantalla un glifo personalizado preconfigurado, el firmware solo necesita transmitir el valor de dirección base CGRAM correspondiente al controlador LCD. Tenga en cuenta que la primera columna de la tabla de consulta de caracteres CGROM no referencia direcciones estáticas CGROM sino que apunta a los índices de glifos CGRAM personalizados. Dentro de la lógica de ejemplo de esta referencia, transmitir el valor de índice 0 representa el primer glifo personalizado, el valor de índice 1 representa el segundo glifo personalizado, y así sucesivamente.

Referencia fundamental del conjunto de comandos del controlador LCD

Todos los bytes transmitidos al módulo LCD sobre el bus de datos D0–D7 se interpretan como códigos de operación de comando del controlador o bytes de datos de caracteres de display, determinados enteramente por el estado lógico del pin de selección de registro RS:

RS = 1 — Los bits del bus de datos D0–D7 representan valores de byte de caracteres ASCII dirigidos a la representación en pantalla. El controlador LCD indexa el mapa de glifos CGROM utilizando este valor de byte y representa el símbolo correspondiente en la posición de dirección DDRAM activa. La dirección DDRAM objetivo está preconfigurada antes de transmitir el byte de carácter o se incrementa automáticamente después de cada operación de escritura de carácter completada.

RS = 0 — Los bits del bus de datos D0–D7 representan códigos de operación del controlador estandarizados que configuran los modos operativos globales del display. Una tabla completa de todos los códigos de comando LCD reconocidos se lista a continuación:

Nombre del comando RS RW D7 D6 D5 D4 D3 D2 D1 D0 Tiempo de ejecución requerido
Limpiar el buffer completo del display 0 0 0 0 0 0 0 0 0 1 1.64ms
Retorno del cursor a la posición de inicio 0 0 0 0 0 0 0 0 1 No importa 1.64ms
Configuración de parámetros del modo de entrada 0 0 0 0 0 0 0 1 I/D S 40μs
Control de alimentación del display y el cursor 0 0 0 0 0 0 1 D U B 40μs
Comando de desplazamiento del cursor / display 0 0 0 0 0 1 D/C R/L No importa No importa 40μs
Conjunto de funciones de la interfaz de hardware 0 0 0 0 1 DL N F No importa No importa 40μs
Escribir la dirección base CGRAM objetivo 0 0 0 1 Desplazamiento de dirección CGRAM de 6 bits 40μs
Escribir la dirección base DDRAM objetivo 0 0 1 Desplazamiento de dirección DDRAM de 7 bits 40μs
Leer la bandera de ocupado (BF) y la dirección DDRAM actual 0 1 BF Dirección DDRAM activa de 7 bits N/A
Escribir byte de datos a CGRAM / DDRAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40μs
Leer byte de datos de CGRAM / DDRAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40μs
I/D 1 = Automatic address increment (+1)         R/L 1 = Shift display contents right
    0 = Automatic address decrement (-1)             0 = Shift display contents left
    
S 1 = Global display scrolling enabled           DL 1 = 8-bit parallel data bus interface
  0 = Global display scrolling disabled             0 = 4-bit split nibble data bus interface
  
D 1 = LCD panel display power active             N 1 = Dual-row character display mode
  0 = LCD panel display power disabled              0 = Single-row character display mode
  
U 1 = Blinking cursor indicator active           F 1 = 5×10 dot character glyph format
  0 = Static cursor indicator disabled              0 = 5×7 dot character glyph format
 
B 1 = Cursor blink animation enabled             D/C 1 = Shift full display buffer
  0 = Cursor blink animation disabled               0 = Shift only cursor position

Explicación del bit de estado de la bandera de ocupado

En relación con el pipeline de ejecución de instrucciones de alta velocidad del microcontrolador, el hardware del controlador LCD opera a velocidades de procesamiento drásticamente más bajas. Se implementó una bandera de señal de estado dedicada para señalar cuándo el controlador completa la ejecución de un comando pendiente y acepta nuevos bytes de datos de entrada. Esta señal de bandera de ocupado es legible a través del pin del bus de datos D7. Cuando el bit BF se limpia a lógico bajo (BF=0), el módulo LCD finaliza todo el procesamiento previo y está listo para recibir nuevos bytes de comando o datos de caracteres.

Topologías de cableado de la interfaz de hardware LCD

Existen dos estándares de cableado distintos para interconectar un módulo LCD con un microcontrolador: modo de bus completo de 8 bits y modo de bus de nibble dividido de 4 bits. El modo operativo objetivo se configura durante las rutinas de inicialización del firmware ejecutadas inmediatamente después del reinicio por encendido. El modo de 8 bits transmite bytes de datos completos de 8 bits a través del bus de datos completo D0–D7 siguiendo la lógica cubierta en las secciones anteriores. La motivación principal de diseño para implementar el modo de bus de 4 bits es la conservación de los pines de E/S de propósito general limitados del microcontrolador; solo se utilizan las cuatro líneas de datos de orden alto D4–D7 para la comunicación, mientras que D0–D3 pueden permanecer desconectadas. Cada byte de datos completo de 8 bits se divide en dos ciclos de transmisión secuenciales: los cuatro bits de nibble de orden alto se transmiten primero sobre D4–D7, seguidos de los cuatro bits de nibble de orden bajo. La secuencia de inicialización configura el controlador LCD para analizar y recombinar correctamente estas transmisiones de nibble divididas. Las operaciones de lectura de datos del módulo LCD rara vez se requieren, ya que el flujo de datos es predominantemente unidireccional del MCU al hardware LCD. Esto habilita una optimización común de ahorro de pines: conectar permanentemente el pin de control de lectura/escritura R/W a tierra. Esta modificación de hardware reduce el recuento requerido de pines de E/S en uno, sin embargo conlleva una compensación funcional: la bandera de estado de ocupado no puede sondearse, eliminando la capacidad de leer cualquier dato almacenado dentro de las particiones de memoria interna del LCD.

Esquema de cableado del microcontrolador LCD de 4 bits

Existe una solución de software sencilla para compensar el sondeo deshabilitado de la bandera de ocupado. Después de transmitir cualquier comando o byte de carácter al módulo LCD, el firmware debe insertar un intervalo de retardo fijo para permitir al controlador tiempo de procesamiento suficiente. Dado que la operación de comando LCD individual más lenta consume un máximo de aproximadamente 1.64ms, un retardo de software estandarizado de 2ms garantiza de manera confiable la finalización completa del comando antes de los ciclos de transmisión subsiguientes.

Inicialización del LCD

El módulo LCD limpia automáticamente todo el contenido de la pantalla al encenderse, un proceso que tarda aproximadamente 15 milisegundos en completarse. Una vez finalizado, el display entra en un estado listo operativo con un conjunto de parámetros operativos predeterminados preconfigurados como se lista a continuación:

  1. Buffer de pantalla completo limpio en blanco
  2. Modo de interfaz de hardware
    • DL = 1: comunicación de bus de datos paralelo de 8 bits habilitada
    • N = 0: modo de display de texto de línea única activo
    • F = 0: fuente de caracteres de matriz de puntos de 5 × 8 seleccionada
  3. Estados de control del display y el cursor
    • D = 0: salida de pantalla LCD deshabilitada
    • U = 0: cursor de texto parpadeante oculto
    • B = 0: animación de parpadeo del cursor deshabilitada
  4. Comportamiento de entrada de caracteres
    • ID = 1: la dirección de memoria DDRAM se auto-incrementa por 1 después de cada escritura de carácter
    • S = 0: desplazamiento automático horizontal de texto deshabilitado

La secuencia de reinicio automático por encendido incorporada funciona de manera confiable bajo la mayoría de las condiciones estándar de fuente de alimentación, sin embargo no es universalmente libre de fallas. Si la tensión de alimentación no alcanza su nivel nominal completo dentro de una ventana de encendido de 10 milisegundos, el controlador LCD se comportará erráticamente con salida de representación impredecible. Cuando el circuito de fuente de alimentación no puede satisfacer este requisito de rampa de tensión rápida, o la operación de display estable consistente es obligatoria para el producto, debe ejecutarse una secuencia de inicialización de software manual. Esta rutina de inicialización desencadena un reinicio completo del controlador interno para restaurar una funcionalidad de display estable y predecible.

Consulte el diagrama siguiente para el flujo de trabajo completo de inicialización de bus de 8 bits:

Diagrama de flujo de inicialización LCD de 8 bits

Esta repetición de tres transmisiones idénticas de comandos en secuencia no es un error tipográfico ni un error en el algoritmo.
La secuencia de inicialización envía intencionalmente el mismo comando de conjunto de funciones tres veces consecutivas.

El procedimiento estandarizado de inicialización de bus de 4 bits se muestra en el diagrama siguiente:

Diagrama de flujo de inicialización LCD de 4 bits

6.3 Ejemplos de aplicación práctica

El esquema de circuito mostrado a continuación sirve como la plataforma de hardware compartida para todos los programas de demostración subsiguientes:

Esquema del circuito de prueba de LED

Además de la circuitería de soporte central del microcontrolador, incluidos el oscilador de cristal con capacitores de carga y los componentes pasivos mínimos de reinicio, la placa cuenta con múltiples LEDs indicadores y un pulsador táctil. Estos periféricos proporcionan retroalimentación visible del estado en tiempo de ejecución para todos los ejemplos de firmware.

Todos los LEDs están cableados como indicadores de tipo sumidero: cada LED se ilumina cuando su pin GPIO correspondiente del microcontrolador se lleva al nivel lógico 0 (bajo).

Demostración de parpadeo de LED

El objetivo central de este ejemplo no es simplemente demostrar la operación básica del LED, sino ilustrar la velocidad rápida de ejecución de instrucciones nativas del microcontrolador. Para producir una conmutación de encendido-apagado del LED visible y perceptible por humanos, deben insertarse retardos de tiempo intencionales entre cada inversión de estado del pin. Esta demostración implementa una subrutina de retardo de software reutilizable llamada Delay. El bucle triple anidado mantiene la ejecución del programa durante aproximadamente 0.5 segundos decrementando continuamente los valores almacenados en los registros de propósito general R0, R1 y R2. Una vez que la subrutina de retardo regresa, el nivel lógico del pin de E/S objetivo se invierte, y el ciclo completo se repite indefinidamente...

;************************************************************************
;* PROGRAM NAME : Delay.ASM
;* DESCRIPTION: Toggles the LED connected to pin P1.0 using software delay loops
;************************************************************************
;BASIC ASSEMBLER DIRECTIVES
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK SEGMENT DEFINITION
        DSEG    AT    03FH
STACK_START:    DS    040H

;RESET INTERRUPT VECTOR
       CSEG     AT    0
       JMP      XRESET                  ; Jump to main reset entry point
       
       ORG      100H
       
XRESET: MOV     SP,#STACK_START         ; Initialize stack pointer address
        MOV     P1,#0FFh                ; Configure all Port 1 pins as high-impedance inputs

LOOP:
        CPL     P1.0                    ; Flip the logic state of pin P1.0
        LCALL   Delay                   ; Invoke software delay subroutine
        SJMP    LOOP                    ; Loop back to repeat LED toggle

Delay:
        MOV     R2,#20                  ; Outer loop count for ~500ms total delay
F02:    MOV     R1,#50                  ; Middle loop count for ~25ms per iteration
F01:    MOV     R0,#230                 ; Innermost single-cycle decrement loop
        DJNZ    R0,$
        DJNZ    R1,F01
        DJNZ    R2,F02

END                                     ; End of assembly source file

Demostración del temporizador watchdog

Este ejemplo demuestra la operación impropia del temporizador watchdog para mostrar los reinicios forzados del chip. El temporizador watchdog está configurado con un período nominal de desbordamiento de 1024 milisegundos, sin embargo la instrucción crítica de refresco del watchdog se omite deliberadamente del código. El temporizador siempre se desbordará y desencadenará un reinicio completo del microcontrolador. Ante el reinicio, todos los valores de registro se conservan, la ejecución del programa se reinicia desde la dirección del vector de reinicio, el valor almacenado en el registro R3 se incrementa en uno, y este valor binario se emite directamente al Puerto 1.

Los LEDs conectados muestran el valor del contador incremental en formato binario crudo...

;************************************************************************
;* PROGRAM NAME : WatchDog.ASM
;* DESCRIPTION : On watchdog timeout reset, increment counter R3 and output binary value to Port 1 LEDs
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES
$MOD53
$TITLE(WATCHDOG.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

WMCON     DATA    96H
WDTEN     EQU     00000001B        ; Bit mask to enable watchdog timer module
PERIOD    EQU     11000000B        ; Bit mask to set watchdog overflow period to 1024ms 

;RESET VECTOR DEFINITION
          CSEG    AT      0
          JMP     XRESET           ; Main program entry after hardware reset

          CSEG
          ORG     100H

XRESET:   ORL     WMCON,#PERIOD    ; Configure watchdog timer overflow interval
          ORL     WMCON,#WDTEN     ; Activate watchdog counter operation

          MOV     A,R3             ; Load counter value R3 into accumulator
          MOV     P1,A             ; Output accumulator binary state to Port 1 LEDs
          INC     R3               ; Increment counter register R3 by 1

LAB:      SJMP    LAB              ; Infinite idle loop with no watchdog refresh

          END                      ; End of assembly source file

Temporizador T0 operando en modo 1

El programa principal pasa casi todo el tiempo de ejecución dentro de un bucle de espera infinito esperando que el Temporizador T0 complete un ciclo completo de conteo de 16 bits. Cuando el temporizador se desborda, se dispara una señal de interrupción de hardware, activando la rutina de servicio de interrupción TIM0_ISR. Dentro de la ISR, un bit lógico bajo (0) almacenado en el acumulador se desplaza a la derecha una posición a través del Puerto 1. Esta demostración muestra visualmente la alta velocidad de procesamiento del microcontrolador, ya que cada desplazamiento de bit individual representa la finalización de 216 ¡pulsos de reloj de temporizador externos!

;************************************************************************
;* PROGRAM NAME : Tim0Mod1.ASM
;* DESCRIPTION: Rotates a logic low bit across Port 1 LEDs using Timer T0 in 16-bit Mode 1
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(TIM0MOD1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;VARIABLE STORAGE DECLARATIONS

;STACK MEMORY ALLOCATION

        DSEG     AT     03FH
STACK_START:     DS     040H

;INTERRUPT VECTOR TABLE
       CSEG      AT 0
       JMP       XRESET             ; Primary hardware reset vector

       ORG       00BH
       JMP       TIM0_ISR           ; Timer T0 overflow interrupt vector

       ORG       100H

XRESET: MOV      SP,#STACK_START    ; Initialize stack pointer register
       MOV       TMOD,#01H          ; Set Timer0 to 16-bit Mode 1 operation
       MOV       A,#0FFH
       MOV       P1,#0FFH
       SETB      TR0                ; Start Timer T0 counting
       MOV       IE,#082H           ; Global interrupt enable + Timer0 interrupt enable
       CLR       C                  ; Clear carry flag for bit rotation

LOOP1: SJMP      LOOP1              ; Idle infinite main loop

TIM0_ISR:        RRC     A          ; Rotate accumulator right through carry flag
                 MOV     P1,A       ; Write updated accumulator value to Port 1
                 RETI               ; Return from interrupt service routine

       END                          ; End of assembly source file

Temporizador T0 dividido (Modo 3)

Similar al ejemplo de temporizador previo, el programa principal reside en un bucle de espera continuo etiquetado LOOP1. Cuando el Temporizador T0 se configura en el Modo 3, su contador único de 16 bits se divide en dos temporizadores independientes de 8 bits TL0 y TL1, cada uno con su propio disparo de interrupción dedicado.

La primera interrupción se dispara cuando TL0 se desborda, ejecutando la rutina de servicio TIM0_ISR para rotar un bit lógico bajo a través de los LEDs del Puerto 1, creando el efecto visual de luces iluminadas desplazándose a través del puerto.

La segunda interrupción se dispara con el desbordamiento de TL1, ejecutando TIM1_ISR para invertir el bit de estado DIRECTION. Este bit controla la dirección de rotación izquierda/derecha del patrón de bits LED, por lo que invertirlo revierte el movimiento de desplazamiento de las luces indicadoras.
Si se presiona el pulsador táctil conectado al pin P3.2, el nivel lógico bajo en este pin detiene la operación de conteo del Temporizador T1.

;************************************************************************
;* PROGRAM NAME : Split.ASM
;* DESCRIPTION: TL0 shifts LED bits on Port P1, TL1 controls rotation direction. Both timers run in Mode 3 split operation. Logic low on P3.2 disables Port 1 bit rotation.
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(SPLIT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;BIT VARIABLE MEMORY AREA

        BSEG    AT    0

;BIT FLAG DEFINITIONS

SEMAPHORE:      DBIT    8
DIRECTION       BIT     SEMAPHORE

;STACK SEGMENT DEFINITION
        DSEG    AT    03FH
STACK_START:    DS    040H

;INTERRUPT VECTOR TABLE

        CSEG    AT    0
        JMP     XRESET                    ; Hardware reset entry point
        ORG     00BH

        JMP     TIM0_ISR                  ; TL0 overflow interrupt vector

        ORG     01BH
        JMP     TIM1_ISR                  ; TL1 overflow interrupt vector

        ORG     100H
XRESET: MOV     SP,#STACK_START           ; Initialize stack pointer
        MOV     TMOD,#00001011B           ; Configure Timer0 to Mode 3 split dual 8-bit timers
        MOV     A,#0FFH
        MOV     P1,#0FFH
        MOV     R0,#30D
        SETB    TR0                       ; Enable TL0 counter operation
        SETB    TR1                       ; Enable TL1 counter operation
        MOV     IE,#08AH                  ; Enable global, Timer0 and Timer1 interrupts
        CLR     C
        CLR     DIRECTION                 ; Set initial bit rotation direction to right

LOOP1:  SJMP    LOOP1                     ; Main idle loop

TIM0_ISR:
        DJNZ    R0,LAB3                   ; Slow down LED rotation refresh rate
        JB      DIRECTION,LAB1
        RRC     A                         ; Rotate accumulator contents right via carry flag

        SJMP    LAB2
LAB1:   RLC     A                         ; Rotate accumulator contents left via carry flag
LAB2:   MOV     P1,A                      ; Output rotated bit pattern to Port 1 LEDs
LAB3:   RETI                              ; Exit interrupt service routine

TIM1_ISR:
        DJNZ    R1,LAB4                   ; Delay direction toggle timing
        DJNZ    R2,LAB4                   ; Set hold time before reversing scroll direction
        CPL     DIRECTION                 ; Flip rotation direction flag
        MOV     R2,#30D
LAB4:   RETI

        END                               ; End of assembly source file

Temporizadores duales concurrentes T0 y T1

Este programa se basa en la lógica de la demostración del temporizador dividido. El concepto central permanece idéntico, pero esta implementación usa dos temporizadores de hardware de 16 bits totalmente independientes T0 y T1 en lugar de contadores divididos de 8 bits dentro de un módulo de temporizador. Para demostrar la operación paralela simultánea de temporizadores en un solo puerto de E/S, los eventos de desbordamiento del Temporizador T0 manejan el desplazamiento del patrón de bits lógico bajo a través de los LEDs del Puerto 1, mientras que los eventos de desbordamiento del Temporizador T1 conmutan la bandera de dirección de desplazamiento. El firmware pasa casi todo el tiempo de ejecución dentro del bucle de espera LOOP1, esperando disparos de interrupción de hardware. Al leer el bit de bandera DIRECTION, las ISR determinan si desplazar el patrón de bits del acumulador a la izquierda o a la derecha, cambiando la dirección del movimiento visual de los LEDs del puerto.

;************************************************************************
;* PROGRAM NAME : Tim0Tim1.ASM
;* DESCRIPTION: Timer0 shifts bit pattern on Port P1, Timer1 toggles rotation direction. Both timers configured for 16-bit Mode 1.
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(TIM0TIM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;BIT VARIABLE MEMORY AREA

       BSEG    AT    0

;BIT FLAG DEFINITIONS

SEMAPHORE:      DBIT    8
DIRECTION       BIT     SEMAPHORE

;STACK SEGMENT ALLOCATION
       DSEG    AT    03FH
STACK_START:   DS    040H

;INTERRUPT VECTOR TABLE
       CSEG    AT    0
       JMP     XRESET                     ; Hardware reset entry point

       ORG     00BH                       ; Timer 0 overflow interrupt vector
       JMP     TIM0_ISR

       ORG     01BH                       ; Timer 1 overflow interrupt vector
       JMP     TIM1_ISR

       ORG     100H


XRESET: MOV    SP,#STACK_START            ; Initialize stack pointer register
        MOV    TMOD,#11H                  ; Set both Timer0 and Timer1 to 16-bit Mode 1
        MOV    A,#0FFH
        MOV    P1,#0FFH
        MOV    R0,#30D                    ; Initialize timing delay counter
        SETB   TR0                        ; Start Timer0 counting
        SETB   TR1                        ; Start Timer1 counting
        MOV    IE,#08AH                   ; Enable global, Timer0 and Timer1 interrupts
        CLR    C
        CLR    DIRECTION                  ; Set initial bit rotation to right

LOOP1:  SJMP   LOOP1                      ; Main idle infinite loop


TIM0_ISR:
        JB     DIRECTION,LAB1
        RRC A                             ; Rotate accumulator right through carry flag
        SJMP   LAB2
LAB1:   RLC    A                          ; Rotate accumulator left through carry flag
LAB2:   MOV    P1,A                       ; Write updated bit pattern to Port 1 LEDs
        RETI                              ; Return from interrupt

TIM1_ISR:
        DJNZ   R0,LAB3                    ; Hold delay before reversing scroll direction
        CPL    DIRECTION                  ; Toggle rotation direction flag
        MOV    R0,#30D                    ; Reload delay counter value
LAB3:
        RETI
        END                               ; End of assembly source file

Demostración del modo de recarga automática del Temporizador T2

Este ejemplo ilustra el Temporizador T2 configurado en modo de conteo de recarga automática de hardware. Los LEDs indicadores están conectados al Puerto P3, mientras que un pulsador de disparo manual para el reinicio forzado del temporizador (T2EX) se conecta al pin P1.1.

El flujo de ejecución del programa refleja los ejemplos de temporizador previos. Cuando el Temporizador T2 completa su ciclo completo de conteo, se genera una solicitud de interrupción, ejecutando la rutina de servicio TIM2_ISR. Dentro de la ISR, un bit lógico bajo rota dentro del registro acumulador, y el valor actualizado del acumulador se emite a los LEDs indicadores del Puerto 3. Las banderas de estado de interrupción TF2 y EXF2 se limpian para reconocer la interrupción, y el programa regresa al estado de espera LOOP1 para esperar la próxima solicitud de interrupción de desbordamiento del temporizador...

Presionar el pulsador T2EX desencadena un reinicio de hardware inmediato del contador del Temporizador T2. Esta entrada T2EX dedicada solo reinicia el Temporizador T2, mientras que el pulsador de REINICIO principal separado realiza un reinicio completo global del chip del microcontrolador.

Diagrama del circuito de hardware del Temporizador T2
;************************************************************************
;* PROGRAM NAME : Timer2.ASM
;* DESCRIPTION: Rotates a logic low bit across Port P3 LEDs. Timer T2 controls scroll speed and operates in auto-reload counting mode
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(TIMER2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;REGISTER ADDRESS DEFINITION
        T2MOD    DATA     0C9H
;STACK MEMORY ALLOCATION
        DSEG     AT       03FH
STACK_START:     DS       040H

;INTERRUPT VECTOR TABLE
        CSEG     AT       0
        JMP      XRESET                   ; Hardware reset entry point

        ORG      02BH                     ; Timer T2 overflow interrupt vector
        JMP      TIM2_ISR

        ORG      100H

XRESET: MOV      SP,#STACK_START          ; Initialize stack pointer register
        MOV      A,#0FFH
        MOV      P3,#0FFH
        MOV      RCAP2L,#0FH              ; Set low byte of 16-bit auto-reload capture register
        MOV      RCAP2H,#01H              ; Set high byte of 16-bit auto-reload capture register
        CLR      CAP2                     ; Disable capture mode, enable auto-reload operation
        SETB     EXEN2                    ; Enable T2EX pin external timer reset function
        SETB     TR2                      ; Start Timer T2 counting sequence
        MOV      IE,#0A0H                 ; Enable Timer T2 interrupt requests
        CLR      C

LOOP1:  SJMP     LOOP1                    ; Main idle wait loop

TIM2_ISR:        RRC      A               ; Rotate accumulator contents right through carry flag
                 MOV      P3,A            ; Output accumulator bit pattern to Port 3 LEDs
                 CLR      TF2             ; Clear Timer T2 overflow flag TF2
                 CLR      EXF2            ; Clear T2EX external trigger flag EXF2
                 RETI                     ; Exit interrupt service routine

                 END                      ; End of assembly source file

Demostración de interrupción externa de hardware

Esta sección cubre otro ejemplo de firmware impulsado por interrupciones. Las señales de interrupción externa de hardware se disparan cuando se aplica un nivel lógico bajo al pin de entrada P3.2 (INT0) o P3.3 (INT1). El pin de entrada activo determina qué rutina de servicio de interrupción correspondiente se ejecuta:

Una señal lógica baja en P3.2 activa la rutina de interrupción Isr_Int0, incrementando el valor del contador almacenado en el registro R0 y copiando este valor de conteo binario a los LEDs de salida del Puerto 0. Una señal lógica baja en P3.3 dispara la rutina Isr_Int1, incrementando el registro R1 y escribiendo su valor a los LEDs del Puerto 1.

En resumen, cada presión física del pulsador INT0 o INT1 incrementa su respectivo contador, con el valor de conteo en vivo mostrado en formato binario en los LEDs del puerto correspondiente (un LED iluminado representa el nivel lógico 0).

Esquema del circuito de hardware de interrupción externa
;************************************************************************
;* PROGRAM NAME : Int.ASM
;* DESCRIPTION : Counts INT0 interrupts triggered by falling edge signal on P3.2, output count to Port 0 LEDs. Simultaneously counts INT1 falling-edge interrupts on P3.3 with results displayed on Port 1 LEDs.
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(INT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;INTERRUPT VECTOR TABLE

        CSEG     AT     0
        JMP      XRESET               ; Primary hardware reset vector

        ORG      003H                 ; INT0 external interrupt service vector address
        JMP      Isr_Int0
        ORG 013H                      ; INT1 external interrupt service vector address
        JMP      Isr_Int1

        ORG      100H
XRESET:
        MOV      TCON,#00000101B      ; Configure INT0 and INT1 to trigger on falling edge signal transitions
        MOV      IE,#10000101B        ; Enable global interrupt flag plus INT0 and INT1 interrupts
        MOV      R0,#00H              ; Initialize INT0 counter starting value to zero
        MOV      R1,#00H
        MOV      P0,#00H              ; Clear all Port 0 LED outputs
        MOV      P1,#00H              ; Clear all Port 1 LED outputs

LOOP:   SJMP     LOOP                 ; Main idle waiting loop

Isr_Int0:
        INC R0                        ; Increment INT0 event counter register
        MOV P0,R0                     ; Write counter binary value to Port 0 LEDs
        RETI

Isr_Int1:
        INC R1                        ; Increment INT1 event counter register
        MOV P1,R1                     ; Write counter binary value to Port 1 LEDs
        RETI
        END                           ; End of assembly source file

Descripción general del sistema de display LED de 7 segmentos

El siguiente conjunto de demostraciones cubre la operación de displays LED de 7 segmentos de múltiples dígitos. Todo el hardware usa módulos de display de cátodo común, lo que significa que el terminal de ánodo de cada LED de segmento se conecta directamente a los pines GPIO del microcontrolador. La lógica intuitiva estándar define el nivel lógico 1 como un estado activo "encendido" y el nivel lógico 0 como un estado inactivo "apagado". Para las variantes de display de baja corriente y bajo consumo, cada LED de segmento se cablea en serie con un resistor limitador de corriente de valor moderadamente alto.

Para minimizar el consumo de los pines de E/S limitados del microcontrolador, cuatro displays de dígitos individuales se cablean para operación multiplexada por división de tiempo. Todos los segmentos que comparten etiquetas idénticas se conectan a un solo puerto de salida compartido, y solo un display de dígitos está habilitado e iluminado en cualquier momento individual.

Los transistores de habilitación de dígitos y los segmentos del display conmutan a una tasa de refresco rápida, creando la ilusión visual de persistencia de que todos los dígitos numéricos se iluminan simultáneamente.

Esquema del circuito LED multiplexado de 7 segmentos de 4 dígitos

Salida de dígito estático único en display de 7 segmentos

Este firmware introductorio sirve como un ejercicio básico de calentamiento para trabajar con displays de segmentos. El objetivo central es representar un dígito numérico estático en una sola unidad de display; la lógica de multiplexación no se implementa aquí. El valor de dígito 3 está codificado en duro para mostrarse exclusivamente en la posición de dígito más a la derecha.

El microcontrolador no tiene comprensión nativa incorporada de las formas de dígitos decimales legibles por humanos, que se representan en binario crudo como simples valores de 8 bits (el número 3 se almacena como binario 0000 0011). Una subrutina de consulta dedicada llamada Disp convierte los valores numéricos crudos en los patrones de máscara de bits de activación de segmentos correspondientes requeridos para la representación visual de dígitos. El principio de operación es sencillo: añadir el valor del dígito de entrada a la dirección del contador de programa para realizar un salto de tabla, donde cada ubicación de memoria almacena una combinación de bits única precomputada para los dígitos del 0 al 9. Emitir este valor de máscara de bits al puerto de segmentos ilumina los segmentos correctos para formar la forma del dígito objetivo en el display.

;************************************************************************
;* PROGRAM NAME : 7Seg1.ASM
;* DESCRIPTION: Displays static digit "3" on a single 7-segment common cathode LED display
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(7SEG1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK SEGMENT ALLOCATION
          DSEG     AT     03FH
STACK_START:       DS     040H

;RESET VECTOR DEFINITION
          CSEG     AT     0
          JMP      XRESET               ; Hardware reset entry point

          ORG      100H

XRESET:   MOV      SP,#STACK_START      ; Initialize stack pointer register
          MOV      P1,#0                ; Clear all segment output pins to turn off all LEDs
          MOV      P3,#20h              ; Activate the rightmost digit display D4

LOOP:
          MOV      A,#03                ; Load target digit value 3 into accumulator
          LCALL    Disp                 ; Call segment mask lookup subroutine
          MOV      P1,A                 ; Output digit bitmask to segment port P1
          SJMP     LOOP                 ; Infinite static display loop

Disp:                                   ; Digit-to-segment bitmask lookup subroutine
          INC      A
          MOVC     A,@A+PC
          RET
          DB       3FH                  ; Segment mask for digit 0
          DB       06H                  ; Segment mask for digit 1
          DB       5BH                  ; Segment mask for digit 2
          DB       4FH                  ; Segment mask for digit 3
          DB       66H                  ; Segment mask for digit 4
          DB       6DH                  ; Segment mask for digit 5
          DB       7DH                  ; Segment mask for digit 6
          DB       07H                  ; Segment mask for digit 7
          DB       7FH                  ; Segment mask for digit 8
          DB       6FH                  ; Segment mask for digit 9
          END                           ; End of assembly source file

Display de dígitos de conteo secuencial (dígito estático único)

Este programa extiende la funcionalidad de la demostración previa de dígito único, aún utilizando solo la posición de display más a la derecha sin lógica de multiplexación. A diferencia del ejemplo anterior, este firmware cicla secuencialmente a través de todos los dígitos decimales del 0 al 9. Una subrutina corta de retardo de software L2 se ejecuta entre cada actualización de dígito para reducir la velocidad de conteo a un ritmo legible por humanos. La secuencia completa se ejecuta continuamente dentro del bucle principal etiquetado LOOP siguiendo estos pasos definidos:

  1. Copiar el valor del contador almacenado en el registro R3 al acumulador y ejecutar la subrutina de consulta de máscara de dígitos Disp;
  2. Escribir la máscara de bits de segmentos convertida del acumulador al puerto de salida de segmentos para representar el dígito;
  3. Incrementar el valor del contador contenido en el registro R3;
  4. Verificar si el contador ha alcanzado 10; si es verdadero, reiniciar el registro R3 a cero para reiniciar el ciclo de conteo desde 0;
  5. Ejecutar la subrutina de retardo etiquetada L2 para mantener el dígito en pantalla durante una duración fija.
;************************************************************************
;* PROGRAM NAME: 7Seg2.ASM
;* DESCRIPTION: Sequentially counts and displays all digits 0 through 9 on a single static 7-segment display
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(7SEG2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK MEMORY ALLOCATION
         DSEG     AT     03FH
STACK_START:      DS     040H

;RESET INTERRUPT VECTOR
         CSEG     AT     0
         JMP      XRESET                   ; Hardware reset entry point

         ORG      100H

XRESET:  MOV      SP,#STACK_START          ; Initialize stack pointer register
         MOV      R3,#0                    ; Initialize digit counter starting at 0
         MOV      P1,#0                    ; Clear all segment output pins
         MOV      P3,#20h                  ; Enable rightmost digit display D4

LOOP:
         MOV      A,R3
         LCALL    Disp                     ; Convert raw counter value to segment bitmask
         MOV      P1,A                     ; Output bitmask to segment port
         INC      R3                       ; Advance counter value by one
         CJNE     R3,#10,L2                ; Skip counter reset if value not equal to 10
         MOV      R3,#0                    ; Reset counter to zero after reaching digit 9
L2:
         MOV      R2,#20                   ; Outer loop count for ~500ms display hold delay
F02:     MOV      R1,#50                   ; Middle loop ~25ms iteration delay
F01:     MOV      R0,#230
         DJNZ     R0,$
         DJNZ     R1,F01
         DJNZ     R2,F02
         SJMP     LOOP                     ; Return to main counting loop

Disp:                                      ; Digit segment bitmask lookup subroutine
         INC      A
         MOVC     A,@A+PC
         RET
         DB       3FH                      ; Digit 0 segment mask
         DB       06H                      ; Digit 1 segment mask
         DB       5BH                      ; Digit 2 segment mask
         DB       4FH                      ; Digit 3 segment mask
         DB       66H                      ; Digit 4 segment mask
         DB       6DH                      ; Digit 5 segment mask
         DB       7DH                      ; Digit 6 segment mask
         DB       07H                      ; Digit 7 segment mask
         DB       7FH                      ; Digit 8 segment mask
         DB       6FH                      ; Digit 9 segment mask

         END                               ; End of assembly source file

Display de número estático multiplexado de dos dígitos

Este ejemplo introduce la multiplexación por división de tiempo para displays de múltiples dígitos, la implementación más básica que representa el valor fijo de dos dígitos 23 en posiciones separadas de decenas y unidades. La sincronización precisa de temporización es el requisito central crítico para una salida multiplexada sin parpadeo; toda la demás lógica permanece sencilla. El transistor T4 habilita el display de unidades D4 mientras el patrón de máscara de bits correspondiente para el dígito 3 se emite al puerto de segmentos. El transistor de habilitación de dígitos luego se deshabilita, y el proceso se repite con el transistor T3 activando el display de decenas D3 para representar el dígito 2. Esta secuencia completa se repite continuamente a alta velocidad de refresco para crear la ilusión visual de que ambos dígitos están iluminados simultáneamente.

;************************************************************************
;* PROGRAM NAME: 7Seg3.ASM
;* DESCRIPTION: Multiplexed two-digit static display showing fixed number "23" on dual 7-segment modules
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(7SEG3.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK SEGMENT ALLOCATION
         DSEG      AT      03FH
STACK_START:       DS      040H

;RESET VECTOR DEFINITION
         CSEG      AT      0
         JMP       XRESET                    ; Hardware reset entry point

         ORG       100H
XRESET:  MOV       SP,#STACK_START           ; Initialize stack pointer register

LOOP:    MOV       P1,#0                     ; Blank all segment outputs before digit switching
         MOV       P3,#20h                   ; Activate units digit display D4
         MOV       A,#03                     ; Load digit value 3 for units position
         LCALL     Disp                      ; Retrieve matching segment bitmask
         MOV       P1,A                      ; Write bitmask to segment port P1
         MOV       P1,#0                     ; Clear segments before switching digit
         MOV       P3,#10h                   ; Activate tens digit display D3
         MOV       A,#02                     ; Load digit value 2 for tens position
         LCALL     Disp                      ; Retrieve matching segment bitmask
         MOV       P1,A                      ; Write bitmask to segment port P1
         SJMP      LOOP                      ; Restart multiplex refresh cycle

Disp:                                        ; Digit segment bitmask lookup subroutine
         INC       A
         MOVC      A,@A+PC
         RET
         DB        3FH                       ; Digit 0 segment mask
         DB        06H                       ; Digit 1 segment mask
         DB        5BH                       ; Digit 2 segment mask
         DB        4FH                       ; Digit 3 segment mask
         DB        66H                       ; Digit 4 segment mask
         DB        6DH                       ; Digit 5 segment mask
         DB        7DH                       ; Digit 6 segment mask
         DB        07H                       ; Digit 7 segment mask
         DB        7FH                       ; Digit 8 segment mask
         DB        6FH                       ; Digit 9 segment mask

         END                                 ; End of assembly source file

Display de valor estático multiplexado de cuatro dígitos

Esta demostración expande la lógica de multiplexación para utilizar las cuatro posiciones de dígitos disponibles, soportando valores numéricos que van de 0000 hasta 9999. El valor estático codificado en duro 1234 se representa a través de los cuatro módulos de display. Después de inicializar el puntero de pila, el firmware entra en el ciclo continuo de refresco LOOP para ejecutar la multiplexación por división de tiempo. La subrutina de consulta compartida Disp convierte los valores binarios de dígito único crudos en los patrones de activación de segmentos correspondientes requeridos para iluminar los segmentos de display correctos.

;************************************************************************
;* PROGRAM NAME : 7Seg5.ASM
;* DESCRIPTION : Multiplexed four-digit static display rendering fixed number "1234" on four 7-segment LED modules
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(7SEG5.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK MEMORY ALLOCATION
         DSEG     AT     03FH
STACK_START:      DS     040H

;RESET VECTOR DEFINITION
         CSEG     AT     0
         JMP      XRESET                  ; Hardware reset entry point

         ORG      100H

XRESET:  MOV      SP,#STACK_START         ; Initialize stack pointer register

LOOP:    MOV      P1,#0                   ; Blank all segment outputs
         MOV      P3,#20h                 ; Activate thousands digit display D4
         MOV      A,#04                   ; Load digit value 4 for thousands place
         LCALL    Disp                    ; Fetch segment bitmask for digit 4
         MOV      P1,A                    ; Output bitmask to segment port
         MOV      P1,#0                   ; Clear segments before next digit switch
         MOV      P3,#10h                 ; Activate hundreds digit display D3
         MOV      A,#03                   ; Load digit value 3 for hundreds place
         LCALL    Disp                    ; Fetch segment bitmask for digit 3
         MOV      P1,A                    ; Output bitmask to segment port
         MOV      P1,#0                   ; Blank segment outputs
         MOV      P3,#08h                 ; Activate tens digit display D2
         MOV      A,#02                   ; Load digit value 2 for tens place
         LCALL    Disp                    ; Fetch segment bitmask for digit 2
         MOV      P1,A                    ; Output bitmask to segment port
         MOV      P1,#0                   ; Blank segment outputs
         MOV      P3,#04h                 ; Activate units digit display D1
         MOV      A,#01                   ; Load digit value 1 for units place
         LCALL    Disp                    ; Fetch segment bitmask for digit 1
         MOV      P1,A                    ; Output bitmask to segment port
         SJMP     LOOP                    ; Restart full four-digit multiplex refresh cycle

Disp:                                     ; Digit segment bitmask lookup subroutine
         INC      A
         MOVC     A,@A+PC
         RET
         DB       3FH                     ; Digit 0 segment mask
         DB       06H                     ; Digit 1 segment mask
         DB       5BH                     ; Digit 2 segment mask
         DB       4FH                     ; Digit 3 segment mask
         DB       66H                     ; Digit 4 segment mask
         DB       6DH                     ; Digit 5 segment mask
         DB       7DH                     ; Digit 6 segment mask
         DB       07H                     ; Digit 7 segment mask
         DB       7FH                     ; Digit 8 segment mask
         DB       6FH                     ; Digit 9 segment mask

         END ; End of assembly source file

Contador incremental multiplexado de dos dígitos

Esta demostración combina la lógica de display multiplexado de múltiples dígitos con la funcionalidad de conteo incremental en vivo para un comportamiento embebido más complejo. Los registros R2 (contador de dígito de unidades) y R3 (contador de dígito de decenas) se incrementan continuamente para generar una secuencia de conteo de dos dígitos rotatoria (97, 98, 99, 00, 01, 02...).

Los transistores de habilitación de dígitos activan cada display durante una duración fija de 25 milisegundos controlada por la subrutina Delay. Incluso con este tiempo de retención visible por dígito, el refresco multiplexado rápido crea la ilusión de iluminación simultánea. Después de completar 20 ciclos completos de refresco de dos dígitos, el valor del contador numérico se incrementa en uno, y la secuencia completa de multiplexación se repite indefinidamente.

;************************************************************************
;* PROGRAM NAME : 7Seg4.ASM
;* DESCRIPTION: Multiplexed dual 7-segment display running continuous two-digit counter from 00 to 99
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(7SEG4.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK SEGMENT ALLOCATION
         DSEG      AT      03FH
STACK_START:       DS      040H

;RESET VECTOR DEFINITION
         CSEG      AT      0
         JMP       XRESET                   ; Hardware reset entry point

         ORG       100H

XRESET:  MOV       SP,#STACK_START          ; Initialize stack pointer register
         MOV       R2,#0                    ; Initialize units digit counter to 0
         MOV       R3,#0                    ; Initialize tens digit counter to 0
         MOV       R4,#0                    ; Multiplex refresh cycle counter

LOOP:    INC       R4                       ; Count full two-digit refresh cycles
         CJNE      R4,#20d,LAB1             ; Hold counter increment until 20 full refreshes complete
         MOV       R4,#0
         MOV       P1,#0                    ; Blank all segment outputs
         INC       R2                       ; Advance units digit counter
         CJNE      R2,#10d,LAB1
         MOV       R2,#0                    ; Reset units digit after reaching 9
         INC       R3                       ; Increment tens digit register
         CJNE      R3,#10d,LAB1
         MOV       R3,#0                    ; Reset tens digit after reaching 9

LAB1:
         MOV       P3,#20h                  ; Enable units digit display D4
         MOV       A,R2                     ; Load units counter value into accumulator
         LCALL     Disp                     ; Convert digit to segment bitmask
         MOV       P1,A                     ; Render units digit on display D4
         LCALL     Delay                    ; 25ms hold delay for visual persistence
         MOV       P1,#0                    ; Blank segment outputs before digit switch
         MOV       P3,#10h                  ; Enable tens digit display D3
         MOV       A,R3                     ; Load tens counter value into accumulator
         LCALL     Disp                     ; Convert digit to segment bitmask
         MOV       P1,A                     ; Render tens digit on display D3
         LCALL     Delay                    ; 25ms hold delay
         SJMP      LOOP                     ; Restart multiplex refresh cycle

Delay:
         MOV       R1,#50                   ; Outer loop for ~5ms base delay
F01:     MOV       R0,#250
         DJNZ      R0,$
         DJNZ      R1,F01
         RET

Disp:                                       ; Digit segment bitmask lookup subroutine
         INC       A
         MOVC      A,@A+PC
         RET
         DB        3FH                      ; Digit 0 segment mask
         DB        06H                      ; Digit 1 segment mask
         DB        5BH                      ; Digit 2 segment mask
         DB        4FH                      ; Digit 3 segment mask
         DB        66H                      ; Digit 4 segment mask
         DB        6DH                      ; Digit 5 segment mask
         DB        7DH                      ; Digit 6 segment mask
         DB        07H                      ; Digit 7 segment mask
         DB        7FH                      ; Digit 8 segment mask
         DB        6FH                      ; Digit 9 segment mask

         END                                ; End of assembly source file

Manejo de EEPROM

Este programa escribe datos en la memoria EEPROM incorporada en el chip. En esta demostración, el valor de datos objetivo es hexadecimal 0x23, que se almacenará en la dirección de memoria EEPROM 0x0000.

A continuación se muestra una lista completa de todos los números de pieza del microcontrolador Atmel 8051:

### Serie Flash estándar (AT89C/S)

- AT89C1051 - AT89C1051U - AT89C2051 - AT89C4051 - AT89C51 - AT89C51AC3 - AT89C51CC03 - AT89C51ED2 - AT89C51IC2 - AT89C51ID2 - AT89C51IE2 - AT89C51RB2 - AT89C51RC - AT89C51RC2 - AT89C51RD2 - AT89C51RE2 - AT89C5115 - AT89C5130 - AT89C5130A - AT89C5131 - AT89C5131A - AT89C5132 - AT89C52 - AT89C55 - AT89S51 - AT89S52 - AT89S53 - AT89S8252

### Serie de baja tensión (AT89LV/LS)

- AT89LS51 - AT89LS52 - AT89LS53 - AT89LV51 - AT89LV52 - AT89LV55

### Serie OTP (programable una sola vez) (AT87F)

- AT87F51 - AT87F51RC - AT87F52 - AT87F55WD

### Serie sin ROM / de funciones especiales (AT83/AT80)

- AT83/87C5103 - AT83/87C5111 - AT83/87C5112 - AT83C5134 - AT83C5135 - AT83C5136 - AT83EB5114 - AT80C31X2 - AT80C51RD2 - AT8032X2

### Serie de bajo consumo / núcleo de ciclo único (AT89LP)

- AT89LP2051 - AT89LP2052 - AT89LP4052 - AT89LP51RB2 - AT89LP52 - AT89LP6440

### Otras series / legadas

- 80C32E - AT48801 - AT85C51SND3 - T80C31 - T80C31X2 - T80C32 - T80C51 - T80C51I2 - T80C51RA2 - T80C51RD2 - T83/87C51RB2 - T83/87C51RC2 - T83/87C51RD2 - T83/87C52X2 - T87C51 - T89C51RB2 - T89C51RC2

Para verificar que el valor de byte se escribió correctamente, el programa espera 10 milisegundos antes de leer de vuelta los datos de la dirección EEPROM idéntica y compara el valor recuperado contra el byte almacenado original. Si los dos valores coinciden, la máscara de segmentos del carácter "F" se emitirá al display LED para señalar la operación de escritura exitosa. Si hay una discrepancia, se mostrará en su lugar la máscara del carácter "E" (que representa una condición de error).

;************************************************************************
;* PROGRAM NAME: EEProm1.ASM
;* DESCRIPTION: Writes a byte to internal EEPROM address 0000h and validates data via readback, outputs status digit on LED segment display
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(EEPROM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

WMCON     DATA     96H
EEMEN     EQU      00001000B              ; Bit mask to enable internal EEPROM access
EEMWE     EQU      00010000B              ; Bit mask to enable EEPROM write operation
TEMP      DATA     030H                   ; Auxiliary general-purpose data register

WRITE_OK  EQU      071H                   ; Segment mask to display character "F" (Pass)
WRITE_ERR EQU      033H                   ; Segment mask to display character "E" (Error)

;STACK MEMORY ALLOCATION
          DSEG     AT     03FH
STACK_START:       DS     040H

;RESET INTERRUPT VECTOR TABLE
          CSEG     AT     0
          JMP      XRESET                 ; Main hardware reset entry point

          ORG      100H

XRESET:   MOV      IE,#00                 ; Disable all global interrupt sources
          MOV      SP,#STACK_START        ; Initialize stack pointer address

          MOV      DPTR,#0000H            ; Target EEPROM memory address 0000h
          ORL      WMCON,#EEMEN           ; Activate EEPROM read/write access control bit
          ORL      WMCON,#EEMWE           ; Enable EEPROM write permission
          MOV      TEMP,#23H              ; Load test byte value 0x23 into temporary register
          MOV      A,TEMP                 ; Copy test data into accumulator register
          MOVX     @DPTR,A                ; Perform byte write to EEPROM address
          CALL     DELAY                  ; Execute 10ms hold delay for EEPROM write cycle completion
          MOVX     A,@DPTR                ; Read back stored byte from the same EEPROM address
          CJNE     A,TEMP,ERROR           ; Compare readback value against original data; jump to error routine if mismatch detected
          MOV      A,#WRITE_OK            ; Load segment mask for pass status "F"
          MOV      P1,A                   ; Output mask to LED segment port P1
          XRL      WMCON,#EEMWE           ; Disable EEPROM write enable bit
          XRL      WMCON,#EEMEN           ; Disable EEPROM memory access entirely
LOOP1:    SJMP     LOOP1                  ; Infinite idle loop after successful write validation

ERROR:    MOV      A,#WRITE_ERR           ; Load segment mask for error status "E"
          MOV      P1,A                   ; Output error mask to LED segment port P1
LOOP2:    SJMP     LOOP2                  ; Infinite idle loop after write failure detection

DELAY:    MOV      A,#0AH                 ; Outer loop counter for ~10ms software delay
          MOV      R3,A
LOOP3:    NOP
LOOP4:    DJNZ     B,LOOP4                ; Inner empty decrement delay loop
LOOP5:    DJNZ     B,LOOP5
          DJNZ     R3,LOOP3
          RET

          END                             ; End of assembly source file

Recepción de datos UART

La comunicación serie UART estable debe cumplir con las especificaciones de señal eléctrica definidas por el estándar RS232, más críticamente las definiciones de nivel de tensión para los estados lógicos binarios. Bajo las reglas de señalización RS232, -10V representa el nivel lógico 1 (estado de marca), mientras que +10V representa el nivel lógico 0 (estado de espacio). El microcontrolador 8051 puede serializar bytes de datos paralelos en flujos de bits UART de forma nativa, sin embargo su lógica central opera en un dominio de suministro único de 5V. La conversión entre los niveles lógicos MCU de 0V/5V y los niveles de señalización RS232 de ±10V requiere hardware dedicado de cambio de nivel integrado en ambas rutas de señal de transmisión y recepción. Este diseño utiliza el IC transceptor MAX232 de Maxim Integrated, una solución ampliamente adoptada, de bajo costo y confiable para la traducción de tensión RS232.

Esta demostración ilustra la recepción de tramas de datos serie enviadas desde una PC de escritorio. El Temporizador T1 genera la señal de reloj precisa de velocidad en baudios para la operación UART. Aquí se usa un oscilador de cristal de cuarzo de 11.0592 MHz, que simplifica la generación precisa de la velocidad en baudios estándar común de 9600 baudios. Cada byte recibido a través del buffer de recepción UART se emite inmediatamente a los pines de E/S de propósito general del Puerto P1 para su observación visual mediante LEDs.

Recepción de datos mediante comunicación serie UART
;************************************************************************
;* PROGRAM NAME : UartR.ASM
;* DESCRIPTION: All bytes received over UART serial port from a PC are output directly to Port P1 LED indicators
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(UARTR.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK SEGMENT DEFINITION
         DSEG     AT     03FH
STACK_START:      DS     040H

;INTERRUPT VECTOR TABLE
         CSEG     AT     0
         JMP      XRESET                ; Primary hardware reset vector
         ORG      023H                  ; UART serial port interrupt service vector address
         JMP      IR_SER

         ORG      100H

XRESET:  MOV      IE,#00                ; Disable all interrupt sources at startup
         MOV      SP,#STACK_START       ; Initialize stack pointer register
         MOV      TMOD,#20H             ; Configure Timer1 for auto-reload Mode 2
         MOV      TH1,#0FDH             ; Auto-reload value for 9600 baud with 11.0592MHz crystal
         MOV      SCON,#50H             ; Enable UART receive mode, 8-bit data frame format
         MOV      IE,#10010000B         ; Enable global interrupt flag and UART receive interrupt
         CLR      TI                    ; Clear UART transmit complete flag
         CLR      RI                    ; Clear UART receive data ready flag
         SETB     TR1                   ; Start Timer1 baud rate generator counter

LOOP:    SJMP     LOOP                  ; Main infinite idle waiting loop

IR_SER:  JNB      RI,OUTPUT             ; Skip data handling if no new byte received
         MOV      A,SBUF                ; Copy received byte from UART data buffer into accumulator
         MOV      P1,A                  ; Write received byte value to Port P1 output pins
         CLR      RI                    ; Clear receive interrupt flag to acknowledge data read
OUTPUT:  RETI                           ; Return from UART interrupt service routine

         END                            ; End of assembly source file

Transmisión de datos UART

Este firmware demuestra cómo implementar la funcionalidad de transmisión de datos serie UART. El programa transmite continuamente valores de byte secuenciales que van de 0 a 255 a una PC conectada a una tasa fija de comunicación de 9600 baudios. Se utiliza un IC de cambio de nivel MAX232 para convertir los niveles lógicos nativos de 5V del MCU a la señalización de tensión RS232 estándar.

;************************************************************************
;* PROGRAM NAME : UartS.ASM
;* DESCRIPTION: Transmits all byte values 0 through 255 sequentially over UART to connected PC terminal
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(UARTS.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK MEMORY ALLOCATION
         DSEG    AT    03FH
STACK_START:     DS    040H

;RESET VECTOR DEFINITION
         CSEG    AT    0
         JMP     XRESET               ; Hardware reset entry vector

         ORG     100H

XRESET:  MOV     IE,#00               ; Disable all interrupts during initialization
         MOV     SP,#STACK_START      ; Configure stack pointer base address
         MOV     TMOD,#20H            ; Set Timer1 to auto-reload Mode 2 for baud rate generation
         MOV     TH1,#0FDH            ; Auto-reload count for 9600 baud @ 11.0592MHz crystal
         MOV     SCON,#40H            ; Configure UART for 8-bit transmit-only operation
         CLR     TI                   ; Clear UART transmit completion flag
         CLR     RI                   ; Clear unused receive interrupt flag
         MOV     R3,#00H              ; Initialize transmission counter starting at 0
         SETB    TR1                  ; Activate Timer1 baud rate clock

START:   MOV     SBUF,R3              ; Load counter byte into UART transmit buffer register
LOOP1:   JNB     TI,LOOP1             ; Block execution until full byte transmission finishes
         CLR     TI                   ; Clear transmit complete flag for next frame
         INC     R3                   ; Increment sequential byte counter value by one

         CJNE    R3,#00H,START        ; Restart transmission loop if counter has not wrapped to zero after 255
LOOP:    SJMP    LOOP                 ; Idle infinite loop once full 0-255 sequence completes

         END                          ; End of assembly source file

Imprimir mensaje de texto en el módulo LCD de caracteres

Esta demostración usa el display LCD de caracteres 16x2 ampliamente adoptado, que soporta dos filas de texto independientes con dieciséis caracteres ASCII imprimibles por fila. Para reducir el consumo de los pines de E/S limitados del microcontrolador, aquí se implementa la interfaz de comunicación paralela de 4 bits. Bajo este protocolo de modo de 4 bits, cada byte de datos completo de 8 bits se divide y se transmite a través de dos ciclos de escritura secuenciales: los cuatro bits de nibble de orden alto se envían primero, seguidos de los cuatro bits de nibble de orden bajo después.

El controlador LCD requiere una secuencia de inicialización estandarizada ejecutada al inicio del programa. La lógica de interacción de hardware repetida se encapsula en subrutinas dedicadas reutilizables para agilizar el flujo del programa principal. Si bien la estructura completa del código parece compleja a primera vista, el flujo de trabajo central consiste en solo un pequeño conjunto de operaciones fundamentales, con el objetivo final de imprimir la cadena de texto "Mikroelektronika Razvojni sistemi" a través de las dos filas del LCD.

Escribir mensaje en la pantalla LCD
;************************************************************************
;* PROGRAM NAME : Lcd.ASM
;* DESCRIPTION : Test firmware for 16x2 HD44780 LCD using 4-bit parallel interface
;* No busy flag polling implemented; fixed software delay intervals separate all LCD commands
;* All LCD control and data lines are wired to Port 1 of the microcontroller
;************************************************************************

;BASIC ASSEMBLER DIRECTIVES

$MOD53
$TITLE(LCD.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK SEGMENT ALLOCATION
          DSEG     AT     0E0h
Stack_Start:       DS     020h

Start_address      EQU    0000h

;RESET INTERRUPT VECTOR TABLE
          CSEG     AT     0
          ORG      Start_address
          JMP      Inic

          ORG      Start_address+100h

          MOV      IE,#00                    ; Disable all interrupt sources
          MOV      SP,#Stack_Start

Inic:     CALL     LCD_inic                  ; Execute full LCD power-on initialization sequence

;*************************************************
;* MAIN PROGRAM EXECUTION ROUTINE
;*************************************************

START:    MOV      A,#80h                    ; Set DDRAM address pointer to first character position of Line 1
          CALL     LCD_status                ; Send address-set command to LCD controller
          MOV      A,#'M'                    ; Load ASCII character 'M' into accumulator
          CALL     LCD_putc                  ; Subroutine to transmit single ASCII character to LCD
          MOV      A,#'i'
          CALL     LCD_putc
          MOV      A,#'k'
          CALL     LCD_putc
          MOV      A,#'r'
          CALL     LCD_putc
          MOV      A,#'o'
          CALL     LCD_putc
          MOV      A,#'e'
          CALL     LCD_putc
          MOV      A,#'l'
          CALL     LCD_putc
          MOV      A,#'e'
          CALL     LCD_putc
          MOV      A,#'k'
          CALL     LCD_putc
          MOV      A,#'t'
          CALL     LCD_putc
          MOV      A,#'r'
          CALL     LCD_putc
          MOV      A,#'o'
          CALL     LCD_putc
          MOV      A,#'n'
          CALL     LCD_putc
          MOV      A,#'i'
          CALL     LCD_putc
          MOV      A,#'k'
          CALL     LCD_putc
          MOV      A,#'a'
          CALL     LCD_putc

          MOV      A,#0c0h                   ; Set DDRAM address pointer to first character position of Line 2
          CALL     LCD_status                ; Send line 2 address command
          MOV      A,#'R'
          CALL     LCD_putc
          MOV      A,#'a'
          CALL     LCD_putc
          MOV      A,#'z'
          CALL     LCD_putc
          MOV      A,#'v'
          CALL     LCD_putc
          MOV      A,#'o'
          CALL     LCD_putc
          MOV      A,#'j'
          CALL     LCD_putc
          MOV      A,#'n'
          CALL     LCD_putc
          MOV      A,#'i'
          CALL     LCD_putc
          MOV      A,#' '                    ; Load ASCII space character
          CALL     LCD_putc
          MOV      A,#'s'
          CALL     LCD_putc
          MOV      A,#'i'
          CALL     LCD_putc
          MOV      A,#'s'
          CALL     LCD_putc
          MOV      A,#'t'
          CALL     LCD_putc
          MOV      A,#'e'
          CALL     LCD_putc
          MOV      A,#'m'
          CALL     LCD_putc
          MOV      A,#'i'
          CALL     LCD_putc

          MOV      R0,#20d                   ; Set delay loop counter for 20 × 10 millisecond hold time
          CALL     Delay_10ms                ; Execute multi-step delay subroutine
          MOV      DPTR,#LCD_DB              ; Load base address of LCD command lookup table
          MOV      A,#6d                     ; Select clear-display command index
          CALL     LCD_inic_status           ; Send clear screen command to LCD
          MOV      R0,#10d                   ; Additional post-clear 10 × 10ms delay
          CALL     Delay_10ms
          JMP      START                     ; Loop back to refresh screen text repeatedly

;*********************************************
;* SUBROUTINE: Delay_10ms
;* FUNCTION: Generate software delay equal to R0 multiplied by 10 milliseconds
;*********************************************

Delay_10ms:  MOV   R5,00h
             MOV   R6,#100d
             MOV   R7,#100d
             DJNZ  R7,$                      ; "$" label references current assembly line address
             DJNZ  R6,$-4
             DJNZ  R5,$-6
             RET

;**************************************************************************************
;* SUBROUTINE: LCD_inic
;* DESCRIPTION: Complete power-on initialization sequence for 4-bit HD44780 LCD interface
;* Hardware Wiring Rule: LCD data pins DB4~DB7 connect to microcontroller port upper nibble Px.4~Px.7
;* Predefined Bit Labels Required: LCD_enable, LCD_read_write, LCD_reg_select, LCD_port
;* Predefined Memory Offsets: Line 1 start address, Line 2 start address
;**************************************************************************************

LCD_enable     BIT    P1.3                   ; I/O bit controlling LCD EN latch strobe pin
LCD_read_write BIT    P1.1                   ; I/O bit controlling LCD R/W read-write select pin
LCD_reg_select BIT    P1.2                   ; I/O bit controlling LCD RS register select pin
LCD_port       EQU    P1                     ; Full 8-bit microcontroller port wired to LCD data bus
Busy           BIT    P1.7                   ; D7 data line carrying LCD busy flag status

LCD_Start_Line1  EQU   00h                   ; DDRAM base address for first character of display line 1
LCD_Start_Line2  EQU   40h                   ; DDRAM base address for first character of display line 2

LCD_DB:        DB     00111100b              ; Command 0: Function Set (8-bit bus, 2-line, 5x10 font)
               DB     00101100b              ; Command 1: Function Set (4-bit bus, 2-line, 5x10 font)
               DB     00011000b              ; Command 2: Cursor/Display Shift control
               DB     00001100b              ; Command 3: Display ON, Cursor OFF, Blink OFF
               DB     00000110b              ; Command 4: Entry Mode (Address increment, no auto shift)
               DB     00000010b              ; Command 5: Return Cursor to Home Position
               DB     00000001b              ; Command 6: Clear entire LCD display buffer
               DB     00001000b              ; Command 7: Display OFF, Cursor OFF, Blink OFF

LCD_inic:
               MOV    DPTR,#LCD_DB

               MOV    A,#00d                 ; Triple 8-bit mode pre-initialization sequence for unstable power ramp
               CALL  LCD_inic_status_8
               MOV   A,#00d
               CALL  LCD_inic_status_8
               MOV   A,#00d
               LCALL LCD_inic_status_8

               MOV   A,#1d                   ; Send command to switch hardware interface from 8-bit to 4-bit mode
               CALL  LCD_inic_status_8
               MOV   A,#1d
               CALL  LCD_inic_status

               MOV   A,#3d                   ; Remaining initialization commands executed under active 4-bit bus mode
               CALL  LCD_inic_status
               MOV   A,#6d
               CALL  LCD_inic_status
               MOV   A,#4d
               CALL  LCD_inic_status

               RET

LCD_inic_status_8:
               PUSH  B

               MOVC  A,@A+DPTR
               CLR   LCD_reg_select          ; RS=0: Transmission classified as controller command
               CLR   LCD_read_write          ; R/W=0: Write operation mode selected

               MOV   B,LCD_port              ; Preserve lower four port bits unrelated to LCD data bus
               ORL   B,#11110000b
               ORL   A,#00001111b
               ANL   A,B

               MOV   LCD_port,A              ; Output prepared command byte to microcontroller port
               SETB  LCD_enable              ; Generate high-to-low strobe pulse on LCD EN pin to latch data
               CLR   LCD_enable               

               MOV   B,#255d                 ; Extended delay to compensate for slow power-up initialization timing

               DJNZ  B,$
               DJNZ B,$
               DJNZ B,$

               POP B
               RET

LCD_inic_status:
               MOVC  A,@A+DPTR
               CALL  LCD_status
               RET

;****************************************************************************
;* SUBROUTINE: LCD_status
;* FUNCTION: Transmit LCD controller command in split 4-bit nibble format
;****************************************************************************

LCD_status:    PUSH  B
               MOV   B,#255d
               DJNZ  B,$
               DJNZ  B,$
               DJNZ  B,$
               CLR   LCD_reg_select          ; RS=0: Data frame interpreted as LCD command
               CALL  LCD_port_out

               SWAP  A                       ; Swap high/low nibbles within accumulator register

               DJNZ  B,$
               DJNZ  B,$
               DJNZ  B,$
               CLR   LCD_reg_select
               CALL  LCD_port_out

               POP   B
               RET

;****************************************************************************
;* SUBROUTINE: LCD_putc
;* FUNCTION: Transmit single ASCII character data byte to LCD display buffer
;****************************************************************************

LCD_putc:      PUSH  B
               MOV   B,#255d
               DJNZ  B,$
               SETB  LCD_reg_select          ; RS=1: Data frame interpreted as printable character
               CALL  LCD_port_out

               SWAP  A                       ; Swap accumulator nibbles for second 4-bit transmission cycle

               DJNZ  B,$
               SETB  LCD_reg_select
               CALL  LCD_port_out
               POP   B
               RET

;****************************************************************************
;* SUBROUTINE: LCD_port_out
;* FUNCTION: Output 4-bit nibble to LCD data bus and generate EN latch strobe pulse
;****************************************************************************

LCD_port_out:  PUSH  ACC
               PUSH  B
               MOV   B,LCD_port              ; Save unused lower four port bits
               ORL   B,#11110000b
               ORL   A,#00001111b
               ANL   A,B

               MOV   LCD_port,A              ; Write processed nibble data to port register

               SETB  LCD_enable              ; Generate falling edge strobe signal on LCD EN pin
               CLR   LCD_enable               

               POP   B
               POP   ACC
               RET

               END                           ; End of assembly source file

Subrutina de conversión de entero binario a decimal

Al trabajar con displays LED de siete segmentos o LCD de caracteres, convertir los valores de registro binarios crudos al formato de dígitos decimales legibles por humanos es una operación común obligatoria. Por ejemplo, si un número binario de 8 bits almacenado dentro de un registro necesita representarse en un display multiplexado de 7 segmentos de tres dígitos, el valor binario debe primero dividirse en dígitos decimales independientes de centenas, decenas y unidades. Cada valor de dígito aislado luego mapea a una máscara de bits de activación de segmentos única para la posición de display correspondiente (izquierda = centenas, medio = decenas, derecha = unidades).

La subrutina reutilizable listada a continuación convierte un solo valor de byte binario de 8 bits cargado dentro del registro acumulador en tres dígitos decimales separados. Después de la ejecución de la subrutina, el dígito de unidades se almacena en el registro R3, el dígito de decenas se almacena en el registro R2, y el dígito de centenas permanece dentro del registro acumulador para el procesamiento inmediato del display.

;************************************************************************
;* SUBROUTINE NAME : BinDec.ASM
;* DESCRIPTION : Converts 8-bit binary value held in Accumulator into separate hundreds, tens, units decimal digits
;************************************************************************

BINDEC:            MOV     B,#10d         ; Load decimal divisor constant 10 into register B
                   DIV     AB             ; Divide Accumulator value by 10; quotient stored in A, remainder in B
                   MOV     R3,B           ; Store remainder (units digit) into register R3
                   MOV     B,#10d         ; Reload divisor value 10 for second division cycle
                   DIV     AB             ; Divide quotient by 10 again; new remainder = tens digit
                   MOV     R2,B           ; Store tens digit remainder into register R2
                   MOV     B,#10d         ; Reload divisor 10 for third division cycle
                   DIV     AB             ; Final division step; remainder = hundreds digit
                   MOV     A,B            ; Move hundreds digit value back into accumulator register
                   RET                    ; Return execution flow back to main calling program

Este capítulo ha cubierto todos los primitivos fundamentales de control de hardware para el desarrollo de microcontroladores, sin embargo estas rutinas básicas idénticas son objetivos de ataque frecuentes en la explotación maliciosa de sistemas embebidos. Como un ejemplo, los simples bucles de retardo de software implementados para el parpadeo de LED pueden aprovecharse para medir variaciones precisas de temporización a través de las ramas de ejecución, permitiendo a los atacantes inferir rutas ocultas de ejecución de código secreto mediante análisis de canal lateral de temporización. La demostración del temporizador watchdog, aunque diseñada como un mecanismo de recuperación de seguridad, también demuestra la funcionalidad completa de reinicio del chip — un comportamiento de hardware que puede abusarse para forzar secuencias no autorizadas de recuperación de dispositivos o eludir las protecciones de bloqueo de seguridad si la lógica de tiempo de espera del watchdog está configurada inadecuadamente. Los ejemplos de temporizador e interrupción externa enseñan control preciso de temporización exacto a nivel de ciclo, una habilidad crítica tanto para diseñar protocolos de comunicación seguros como para realizar la ingeniería inversa completa de sistemas de hardware embebido propietarios desconocidos. Las interfaces de comunicación serie UART presentan riesgos notables de exposición de seguridad, ya que el tráfico serie sin cifrar permite a los adversarios capturar pasivamente datos de lectura crudos transmitidos sobre el cableado físico; sin encuadre criptográfico, los atacantes pueden capturar volcados de bytes completos del tráfico serie y reconstruir la lógica completa del comportamiento del firmware en tiempo de ejecución. La rutina de verificación de lectura-escritura EEPROM interactúa directamente con la memoria de almacenamiento persistente no volátil, un objetivo de ataque principal para los actores malintencionados que buscan volcar el contenido completo de la memoria flash o alterar los parámetros de calibración de fábrica para desbloquear la funcionalidad premium restringida del dispositivo. Incluso los circuitos de display LED multiplexado demuestran técnicas de conmutación de señales intercaladas, un concepto que los ingenieros hostiles pueden replicar para confundir los intentos de sondeo físico del silicio durante los ataques completos de decapsulación de chips. Como se demostró a través de cada módulo de hardware cubierto aquí, cada pin de E/S de propósito general y registro de CPU puede convertirse en un vector de ataque viable para la extracción completa de firmware cuando los fusibles de seguridad se dejan sin configurar. El fusible de hardware de bit de bloqueo es típicamente la única barrera defensiva primaria que separa el código ejecutable protegido del acceso no autorizado, sin embargo innumerables productos comerciales de consumo e industriales llegan al mercado con las protecciones de bit de bloqueo deshabilitadas o configuradas incorrectamente. Esta realidad obliga a los ingenieros embebidos profesionales a tratar la extracción completa de firmware como un riesgo comercial tangible e invertir fuertemente en empaques resistentes a la manipulación, blindaje EMI activo y salvaguardas de seguridad de hardware multicapa. El flujo de trabajo de validación de escritura-y-verificación EEPROM sirve como una plantilla fundacional para el diseño seguro de almacenamiento de datos persistentes, pero la verificación de lectura-escritura independiente no puede prevenir la duplicación del dispositivo a menos que se combine con esquemas robustos de cifrado de datos de extremo a extremo. En escenarios de amenaza del mundo real, los adversarios sofisticados utilizan estaciones de trabajo de decapsulación láser para grabar el empaque de epoxi protector y exponer los fusibles internos de silicio, seguidas de estaciones de micro-sondeo para realizar directamente la lectura completa de la memoria flash sin credenciales de autenticación. Si bien tales ataques de hardware basados en laboratorio conllevan altos costos iniciales de equipo, permanecen económicamente viables para activos de hardware propietarios de alto valor con flujos de ingresos significativos de propiedad intelectual. Por esta razón, todos los ejemplos de hardware introductorios en este capítulo deben tratarse no solo como ejercicios educativos de programación sino también como recordatorios constantes de las amenazas persistentes de seguridad embebida. El microcontrolador mismo funciona como una plataforma flexible de automatización y control, sin embargo sus mecanismos nativos de bloqueo de seguridad de hardware exigen una configuración cuidadosa y deliberada durante el diseño del producto. Si bien la recuperación de una contraseña administrativa perdida del dispositivo puede depender de una puerta trasera de hardware oculta durante el mantenimiento legítimo, ese punto de acceso de puerta trasera idéntico puede ser armado por los atacantes para volcar el binario completo del código de aplicación. Para resumir, cada programa de ensamblador simple presentado en este capítulo conlleva una dimensión de riesgo de seguridad subyacente que se vuelve crítica para la misión cuando se despliega en hardware comercial de producción masiva. La ingeniería inversa de estas rutinas de control elementales es casi siempre la fase inicial de reconocimiento de una campaña más grande de hacking de hardware, exigiendo que los desarrolladores adopten una mentalidad de seguridad-primero desde las etapas más tempranas del diseño de prototipos. El conocimiento integral de cómo desbloquear la memoria restringida del dispositivo mediante fluctuaciones de temporización de software o inyección de fallos de tensión de hardware es igualmente vital que comprender cómo implementar contramedidas para bloquear tales exploits. En última instancia, este capítulo sienta el conocimiento fundacional de hardware y software requerido para construir sistemas de control embebidos totalmente resistentes a la manipulación — siempre que los desarrolladores internalicen adecuadamente las lecciones críticas sobre los fusibles de seguridad, la configuración de bits de bloqueo y la protección cifrada del almacenamiento EEPROM. Al dominar estos principios combinados de hardware y seguridad, los ingenieros de diseño pueden entregar productos listos para el mercado resistentes contra la clonación no autorizada de hardware y preservar por completo la confidencialidad de los activos de propiedad intelectual propietarios. El viaje de ingeniería completo desde un simple indicador LED parpadeante hasta un sistema de control industrial endurecido a prueba de manipulaciones comienza con el dominio de estos primitivos básicos de microcontrolador — y reconociendo plenamente todas las vulnerabilidades de seguridad embebida asociadas que acompañan a cada recurso periférico y de memoria.

  • Lista de ingeniería inversa de MCU SST 8051 de Mikatech:
  • Protección de copia de lectura de MCU de la serie SST89Cxx: SST89C54 SST89C58 SST89C583 SST89C5833 SST89C58RC SST89C59 ...

    Protección de copia de ruptura de MCU de la serie SST89Exx: SST89E516RD SST89E516RD2 SST89E554 SST89E52RC SST89E52RD SST89E52RD2 SST89E54RC SST89E54RD SST89E54RD2 SST89E554RC SST89E564RD SST89E58RD SST89E58RD2 ...

    Protección de bit de bloqueo de copia de lectura de MCU de la serie SST89Vxx: SST89V516RD SST89V516RD2 SST89V52RD SST89V52RD2 SST89V54RD2 SST89V554RC SST89V564RD SST89V58RD2...

    Protección de copia de bit de bloqueo de ruptura de MCU de la serie SST89VFxx: SST39VF1682 SST39VF1681 SST39VF6402B SST39VF6401B SST39VF6402 SST39VF6401 SST39VF3202 SST39VF3201 SST39VF1602 SST39VF1601 ...

Preguntas generales sobre la extracción de firmware de microcontroladores


  • ¿Es seguro enviar el pago a MikaTech ?

    Si MikaTech fuera una mala empresa, podrías encontrar toneladas de malas reputaciones sobre su servicio en internet a lo largo de los 28 años de historia

    ¡Entonces, la respuesta es SÍ! Somos buenas personas.

    Por qué elegir Mikatech, por favor haga clic aquí para averiguarlo


  • ¿Puede Mikatech romper circuitos integrados no listados en este sitio ?

    Los diferentes fabricantes de chips tienen diferentes números de pieza, pero el núcleo interno del chip puede estar hecho con la misma tecnología, sería bastante imposible listar todos los números de pieza donde nuestra tecnología puede aplicarse, como MYSON, STK, FEELING, ANALOG, FUJITSU, NOVATEK, LG/HYNDAI.

    También, con el avance de la tecnología, cada día ganamos más y más experiencia y desarrollamos nuevos métodos de ingeniería inversa para diferentes partes de Circuitos Integrados. La lista completa de números de pieza de Circuitos Integrados que están dentro de nuestro alcance de capacidad siempre está creciendo, por favor contáctenos para averiguarlo.

  • ¿Se protegerá mi privacidad ?

    Mikatech Innovative Limited comprende la importancia de la privacidad de sus clientes. En el momento en que contactas a Mikatech, la información personal tuya se pondrá bajo protección por nuestras regulaciones de gestión desarrolladas por nuestros años de práctica, Mikatech utiliza esta información para personalizar su servicio para ti, nunca divulgará esta información a terceros por ninguna razón.
    Cada proyecto que hacemos, eliminaremos todos los datos, materiales y códigos 60 días después de entregar los archivos, nos protegerá y protegerá tu privacidad.

  • ¿Es legal obtener el servicio de Mikatech ?

    Sí, es totalmente legal.
    Mikatech entrega sus servicios de ingeniería inversa solo con fines educativos, puede ser ilegal usar los servicios mencionados anteriormente en algunos países o regiones, por favor verifica tus leyes locales. Mikatech no asume ninguna responsabilidad en relación con el uso de los servicios mencionados anteriormente que puedan considerarse ilegales.


  • Te envié un correo electrónico, ¿por qué no hay respuesta ?

    • A. Nuestro servidor de correo se averió temporalmente, tu mensaje no ha sido entregado a nuestro buzón incluso si el mensaje de envío exitoso se muestra en la pantalla, por favor contáctanos de nuevo.
    • B. Nuestro correo es reconocido como correo no deseado por tu servidor de correo, por lo que nuestra respuesta ha sido rechazada por tu servidor de correo o se desvía a tu buzón de correo no deseado, por favor elimina nuestra cuenta de la lista de correo no deseado o revisa tu buzón de correo no deseado, o usa otra cuenta de correo para contactarnos como gmail.
    • C. Tu correo es reconocido como correo no deseado por nuestro servidor de correo, por lo que tu correo fue puesto en nuestro buzón de correo no deseado, por favor usa otra cuenta de correo para contactarnos de nuevo.



    tiempo_de_hackeo_de_microcontrolador

    Años

    28 +
    países de hackeo de microcontroladores

    Países

    110 +
    clientes de ataque de microcontroladores

    Clientes

    5000 +
    proyectos de microcontroladores desbloqueados

    Proyectos

    60000 +