当前位置:网站首页>STM32CubeMX 学习(6)外部中断实验
STM32CubeMX 学习(6)外部中断实验
2022-06-29 18:38:00 【小辉_Super】
个人学习记录
一、新建工程

二、选择芯片型号
我使用的开发板是正点原子 STM32F103ZET6 核心板

三、配置时钟
开发板焊接了外部晶振,所以我 RCC(Reset and Cock Control) 配置选择了 Crystal/Ceramic Resonator(石英/陶瓷谐振器),配置完成后,右边的 Pinout view 里相关引脚就会被标绿。

外部高速时钟配置完成后,进入 Clock Configuration 选项,根据实际情况,将系统时钟配置为 72 MHz,配置步骤如下,最后按下回车,软件会自动调整分频和倍频参数。

四、配置调试模式
ST-Link 就是 Serial Wire 调试模式,一定要设置!!!
以前使用 M0 的芯片,不配置这个模式没出现问题,但现在这个型号,如果不配置 Serial Wire 模式,程序一旦通过 ST-Link 烧录到芯片中,芯片就再也不能被ST-Link 识别了。(后来我是通过 STMISP 工具烧录程序/擦除后才恢复正常的)

五、外部中断参数配置

我所用的开发板上有两个按键,分别与单片机的两个 IO 相连,另一脚上拉,所以当按键按下时,IO 能收到高电平信号。
按照下面的步骤来配置这两个 GPIO:将 GPIO 设置为外部中断功能,中断模式为上升沿/下降沿触发(本实验主要用到了上升沿触发)

外部中断还需要使能,可以在 GPIO 的 NVIC 配置中使能,也可以直接在 NVIC 总配置中开启相应的中断线。另外,由于我的实验中会用到 Hal 库延时函数(放在外部中断处理函数中,由滴答定时器中断实现)所以必须让滴答定时器的中断优先等级高于外部中断的优先级。

六、生成 Keil 工程
设置 IDE 和 工程目录及名称:

将每种外设的代码存放到不同的 .c /.h 文件中,便于管理(不然都会被放到 main.c 中)。

下面是生成 Keil 工程中关于 GPIO(EXTI)初始化的代码:
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {
0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PE4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_SetPriority(EXTI4_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI4_IRQn);
}
七、中断函数写在哪
在使用标准库时,我们是将中断处理写在最底层的中断处理函数中,如 EXTI0_IRQHandler(),但 Hal 库增加了回调函数,将中断底层一些必要的操作 “隐藏” 了起来(如清除中断)。
中断的调用顺序是(以 EXTI0 为例):EXTI0_IRQHandler() —> HAL_GPIO_EXTI_IRQHandler() —> HAL_GPIO_EXTI_Callback()。
/** * @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 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);
}
}
八、测试示例
实验中用到了串口,上文配置中没提及,串口配置可以参考 STM32CubeMx 学习(2)USART 串口实验
我的实验代码的核心部分为中断回调函数:
// 外部中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0)
{
HAL_Delay(10); // 消除抖动(实际使用中不建议在中断中延时)
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == SET)
{
Exti_Flag1 = 1; // 外部中断标志置1,在main函数中处理
}
}
if(GPIO_Pin == GPIO_PIN_4)
{
HAL_Delay(10); // 消除抖动(实际使用中不建议在中断中延时)
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == SET)
{
Exti_Flag2 = 1; // 外部中断标志置1,在main函数中处理
}
}
}
完整 main.c
/* USER CODE BEGIN Header */
/** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2022 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
uint8_t Exti_Flag1; // 外部中断触发标志
uint8_t Exti_Flag2; // 外部中断触发标志
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/** * @brief The application entry point. * @retval int */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(Exti_Flag1)
{
// 串口发送数据
HAL_UART_Transmit(&huart1, "WK_UP is pressed.\r\n", 19, 0xffff);
// 清除标志
Exti_Flag1 = 0;
}
if(Exti_Flag2)
{
// 串口发送数据
HAL_UART_Transmit(&huart1, "KEY0 is pressed.\r\n", 18, 0xffff);
// 清除标志
Exti_Flag2 = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/** * @brief System Clock Configuration * @retval None */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {
0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {
0};
/** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
// 外部中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0)
{
HAL_Delay(10); // 消除抖动(实际使用中不建议在中断中延时)
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == SET)
{
Exti_Flag1 = 1; // 外部中断标志置1,在main函数中处理
}
}
if(GPIO_Pin == GPIO_PIN_4)
{
HAL_Delay(10); // 消除抖动(实际使用中不建议在中断中延时)
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == SET)
{
Exti_Flag2 = 1; // 外部中断标志置1,在main函数中处理
}
}
}
/* USER CODE END 4 */
/** * @brief This function is executed in case of error occurrence. * @retval None */
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
实验效果:
我没有使用实物进行测试,而是使用了 Keil 的软件调试功能,这个功能我已经在 重映射串口到 rt_kprintf 函数(学习笔记) 提及,这里不作介绍。
软件仿真中,设置按键对应的 GPIO 的输入电平,串口就会打印相应的数据,说明按键中断(外部中断)成功触发且中断回调函数成功执行。

边栏推荐
- Basis of data analysis -- prediction model
- 2. 在STM32CubeMX建立的Keil5工程中添加自定义的相关文件
- C Primer Plus 第12章_存储类别、链接和内存管理_代码和练习题
- 第三方工具与框架集成
- 75.二叉搜索树额最近公共祖先
- Apache inlong million billion level data stream processing
- Mac: MySQL 66 questions, 20000 words + 50 pictures!
- curl下载示例
- 山东大学项目实训(七)添加导航栏选择城市
- The strategy of convertible bonds -- - (cake sharing, premium, forced redemption, downward revision, double low)
猜你喜欢

Machine learning 8-artificial neural network

【️爬虫必备->Scrapy框架从黑铁到王者️】初篇——万字博文详解(建议收藏)

Dragon canvas animation

细说GaussDB(DWS)复杂多样的资源负载管理手段

Advanced features of selenium webdriver

Apache inlong million billion level data stream processing

网站加了CDN后,字体图标报错Access-Control-Allow-Origin
![报错[warning] Neural network inference was performed on socket ‘RGB’, depth frame is aligned to socket](/img/8a/ebad75daa581e22d50dddde49e1fac.jpg)
报错[warning] Neural network inference was performed on socket ‘RGB’, depth frame is aligned to socket

Know that Chuangyu has helped the energy industry in asset management and was selected into the 2021 IOT demonstration project of the Ministry of industry and information technology

Apache Doris basic usage summary
随机推荐
Basis of data analysis -- prediction model
Us judge ruled that the former security director of Uber accused of covering up hacking must face fraud charges
建立自己的网站(12)
BeanUtils属性复制的用法
C Primer Plus 第12章_存储类别、链接和内存管理_代码和练习题
garbage collector
第三方工具与框架集成
Hello, do you have any official website samples for MySQL CDC, PostgreSQL CDC? Give me a link to learn
习题8 #第8章 Verilog有限状态机设计-4 #Verilog #Quartus #modelsim
Shandong University project training (VIII) design rotation map entry page
微信推出图片大爆炸功能;苹果自研 5G 芯片或已失败;微软解决导致 Edge 停止响应的 bug|极客头条
Source code installation mavros
How to use an oak camera as a webcam?
JS text particle dynamic background
The strategy of convertible bonds -- - (cake sharing, premium, forced redemption, downward revision, double low)
Anfulai embedded weekly report no. 271: June 20, 2022 to June 26, 2022
2022.6.29-----leetcode. five hundred and thirty-five
Apache Doris basic usage summary
数据分析--时间序列预测
炒股用同花顺开户交易安全吗?