一、设置分组
stm32f1xx_hal_cortex.c
查看分组
五个形参,分组0~4
stm32f1xx_hal.c
设置了分组为2, 此工程就不需要再设置了
再回到stm32f1xx_hal_cortex.c
查看NVIC_SetPriorityGrouping的界说,若无法跳转,先编译一下,
继续找界说
这段代码是用于设置 NVIC 的优先级分组的内联函数。关键部门:
- SCB->AIRCR = reg_value;: 最后,将更新后的寄存器值写入 SCB_AIRCR 寄存器,完成对 NVIC 优先级分组的设置。
总的来说,这个函数的目标是安全地设置 NVIC 的优先级分组,确保在举行任何更改之前正确地处理了旧的设置值,而且将写入操作限定在答应的范围内。
二、设置优先级
stm32f1xx_hal_cortex.c
没有返回值,三个形参
这段代码是用于设置特定制止的优先级的函数。
- void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority): 这是一个函数声明,用于设置特定制止的优先级。它担当三个参数,分别是制止号 IRQn,抢占优先级 PreemptPriority,以及响应优先级 SubPriority。
- uint32_t prioritygroup = 0x00U;: 这一行界说了一个变量 prioritygroup 并初始化为 0x00U,该变量用于存储当前 NVIC 的优先级分组。
- assert_param(IS_NVIC_SUB_PRIORITY(SubPriority)); 和 assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));: 这两行是参数查抄,确保传递给函数的 SubPriority 和 PreemptPriority 在有效范围内。如果参数不在有效范围内,这些断言将会触发。
- prioritygroup = NVIC_GetPriorityGrouping();: 这一行调用了 NVIC_GetPriorityGrouping() 函数,获取当前 NVIC 的优先级分组。
- NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));: 这一行调用了 NVIC_SetPriority() 函数,设置指定制止的优先级。它使用了 NVIC_EncodePriority() 函数将抢占优先级和子优先级编码为一个优先级值,并将其传递给 NVIC_SetPriority() 函数来设置制止的优先级。
这个函数的目标是设置特定制止的优先级,确保传递给函数的优先级参数在有效范围内,并将优先级值编码后传递给 NVIC。
查看IRQn_Type界说
跳转到stm32f103xe.h
举个例子
RTC_IRQn
制止号是3
NVIC_SetPriority
看界说
跳转到这里,再去看界说
跳转到:
用于设置特定制止的优先级的内联函数。每个部门的作用:
- __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority): 这是一个内联函数的声明,用于设置特定制止的优先级。它担当两个参数,一个是制止号 IRQn,另一个是优先级 priority。
- if ((int32_t)(IRQn) >= 0): 这个条件语句查抄制止号是否为非负值,如果是非负值,则说明是可编程制止,需要设置 NVIC->IP 寄存器的相应位置;如果是负值,则说明是固定优先级制止,需要设置 SCB->SHP 寄存器的相应位置。
- NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);: 如果是可编程制止,就将优先级值左移以便正确放置到 NVIC->IP 寄存器相应位置。这里通过移位来确保优先级值的正确性,同时保留了 __NVIC_PRIO_BITS 指定的位数,这是由硬件界说的。
- SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);: 如果是固定优先级制止,则将优先级值左移并设置到 SCB->SHP 寄存器的相应位置。由于固定优先级制止的索引不是从零开始的,因此需要举行一些偏移和掩码操作。
这个函数的目标是根据制止类型设置对应制止的优先级,确保优先级值在正确的范围内,并将其正确地写入到相应的寄存器中。
stm32f1xx_hal_cortex.c对cortex_cm3.h文件里的函数举行了封装
这段代码是一个内联函数,用于查抄特定制止是否已经被使能。让我们渐渐解释每个部门的作用:
- __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn): 这是一个内联函数的声明,用于获取特定制止是否已经被使能。它担当一个参数,即制止号 IRQn。
- if ((int32_t)(IRQn) >= 0): 这个条件语句查抄制止号是否为非负值,如果是非负值,则说明是可编程制止,需要查抄 NVIC->ISER 寄存器的相应位;如果是负值,则说明是固定优先级制止,这些制止无法被使能,直接返回 0。
- return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));: 如果是可编程制止,则查抄 NVIC->ISER 寄存器中相应位是否被置位,如果被置位则返回 1,否则返回 0。这里通过对制止号举行移位和掩码操作来确定具体的位位置。
- return(0U);: 如果是固定优先级制止,则直接返回 0,表现该制止无法被使能。
这个函数的目标是根据制止类型查抄特定制止是否已经被使能,并返回相应的结果。
三、EXTI
p60
P61
两种制止
四、GPIO外部制止
复制跑马灯实验,BSP新建EXTI文件夹,keil5中新建exti.c与exti.h并添加到EXTI文件夹,添加到工程里
复制拿过来用
若无法跳转界说,参考这份博客
http://t.csdnimg.cn/RCJyL
重新编译步伐
再次执行Go To Definition of ''的操作,可以了
参考
需选用外部制止下降沿触发,且输入上拉
- #define GPIO_MODE_IT_RISING 0x10110000u /*!< External Interrupt Mode with Rising edge trigger detection */
- #define GPIO_MODE_IT_FALLING 0x10210000u /*!< External Interrupt Mode with Falling edge trigger detection */
- #define GPIO_MODE_IT_RISING_FALLING 0x10310000u /*!< External Interrupt Mode with Rising/Falling edge trigger detection */
- #define GPIO_MODE_EVT_RISING 0x10120000u /*!< External Event Mode with Rising edge trigger detection */
- #define GPIO_MODE_EVT_FALLING 0x10220000u /*!< External Event Mode with Falling edge trigger detection */
- #define GPIO_MODE_EVT_RISING_FALLING 0x10320000u /*!< External Event Mode with Rising/Falling edge trigger detection */
复制代码
这些宏界说了用于 GPIO(通用输入/输出)引脚的不同模式,用于处理外部制止和事件,根据触发边沿的不同来触发。具体而言:
- GPIO_MODE_IT_RISING:表现外部制止模式,检测上升沿触发。
- GPIO_MODE_IT_FALLING:表现外部制止模式,检测下降沿触发。
- GPIO_MODE_IT_RISING_FALLING:表现外部制止模式,同时检测上升沿和下降沿触发。
雷同地:
- GPIO_MODE_EVT_RISING:表现外部事件模式,检测上升沿触发。
- GPIO_MODE_EVT_FALLING:表现外部事件模式,检测下降沿触发。
- GPIO_MODE_EVT_RISING_FALLING:表现外部事件模式,同时检测上升沿和下降沿触发。
这些宏通常与 GPIO 设置函数一起使用,以设置 GPIO 引脚的所需模式,以便根据特定边沿触发来处理外部制止或事件。
上下拉设置
- #define GPIO_NOPULL 0x00000000u /*!< No Pull-up or Pull-down activation */
- #define GPIO_PULLUP 0x00000001u /*!< Pull-up activation */
- #define GPIO_PULLDOWN 0x00000002u /*!< Pull-down activation */
复制代码 这些宏界说了用于 GPIO 引脚的不同上拉和下拉设置选项。具体来说:
- GPIO_NOPULL:表现不启用上拉或下拉。
- GPIO_PULLUP:表现启用上拉。
- GPIO_PULLDOWN:表现启用下拉。
这些选项通常用于设置 GPIO 引脚的电气特性,以确保引脚在特定条件下的正确操作,如减少干扰、提高信号质量等。
选择输入上拉
制止优先级:HAL_NVIC_SetPriority()
go to definition
选择制止号
笔者选用的是B1,选择EXTI1_IRQn
设置抢断优先级与响应优先级
笔者设置的是2和0
使能制止:HAL_NVIC_EnableIRQ()
笔者的是EXTI1_IRQn
设计制止服务函数:
去到设置文件查找
选择EXTI1_IRQHandler
- 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);
- }
- }
复制代码 这段代码是一个 HAL(Hardware Abstraction Layer,硬件抽象层)的 GPIO(通用输入/输出)外部制止处理函数。让我来解释它:
- HAL_GPIO_EXTI_IRQHandler 是一个函数,用于处理外部制止事件。它接收一个参数 GPIO_Pin,表现触发了外部制止的 GPIO 引脚。
- 在函数内部,起首检测是否检测到了 EXTI(外部制止)线的制止事件。
- 如果 GPIO_Pin 对应的 EXTI 制止事件标志被置位(不为 0),则说明该 GPIO 引脚触发了外部制止。
- 接着,通过 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin) 清除相应的制止标志。
- 最后,调用 HAL_GPIO_EXTI_Callback(GPIO_Pin),这是一个回调函数,用于在外部制止触发时执行用户界说的操作。这个函数的实现应该由用户在步伐的其他地方提供。
用于在外部制止事件发生时执行相应的操作,如清除制止标志并调用用户界说的回调函数。
回调函数
- __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
- {
- /* Prevent unused argument(s) compilation warning */
- UNUSED(GPIO_Pin);
- /* NOTE: This function Should not be modified, when the callback is needed,
- the HAL_GPIO_EXTI_Callback could be implemented in the user file
- */
- }
复制代码 用于处理 GPIO 外部制止回调的弱界说函数 HAL_GPIO_EXTI_Callback。
- __weak 关键字表现这是一个弱界说的函数,它可以被用户在步伐的其他地方重新界说以满足特定需求。
- 这个函数的目标是处理 GPIO 外部制止事件。它接收一个参数 GPIO_Pin,表现触发了外部制止的 GPIO 引脚。
- 函数内部通过调用 UNUSED(GPIO_Pin) 来避免编译器产生未使用参数的告诫。这是因为在某些环境下,用户大概不需要使用该参数。
- 注释部门指出,如果需要在外部制止发生时执行特定的操作,用户应该在自己的代码文件中实现 HAL_GPIO_EXTI_Callback 函数,并在此中编写所需的处理逻辑。
这个函数提供了一个默认的外部制止处理回调函数,并答应用户根据需要举行修改或扩展。
制止信号到来,去翻转led引脚的信号,在led.h中查看引脚是B5
4.1使能GPIO时钟
- __HAL_RCC_GPIOB_CLK_ENABLE();
复制代码 4.2 HAL_GPIO_init
- GPIO_InitTypeDef gpio_init_struct;
- __HAL_RCC_GPIOB_CLK_ENABLE();
- gpio_init_struct.Pin = LED0_GPI1_PIN; /* 引脚B1 */
- gpio_init_struct.Mode = GPIO_MODE_IT_FALLING; /* 推挽输出 */
- gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
- HAL_GPIO_Init(GPIOB, &gpio_init_struct); /* 初始化 */
-
复制代码 4.3 设置制止分组
设置文件已设置分组为2
4.4 设置制止优先级
- HAL_NVIC_SetPriority(EXTI1_IRQn,2,0);
复制代码 4.5 使能制止
- HAL_NVIC_EnableIRQ(EXTI1_IRQn);
复制代码
4.6 设计制止服务函数
- void EXTI1_IRQHandler(void)
- {
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
- }
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
- {
- delay_ms(20);
- if(GPIO_Pin=GPIO_Pin_1)
- {
- if(HAL_GPIO_ReadPin(GPIOB,GPIO_Pin_1) ==0)
- {
- HAL_GPIO_TogglePin(GPIOB,GPIO_Pin_5);
-
- }
- }
- }
复制代码 exti.h
函数声明
EXTI1_IRQHandler与HAL_GPIO_EXTI_Callback已经在设置文件里声明过
startup_stm32f103xe.s
stm32f1xx_hal_gpio.h
五、源码
exti.h
- #ifndef _EXTI_H
- #define _EXTI_H
- #include "./SYSTEM/sys/sys.h"
- void exti_init(void);
- #endif
复制代码 exit.c
- #include "./BSP/EXTI/exti.h"
- void exti_init(void)
- {
- GPIO_InitTypeDef gpio_init_struct;
- __HAL_RCC_GPIOB_CLK_ENABLE();
- gpio_init_struct.Pin = GPIO_PIN_1; /* 引脚B1 */
- gpio_init_struct.Mode = GPIO_MODE_IT_FALLING; /* 推挽输出 */
- gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
- HAL_GPIO_Init(GPIOB, &gpio_init_struct); /* 初始化 */
-
- HAL_NVIC_SetPriority(EXTI1_IRQn,2,0);
- HAL_NVIC_EnableIRQ(EXTI1_IRQn);
- }
- void EXTI1_IRQHandler(void)
- {
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
- }
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
- {
- delay_ms(20);
- if(GPIO_Pin == GPIO_PIN_1)
- {
- if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) ==0)
- {
- HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
-
- }
-
- }
- }
复制代码
main.c
- #include "./SYSTEM/sys/sys.h"
- #include "./SYSTEM/delay/delay.h"
- #include "./SYSTEM/usart/usart.h"
- #include "./BSP/LED/led.h"
- #include "./BSP/EXTI/exti.h"
- int main(void)
- {
- HAL_Init(); /* 初始化HAL库 */
- sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟,72M */
- delay_init(72); /* 初始化延时函数 */
- led_init(); /* 初始化LED */
- exti_init();
-
-
- while(1)
- {
- HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
- delay_ms(5000);
-
- }
- }
复制代码
参考
【【正点原子】手把手教你学STM32 HAL库开辟全集【真人出镜】STM32入门教学视频教程 单片机 嵌入式】https://www.bilibili.com/video/BV1bv4y1R7dp?p=56&vd_source=be33b1553b08cc7b94afdd6c8a50dc5a
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |