Temporizadores
Timers: Match e interrupciones periódicas
TC, PR, MR0 = Ftick·T − 1, MCR, IR y EMR
Idea clave. Un Timer es un contador que avanza solo a un ritmo conocido. Cuando llega a un valor que tú eliges (un Match), puede interrumpir, reiniciarse o cambiar un pin. Casi todo se reduce a una cuenta: cuántos «tics» caben en el tiempo que quieres.
Cómo está hecho un Timer
El LPC1768 tiene cuatro Timers (0–3), iguales. Cada uno tiene:
- PR (Prescaler) y PC: dividen el reloj. El contador avanza a . Con PR = 0 (el de reset), MHz.
- TC (Timer Counter): el contador de 32 bits.
- MR0–MR3: cuatro registros de Match. Un comparador mira en cada tic si TC = MRx.
- CR0–CR1: dos registros de captura (tema 4).
- Pines: salidas MATn.0–MATn.3 y entradas CAPn.0–CAPn.1.
| Bits | Campo | Qué hace |
|---|---|---|
| 0 | Counter Enable | 1 = el TC y el PC cuentan; 0 = parados |
| 1 | Counter Reset | 1 = TC y PC a 0 (y se quedan a 0 hasta volver a escribir 0) |
Qué pasa en un Match: MCR
Cada Match tiene tres bits en MCR. Con cuatro Match son 12 bits:
| Bits | Campo | Qué hace |
|---|---|---|
| 0 | MR0I | Interrumpir cuando TC = MR0 |
| 1 | MR0R | Reiniciar el TC (vuelve a 0) |
| 2 | MR0S | Parar el TC (pone a 0 el bit 0 de TCR) |
| 5:3 | MR1I, MR1R, MR1S | Lo mismo para MR1 |
| 11:9 | MR3I, MR3R, MR3S | Lo mismo para MR3 |
Y los flags de cada fuente están en IR: bits 0–3 para MR0–MR3 y bits 4–5 para CR0–CR1. Se borran escribiendo un 1.
a) Interrupción periódica
Práctica 3 (Servomotor con un Timer) · conviene dominarlo
Con MR0I y MR0R activos, el TC sube de 0 a MR0, interrumpe y vuelve a 0. Cuenta tics, así que:
LPC_TIM0->PR = 0; // F_tick = F_PCLK = 25 MHz
LPC_TIM0->MR0 = 25000000 / 1000 - 1; // 1 ms
LPC_TIM0->MCR = (1 << 0) | (1 << 1); // MR0I y MR0R
NVIC_EnableIRQ(TIMER0_IRQn);
LPC_TIM0->TCR = 1; // arranca
void TIMER0_IRQHandler(void) {
LPC_TIM0->IR = (1 << 0); // borrar el flag de MR0
// … lo que toque cada 1 ms
}
Es lo mismo que el SysTick, pero con cualquier Timer y con 32 bits. Si no cabe en 32 bits (periodos de minutos), se sube PR.
Sin reset: el TC corre libre
Si no se reinicia el TC, en cada interrupción se adelanta el Match:
void TIMER0_IRQHandler(void) {
LPC_TIM0->IR = (1 << 0);
LPC_TIM0->MR0 += N; // N = F_tick · T
}
Aquí , sin el −1: ya no se cuenta desde 0, sino desde el Match anterior. La ventaja es que cada Match lleva su propio periodo, porque ninguno reinicia el contador. Cuando el TC llega a da la vuelta a 0, y la suma también, así que sigue funcionando.
b) Señal cuadrada por hardware (sin interrupción)
EMR conecta cada Match con su pin MATn.x. Sin entrar en ninguna ISR, el pin puede ponerse a 0, a 1 o conmutar:
| Bits | Campo | Qué hace |
|---|---|---|
| 0–3 | EM0–EM3 | Nivel actual de cada salida (se puede leer y escribir) |
| 5:4 | EMC0 | En el Match 0: 00 nada, 01 a 0, 10 a 1, 11 conmuta |
| 7:6 | EMC1 | Igual para el Match 1 |
| 9:8 | EMC2 | Igual para el Match 2 |
| 11:10 | EMC3 | Igual para el Match 3 |
Con toggle y reset en MR0, el pin cambia cada tics: dos cambios por periodo.
El problema: el reset en MR0 reinicia el TC para todos los Match. Con este método sale una sola frecuencia por timer.
c) Varias señales con un timer
Para tener varias frecuencias se juntan los dos trucos: toggle sin reset y sumar en la ISR. Cada Match conmuta su pin y se adelanta medio periodo:
void TIMER0_IRQHandler(void) {
if (LPC_TIM0->IR & (1 << 0)) { // ¿ha sido MR0?
LPC_TIM0->IR = (1 << 0);
LPC_TIM0->MR0 += N0; // N0 = F_tick / (2 · F_0)
}
if (LPC_TIM0->IR & (1 << 1)) { // ¿ha sido MR1?
LPC_TIM0->IR = (1 << 1);
LPC_TIM0->MR1 += N1;
}
}
Salen hasta 4 señales por timer. Hay que mirar en IR qué Match ha interrumpido, porque todos comparten la misma ISR. Las señales rápidas interrumpen más veces, y si todas las frecuencias son múltiplos, pueden coincidir y entrar en todos los if de una vez.
Límite de frecuencia. Entre dos conmutaciones tiene que dar tiempo a entrar en la ISR y ejecutarla. Si en el peor caso coinciden dos señales:
De ahí sale . Además, cuanto más alta la frecuencia, más tiempo de CPU se come la ISR.
Preguntas de examen
Calcula MR0 para generar con MAT0.0 una señal cuadrada de 1 kHz por hardware (F_PCLK = 25 MHz, PR = 0) y di cómo configurarías MCR y EMR.
Un semiperiodo son 0,5 ms: . MCR: solo MR0R (bit 1), sin interrupción. EMR: EMC0 = 11 (bits 5:4, conmutar). Y el pin de MAT0.0 (P1.28 o P3.25) en esa función con PINSEL. (Respuesta redactada a partir de los apuntes.)
¿Por qué en la interrupción periódica es MR0 = F_tick·T − 1, pero al sumar en la ISR es N = F_tick·T?
Con reset, el TC pasa por 0, 1, …, MR0: son cuentas por periodo, de ahí el −1. Sin reset, el siguiente Match está N cuentas después del anterior, así que el periodo es exactamente tics. (Respuesta redactada a partir de los apuntes.)
Quieres dos señales de 1 kHz y 3 kHz con el mismo timer. ¿Qué método usas y qué valores de N?
Toggle sin reset y suma en la ISR. Con MHz: y (redondeando, 2,9994 kHz). Con toggle y reset no se podría, porque MR0 marcaría el periodo de las dos. (Respuesta redactada a partir de los apuntes.)
Material del curso usado: Apuntes de Miguel · Temporizadores del LPC17xx (diapositivas de clase) · UM10360 (manual del LPC17xx), cap. 21.