¿Qué debo hacer si STM32 interrumpe el experimento?
Dependiendo de la situación específica, puedes ver mi experimento a continuación para analizar tu problema:
Propósito del experimento:
Cuando se presiona el botón, deje que se encienda la luz LED del pin PF10.
Cuando se presiona nuevamente el botón, la luz LED del pin PF10 se apaga;
Ya sea que se presione o no, el La luz LED del pin PF9 circula Parpadeando;
Pasos experimentales:
Procedimientos experimentales:
[cpp]?ver plano?copia
/***** *******************************led.c********** ******** ****************/?
#include?"stm32f4xx.h"?//Se puede encontrar en el SISTEMA directorio?
#include?"sys.h"?
void?LED_Init(void){?
RCC->AHB1ENR?=?1<< 5;?//Habilitar reloj del puerto GPIO F
GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_25M,GPIO_PUPD_PU);?
PFout(9)?=?1 ;?
PFout(10)?=?1;?
}?
[cpp]?ver plano?copia
/****** *******************************led.h********* ********* ****************/?
#ifndef?_LED_H?
#define?_LED_H?
¿nulo? LED_Init(nulo);?
#endif?
[cpp]?ver plano?copia
/** ********** **********************************clave.c**** ************ *************************/?
#include?" sys.h"?
void?Key_Init(void){?
RCC->AHB1ENR|=1<<4;?//¿Habilitar reloj PORTE?
//void?GPIO_Set(GPIO_TypeDef*? GPIOx,u32?BITx,u32?MODE,u32?OTYPE,u32?OSPEED,u32?PUPD);//Función de configuración de GPIO
GPIO_Set(GPIOE, PIN3,GPIO_MODE_IN,0,0,GPIO_PUPD_PU); ?//PE3 establece la entrada pull-up, en este caso,?
//Cuando no se presiona el botón, el nivel predeterminado es alto;?
}?
[cpp]?ver plano?copiar
/****************** ************** ************clave.h********************* ********************* ****/?
#ifndef?_KEY_H?
#define?_KEY_H ?
void?Key_Init(void);?
#endif?
[cpp]?view Plain?copy
/* ********************** *********
*****exti.c************************************/?
# include?"sys.h"?
#include?"delay.h"?
#include?"stm32f4xx.h"?
/ *?
La función de este ejemplo es,?
Cuando se presiona el botón, sonará el timbre,?
Cuando se presiona el botón nuevamente, el timbre sonará y silenciará el dispositivo;?
*/?
/*?
Función de inicialización de interrupción:?
Principalmente. relacionado con la configuración de registros ?
*/?
void?EXTI3_Init(void){?
//Método 1: ?
RCC->APB2ENR ?|=?1?<14;?//¿Encender el reloj SYSCFG?
SYSCFG->EXTICR[0]?|=?0x4?<12 ;//Establecer el puerto IO y la relación de mapeo central de desconexión;?
EXTI->IMR?|=?1?<3;?//¿Habilitar la interrupción en la línea de interrupción correspondiente?
EXTI- >FTSR?|=?1?<3;?//¿Establecer condiciones de activación de interrupción?
//Para SCB y NVIC, consulte STM32F3 y STM32F4 series Cortex?M4 core programming manual.pdf?
SCB->AIRCR?|=?0x5?<8;?//¿Establecer agrupación?
NVIC->IP[ 9]?|=?0;?// Establecer la prioridad Para obtener más detalles, puede analizar la función MY_NVIC_Init();?
NVIC->ISER[0]?|=?1?<< ?9;?//Habilitar interrupciones;?
//Método 2:?
/********************* ***************** ***?
Utilice la API proporcionada en el directorio del SISTEMA para implementar,?
Para más detalles, ¿Consulta el ejemplo del átomo puntual?
******* **************************** */?
}?
void?EXTI3_IRQHandler (void){?
/*?
Este botón no se maneja bien cuando se presiona el botón?
Necesita más mejoras, principalmente hacer doble clic en ese enlace.
?
*/?
delay_ms(20);?//¿Rebote?
if(PEin(3)?==?0){? /p>
PFout(10)?=?!PFout(10);?
}?
/*?
Dentro de la interrupción Finalmente , recuerda borrar la interrupción:?
*/?
EXTI->PR?|=?1?<3;?
}
[cpp]?ver plano?copia
/****************************** ** *******exti.h************************************/?
#ifndef?_EXTI_H?
#define?_EXTI_H?
void?EXTI3_Init(void);?
#endif?
[cpp]?ver plano?copia
/****************************** ************** **prueba.c******************************/ ?
#include?"sys .h"?
#include?"delay.h"?
#include?"key.h"?
#include?"beep.h "?
#include?"exti.h"?
#include?"led.h"?
//int?i?=?0 ;?
int?main(void){?
Stm32_Clock_Init(336,8,2,7);// Configure el reloj, 168 Mhz
delay_init( 168);//¿Función de retardo de inicialización?
Beep_Init();?
Key_Init();?
EXTI3_Init();?
LED_Init();?
mientras(1){?
PFout(9)?=?0; ?
delay_ms(500); ?
PFout(9)?=?1;?
delay_ms(500);?
}?
}?
Análisis experimental:
Analizamos principalmente los pasos de configuración del registro en exti.c:
1 RCC->APB2ENR |= 1 < < 14;
La función de este paso es habilitar el reloj SYSCFG.
Cuando se utilizan interrupciones externas, el reloj SYSCFG debe habilitarse primero. ;
2. SYSCFG->EXTICR[0] |= 0x4 << 12;
La función de este paso es establecer la relación de mapeo entre el puerto IO y la línea de interrupción. ;
Entonces la pregunta es: ¿Cómo sé a qué línea de interrupción está asociado mi puerto IO?
Y usamos el botón KEY1, y el puerto IO correspondiente es PE3, por lo que a partir de la relación de mapeo en la figura anterior, sabemos que debemos elegir la línea de interrupción 3 para que corresponda;
En el archivo de encabezado proporcionado oficialmente stm32f4xx.h, podemos ver:
[cpp]?view Plain?copy
typedef?struct?
{ ?
__IO?uint32_t?MEMRMP;/*!
__IO?
uint32_t?PMC;?/*!
__IO?uint32_t?EXTICR[4];/*!
uint32_t?RESERVED[2];?/*!
[cpp]?vista simple?copia
__IO?uint32_t?CMPCR;/*!
SYSCFG_TypeDef;?
Combinando las tres imágenes anteriores, podemos saber:
Debido a la línea de interrupción correspondiente a PE3 Es EXTI3, por lo que solo necesitamos configurar EXTI3 aquí, y EXTI3 está en SYSCFG_EXTICR1;
Entonces solo necesitamos configurar los bits 12-15 del registro SYSCFG_EXTICR1 en 0100, y el registro SYSCFG_EXTICR1 está en el archivo de configuración,
corresponde a SYSCFG->EXTICR[0], por lo que escribimos SYSCFG->EXTICR[0] |= 0x4 << 12;
3. |= 1 << 3;
La función de esta declaración es habilitar la interrupción en la línea de interrupción correspondiente
Dado que la línea de interrupción que operamos es EXTI3 e IMR La explicación de el registro es el siguiente:
Entonces, en consecuencia, podemos operar el tercer bit MR3 del registro EXTI_IMR;
Entonces esta declaración se escribe como: EXTI->IMR |= 1 < < 3
4. EXTI->FTSR |= 1 << 3;
La función de esta declaración es establecer la condición de activación de la interrupción;
En mi caso En la placa de desarrollo, cuando se presiona el botón, su puerto pasará a nivel bajo, y cuando no se presiona, será de nivel alto;
Porque en nuestra clave.c, El pin del botón está configurado para tirar hacia arriba; así que aquí tengo que configurarlo para que funcione con flanco descendente;
Al mismo tiempo, mirando el registro EXTI_FTSR, puedes ver:
Y dado que nuestra línea de interrupción es la línea de interrupción 3, esta declaración se escribe como: EXTI->FTSR |= 1 << 3
5 SCB->AIRCR |= 0x5 << 8;
La función de esta declaración es establecer la agrupación;
Entonces, aquí solo necesitamos configurar el bit10-8 del AIRCR de SCB para verificar la estructura de SCB, Aprendido:
[cpp]?ver plano?copia
typedef?struct?
{?
__I?uint32_t?CPUID ;/*!
__IO?uint32_t?ICSR;/*!
__IO?uint32_t?VTOR;/*!
?0x008?(R/W)?Vector?Tabla?Offset?Registro?*/?
__IO?uint32_t?AIRCR;/*!
__IO?uint32_t?SCR;?/*!
__IO?uint32_t?CCR;?/*!
__IO?uint8_t ?SHP[12];?/*!
__IO?uint32_t?SHCSR;/*!
__IO?uint32_t?CFSR;/*!
__IO?uint32_t?HFSR;/*!< ?Offset:?0x02C?(R/W)?HardFault?Status?Register?*/?
__IO?uint32_t?DFSR;/*!
__IO?uint32_t?MMFAR;/*!
__IO?uint32_t?BFAR;/*!
__IO?uint32_t?AFSR ;/*!
__I?uint32_t?PFR[2];?/*!
__I?uint32_t?DFR;?/*!
__I?uint32_t?ADR;?/*!
__I?uint32_t?MMFR[4];?/*!
__I?uint32_t?ISAR [5];?/*!
uint32_t?R
ESERVED0[5];?
__IO?uint32_t?CPACR;/*!
}?SCB_Type;?
Entonces, aquí escribimos esta declaración como SCB->AIRCR |= 0x5 << 8;
Es decir, se establece en 101, es decir, la prioridad de preferencia ocupa 2 bits y la prioridad de respuesta ocupa 2 bits;
Nota: La prioridad de preferencia es la misma que la prioridad de respuesta. Cuanto menor sea el valor, mayor será la prioridad;
La subprioridad mencionada anteriormente es también lo que llamamos prioridad de respuesta;
6. NVIC->IP[9] |= 0;
Está la anterior. declaración, podemos saber que: el registro IP consta de 240 registros de 8 bits, y cada interrupción enmascarable ocupa 8 bits, por lo que el total puede representar 240 interrupciones enmascarables, y STM32F4 solo usa 82. IP [81] ~ IP [0] corresponden a las interrupciones 81 ~ 0 respectivamente. No se utilizan todos los 8 bits ocupados por cada interrupción enmascarable, solo se utilizan los 4 bits superiores;
Estos 4 bits, Se divide además en prioridad de preferencia y prioridad de respuesta; la prioridad de preferencia está al frente y la prioridad de respuesta está detrás, es decir, la prioridad de preferencia está en un nivel alto y la prioridad de respuesta está en un nivel bajo;
Y sabemos: nuestra interrupción es la interrupción externa 3, por lo que podemos verlo en la tabla de vectores de interrupción:
Se puede ver que la posición de interrupción de EXTI3 es 9, por lo que solo necesitamos configurar NVIC ->IP[9];
Aquí ponemos NVIC->IP[9] |= 0;, lo que significa que establecemos la prioridad de preferencia de la interrupción externa 3 en 0, y la prioridad de respuesta también es 0, cada uno ocupa 2 bits;
7.NVIC->ISER[0] |= 1 << 9;
La función de este paso es habilitar la interrupción ; p>
ISER es un grupo de registros de habilitación de interrupciones; aquí se utilizan ocho registros de 32 bits para controlar, cada bit controla una interrupción pero las interrupciones enmascarables de STM32F4 solo tienen un máximo de 82, por lo que para nosotros, las tres más; los útiles son (ISER [0 ~ 2]), el total puede representar 96 interrupciones, mientras que STM32F4 solo usa las primeras 82 interrupciones, 0 bits ~ 31 de ISER [0] corresponden a las interrupciones 0 ~ 31 de ISER. [1] corresponde a la interrupción 32~63; bit0~32 de ISER[2] corresponde a la interrupción 64~81;
Aquí sabemos: Nuestro EXTI3 corresponde a La posición de interrupción es 9, por lo que solo necesitamos configurar el noveno bit de ISER[0], así que escribimos esta
declaración aquí como: NVIC->ISER[0] |= 1 << 9;?
8 En cuanto a cómo escribir el nombre de la función de interrupción externa, podemos encontrarlo en el archivo de inicio;
Cuando configuramos la función de interrupción externa y el archivo de inicio Cuando los nombres definidos en son consistentes,<. /p>
luego, cuando se cumpla la condición de interrupción, el cuerpo de su función se ejecutará en la función de interrupción;
Solo debemos recordar borrar la interrupción para evitar interrupciones repetidas;
Notas:
En este experimento, el procesamiento del botón no se manejó muy bien.
Lo principal debería ser que actualmente estoy haciendo clic en esta área, así que no lo he hecho. Aún no lo he ajustado. Lo haré de nuevo cuando lo necesite.
Reimpreso en /u010661782/article/details/50281229 Gracias al autor original por su guía y estudio tan detallados.
Primera introducción a las interrupciones STM32
Hace algún tiempo usé a menudo el descubrimiento stm32f4, pero como no sé mucho sobre NVIC y EXTI, he estado evitando el uso de interrupciones en el pasado. Dos días. No tengo nada que hacer y decidí aprender las interrupciones de stm32 y escribir mi experiencia. Si hay algún error, corríjame. ?
Utilicé varios documentos de registro de documentos (RM0090), "Manual de referencia técnica de Cortex-M", "Guía genérica del usuario de dispositivos Cortex?-M4", "Manual de referencia de arquitectura ARMv7-M" 》Póngalo Baidu Cloud Si lo necesita, ¿puede recogerlo usted mismo? Contraseña: enlace web 4g91