Interrupciones EINT0 y EINT2, SysTick y multiplexado de display en LPC1768
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
}