Saltar al contenido
Apuntes GITT 4º

Escribe al menos dos letras.

    SEDAPWM y servosPEI1 · 19:00 en 20 días

    Temporizadores

    PWM y servos

    PWM con un Timer, el periférico PWM1 y el control de un servo

    Idea clave. Una PWM es una señal de periodo fijo en la que solo cambia cuánto tiempo está en alto. Con eso se regula el brillo de una pantalla o se le dice a un servo a qué ángulo ir. Se puede generar con un Timer normal (gastando interrupciones) o con el periférico PWM1, que lo hace todo en hardware.

    Qué es una PWM

    D=THTPWM0≤D≤1D = \frac{T_H}{T_{PWM}} \qquad 0 \le D \le 1

    TPWMT_{PWM} es el periodo (fijo) y THT_H el tiempo en alto. En cuentas del timer: NT=Ftick⋅TPWMN_T = F_{tick}\cdot T_{PWM}, NH=D⋅NTN_H = D\cdot N_T y NL=NT−NHN_L = N_T - N_H.

    PWM con un Timer y toggle

    Es el método de las varias señales del tema 2, pero sumando una cantidad distinta según el nivel del pin. Con EMCx = 11 (conmutar) y sin reset:

    void TIMER0_IRQHandler(void) {
      LPC_TIM0->IR = (1 << 0);
      if (LPC_TIM0->EMR & (1 << 0))   // EM0: el pin acaba de pasar a 1
        LPC_TIM0->MR0 += N_H;         // la próxima conmutación, dentro de T_H
      else
        LPC_TIM0->MR0 += N_L;
    }

    El bit EM0 de EMR dice el nivel actual de MAT0.0, así que no hace falta leer el pin. El límite: si THT_H o TLT_L son más cortos que latencia + ejecución de la ISR, cuando se suma el Match ya ha pasado y se pierde un flanco. Los ciclos de trabajo muy pequeños o muy grandes (D ≈ 0,001 o D ≈ 1) a frecuencia alta no salen.

    PWM con un Timer y dos Match

    Una alternativa con una sola interrupción por periodo:

    MR0=FtickFPWM−10≤MR1≤MR0D≈MR1MR0MR0 = \frac{F_{tick}}{F_{PWM}} - 1 \qquad 0 \le MR1 \le MR0 \qquad D \approx \frac{MR1}{MR0}
    void TIMER0_IRQHandler(void) {
      LPC_TIM0->IR  = (1 << 1);       // flag de MR1
      LPC_TIM0->EMR &= ~(1 << 0);     // MAT0.0 a 0
    }

    Con MR2 y MR3 se pueden sacar más PWM con el mismo periodo (cada una en su pin y con su parte de código en la ISR). Con periodos distintos, no: el periodo lo marca MR0 para todo el timer.

    El periférico PWM1

    Práctica 2 (PWM para el brillo del LCD) · conviene dominarlo

    Para no gastar CPU, el LPC1768 tiene un periférico dedicado: PWM1. Es un Timer con 7 Match (MR0–MR6) y 6 salidas (PWM1.1–PWM1.6):

    PWM1MR0=FtickFPWM−10≤PWM1MRx≤PWM1MR0PWM1MR0 = \frac{F_{tick}}{F_{PWM}} - 1 \qquad 0 \le PWM1MRx \le PWM1MR0

    En flanco único (single edge, el de reset), la salida sube al empezar el periodo y baja cuando TC = MRx:

    TH=MRxFtickD=MRxMR0+1T_H = \frac{MRx}{F_{tick}} \qquad D = \frac{MRx}{MR0 + 1}

    Ojo con el −1. Estas fórmulas son las de clase, que cuentan de 0 a MR0 como un Timer. El UM10360 dice que en modo PWM el contador vuelve a 1 (no a 0), y su ejemplo pone MR0 = 100 para un periodo de 100 cuentas; con esa lectura, PWM1MR0=Ftick/FPWMPWM1MR0 = F_{tick}/F_{PWM}. Con valores grandes (24 999 o 25 000) la diferencia es de una cuenta; en el examen, usa la convención de clase.

    En doble flanco (bits PWMSEL de PCR), la subida y la bajada las marcan dos Match. Así se pueden desplazar los pulsos, pero solo salen 3 salidas.

    PWM1TCR · control
    BitsCampoQué hace
    0Counter Enable1 = contar
    1Counter Reset1 = TC y PC a 0
    3PWM Enable1 = modo PWM (activa los registros sombra)
    PWM1MCR · qué hace cada Match
    BitsCampoQué hace
    0, 1, 2PWMMR0I, PWMMR0R, PWMMR0SInterrumpir, poner el TC a 0 o parar en MR0. Para una PWM: PWMMR0R
    3–20MR1–MR6Lo mismo para cada Match, 3 bits por Match (para PWM se dejan a 0)
    PWM1PCR · tipo y habilitación de cada salida
    BitsCampoQué hace
    2–6PWMSEL2–61 = doble flanco en esa salida; 0 = flanco único
    9–14PWMENA1–61 = salida PWM1.1…PWM1.6 habilitada
    PWM1LER · cargar los registros sombra
    BitsCampoQué hace
    0–6Enable PWM Match 0–6 LatchEl valor escrito en MRx se usa a partir del siguiente MR0

    Por qué hay registros sombra. Si se cambiase MRx a mitad de periodo, podría salir un pulso cortado o doble. Con LER, el valor nuevo espera al siguiente MR0 y el cambio siempre empieza en un periodo limpio.

    void set_ciclo(float ciclo) {          // ciclo en %, de 0 a 100
      LPC_PWM1->MR5 = ciclo * LPC_PWM1->MR0 / 100;
      LPC_PWM1->LER = (1 << 5);            // se aplica en el próximo periodo
    }

    La configuración inicial: alimentar (PWM1 ya está encendido tras el reset), llevar el pin a su función PWM1.x con PINSEL, escribir MR0 con MR0R en MCR, habilitar la salida en PCR, poner los bits de LER y arrancar con Counter Enable + PWM Enable en TCR.

    Servos

    Práctica 3 (Servomotor con un Timer) · conviene dominarlo

    Un servo de radiocontrol lleva dentro un motor, una reductora y un control de lazo cerrado: compara su posición con la que le pide la señal y se mueve hasta igualarlas. Tiene tres cables (alimentación, masa y control), y por el de control recibe una PWM: el ancho del pulso dice el ángulo.

    TH=0,4+2⋅grados180 msT_H = 0{,}4 + 2\cdot\frac{grados}{180}\ \text{ms}
    void set_servo(float grados) {
      LPC_PWM1->MR5 = Ftick * 0.4e-3 + Ftick * 2e-3 * grados / 180;
      LPC_PWM1->LER = (1 << 5);
    }

    Cada servo tiene sus extremos reales algo distintos, así que se calibran los anchos mínimo y máximo antes de fijar la fórmula.

    Preguntas de examen

    Genera con PWM1 una señal de 1 kHz con D = 30 % (F_PCLK = 25 MHz). Da MR0, MRx y los registros que tocas.

    PWM1MR0=25⋅106/1000−1=24 999PWM1MR0 = 25\cdot 10^6/1000 - 1 = 24\,999. MRx=0,3⋅(MR0+1)=7 500MRx = 0{,}3\cdot(MR0+1) = 7\,500. MCR: MR0R (bit 1). PCR: PWMENAx. LER: bits 0 y x. TCR: bits 0 y 3. Y el pin en su función PWM1.x con PINSEL. (Respuesta redactada a partir de los apuntes.)

    ¿Qué ventajas tiene PWM1 frente a generar la PWM con un Timer e interrupciones?

    No gasta CPU (no hay ISR por flanco), no tiene el límite de latencia (D muy pequeños o muy grandes salen bien), da hasta 6 salidas con la misma frecuencia y, gracias a los registros sombra, cambiar el ciclo de trabajo no corta ningún periodo. La pega: todas sus salidas comparten frecuencia. (Respuesta redactada a partir de los apuntes.)

    Escribe set_servo(grados) para un servo de 0,4–2,4 ms y explica cada término.

    MR5 = Ftick*0.4e-3 + Ftick*2e-3*grados/180: el primer término son las cuentas del ancho mínimo (0,4 ms, 0°); el segundo añade la parte proporcional al ángulo, hasta 2 ms más a 180°. Luego LER = (1 << 5) para que se aplique en el siguiente periodo. (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 y 24.