Saltar al contenido
Apuntes GITT 4º

Escribe al menos dos letras.

    SEDATimers: Match e interrupciones periódicasPEI1 · 19:00 en 20 días

    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:

    TnTCR · control del contador
    BitsCampoQué hace
    0Counter Enable1 = el TC y el PC cuentan; 0 = parados
    1Counter Reset1 = 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:

    TnMCR · acción en cada Match (MR0; MR1–MR3 siguen igual de 3 en 3)
    BitsCampoQué hace
    0MR0IInterrumpir cuando TC = MR0
    1MR0RReiniciar el TC (vuelve a 0)
    2MR0SParar el TC (pone a 0 el bit 0 de TCR)
    5:3MR1I, MR1R, MR1SLo mismo para MR1
    11:9MR3I, MR3R, MR3SLo 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 MR0+1MR0 + 1 tics, así que:

    Tint=MR0+1Ftick⟹MR0=Ftick⋅Tint−1T_{int} = \frac{MR0 + 1}{F_{tick}} \quad\Longrightarrow\quad MR0 = F_{tick}\cdot T_{int} - 1
    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 Ftick⋅TF_{tick}\cdot T no cabe en 32 bits (periodos de minutos), se sube PR.

    Para resolver

    Calculadora de Timer: MR0 para un periodo

    Desarrollo

      Con T = 1 ms y FPCLK = 25 MHz: PR = 0, MR0 = 24999.

      Desarrollo

      1. Cuentas del TC en un periodo:

      2. El TC cuenta de 0 a MR0 (MR0 + 1 estados), así que:

      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í N=Ftick⋅TN = F_{tick}\cdot T, 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 232−12^{32}-1 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:

      TnEMR · salidas de Match
      BitsCampoQué hace
      0–3EM0–EM3Nivel actual de cada salida (se puede leer y escribir)
      5:4EMC0En el Match 0: 00 nada, 01 a 0, 10 a 1, 11 conmuta
      7:6EMC1Igual para el Match 1
      9:8EMC2Igual para el Match 2
      11:10EMC3Igual para el Match 3

      Con toggle y reset en MR0, el pin cambia cada MR0+1MR0 + 1 tics: dos cambios por periodo.

      Tout2=MR0+1Ftick⟹MR0=Ftick2⋅Fout−1\frac{T_{out}}{2} = \frac{MR0 + 1}{F_{tick}} \quad\Longrightarrow\quad MR0 = \frac{F_{tick}}{2\cdot F_{out}} - 1

      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 NN 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:

      2⋅(tlatencia+tejecucioˊn)≤Tout22\cdot(t_{\text{latencia}} + t_{\text{ejecución}}) \le \frac{T_{out}}{2}

      De ahí sale FmaxF_{max}. 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: MR0=25⋅1062⋅1000−1=12 499MR0 = \dfrac{25\cdot 10^6}{2\cdot 1000} - 1 = 12\,499. 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 MR0+1MR0 + 1 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 NN 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 Ftick=25F_{tick} = 25 MHz: N0=25⋅1062⋅1000=12 500N_0 = \dfrac{25\cdot 10^6}{2\cdot 1000} = 12\,500 y N1=25⋅1062⋅3000≈4 167N_1 = \dfrac{25\cdot 10^6}{2\cdot 3000} \approx 4\,167 (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.