Catto / Mapa de Temas · Electrónica Digital III 6° año
Electrónica Digital III · 144 h · Eje 3 de 7

Periféricos

Los periféricos son hardware que trabaja solo, en paralelo con la CPU. Un temporizador cuenta mientras el programa hace otra cosa; un módulo PWM sostiene una salida sin que nadie lo atienda. Entenderlos cambia la manera de escribir programas: se deja de esperar.

Microcontroladores Temporizadores Interrupciones PWM Conversor A/D

01Dejar de esperar

El primer programa de cualquiera hace parpadear un LED con un retardo. El problema aparece con el segundo requerimiento: mientras espera, el programa no puede hacer nada más. Ni leer un pulsador, ni atender el puerto serie, ni medir una temperatura.

// Así NO: mientras dura el retardo, el micro está preso
while (1) {
    led_on();  _delay_ms(500);
    led_off(); _delay_ms(500);      // un pulsador apretado acá no se detecta
}

// Así SÍ: el temporizador cuenta solo y avisa; el lazo queda libre
while (1) {
    if (bandera_500ms) { bandera_500ms = 0; led_toggle(); }
    atender_pulsadores();
    atender_puerto_serie();
}

El segundo esquema —lazo principal que nunca se bloquea más banderas que ponen las interrupciones— es la estructura de casi todo programa embebido serio.

PeriféricoQué hace soloEjemplo típico
Temporizador / contadorCuenta pulsos de reloj o eventos externosBase de tiempo, medir frecuencia, generar retardos
PWMSostiene una onda cuadrada de ciclo de trabajo ajustableBrillo de un LED, velocidad de un motor, servo
Captura (CCP)Guarda el valor del contador cuando llega un flancoMedir el ancho de un pulso, un período, un sensor ultrasónico
ComparaciónDispara un evento cuando el contador llega a un valorInterrupción periódica exacta, generar frecuencias
Conversor A/DConvierte una tensión en un númeroSensores, potenciómetros, medición de batería
USART, SPI, I²CArma y desarma tramasMódulo de comunicación
WatchdogVigila que el programa no se cuelgueSeguridad en equipos que quedan solos

02Temporizadores

Un temporizador es un contador binario —lo mismo que se vio en contadores programables— alimentado por el reloj del sistema a través de un preescaler, que es simplemente un divisor.

OCR = 249 · comparación desborde (255) salida valor del contador tiempo En modo CTC el contador se reinicia al llegar a OCR: el período queda fijo y exacto.
Figura 1. El contador y sus dos eventos, animado. Cuando llega al valor cargado en el registro de comparación se produce un evento y —si está en modo CTC— el contador se reinicia. Si nadie lo detiene, sigue hasta el desborde y vuelve a cero solo.
ttick=NfoscOCR=fosc·tN1 N es el preescaler (1, 8, 64, 256, 1024). El «−1» está porque el contador arranca en cero: si se quieren 250 cuentas, el valor de comparación es 249.
Ejemplo resuelto · Una interrupción cada milisegundo

Cristal de 16 MHz, temporizador de 8 bits en modo CTC:

  1. Con preescaler 64, cada cuenta dura 64/16 000 000 = 4 µs.
  2. Para 1 ms hacen falta 1000/4 = 250 cuentas.
  3. Se carga OCR = 250 − 1 = 249. Como entra en 8 bits (máximo 255), sirve.
  4. Verificación: (249 + 1) × 4 µs = 1000 µs exactos. Sin error, porque 16 MHz es múltiplo de 64 × 1000.

Con preescaler 8 harían falta 2000 cuentas: no entra en 8 bits y hay que usar el temporizador de 16 bits. Ese es el razonamiento completo: elegir el preescaler más chico cuyo resultado entre en el contador, porque cuanto menor es el preescaler, mejor es la resolución.

Los modos que hay que conocer
  • Normal: cuenta hasta el máximo y desborda. Simple, pero el período queda fijo por el preescaler.
  • CTC (comparar y borrar): cuenta hasta OCR y se reinicia. Es el modo de las bases de tiempo exactas.
  • Fast PWM y PWM de fase correcta: la salida cambia sola según el valor de comparación. Ver la sección de PWM.
  • Contador de eventos externos: en vez del reloj interno cuenta flancos en una pata. Es un frecuencímetro con dos líneas de código.

03Interrupciones

Una interrupción es un desvío automático: cuando el periférico levanta su bandera, la CPU termina la instrucción en curso, guarda dónde estaba y salta a una rutina especial. Al terminar, vuelve exactamente al mismo lugar. El programa principal ni se entera.

Qué se gana
  • Respuesta inmediata a un evento, sin estar preguntando.
  • El lazo principal queda libre.
  • Permite dormir el micro y despertarlo sólo cuando pasa algo.
Las reglas de una ISR
  • Cortísima. Poner una bandera, leer un dato, y salir. Nada de retardos, cálculos largos ni mandar caracteres por el puerto serie.
  • Las variables que comparte con el lazo principal se declaran volatile, o el compilador las optimiza y el programa deja de ver los cambios.
  • Si la variable compartida es de más de un byte, hay que leerla con las interrupciones deshabilitadas: si no, se puede leer la mitad vieja y la mitad nueva.
  • La bandera se limpia sola o hay que limpiarla a mano según el periférico: si no se limpia, la interrupción se dispara para siempre.
// Base de tiempo de 1 ms con el temporizador en CTC
volatile uint16_t ms = 0;      // volatile: la modifica una interrupción

ISR(TIMER0_COMPA_vect) {          // se ejecuta cada 1 ms
    ms++;                         // y nada más: la ISR termina acá
}

int main(void) {
    TCCR0A = (1 << WGM01);                    // modo CTC
    TCCR0B = (1 << CS01) | (1 << CS00);      // preescaler 64
    OCR0A  = 249;                            // 250 cuentas de 4 µs = 1 ms
    TIMSK0 = (1 << OCIE0A);                   // habilita la interrupción
    sei();                                     // habilita globalmente
    while (1) { /* el lazo queda libre para todo lo demás */ }
}
Latencia y prioridades

Entre que ocurre el evento y que empieza la ISR pasan algunos microsegundos: la CPU termina la instrucción en curso y guarda el contexto. Si además hay otra interrupción ejecutándose, hay que esperarla. Por eso las ISR largas arruinan la respuesta de todo el sistema: una que tarda 2 ms hace perder pulsos a todas las demás. En los micros chicos las prioridades son fijas y están en la tabla de vectores de la hoja de datos.

04PWM: modulación por ancho de pulso

Una salida que conmuta rápido entre 0 y VCC, con el tiempo en alto ajustable. El valor medio es proporcional a ese tiempo, y con eso se regula potencia sin disipar: el transistor está saturado o cortado, nunca en el medio.

0 V 5 V valor medio = 0,50 V ciclo de trabajo = 10 % valor medio = 1,75 V ciclo de trabajo = 35 % valor medio = 3,25 V ciclo de trabajo = 65 % valor medio = 4,50 V ciclo de trabajo = 90 % brillo La frecuencia no cambia: lo que cambia es cuánto tiempo la salida está en alto. El transistor está saturado o cortado: no disipa, y por eso se regula potencia sin calentar.
Figura 2. Ciclo de trabajo, animado. La frecuencia no cambia; lo que cambia es cuánto tiempo la salida está en alto. La línea punteada es el valor medio, que es lo que ve una lámpara, un motor o un filtro R-C.
D=taltoT·100Vmed=D·VCCfPWM=foscN·2n Con 16 MHz, preescaler 64 y 8 bits de resolución: f = 16 000 000/(64 × 256) = 976,6 Hz. Subir la resolución baja la frecuencia, y viceversa: es el compromiso central del PWM.
AplicaciónFrecuencia adecuadaPor qué
Brillo de un LED> 100 HzPor debajo se ve el parpadeo, sobre todo al mover la vista.
Motor de continua1 a 20 kHzPor debajo de 20 kHz se escucha el zumbido; por encima, las pérdidas de conmutación crecen.
Calefactor o carga térmica< 10 HzLa inercia térmica promedia sola: no hace falta conmutar rápido.
Servomotor50 Hz exactosNo regula por valor medio: el ángulo lo fija el ancho del pulso, entre 1 y 2 ms.
Salida analógica (con filtro R-C)Alta, y filtro lentoCuanto más alta la frecuencia, más chico el rizado que queda.
Ejemplo · Un servo con el temporizador de 16 bits

Cristal de 16 MHz, preescaler 8 → cada cuenta dura 0,5 µs.

  • Período de 20 ms (50 Hz) = 20 000 µs / 0,5 = 40 000 cuentas: entra justo en 16 bits.
  • Pulso de 1 ms (0°) = 2000 cuentas. Pulso de 2 ms (180°) = 4000 cuentas.
  • Cada grado son (4000 − 2000)/180 = 11,1 cuentas: hay resolución de sobra.

Con el temporizador de 8 bits esto no se puede hacer: no alcanzan las cuentas para 20 ms con resolución útil. Elegir el temporizador correcto es parte del problema.

05Captura y comparación

Captura

Cuando llega un flanco a una pata, el módulo copia el valor del contador en un registro y avisa. La CPU no tiene que estar mirando: el instante queda registrado con la precisión del temporizador.

Con dos capturas —flanco de subida y de bajada— se mide el ancho de un pulso. Es la manera correcta de leer un sensor ultrasónico HC-SR04, un receptor de control remoto o la señal de un caudalímetro.

Comparación

Al revés: cuando el contador llega a un valor cargado, dispara un evento —interrupción, cambio de una pata, reinicio del contador—. Es lo que hay debajo del modo CTC y del PWM.

Ejemplo · Medir distancia con ultrasonido

El sensor devuelve un pulso cuyo ancho es proporcional al tiempo de ida y vuelta del sonido.

  • Con preescaler 8 a 16 MHz, cada cuenta son 0,5 µs.
  • Se capturan los dos flancos y se restan: si la diferencia es de 2320 cuentas, el pulso duró 2320 × 0,5 = 1160 µs.
  • El sonido viaja a 343 m/s: recorrió 0,001160 × 343 = 0,398 m, ida y vuelta. La distancia es la mitad: 19,9 cm.

Midiendo lo mismo con un lazo de espera, cualquier interrupción que ocurra en el medio arruina la medición. Con captura, no.

06El conversor A/D interno

Casi siempre es de aproximaciones sucesivas, de 10 o 12 bits, con un multiplexor que permite elegir entre varias patas. Todo lo conceptual está en conversores A/D y D/A; acá interesan los cuatro parámetros que hay que configurar.

Qué se eligeDetalle
CanalQué pata se mide. El multiplexor es uno solo: se mide un canal por vez, y hay que esperar entre cambios.
ReferenciaLa alimentación, una referencia interna (1,1 V típica) o una externa por AREF. Define la escala completa y con ella la resolución.
Reloj del conversorCon preescaler propio: debe quedar entre 50 y 200 kHz para la máxima exactitud. A 16 MHz con preescaler 128 da 125 kHz, y una conversión tarda unos 104 µs.
Alineación y disparoSi el resultado se alinea a izquierda (útil para leer sólo 8 bits) y si la conversión arranca por software o por un evento del temporizador.
Los tres errores que arruinan una medición analógica
  • Referencia sucia: si se usa VCC como referencia y la alimentación tiene rizado, la lectura fluctúa aunque la entrada esté quieta. Referencia interna o externa filtrada.
  • Fuente de alta impedancia: el capacitor del sample & hold no llega a cargarse. La hoja de datos pide menos de 10 kΩ; con más, hace falta un seguidor con operacional.
  • Ruido digital: conmutaciones del propio micro acopladas a la entrada. Se promedia, se separan las masas y, en los micros que lo tienen, se usa el modo de reducción de ruido que duerme la CPU durante la conversión.

07En el laboratorio

Práctica 1 · Base de tiempo exacta

Configurar el temporizador en CTC para una interrupción cada 1 ms y conmutar una pata en cada interrupción. Medir con el osciloscopio: deben salir 500 Hz exactos. Después cambiar el preescaler sin cambiar OCR y ver cómo se corre la frecuencia. Con eso queda clara la fórmula.

Práctica 2 · Parpadeo sin bloquear

Escribir el mismo parpadeo de dos maneras: con _delay_ms() y con la base de tiempo por interrupción. En las dos, agregar un pulsador que encienda otro LED. Con el retardo, el pulsador responde tarde o no responde; con la interrupción, responde siempre. Es la práctica que justifica todo el eje.

Práctica 3 · PWM y valor medio

Generar PWM a 1 kHz y variar el ciclo de trabajo con un potenciómetro leído por el A/D. Medir con el osciloscopio el ancho del pulso y, con el multímetro en continua, el valor medio. Verificar que Vmed = D × VCC. Después agregar un filtro R-C y comparar la salida filtrada con la cruda.

Práctica 4 · Servo

Con el temporizador de 16 bits, mover un servo de 0° a 180° según el potenciómetro. Medir el ancho del pulso en los extremos y verificar que sean 1 y 2 ms. Anotar qué pasa si la frecuencia no es de 50 Hz.

Práctica 5 · Medir un pulso con captura

Generar un pulso de ancho conocido con un 555 y medirlo con el módulo de captura. Comparar con la medición del osciloscopio. Repetir agregando una interrupción que consuma tiempo: la medición por captura no cambia, y ese es el punto.

08Errores frecuentes

SíntomaCausa habitual
La interrupción se dispara sin pararNo se limpió la bandera del periférico, o se la limpió mal.
El programa principal no ve el cambio de una variableFalta volatile: el compilador la guardó en un registro y no la relee.
Un contador de 16 bits da valores absurdos de vez en cuandoSe lo leyó mientras la interrupción lo modificaba. Hay que leerlo con interrupciones deshabilitadas.
El sistema responde lento o pierde pulsosUna ISR demasiado larga. Sacar todo lo que no sea imprescindible al lazo principal.
El tiempo del temporizador no da lo calculadoSe olvidó el «−1» del registro de comparación, o el reloj real no es el supuesto (fuses, divisor por 8 activado).
El LED con PWM parpadea de manera visibleFrecuencia demasiado baja: subirla por encima de 100 Hz.
El motor con PWM chillaFrecuencia dentro de la banda audible. Llevarla por encima de 18 a 20 kHz.
El servo tiembla o no llega a los extremosPeríodo distinto de 20 ms, o anchos fuera del rango del modelo. Cada servo tiene el suyo.
La lectura del A/D salta varias cuentasReferencia con rizado, fuente de alta impedancia o ruido. Promediar y revisar las tres causas.
Al cambiar de canal, la primera lectura está malFalta esperar el tiempo de adquisición después de mover el multiplexor. Se descarta la primera conversión.

09Autoevaluación

¿Qué ventaja concreta tiene un temporizador frente a un lazo de retardo?

Que cuenta solo, en paralelo con la CPU. El programa no queda bloqueado y puede atender otras cosas; además, el tiempo no depende de lo que el programa esté haciendo.

Con 8 MHz y preescaler 256, ¿cuánto dura una cuenta y cuánto un desborde de 8 bits?

Cada cuenta dura 256/8 000 000 = 32 µs; el desborde ocurre cada 256 × 32 = 8,192 ms.

Se quiere una interrupción cada 2 ms con 16 MHz y preescaler 64. ¿Qué valor de comparación?

Cada cuenta son 4 µs; 2000/4 = 500 cuentas → OCR = 499. Como no entra en 8 bits, hay que usar el temporizador de 16 bits (o preescaler 256, con OCR = 124).

¿Por qué una variable compartida con una ISR se declara volatile?

Porque el compilador, al no ver que nadie más la modifica, puede guardarla en un registro y no volver a leerla de memoria. volatile le prohíbe esa optimización y obliga a leerla cada vez.

¿Qué debe hacer —y qué no— una rutina de atención de interrupción?

Debe: leer el dato o poner una bandera y salir. No debe: usar retardos, hacer cálculos largos, mandar por el puerto serie ni refrescar el watchdog.

Con PWM de 8 bits, preescaler 8 y 16 MHz, ¿cuál es la frecuencia?

f = 16 000 000/(8 × 256) = 7812,5 Hz. Sirve para un motor —está por debajo de lo audible molesto pero conmuta rápido— y de sobra para un LED.

¿Por qué un servo no se controla por valor medio?

Porque su electrónica interna mide el ancho del pulso, no el promedio: entre 1 y 2 ms dentro de un período de 20 ms. Dos señales con el mismo valor medio y distinto ancho dan ángulos distintos.

¿Para qué sirve el módulo de captura?

Para registrar el instante exacto en que llega un flanco, copiando el valor del contador sin intervención de la CPU. Con dos capturas se mide el ancho de un pulso o un período sin que otras tareas afecten la medición.

Se mide una tensión que varía muy poco y la lectura del A/D salta ±3 cuentas. ¿Qué se revisa?

La referencia (rizado de la alimentación), la impedancia de la fuente (demasiado alta para el sample & hold) y el ruido digital acoplado. Además conviene promediar varias lecturas.

¿Por qué conviene descartar la primera conversión después de cambiar de canal?

Porque el capacitor de retención todavía tiene la carga del canal anterior y necesita un tiempo de adquisición para tomar el valor nuevo. La primera lectura queda contaminada por la medición previa.

Desarrollo del eje «Periféricos» de Electrónica Digital III (6° año), según la «Propuesta Curricular – Segundo Ciclo de la Modalidad Técnico Profesional, Educación Secundaria – Electrónica», Ministerio de Educación de la Provincia de Córdoba, DGETyFP. Volver al Mapa de Temas · catto.ar