IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于cubemx的stm32开发之路(使用正点原子战舰V3开发板)——按键外部中断 -> 正文阅读

[嵌入式]基于cubemx的stm32开发之路(使用正点原子战舰V3开发板)——按键外部中断

CubeMX上的gpio配置

输出output配置选项

output_pin_configuration

选项解释可选模式
GPIO output level引脚电平设置High/Low (高/低)
GPIO modeGPIO模式Output Push Pull/Output Open Drain ( 推挽输出/开漏输出)
GPIO Pull-up/Pull-dowm上拉下拉电阻Pull-up/Pull-down/No Pull-up and no pull-down (上拉电阻/下拉电阻/无上拉或下拉)
Maxinum output speed引脚速度设置Low/Medium/High (2MHZ 低速/25MHZ中速/50MHZ高速)
User Label用户标签给引脚设置名称 如LED0

输入input配置选项

input_configuration

选项解释可选模式
GPIO modeGPIO模式Output Push Pull/Output Open Drain ( 推挽输入/开漏输入)
GPIO Pull-up/Pull-dowm上拉下拉电阻Pull-up/Pull-down/No Pull-up and no pull-down (上拉电阻/下拉电阻/无上拉或下拉)
User Label用户标签给引脚设置名称 KEY0

当作为外部中断时的配置选项

external_interruot_gpio

选项解释可选模式
GPIO Mode外部中断模式选择External interrupt with Rising edge triggerdetection(上升沿有效触发外部中断)
External interrupt with Falling edge triggerdetection(下降沿有效触发外部中断)
External interrupt with Rising /Falling edge triggerdetection(上升沿/下降沿有效触发外部中断)
External Event Mode with Rising edge trigger detection (上升沿有效触发外部事件)
External Event Mode with Falling edge trigger detection(下降沿有效触发外部事件)
External Event Mode with Rising/Falling edge trigger detection(上升/下降沿有效触发外部事件)
GPIO Pull-up/Pull-dowm上拉下拉电阻Pull-up/Pull-down/No Pull-up and no pull-down (上拉电阻/下拉电阻/无上拉或下拉)
User Label用户标签给引脚设置名称 KEY0

注释:中断模式是指外部信号产生电平变化时,EXTI将该信号给NVIC处理,从而触发中断,执行中断服务函数,完成对应操作。
中断和事件的产生源是一样的,中断需要软件实现相应功能,而事件是由硬件触发后执行相应操作。前者需要CPU参与功能实现,可以实现的功能更多,后者无需CPU参与,具有更高的响应速度。

事件模式是指外部信号产生电平变化时,EXTI根据配置,联动ADC或TIM执行相关操作。

gpio库文件分析(stm32f1xx_hal_gpio.c)

在官方的HAL库stm32f1xx_hal_gpio.c文件中,所有的函数都有使用说明,例如:

  * @brief  Reads the specified input port pin.		//简述
  * @param  GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
  * @param  GPIO_Pin: specifies the port bit to read.	//参数说明
  *         This parameter can be GPIO_PIN_x where x can be (0..15).
  * @retval The input port pin value.			//返回值

void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)

//初始化我们需要用到的引脚的工作模式,包括具体引脚的工作速度、是否复用模式、上下拉等等参数。

void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)

//将初始化之后的引脚恢复成默认的状态–各个寄存器复位时的值

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

//读取我们想要知道的引脚的电平状态、函数返回值为0或1。

void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)

//给某个引脚写0或1,但是不要理解成,写1就是使能之类的意思,有些寄存器写1是擦除的意思

void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

//翻转某个引脚的电平状态

HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

//如果一个管脚的当前状态是1,读管脚值使用锁定,当这个管脚电平变化时保持锁定时的值,直到重置才改变

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)

//这个函数是外部中断服务函数,用来响应外部中断的触发,函数实体里面有两个功能,1是清除中断标记位,2是调用下面要介绍的回调函数。实际调用的是下边的中断回调函数

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

//中断回调函数,可以理解为中断函数具体要响应的动作。 按照官方提示我们应该再次定义该函数,__weak 是一个弱化标识,带有这个的函数就是一个弱化函数,就是你可以在其他地方写一个名称和参数都一模一样的函数,编译器就会忽略这一个函数,而去执行你写的那个函数

按键外部中断

实验现象

外部中断驱动按键,实现按键控制LED灯的开关
按键KEY0控制LED1的亮灭
按键KEY1控制LED0的亮灭
存在按键的抖动,原因:中断优先级没有进行配置,无法消抖,若需要消抖,需调整中断优先级。

实验设备

正点原子新战舰V3 STM32F103ZET6开发板学习板
st-link烧录器

中断管理(中断嵌套)

STM32的中断管理是属于内核部分,不属于芯片外设。STM32F103ZET6是Cortex-M3内核的IC。Cortex-M3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256(2的8次幂)级的可编程中断设置。级的可编程中断设置。但STM32并没有使用CM3内核的全部东西,而是只用了它的一部分:STM32只有84个中断,包括16个内核中断和68个可屏蔽中断,具有16(4位)级可编程的中断优先级。
STM32的中断优先级分组:STM32将中断分为5个组,组0-4。该分组的设置是由SCB>AIRCR 寄存器的bit10~8来定义的。具体的分配关系如表所示:

Column 1ColumnColumnColumn
AIRCR[10:8]bit[7:4]分配情况
01110:40位抢占优先级,4位响应优先级
11101:31位抢占优先级,3位响应优先级
21012:22位抢占优先级,2位响应优先级
31003:13位抢占优先级,1位响应优先级
40114:04位抢占优先级,0位响应优先级

正点原子开发指南中对优先级的解释:

例如组设置为3,那么此时所有的60个中断,每个中断的中断优先寄存器的高四位中的最高3位是抢占优先级,低1位是响应优先级。每个中断,你可以设置抢占优先级为0~7(2^3) ,响应优先级为1或0(2^1)。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。
这里需要注意两点:第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。
结合实例说明一下:假定设置中断优先级组为2,然后设置中断3(RTC中断)的抢占优先级为2,响应优先级为1。中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。那么这3个中断的优先级顺序为:中断7>中断3>中断6。
上面例子中的中断3和中断7都可以打断中断6的中断。而中断7和中断3却不可以相互打断!

中断服务函数编写的要求

  • 不能返回值;
  • 不能向ISR传递参数;
  • ISR应该尽可能的短小精悍;
  • printf(char *lpFormatString,…)函数会带来重入和性能问题,不能在ISR中采用

具体步骤

1.RCC配置与sys配置

rcc_configuration
sys_configuration

2.时钟树配置

clock_configuration

3.GPIO配置

gpio_configuration

4.中断优先级配置

interrupt_configuration

5.项目配置

project_configuration

代码编写

Cube MX生成得main.c

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();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* 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 */

/* 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 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

关于中断配置得对应函数都生成在 stm32f1xx_it.c中

对应得中断服务回调函数如下,所以我们只需要在main.c中编写我们想要的中断服务函数即可

void EXTI3_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI3_IRQn 0 */

  /* USER CODE END EXTI3_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
  /* USER CODE BEGIN EXTI3_IRQn 1 */

  /* USER CODE END EXTI3_IRQn 1 */
}

/**
  * @brief This function handles EXTI line4 interrupt.
  */
void EXTI4_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI4_IRQn 0 */

  /* USER CODE END EXTI4_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
  /* USER CODE BEGIN EXTI4_IRQn 1 */

  /* USER CODE END EXTI4_IRQn 1 */
}

在main.c中编写的中断服务函数

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)		//在默认得中断优先级配置时,按键中断里面写延时函数会卡死
{
	if(GPIO_Pin==KEY0_Pin)
	{

		HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
	}
	if(GPIO_Pin==KEY1_Pin)
	{

		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
	}
}
/* USER CODE END 4 */

源文件可以点击https://download.csdn.net/download/weixin_46074226/20551206下载

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 07:59:49  更:2021-07-28 08:00:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:16:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码