Interrupciones EINT0 y EINT2, SysTick y multiplexado de display en LPC1768

Informática6,66 KB

Interrupciones, temporización y multiplexado de display en LPC1768

A continuación se presenta el código en C para un microcontrolador LPC1768, que gestiona interrupciones externas, un temporizador SysTick y el multiplexado de un display de 7 segmentos.

Rutinas de interrupción externa

void EINT0_IRQHandler(void){
    LPC_SC->EXTINT |= (1 << 0); // Flag EXTINT
    if(antirebotes > 0) return;
    antirebotes = 200;
    estado = 1;
cuentas_tiempo = 10000;
}

void EINT2_IRQHandler(void){
    LPC_SC->EXTINT |= (1 << 0);
    if(antirebotes > 0) return;
    antirebotes = 200;
    if(LPC_GPIO0->FIOPIN & (1 << 10)) frecuencia = 500;
    else frecuencia = 250;
}

Presentación en display

La función presentar_en_display() selecciona, mediante multiplexado, el dígito a mostrar según el estado del sistema:

  • Estado 0: recorre los seis dígitos del mensaje.
  • Estado 1: muestra los segundos restantes en el primer dígito.
void presentar_en_display(){
    switch (estado) {
        case 0: {
            indice++;
            if(indice > 5) indice = 0;
            LPC_GPIO0->FIOCLR = (0x3F << 4);            // Apago los 6 ánodos
            LPC_GPIO0->FIOSET = (1 << (indice + 4));
            LPC_GPIO2->FIOSET = (0xFF);                    // Apago los segmentos
            LPC_GPIO2->FIOCLR = ~(mensaje[indice] << 0);
        } break;
        case 1: {
            LPC_GPIO0->FIOCLR = (0x3F << 4);
            LPC_GPIO0->FIOSET = (1 << 4);
            LPC_GPIO2->FIOSET = (0xFF);
            LPC_GPIO2->FIOCLR = ~(BCDto7seg[segundos] << 0);
        } break;
        default: break;
    }
}

Manejador del temporizador SysTick

La interrupción SysTick_Handler gestiona el antirrebotes, controla el parpadeo de un LED en el estado 0, la cuenta regresiva en el estado 1 y activa el multiplexado del display cada tres interrupciones.

void SysTick_Handler(void) {
    if(antirebotes > 0) antirebotes--;
    switch (estado) {
        case 0:
            cuentas_frecuencia++;
            if (cuentas_frecuencia > frecuencia) {
                cuentas_frecuencia = 0;
                LPC_GPIO0->FIOPIN ^= (1 << 16);
            }
            break;
        case 1:
            cuentas_tiempo--;
            LPC_GPIO0->FIOCLR |= (1 << 16);
            LPC_GPIO0->FIOPIN |= (3 << 17);
            segundos = cuentas_tiempo / 2000;
            if (cuentas_tiempo == 0) {
                estado = 0;
                LPC_GPIO0->FIOPIN &= ~(3 << 17);
            }
            break;
        default: break;
    }
    cuentas_MUX_display++;
    if(cuentas_MUX_display > 2) {
        cuentas_MUX_display = 0;
        presentar_en_display();
    }
}

Configuración del SysTick

void Configura_SysTick(void) {
    SysTick->LOAD = 50e3 - 1;
    SysTick->VAL = 0;
    SysTick->CTRL = 7;
}

Configuración de pines

La función Configura_Pines() configura los puertos GPIO como salida o entrada, y establece el modo de pull-up mediante PINSEL y PINMODE.

void Configura_Pines(void) {
    LPC_PINCON->PINSEL0 &= ~((3 << (4*2)) | (3 << (5*2)) | (3 << (6*2)) | (3 << (7*2)) | (3 << (8*2)) | (3 << (9*2)) | (3 << (10*2)));
    LPC_PINCON->PINMODE0 &= ~(3 << (10*2));
    LPC_PINCON->PINMODE0 &= ~((1 << (4*2)) | (1 << (5*2)) | (1 << (6*2)) | (1 << (7*2)) | (1 << (8*2)) | (1 << (9*2)) | (1 << (10*2)));
    LPC_PINCON->PINMODE0 |= ((2 << (4*2)) | (2 << (5*2)) | (2 << (6*2)) | (2 << (7*2)) | (2 << (8*2)) | (2 << (9*2)) | (2 << (10*2)));
    LPC_GPIO0->FIODIR |= (0x3F << 4) | (0x07 << 16);
    LPC_GPIO0->FIODIR &= ~(1 << (10*2));
    LPC_GPIO0->FIOCLR = (0x3F << 0) | (0x07 << 16);
    LPC_PINCON->PINSEL1 &= ~((3 << (16-16)*2) | (3 << (17-16)*2) | (3 << (18-16)*2));
    LPC_PINCON->PINMODE1 &= ~((1 << (16-16)*2) | (1 << (17-16)*2) | (1 << (18-16)*2));
    LPC_PINCON->PINMODE1 |= ((2 << (16-16)*2) | (2 << (17-16)*2) | (2 << (18-16)*2));
    LPC_PINCON->PINSEL4 &= ~((3 << (0*2)) | (3 << (1*2)) | (3 << (2*2)) | (3 << (3*2)) | (3 << (4*2)) | (3 << (5*2)) | (3 << (6*2)) | (3 << (7*2)));
    LPC_PINCON->PINMODE4 &= ~((1 << (0*2)) | (1 << (1*2)) | (1 << (2*2)) | (1 << (3*2)) | (1 << (4*2)) | (1 << (5*2)) | (1 << (6*2)) | (1 << (7*2)));
    LPC_PINCON->PINMODE4 |= ((2 << (0*2)) | (2 << (1*2)) | (2 << (2*2)) | (2 << (3*2)) | (2 << (4*2)) | (2 << (5*2)) | (2 << (6*2)) | (2 << (7*2)));
    LPC_GPIO2->FIODIR |= (0xFF << 0);
    LPC_GPIO2->FIOSET = (0xFF << 0);
}

Configuración de interrupciones

La función Configura_IRQs() configura las interrupciones externas EINT0 y EINT2 por flanco, define las prioridades en el NVIC y habilita dichas interrupciones.

void Configura_IRQs(void) {
    // Configuración pin 2.10 EINT0
    LPC_PINCON->PINSEL4 |= (1 << (10*2));
    LPC_PINCON->PINSEL4 &= ~(2 << (10*2));
    LPC_SC->EXTMODE |= (1 << 0);   // Por flanco
    LPC_SC->EXTPOLAR |= (1 << 0);

    // Configuración pin 2.12 EINT2
    LPC_PINCON->PINSEL4 |= (1 << (12*2));
    LPC_PINCON->PINSEL4 &= ~(2 << (12*2));
    LPC_SC->EXTMODE |= (1 << 2);   // Por flanco
    LPC_SC->EXTPOLAR |= (1 << 2);  // Por flanco

    LPC_SC->EXTINT |= (0xF);             // Borrado flag EXTINT
    NVIC_ClearPendingIRQ(EINT0_IRQn);       // Borrado de INT pendiente
    NVIC_ClearPendingIRQ(EINT2_IRQn);       // Borrado de INT pendiente

    NVIC_SetPriorityGrouping(4);
    NVIC_SetPriority(SysTick_IRQn, 0x4);
    NVIC_SetPriority(EINT0_IRQn, 0x8);
    NVIC_SetPriority(EINT2_IRQn, 0x8);
    NVIC_EnableIRQ(EINT0_IRQn);             // Habilitar interrupción EINT0
    NVIC_EnableIRQ(EINT2_IRQn);             // Habilitar interrupción EINT2
}

Descargar

PDF Word HTML