Saltar al contenido
Apuntes GITT 4º

Escribe al menos dos letras.

    SEDAReloj, GPIO e interrupcionesPEI1 · 19:00 en 20 días

    El LPC1768

    Reloj, GPIO e interrupciones

    De 12 MHz a 100 MHz, PCLK, PCONP, pines y NVIC

    Idea clave. Antes de usar cualquier periférico del LPC1768 hay que hacer siempre lo mismo: alimentarlo (PCONP), elegir su reloj (PCLKSEL), llevarlo a sus pines (PINSEL) y, si va a interrumpir, habilitar su interrupción en el NVIC. Este tema explica cada paso. Los siguientes solo cambian el periférico.

    El reloj: de 12 MHz a 100 MHz

    La Mini-DK2 lleva un cristal de 12 MHz (el oscilador principal). Al arrancar, la función SystemInit() de system_LPC17xx.c monta esta cadena:

    PasoQué haceValor por defecto
    CLKSRCSELElige la fuente: oscilador principal, oscilador RC interno (4 MHz) o el del RTCOscilador principal, 12 MHz
    PLL0Multiplica: FCCO=2⋅M⋅FinNF_{CCO} = \dfrac{2\cdot M\cdot F_{in}}{N}M=100M = 100, N=6N = 6 → 400 MHz
    Divisor de CPUCCLK=FCCOCCLKSEL+1CCLK = \dfrac{F_{CCO}}{CCLKSEL + 1}÷4 → 100 MHz
    PCLKSEL0/1Reloj de cada periférico÷4 → 25 MHz
    PLLCLK=2⋅100⋅12 MHz6=400 MHzCCLK=4004=100 MHzFPCLK=CCLK4=25 MHzPLLCLK = \frac{2\cdot 100\cdot 12\ \text{MHz}}{6} = 400\ \text{MHz} \qquad CCLK = \frac{400}{4} = 100\ \text{MHz} \qquad F_{PCLK} = \frac{CCLK}{4} = 25\ \text{MHz}

    Ese 25 MHz aparece en casi todas las cuentas de timers, PWM y UART. Si en un examen no dicen otra cosa, es el FPCLKF_{PCLK} de partida.

    PCLKSEL0 · reloj de cada periférico (2 bits por periférico)
    BitsCampoQué hace
    3:2PCLK_TIMER0Reloj del Timer 0
    5:4PCLK_TIMER1Reloj del Timer 1
    7:6PCLK_UART0Reloj de la UART0
    13:12PCLK_PWM1Reloj del PWM1
    25:24PCLK_ADCReloj del ADC

    Cada par de bits vale 00 = CCLK/4 (el de reset), 01 = CCLK, 10 = CCLK/2 y 11 = CCLK/8. Timer 2/3 y UART 2/3 están en PCLKSEL1.

    Alimentar el periférico: PCONP

    Para ahorrar energía, no todos los periféricos arrancan encendidos. Cada uno tiene un bit en PCONP:

    Encendidos tras el resetApagados tras el reset
    Timer 0 y 1 (PCTIM0, PCTIM1), UART 0 y 1, PWM1, GPIOTimer 2 y 3 (bits 22 y 23), UART 2 y 3 (bits 24 y 25), ADC (bit 12)
    LPC_SC->PCONP |= (1 << 22);   // enciende el Timer 2 (PCTIM2)

    El |= («o» bit a bit) pone a 1 solo el bit 22 y deja el resto como estaba. (1 << 22) es un 1 desplazado 22 posiciones: la máscara de ese bit.

    Pines: función y modo

    Cada pin del LPC1768 puede tener hasta cuatro funciones (GPIO o la de un periférico). Se elige con PINSEL0…10, con 2 bits por pin: 00 es GPIO y 01, 10, 11 son las funciones alternativas que da la tabla del manual (cap. 8).

    PINMODE elige la resistencia interna del pin, también con 2 bits:

    PINMODEModo
    00Pull-up (el de reset)
    01Repetidor
    10Ni pull-up ni pull-down
    11Pull-down

    Por eso un pulsador entre el pin y masa funciona sin resistencia externa: en reposo el pull-up deja el pin a 1, y al pulsar se une a masa y lee 0. En la Mini-DK2 los pulsadores ISP, Key1 y Key2 están en P2.10, P2.11 y P2.12.

    GPIO: entradas y salidas

    Los puertos P0…P4 tienen sus registros en LPC_GPIO0…LPC_GPIO4:

    RegistroPara qué
    FIODIRDirección de cada bit: 1 = salida, 0 = entrada
    FIOSETEscribir 1 en un bit pone ese pin a 1. Los 0 no hacen nada
    FIOCLREscribir 1 en un bit pone ese pin a 0. Los 0 no hacen nada
    FIOPINLeer el nivel de los pines (o escribirlos todos de golpe)
    FIOMASKBits a 1 = pines que los demás registros ignoran
    LPC_GPIO3->FIODIR |= (1 << 25);           // P3.25 como salida
    LPC_GPIO3->FIOSET  = (1 << 25);           // P3.25 a 1
    LPC_GPIO3->FIOCLR  = (1 << 25);           // P3.25 a 0
    if ((LPC_GPIO2->FIOPIN & (1 << 11)) == 0) // ¿P2.11 a 0? (pulsado)

    FIOSET y FIOCLR se escriben con =, no con |=: como los ceros no hacen nada, no hace falta leer antes. La comprobación usa & con la máscara para quedarse solo con el bit 11.

    Interrupciones: el NVIC

    El NVIC (Nested Vectored Interrupt Controller) del Cortex-M3 decide qué interrupción se atiende y cuándo. Lo que hay que saber:

    Interrupciones externas EINT0–EINT3

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

    Son los pines P2.10–P2.13 en su primera función alternativa (01 en PINSEL4). Se configuran en el bloque de control del sistema (LPC_SC):

    RegistroPara qué
    EXTMODEBit a 0 = por nivel, bit a 1 = por flanco
    EXTPOLARNivel bajo o flanco de bajada (0), nivel alto o flanco de subida (1)
    EXTINTFlags. Se borran escribiendo un 1 en su bit
    void EINT1_IRQHandler(void) {   // Key1 (P2.11)
      LPC_SC->EXTINT = (1 << 1);    // borrar el flag de EINT1
      pulsado = 1;                  // volatile: lo lee el main
    }

    Por nivel, el flag no se puede borrar mientras el nivel siga activo, así que la interrupción se relanza. Para un pulsador se usa casi siempre flanco de bajada.

    SysTick

    Es un temporizador de 24 bits que lleva el propio Cortex-M3, pensado para dar un «tic» periódico. SysTick_Config(SystemCoreClock / 100) genera una interrupción cada 10 ms en SysTick_Handler. Para periodos que no caben en 24 bits, o para varias señales, se usan los Timers del tema siguiente.

    Preguntas de examen

    Explica el camino del reloj desde el cristal hasta un periférico, con las frecuencias por defecto.

    Cristal de 12 MHz → la PLL0 multiplica a FCCO=2⋅M⋅Fin/N=2⋅100⋅12/6=400F_{CCO} = 2\cdot M\cdot F_{in}/N = 2\cdot 100\cdot 12/6 = 400 MHz → el divisor de CPU divide entre 4: CCLK = 100 MHz → cada periférico divide CCLK según sus bits de PCLKSEL (por defecto ÷4): FPCLK=25F_{PCLK} = 25 MHz. (Respuesta redactada a partir de los apuntes.)

    ¿Qué pasos hay que dar para usar el Timer 2 con interrupción?
    1. Alimentarlo: PCONP |= (1 << 22).
    2. Elegir su reloj en PCLKSEL1 (o dejar CCLK/4).
    3. Si saca señal por un pin, elegir esa función en PINSEL.
    4. Configurar el timer (PR, MR, MCR) y arrancarlo.
    5. NVIC_SetPriority(TIMER2_IRQn, …) y NVIC_EnableIRQ(TIMER2_IRQn).
    6. En TIMER2_IRQHandler, borrar el flag en IR.

    (Respuesta redactada a partir de los apuntes.)

    ¿Por qué FIOSET y FIOCLR se escriben con «=» y no con «|=»?

    Porque en esos registros un 0 no hace nada: solo actúan los bits que se escriben a 1. Con = se cambia únicamente el pin de la máscara, sin leer el registro antes y sin riesgo de tocar los demás pines. (Respuesta redactada a partir de los apuntes.)

    Material del curso usado: Apuntes de Miguel · Resumen de interrupciones del LPC1768 (diapositivas de clase) · Resumen de GPIO del LPC1768 (diapositivas de clase) · UM10360 (manual del LPC17xx), cap. 4, 6, 8 y 9.