01 · Lo que recorriste
Lo que recorriste
El curso fue una escalera con cuatro tramos, cada uno apoyado en el anterior:
| Tramo | Temas | Idea que quedó |
|---|---|---|
| Recordar con realimentación | 1 a 12 | Dos compuertas cruzadas forman un latch; con un reloj y una disciplina de tiempos (preparación y retención) se convierten en flip-flops, el átomo de la memoria sincrónica |
| Registros y contadores | 13 a 21 | Con flip-flops se arman registros que guardan, registros que desplazan, contadores que cuentan y anillos que circulan |
| Máquinas de estados | 22 a 25 | Estado + entradas → estado siguiente y salidas: una tabla y un registro describen cualquier comportamiento secuencial |
| Memoria y tiempo | 26 a 33 | Las memorias son tablas direccionables (SRAM, DRAM, ROM, EEPROM, Flash); el tiempo se genera con osciladores, divisores y comparaciones |
| Proyectos | 34 y 35 | Un semáforo con máquina de estados y un secuenciador con memoria: la misma cosa, una vez en lógica y otra en datos |
02 · Elegir bloques
Elegir bloques a partir de requisitos
Ante un problema nuevo, el primer error es empezar a conectar integrados. El método de los dos proyectos fue siempre el mismo: requisitos numerados, bloques con interfaces claras, verificación en código y recién entonces el armado. La decisión clave es qué bloque corresponde a cada necesidad:
| Necesito… | Bloque | Dónde lo viste |
|---|---|---|
| Recordar un bit o una palabra | Latch, flip-flop, registro | Temas 5 a 13 |
| Pasar de paralelo a serie, o al revés | Registro de desplazamiento (74HC595, 74HC165) | Temas 14 a 16 |
| Contar eventos o medir tiempo | Contador y comparador | Temas 17 a 20 y 32 |
| Un comportamiento que depende de lo que pasó antes | Máquina de estados: registro + tabla de próximo estado | Temas 22 a 25 y 34 |
| Almacenar muchas palabras o una tabla fija | RAM, ROM, EEPROM o Flash | Temas 26 a 31 |
| Una secuencia larga de salidas | Contador + ROM | Tema 35 |
| Una frecuencia exacta | Cristal + divisor | Temas 32 y 33 |
| Aceptar una señal asíncrona | Antirrebote + latch + sincronizador de dos flip-flops | Temas 11, 20 y 34 |
| Ajustar una potencia o un brillo | PWM: contador + comparador | Tema 33 |
Cuatro preguntas ayudan a decidir: ¿hay memoria? (si la salida depende del pasado, hace falta estado), ¿hay tiempo? (si hay duraciones, hace falta una base de tiempo y un contador), ¿hay una entrada que no es del sistema? (si es asíncrona, hace falta sincronizarla), y ¿cambiará? (si el comportamiento va a cambiar, conviene que sea un dato y no un cableado).
03 · Depurar
Depurar con cronogramas
Un sistema secuencial falla en el tiempo: lo que está mal no es un valor, es un valor en un instante. La herramienta de depuración es el cronograma, la gráfica de varias señales contra el tiempo, obtenida con un analizador lógico o un osciloscopio de varios canales. Un método que sirve siempre:
- Definí el disparo. Elegí una señal de referencia (un flanco del reloj o una señal de inicio) y capturá siempre con el mismo disparo, para que las capturas sean comparables.
- Dibujá antes lo que esperás. Hacé el cronograma esperado a mano o en código; después compará. Es la misma disciplina del «predecí antes de simular».
- Mirá primero lo básico: alimentación, reloj (frecuencia y forma), reset (se libera después de que el reloj arranca).
- Buscá el primer desvío. No importa dónde termina mal, sino dónde se aparta primero de lo esperado; la causa está en o antes de ese punto.
- Cambiá una sola cosa por vez y repetí la captura.
| Síntoma en el cronograma | Causa probable | Tema |
|---|---|---|
| Pulsos angostos o dobles en una salida de ROM o de compuertas | Glitch por entradas que no cambian a la vez; falta un registro de salida | 35 |
| Un contador salta valores o cuenta de más | Rebotes en la entrada de reloj; falta Schmitt y antirrebote | 7 y 20 |
| Un flip-flop queda a veces en un nivel intermedio | Metaestabilidad: una entrada cambió cerca del flanco; falta sincronizador | 11 |
| Un registro captura el dato viejo | Violación de preparación o retención (dato tardío o reloj con desfasaje) | 8 y 13 |
| La máquina arranca en un estado raro | Reset ausente o liberado antes que el reloj; estados no usados sin salida | 10, 24 y 34 |
| Dos salidas en un bus pelean y se calientan | Dos tri-estados habilitados a la vez; falta decodificar con exclusión | 26 y 31 |
| Datos leídos de una EEPROM o Flash incorrectos | Escritura sin esperar el fin o lectura antes de tiempo (tiempos de acceso) | 29 y 30 |
| El sistema falla solo con ruido o al cambiar de carga | Falta de condensadores de desacople de 100 nF o masa compartida | 2 y 35 |
El mismo método sirve en un microcontrolador: el analizador lógico no distingue si la señal sale de un 74HC o de un pin configurado como salida, y los problemas son los mismos (rebotes, glitches, metaestabilidad, reset, desacople).
04 · Periféricos
Los periféricos son bloques que ya conocés
Cuando abras la hoja de datos de un microcontrolador, la lista de periféricos va a parecer larga. Casi todos son uno de los bloques del curso con un registro de configuración al lado, que el procesador escribe y lee como si fuera una memoria:
| Periférico | Qué es por dentro | Tema |
|---|---|---|
| Puerto GPIO | Un registro de salida (74HC574), un buffer de tres estados que lo conecta al pin y un buffer de lectura; un registro de dirección elige entre entrada y salida | 13 y 26 |
| Timer | Contador con prescaler (divisor) y registro de comparación; el desborde o la igualdad son los eventos | 17, 19 y 33 |
| PWM | El mismo contador comparado con un umbral: la salida es alta mientras la cuenta es menor | 33 |
| SPI | Registro de desplazamiento con un contador de 8 pulsos y una bandera de fin (74HC595 más 74HC165) | 14 a 16 |
| UART | Registro de desplazamiento más una máquina de estados (inicio, 8 datos, parada) y un divisor de baudios | 14, 22 y 33 |
| I²C | Máquina de estados que maneja dos líneas de colector abierto con un registro de desplazamiento | 14 y 22 |
| Interrupción | Un latch que memoriza el evento, un sincronizador y una máscara; la bandera se borra cuando se atiende, igual que el borrado de la solicitud del semáforo | 11 y 34 |
| Watchdog | Un contador (o monoestable) que reinicia al sistema si no se rearma a tiempo | 32 |
| Reloj de la CPU | Oscilador de cristal o RC, divisores y multiplicadores (PLL) | 32 y 33 |
| RAM interna | SRAM: filas y columnas de celdas con decodificador de direcciones | 26 y 27 |
| Flash de programa | Memoria no volátil con borrado por bloques y ciclos limitados | 30 |
| EEPROM de datos | Memoria no volátil con escritura por byte y tiempos de espera | 29 |
Lo que cambia es que todos comparten un bus interno con la CPU: leer o escribir un registro de configuración es acceder a una dirección de un mapa de memoria, igual que en el tema 31. Un pin que parpadea se activa escribiendo un bit en la dirección de su puerto. El mapa de memoria que armaste con el 74HC138 es, en miniatura, el del microcontrolador.
05 · Hardware o software
Hardware o software: cómo decidir
Cada bloque del curso puede hacerse con integrados dedicados o con un programa en un microcontrolador. No hay una respuesta universal:
| Criterio | Hardware dedicado | Microcontrolador |
|---|---|---|
| Velocidad | Todo en paralelo, a la velocidad del integrado (MHz a decenas de MHz) | Una cosa por vez; cada ciclo de CPU cuenta; los periféricos corren en paralelo |
| Cambios | Soldar o recablear | Reprogramar |
| Determinismo | Tiempos exactos, sin sistema operativo ni interrupciones inesperadas | Depende del código y las prioridades de interrupción |
| Complejidad lógica | Crece con la cantidad de integrados y cables | Crece con las líneas de código |
| Costo y tamaño | Pocos bloques: barato. Muchos: grande | Un chip con todo, por pocos dólares |
| Consumo | Muy bajo en reposo si solo cambia lo necesario | Hay modos de bajo consumo, pero el reloj de la CPU cuenta |
| Aprendizaje | Se ve cada señal | Se ve el programa, no las señales |
Una regla práctica: lo que debe ser muy rápido, exactamente simultáneo o independiente del software va a hardware (en un microcontrolador, a un periférico: un timer, un SPI); lo que cambia a menudo o es complejo y lento (un menú, un protocolo de alto nivel) va a software. Entre los dos extremos están los dispositivos programables (FPGA y CPLD), que permiten describir circuitos como los de este curso y que el hardware ejecuta en paralelo.
06 · Lo que cambia
Lo que cambia en un microcontrolador
- El reloj de la CPU no es el del sistema. El procesador ejecuta instrucciones, no «pasos de lógica»; el tiempo de cada una depende del reloj y del código. Para tiempos exactos se usan timers, no bucles de espera.
- Las entradas asíncronas siguen existiendo. Cada pin sincroniza su entrada con dos flip-flops antes de que la CPU lo lea; una interrupción es un latch con prioridad. Los rebotes de un botón siguen necesitando un filtro, por hardware o por software.
- El estado vive en variables. Una máquina de estados en software es una variable de estado y una estructura
switcho una tabla indexada, es decir, la misma tabla de próximo estado. La verificación exhaustiva del tema 34 se traslada igual a las pruebas del programa. - La memoria es parte del sistema. El programa vive en Flash; los datos, en RAM; los parámetros que deben sobrevivir al apagado, en EEPROM o en Flash emulando EEPROM. Todo con los límites de ciclos y de tiempos que viste en los temas 29 y 30.
- La corriente por pin sigue siendo un límite. Un pin típico maneja una corriente del orden de 10 a 25 mA, no más; las cargas mayores van con transistores o buffers, como los LED del tema 35.
- El reset y el arranque son tan importantes como antes. Un microcontrolador sin un buen reset de encendido y sin desacople puede arrancar en estados impredecibles; el watchdog es el último recurso.
07 · El puente en código
Cuatro bloques del curso, dentro de un microcontrolador
Los bloques de código muestran el mismo registro de desplazamiento hecho con hardware y con un bucle, un timer calculado como lo hace un microcontrolador, una UART con su tolerancia a un error de velocidad y un antirrebote por software.
Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.
Paso 1: el registro de desplazamiento, en hardware y en un bucle
class Reg595:
"""Modelo del 74HC595: registro de desplazamiento de 8 bits + registro de almacenamiento (latch)."""
def __init__(self):
self.sr, self.q = 0, 0
def shcp(self, ds): # flanco de SHCP: desplaza e ingresa DS por el bit 0
self.sr = ((self.sr << 1) | ds) & 0xFF
def stcp(self): # flanco de STCP: copia el registro de desplazamiento a las salidas
self.q = self.sr
def enviar_hardware(chip, byte):
for i in range(7, -1, -1): # MSB primero
chip.shcp((byte >> i) & 1)
chip.stcp()
def enviar_software(estado, byte):
"""Lo que hace un microcontrolador con tres pines GPIO: la misma secuencia, en un bucle."""
sr = estado["sr"]
for i in range(7, -1, -1):
bit = (byte >> i) & 1 # poner DS
sr = ((sr << 1) | bit) & 0xFF # pulso en SHCP
estado["sr"] = sr
estado["q"] = sr # pulso en STCP
hw, sw = Reg595(), {"sr": 0, "q": 0}
iguales = True
for byte in (0x00, 0xA5, 0xFF, 0x3C, 0x81):
enviar_hardware(hw, byte)
enviar_software(sw, byte)
iguales &= (hw.q == sw["q"] and hw.sr == sw["sr"])
print(f"byte {byte:02X}: salidas del chip {hw.q:02X}, salidas del bucle de software {sw['q']:02X}")
print("el bucle de software reproduce al registro de hardware:", iguales)
def spi_intercambio(salida, entrada):
"""Un intercambio SPI de 8 bits: en cada pulso de reloj sale un bit propio y entra uno del otro lado."""
recibido = 0
for i in range(7, -1, -1):
miso = (entrada >> i) & 1
recibido = (recibido << 1) | miso
return recibido
print(f"SPI: se enviaron 8 bits y se recibieron {spi_intercambio(0xA5, 0x3C):02X} (lo que tenía el otro lado)")
print("un periférico SPI de microcontrolador es este mismo registro de desplazamiento con un contador de 8 pulsos y una bandera 'terminé'")
El bucle que mueve tres pines (DS, SHCP, STCP) deja las mismas salidas que el 74HC595 para los cinco bytes de prueba. Esa es la razón por la que un SPI «por software» (bit-banging) funciona y por la que un SPI «por hardware» es lo mismo con un contador de ocho pulsos y una bandera: la diferencia es quién genera los pulsos, no qué hacen.
Paso 2: un timer, calculado como en la hoja de datos
import math
F_CPU = 16_000_000 # reloj del microcontrolador (valor típico)
PRESCALERS = (1, 8, 64, 256, 1024)
BITS = 16 # contador de 16 bits
def mejor(f_deseada):
"""Elige prescaler y valor de comparación (como los registros PSC y ARR de un timer)."""
candidatos = []
for p in PRESCALERS:
arr = round(F_CPU / (p * f_deseada)) - 1
if 1 <= arr < 2 ** BITS:
real = F_CPU / (p * (arr + 1))
candidatos.append((abs(real - f_deseada) / f_deseada, p, arr, real))
return min(candidatos)
print("frecuencia pedida -> prescaler, valor de comparación (ARR), frecuencia real, error")
for f in (1, 10, 440, 1000, 20_000):
e, p, arr, real = mejor(f)
print(f" {f:6d} Hz -> prescaler {p:4d}, ARR = {arr:6d}, real {real:11.4f} Hz, error {e * 100:.4f} %")
f = 1000
e, p, arr, real = mejor(f)
print(f"PWM de {f} Hz: el contador cuenta 0..{arr}; el pin está en alto mientras cuenta < comparador")
for duty in (0, 25, 50, 75, 100):
cmp_ = round((arr + 1) * duty / 100)
alto = sum(1 for n in range(arr + 1) if n < cmp_)
print(f" ciclo de trabajo {duty:3d} % -> comparador {cmp_:5d}; ciclos en alto {alto}/{arr + 1} = {100 * alto / (arr + 1):.2f} %")
print("resolución del PWM según la frecuencia (con prescaler 1):")
for f in (100, 1000, 20_000, 100_000):
niveles = F_CPU // f
print(f" {f:7d} Hz: {niveles:6d} niveles = {math.log2(niveles):.1f} bits")
print("a mayor frecuencia, menos niveles: es el compromiso del contador del tema 33")
Con un reloj de 16 MHz, un contador de 16 bits y prescalers de 1 a 1024, se obtienen 1 Hz (prescaler 256, ARR = 62 499), 10 Hz (prescaler 64, ARR = 24 999) y 1 kHz (prescaler 1, ARR = 15 999) sin error. En 440 Hz el error es de 0,001 %. En un PWM de 1 kHz el ciclo de trabajo se fija con el comparador (4000, 8000 y 12 000 para 25, 50 y 75 %), y la resolución cae de 17,3 bits a 100 Hz a 7,3 bits a 100 kHz: el compromiso entre frecuencia y resolución del tema 33. Los 16 MHz y los prescalers son valores típicos usados como ejemplo, no los de un modelo particular.
Paso 3: una UART y su tolerancia al error de velocidad
def trama(byte):
"""Trama UART 8N1: start (0), 8 bits de datos LSB primero, stop (1)."""
return [0] + [(byte >> i) & 1 for i in range(8)] + [1]
def recibir(byte, error, f=0.5):
"""El receptor detecta el flanco de bajada y muestrea en (k + f) de SU período de bit.
error: diferencia relativa entre el período del receptor y el del transmisor."""
bits = trama(byte)
muestras = []
for k in range(10):
t = (k + f) * (1 + error) # instante de muestreo, en períodos del transmisor
idx = int(t // 1) # bit que está presente en la línea en ese instante
muestras.append(bits[idx] if idx < 10 else 1)
dato = sum(b << i for i, b in enumerate(muestras[1:9]))
ok = muestras[0] == 0 and muestras[9] == 1 and dato == byte
return dato, ok
print("recepción de 0x55 y 0x41 con distintos errores de velocidad (muestreo a mitad del bit):")
for e in (0.0, 0.02, 0.04, 0.05, 0.06, -0.04, -0.06):
r55, ok55 = recibir(0x55, e)
r41, ok41 = recibir(0x41, e)
print(f" error {e * 100:+5.1f} %: 0x55 -> {r55:02X} {'bien' if ok55 else 'MAL '} 0x41 -> {r41:02X} {'bien' if ok41 else 'MAL '}")
def tolerancia(f):
"""Mayor error simétrico que todavía recibe bien TODOS los bytes."""
e = 0.0
while e < 0.2:
e2 = e + 0.0005
if not all(recibir(b, s * e2, f)[1] for b in range(256) for s in (1, -1)):
return e
e = e2
return e
print()
print("tolerancia del error de velocidad según el punto de muestreo (con los 256 bytes posibles):")
for f in (0.25, 0.5, 0.75):
print(f" muestreo al {int(f * 100):2d} % del bit: tolera ±{tolerancia(f) * 100:.1f} %")
print("el teórico para muestrear a mitad del bit es ±5,26 %: 9,5 períodos del receptor deben quedar dentro de 9 a 10 del transmisor")
for nombre, ppm in (("cristal de 20 ppm", 20), ("oscilador RC interno (±2 %)", 20000)):
e = ppm * 1e-6
ok = all(recibir(b, 2 * e)[1] for b in range(256))
print(f" {nombre}: dos equipos con el peor error opuesto difieren {2 * e * 100:.3f} % -> {'funciona' if ok else 'falla'}")
Con el muestreo a mitad del bit, 0x55 y 0x41 se reciben bien hasta ±5 % de diferencia de velocidad y mal a ±6 % (el receptor lee D5 y C1: la muestra de D7 cae en el bit de parada y lee un 1). Probando los 256 bytes, la tolerancia es de ±5,3 % al 50 % del bit, pero solo ±2,7 % al 25 % y ±2,9 % al 75 %: el punto de muestreo en el centro es el que más margen deja. Dos cristales de 20 ppm difieren 0,004 %, y dos osciladores RC de ±2 % podrían diferir 4 %: dentro del límite de 5,3 % en teoría, pero sin margen real para jitter y para la detección del flanco inicial, por eso las comunicaciones serie serias usan cristal.
Paso 4: un antirrebote por software
import random
def senal_con_rebotes(rnd, inicio, duracion=600):
"""Una pulsación mecánica muestreada a 1 kHz: unos ms de rebotes al cerrar, contacto firme y rebotes al abrir."""
linea = [0] * duracion
t = inicio
for _ in range(rnd.randint(3, 8)): # al cerrar: alternancias breves
linea[t] = 1
t += rnd.randint(2, 3)
fin = inicio + 300
for k in range(t, fin):
linea[k] = 1
t = fin
for _ in range(rnd.randint(3, 8)): # al abrir: pulsos sueltos
linea[t] = 1
t += rnd.randint(2, 3)
return linea
def flancos(senal):
return sum(1 for a, b in zip(senal, senal[1:]) if a != b)
class Integrador:
"""Antirrebote por software: el contador sube con 1, baja con 0 y satura; la salida cambia solo en los extremos."""
def __init__(self, maximo=10):
self.n, self.maximo, self.salida = 0, maximo, 0
def muestra(self, x):
self.n = min(self.maximo, self.n + 1) if x else max(0, self.n - 1)
if self.n == self.maximo:
self.salida = 1
elif self.n == 0:
self.salida = 0
return self.salida
rnd = random.Random(36)
total_crudo, total_filtrado, eventos_ok = 0, 0, 0
for _ in range(200):
cruda = senal_con_rebotes(rnd, inicio=100)
filtro = Integrador(10)
limpia = [filtro.muestra(x) for x in cruda]
total_crudo += flancos(cruda)
total_filtrado += flancos(limpia)
eventos_ok += (flancos(limpia) == 2)
print(f"200 pulsaciones con rebotes: flancos en la línea cruda {total_crudo} (promedio {total_crudo / 200:.1f}); tras el filtro {total_filtrado} (promedio {total_filtrado / 200:.1f})")
print(f"pulsaciones que dejan exactamente un cierre y una apertura: {eventos_ok}/200")
ej = senal_con_rebotes(random.Random(5), inicio=100)
f = Integrador(10)
limpia = "".join(str(f.muestra(x)) for x in ej)
print("primeras muestras de una pulsación:", "".join(str(x) for x in ej[98:130]))
print("tras el filtro: ", limpia[98:130], "(retardo del orden de 10 ms)")
print("el integrador es el equivalente de software del filtro RC y la compuerta Schmitt del tema 20: la constante de tiempo es el contador")
En 200 pulsaciones simuladas, la línea cruda tiene en promedio 21,8 flancos por pulsación (rebotes de cierre y apertura) y, después de un integrador de 10 muestras, exactamente 2,0: un cierre y una apertura, en las 200 de 200 pulsaciones. El retardo es del orden de 10 ms, porque la constante de tiempo ahora es un contador. Es el mismo trabajo que el filtro RC y la compuerta Schmitt del tema 20, hecho con una variable.
Los cuatro pasos muestran el patrón del puente: lo que hacía un circuito pasa a ser un registro de configuración o un bucle, pero la lógica, las tablas y los problemas de tiempo son los mismos.
08 · Exploración interactiva
El laboratorio: cronograma de una UART
Una UART es el mejor ejemplo de un periférico que es registro de desplazamiento, máquina de estados y divisor de reloj. El laboratorio muestra la trama 8N1 de un carácter (inicio en 0, ocho datos con el bit menos significativo primero, parada en 1) y los instantes en que el receptor la muestrea cuando su velocidad no coincide con la del transmisor. Verde: el receptor lee lo que se envió. Rojo: lee el bit vecino.
Receptor UART con error de velocidad
Sin error de velocidad, el receptor muestrea siempre en el centro de cada bit. Movelo y mirá cuándo se cae un bit.
| Bit | Instante de muestreo | Bit presente en la línea | Enviado | Leído |
|---|---|---|---|---|
| Cargando… | ||||
Recorrido guiado
- Con el error en 0 y el muestreo al 50 %, cada línea cae en el centro de su bit: el margen es de 50 % hacia cada borde.
- Subí el error de a poco. El margen se achica y las líneas se corren hacia la derecha. Los últimos bits son los que primero se acercan al borde, porque acumulan el desvío de varios períodos.
- Pasá de +5,9 %: la muestra de D7 cae en el bit de parada y se lee un 1 en lugar del dato. Del otro lado, a −5,3 % la muestra de la parada cae sobre D7. Por eso el límite que vale para todos los caracteres es el menor de los dos, ±5,3 %.
- Con «Hallar el error máximo tolerado» obtenés el límite para el carácter y el punto de muestreo actuales. Probalo con 0xFF, con 0x00 y con 0x55 y compará: cada carácter tiene su propio límite, pero el del sistema es el del peor carácter.
- Movés el punto de muestreo al 25 % o al 75 %: el límite baja a la mitad, porque la muestra empieza más cerca de un borde.
- Pensá en el hardware de la UART: un divisor genera 16 ticks por bit; un contador de 3 a 4 bits alinea el muestreo al centro; un registro de desplazamiento junta los 8 bits; una máquina de estados cuenta los diez bits. Todo es del curso.
Desafío: tres muestras por bit
Muchos receptores toman tres muestras alrededor del centro y deciden por mayoría. ¿Cómo cambiaría la tolerancia al error de velocidad y al ruido? Con la mayoría, un pulso de ruido de una sola muestra no cambia el bit, pero el tramo de tres muestras ocupa parte del bit y, con error de velocidad grande, la muestra extrema se acerca al borde: se gana inmunidad al ruido y se pierde algo de tolerancia al error de velocidad.
09 · Qué estudiar después
Qué estudiar después
El curso termina acá, pero el camino sigue por varias ramas. Elegí la que más te sirva:
| Si querés… | Estudiá | Qué vas a reconocer |
|---|---|---|
| Programar placas pequeñas | Un microcontrolador de 8 o 32 bits: GPIO, timers, interrupciones, UART, SPI, I²C | Todos los periféricos de la sección 4 |
| Describir circuitos en lugar de armarlos | Un lenguaje de descripción de hardware y una FPGA | Las máquinas de estados y los contadores del curso, escritos como código y ejecutados en paralelo |
| Entender cómo se construye una computadora | Arquitectura de computadoras y organización de un procesador | Registros, buses, memoria, contadores de programa y una máquina de estados enorme |
| Conectar con el mundo físico | Electrónica analógica, sensores, ADC y DAC | El comparador, el filtro RC y la tensión de umbral, ahora en el lado continuo |
| Diseñar sistemas confiables | Sincronización entre dominios de reloj, verificación, tolerancia a fallos | Los sincronizadores, los estados seguros y las verificaciones exhaustivas del curso |
10 · Comprensión
Confusiones frecuentes
«Un microcontrolador reemplaza todo lo del curso»
Lo contiene, pero no lo elimina: sus periféricos son esos bloques, y los problemas de tiempo, rebotes y metaestabilidad persisten. Entender los bloques es lo que permite configurarlos bien.
«Un bucle de espera es un buen temporizador»
Su duración depende del compilador y del reloj, y bloquea al procesador. Un timer cuenta con el reloj del sistema, sin consumir instrucciones.
«Si el programa es correcto, las señales también»
El programa puede ser correcto y el pin tener rebotes, ruido o un desacople insuficiente. Se verifica en el cronograma, no solo en el código.
«Más velocidad de comunicación siempre es mejor»
Más velocidad deja menos margen de tiempo y exige un reloj más exacto. Se elige la menor que cumpla el requisito.
«Los osciladores internos RC alcanzan para una UART»
Con ±2 % en cada extremo se puede llegar al 4 % de diferencia, cerca del límite de 5,3 %. Sin margen para jitter ni para detectar el flanco inicial. Con cristal, la diferencia es de ppm.
«Una interrupción es instantánea»
Hay latencia: la señal se sincroniza, la CPU termina la instrucción en curso, guarda su contexto y salta. Una bandera que no se borra vuelve a disparar.
«El hardware es más difícil que el software»
Es distinto: más lento de modificar, pero cada señal se puede medir. Un buen diseñador de sistemas conoce las dos mitades y decide cuál usar para cada bloque.
«Al terminar el curso ya no hace falta repasar la base»
Los temas 7, 11 y 20 (rebotes, metaestabilidad y entradas limpias) vuelven a aparecer en cada sistema real. Vale la pena revisarlos con la mirada de los proyectos.
11 · Práctica guiada
Predecí antes de simular
1. Identificar el bloque
La hoja de datos de un microcontrolador dice: «contador de 16 bits con prescaler y registro de captura/comparación». ¿Qué bloques del curso son?
Ver solución
Un contador (temas 17 a 19) con un divisor de frecuencia delante (prescaler) y un comparador con un registro (temas 13 y 33). Es el diseño del PWM del tema 33.
2. Calcular un timer
Con un reloj de 8 MHz y prescaler 8, ¿qué valor de comparación da una interrupción cada 100 ms?
Ver solución
Frecuencia del contador = 8 000 000 / 8 = 1 MHz. Para 100 ms hacen falta 100 000 cuentas: ARR = 100 000 − 1 = 99 999, que no entra en 16 bits (máximo 65 535). Con prescaler 64: 125 kHz y 12 500 cuentas, ARR = 12 499.
3. Tolerancia de una UART
Dos equipos usan osciladores de ±1 %. ¿Pueden comunicarse en 8N1 con muestreo a mitad del bit?
Ver solución
La diferencia máxima es 2 %, menor que el límite de ±5,3 %: sí, con 3 puntos de margen. Con ±3 % cada uno, la diferencia de 6 % ya supera el límite.
4. Hardware o software
Un sistema debe generar un pulso de 10 µs de ancho exacto cada vez que llega un flanco de una entrada, sin importar lo que haga el procesador. ¿Dónde lo hacés?
Ver solución razonada
En hardware: un monoestable digital (contador + comparador, tema 32) o el periférico de captura y comparación de un timer, que dispara la salida sin intervención del procesador. En software, la latencia de la interrupción haría variar el ancho.
5. Antirrebote
Con muestreo cada 1 ms y rebotes de hasta 10 ms, ¿qué saturación del integrador alcanza? ¿Qué pasa si se usa un valor de 3?
Ver solución
Un valor de 15 a 20 muestras cubre cómodamente 10 ms de rebotes. Con 3, un tren de rebotes con más de tres unos seguidos puede saturar el contador y producir salidas falsas antes de que el contacto se estabilice.
6. Diagnóstico
Un microcontrolador lee un botón en un pin y cuenta cada pulsación, pero cuenta de 3 a 5 de cada vez. ¿Qué falta y cómo se confirma?
Ver solución razonada
Falta un antirrebote, por hardware (RC y Schmitt) o por software (integrador, o ignorar el pin durante unos 20 ms tras el primer flanco). Se confirma capturando el pin con un analizador lógico: se verá una ráfaga de flancos al cerrar y al abrir.
12 · Síntesis final
Ideas para llevarte
- Todo sistema secuencial se arma con pocos bloques: memoria de un bit (latch y flip-flop), registros, contadores, comparadores, tablas (ROM) y una disciplina de reloj.
- Una máquina de estados es un registro más una tabla de próximo estado y salidas; una secuencia de salidas es un contador más una tabla. Con datos en lugar de cableado, el comportamiento cambia sin tocar el circuito.
- El tiempo se mide contando un reloj estable; la exactitud la da el cristal y el divisor, no la lógica.
- Las entradas externas se filtran (antirrebote), se memorizan (latch) y se sincronizan (dos flip-flops); las salidas de lógica combinacional se registran antes de usarlas.
- Un buen diseño nace de requisitos numerados, se divide en bloques con interfaces claras, se verifica en código y se arma por etapas.
- Depurar es comparar un cronograma esperado con uno medido, buscando el primer desvío y cambiando una cosa por vez.
- Los periféricos de un microcontrolador (GPIO, timer, PWM, SPI, UART, interrupciones, watchdog, memorias) son los bloques del curso, accesibles desde un mapa de memoria.
- Elegir entre hardware y software es una decisión de velocidad, determinismo, flexibilidad y costo, que se toma bloque por bloque.
Fin del curso
Si podés explicar con tus palabras cómo se pasa de un latch a un flip-flop, cómo un contador y una ROM generan una animación, por qué una entrada asíncrona necesita un sincronizador y qué hace por dentro un timer de microcontrolador, el curso cumplió su objetivo. El resto es práctica: armar, medir, equivocarse y volver al cronograma.