1. Nouvelle construction
1. Ouvrez le logiciel STM32CubeMX et cliquez sur "Nouveau projet"
2. Choisissez MCU et package
3. Configurez les
paramètres de l'horloge RCC, sélectionnez HSE (horloge haute vitesse externe),
sélectionnez Configuration de l'horloge pour le résonateur à cristal / céramique (oscillateur à cristal / résonateur en céramique) , configurez l'horloge système SYSCLK à 72 MHz,
modifiez la valeur de HCLK à 72, et appuyez sur Entrée. Modifiez automatiquement toutes les configurations
4. C'est
une étape très importante pour configurer le mode de débogage , sinon le
paramètre SYS du débogueur ne sera pas reconnu après le premier programme de programmation , sélectionnez Déboguer comme Serial Wire
Deux, interruption externe EXTI
2.1 Configuration des paramètres
Lors de la System Core
sélection des GPIO
paramètres.
Trouvez la broche correspondante du bouton dans la figure de droite et sélectionnez-la GPIO_EXTIx
.
Ici, le x
moyen monté sur plusieurs lignes d'interruption, est monté sur une telle interruption GPIO_EXTI0 0.
-
Ouvrir front descendant déclenché interruption: à savoir, lorsque la touche est enfoncée niveau lorsqu'il est déclenché par un haut en bas, puis la
GPIO mode
choisiExternal Interrupt Mode with Falling edge trigger detection
-
Ouvrir front montant interruptions déclenchées: à savoir, lorsque le bouton de déverrouillage est enfoncé après que les changements de niveau de déclenchement de faible à élevé, la
GPIO mode
sélectionExternal Interrupt Mode with Rising edge trigger detection
-
Les interruptions déclenchées par front montant sont activées en descendant: cela se déclenche lorsque vous appuyez à nouveau lorsque vous relâchez la gâchette , puis
GPIO mode
sélectionnezExternal Interrupt Mode with Rising/Falling edge trigger detection
-
S'il s'agit d'un matériel externe de traction ou de retrait, ne
GPIO Pull-up/Pull-down
sélectionnezNo pull-up and no pull-down
ni pull-up ni pull-down. -
Si le matériel n'est pas une traction externe,
GPIO Pull-up/Pull-down
sélectionnezPull-up
une résistance pullup interne.
Configuration LesNVIC
règles de regroupement de priorité d'interruption sontPriority Group
définies par défaut sur quatre bits, ne changent généralement pas.
Vérifiez la configuration externe, interrompez simplement 0 et 13, et configurez la priorité de préemptionPreemption Priority
et en réponse à la prioritéSub Priority
.- Préemptez la priorité, plus le nombre est petit, plus la priorité est élevée
- Si la priorité de préemption est la même, déterminez la sous-priorité. De même, plus le nombre est petit, plus la priorité est élevée
2.2 Générer du code
Noms des éléments de chemin et
sélection des entrées des éléments d'un environnement de développement d'application IDE MDK-ARM V5
chaque périphérique génère un ’.c/.h’
fichier séparé
non hook: tout le code d'initialisation est généré dans main.c
vérifié: fichier de code d'initialisation généré dans le périphérique associé. Par exemple, le code d'initialisation GPIO est généré dans gpio.c.
Cliquez sur GÉNÉRER LE CODE pour générer du code
2.3 Modifier la fonction de rappel d'interruption
Ouvrez le stm32f1xx_it.c
fichier de routine de service d'interruption, recherchez le service d'interruption de routine de service d'interruption EXTI0 EXTI0_IRQHandler()
à l'intérieur de la fonction s'appelle le gestionnaire d'interruption externe GPIO HAL_GPIO_EXTI_IRQHandler()
pour ouvrir le stm32f1xx_hal_gpio.c
fichier, recherchez le prototype de gestionnaire d'interruption externe HAL_GPIO_EXTI_IRQHandler()
, son rôle principal est de déterminer les interruptions de ligne de date, effacer le indicateur d'interruption, puis appelez la fonction de rappel d'interruption HAL_GPIO_EXTI_Callback()
.
/ * REMARQUE: Cette fonction ne doit pas être modifiée, lorsque le rappel est nécessaire,
le HAL_GPIO_EXTI_Callback peut être implémenté dans le fichier utilisateur
* /
Cette fonction ne doit pas être modifiée, si vous devez utiliser la fonction de rappel, veuillez réimplémenter la fonction dans le fichier utilisateur.
HAL_GPIO_EXTI_Callback()
Selon l'invite officielle, nous devrions redéfinir la fonction, qui __weak
est un indicateur affaibli. La fonction avec ceci est une fonction affaiblie, c'est-à-dire que vous pouvez écrire une fonction avec exactement le même nom et les mêmes paramètres ailleurs, et le compilateur ignorera cette fonction. À la place UNUSED(GPIO_Pin)
, exécutez la fonction que vous avez écrite; et , ceci est une définition sans erreur. Lorsque le numéro de port GPIO entrant n'est pas traité de quelque manière que ce soit, le compilateur ne signale pas d'avertissement. En fait, nous n'avons plus besoin de nous soucier de la fonction de service d'interruption lorsque nous développons. Nous devons seulement trouver la fonction de rappel d'interruption et la réécrire. Il y a un autre aspect très pratique de cette fonction de rappel qui n'est pas reflété ici. Lorsque plusieurs interruptions sont activées, STM32CubeMX organise automatiquement les fonctions de service de plusieurs interruptions ensemble et appelle une fonction de rappel, c'est-à-dire que quel que soit le nombre d'interruptions, il suffit de réécrire une fonction de rappel et de juger le numéro de port entrant OK.
Ensuite, nous stm32f1xx_it.c
ajoutons simplement le bas de ce documentHAL_GPIO_EXTI_Callback()
/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==KEY1_Pin)
{
// 自定义应用程序
HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
}
}
/* USER CODE END 1 */
2.3 Comparaison de la bibliothèque HAL et du code de la bibliothèque standard
STM32CubeMX utilise le code généré par la bibliothèque HAL:
#define KEY2_Pin GPIO_PIN_13
#define KEY2_GPIO_Port GPIOC
#define KEY2_EXTI_IRQn EXTI15_10_IRQn
#define KEY1_Pin GPIO_PIN_0
#define KEY1_GPIO_Port GPIOA
#define KEY1_EXTI_IRQn EXTI0_IRQn
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {
0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : KEY2_Pin */
GPIO_InitStruct.Pin = KEY2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : KEY1_Pin */
GPIO_InitStruct.Pin = KEY1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
/**
* @brief This function handles EXTI line0 interrupt.
*/
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
/* USER CODE END EXTI0_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
/* USER CODE BEGIN EXTI0_IRQn 1 */
/* USER CODE END EXTI0_IRQn 1 */
}
/**
* @brief This function handles EXTI line[15:10] interrupts.
*/
void EXTI15_10_IRQHandler(void)
{
/* USER CODE BEGIN EXTI15_10_IRQn 0 */
/* USER CODE END EXTI15_10_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
/* USER CODE BEGIN EXTI15_10_IRQn 1 */
/* USER CODE END EXTI15_10_IRQn 1 */
}
/**
* @brief This function handles EXTI interrupt request.
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
Utilisez le code de bibliothèque standard STM32:
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE GPIO_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
#define KEY2_IRQHandler EXTI15_10_IRQHandler
/**
* @brief 配置嵌套向量中断控制器NVIC
* @param 无
* @retval 无
*/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 配置NVIC为优先级组1 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* 配置中断源:按键1 */
NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
/* 配置抢占优先级 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 配置子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断通道 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 配置中断源:按键2,其他使用上面相关配置 */
NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief 配置 IO为EXTI中断口,并设置中断优先级
* @param 无
* @retval 无
*/
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/*开启按键GPIO口的时钟*/
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
/* 配置 NVIC 中断*/
NVIC_Configuration();
/*--------------------------KEY1配置-----------------------------*/
/* 选择按键用到的GPIO */
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
/* 配置为浮空输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
/* 选择EXTI的信号源 */
GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
/* EXTI为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 上升沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/*--------------------------KEY2配置-----------------------------*/
/* 选择按键用到的GPIO */
GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
/* 配置为浮空输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
/* 选择EXTI的信号源 */
GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
/* EXTI为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 下降沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
void KEY1_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET)
{
// LED1 取反
LED1_TOGGLE;
//清除中断标志位
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
void KEY2_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET)
{
// LED2 取反
LED2_TOGGLE;
//清除中断标志位
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
}
__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();
Correspondant au RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);
correspondant GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);HAL_NVIC_EnableIRQ(EXTI0_IRQn);
correspondant à NVIC_Init(&NVIC_InitStructure);EXTI_Init(&EXTI_InitStructure);
__HAL_GPIO_EXTI_GET_IT(GPIO_Pin)
un correspondant EXTI_GetITStatus(KEY1_INT_EXTI_LINE)
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin)
un correspondantEXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE)
Trois, les questions nécessitant une attention
Code utilisateur à ajouter USER CODE BEGIN N
et USER CODE END N
entre, sinon la prochaine utilisation après que STM32CubeMX régénère le code, il sera supprimé.
• Écrit par Leung le 12 janvier 2021
• Référence: Didacticiel 2 de la série STM32CubeMX : Interruption externe (EXIT)
[STM32Cube_05] Utiliser le bouton de détection d'interruption EXIT (configuration NVIC + mécanisme de gestion des interruptions de la bibliothèque HAL)
"Embedded-STM32 Development Guide" Partie 2 Bases - Chapitre 3 Boutons (bibliothèque HAL)
STM32CubeMX tutoriel de combat réel (trois) -interruption externe (fonction interruption et HAL_Delay pour éviter les fosses)