STM32学习
Posted Caramel_biscuit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32学习相关的知识,希望对你有一定的参考价值。
中断
打断CPU执行正常的程序,转而处理紧急程序,然后返回原暂停的程序继续运行,就叫中断。
中断的作用和意义
- 实时控制:在确定时间内对相应事件做出响应,如温度控制。
- 故障处理:检测到故障,需要第一时间处理,如电梯门夹人。
- 数据传输:不确定数据何时会来,如:串口接收数据
中断的意义:高效处理紧急程序,不会一直占用CPU资源。
GPIO外部中断简图
NVIC
Nested vectored interrupt controller,嵌套向量中断控制器,属于内核(M3/M4/M7).
NVIC支持:256个中断(16个内核+240外部),支持:256个优先级,允许裁剪!
中断向量表
定义一块固定的内存,以4字节对齐(STM32是32位单片机,所以每次取地址是32位,所以是4字节对齐),存放各个中断服务程序的首地址。
中断向量表定义在启动文件,当发生中断时,CPU会自动执行对应的中断服务函数。
NVIC工作原理
STM32中断优先级基本概念
- 抢占优先级(pre):高抢占优先级可以打断正在执行的低抢占优先级。
- 响应优先级(sub):当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断。
- 抢占和相应优先级相同的情况下,自然优先级越高的,先执行。
- 自然优先级:中断向量表的优先级。
- 数值越小:表示优先级越高。
STM32中断优先级分组
一个工程中,一般只设置一次中断优先级分组。
STM32中断优先级举例(假设分组是2)
NVIC的使用
@endverbatim
* @
*/
/**
* @brief Sets the priority grouping field (preemption priority and subpriority)
* using the required unlock sequence.
* @param PriorityGroup: The priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority
* 4 bits for subpriority
* @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
* 3 bits for subpriority
* @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
* 2 bits for subpriority
* @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
* 1 bits for subpriority
* @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
* 0 bits for subpriority
* @note When the NVIC_PriorityGroup_0 is selected, IRQ preemption is no more possible.
* The pending IRQ priority will be managed only by the subpriority.
* @retval None
*/
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));//断言:判断形参是否有效
/* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
NVIC_SetPriorityGrouping(PriorityGroup);
/**
\\brief Set Priority Grouping
\\details Sets the priority grouping field using the required unlock sequence.
The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
Only values from 0..7 are used.
In case of a conflict between priority grouping and available
priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
\\param [in] PriorityGroup Priority grouping field.
*/
__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
reg_value = SCB->AIRCR; /* read old register configuration */
reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
reg_value = (reg_value |
((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
(PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
SCB->AIRCR = reg_value;
/**
\\brief Get Priority Grouping
\\details Reads the priority grouping field from the NVIC Interrupt Controller.
\\return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
*/
__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
设置优先级分组主要是操作AIRCR寄存器
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
uint32_t prioritygroup = 0x00U;
/* Check the parameters */
assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
prioritygroup = NVIC_GetPriorityGrouping();
NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
/*!< Interrupt Number Definition */
typedef enum
/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
HardFault_IRQn = -13, /*!< 3 Cortex-M3 Hard Fault Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers *********************************************************/
WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
TAMPER_IRQn = 2, /*!< Tamper Interrupt */
RTC_IRQn = 3, /*!< RTC global Interrupt */
FLASH_IRQn = 4, /*!< FLASH global Interrupt */
RCC_IRQn = 5, /*!< RCC global Interrupt */
EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */
DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */
DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */
DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */
USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */
USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */
CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */
CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */
EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */
TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */
TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */
TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */
TIM2_IRQn = 28, /*!< TIM2 global Interrupt */
TIM3_IRQn = 29, /*!< TIM3 global Interrupt */
TIM4_IRQn = 30, /*!< TIM4 global Interrupt */
I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */
I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */
I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */
I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */
SPI1_IRQn = 35, /*!< SPI1 global Interrupt */
SPI2_IRQn = 36, /*!< SPI2 global Interrupt */
USART1_IRQn = 37, /*!< USART1 global Interrupt */
USART2_IRQn = 38, /*!< USART2 global Interrupt */
USART3_IRQn = 39, /*!< USART3 global Interrupt */
EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
RTC_Alarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */
USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */
TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */
TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */
TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */
TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */
ADC3_IRQn = 47, /*!< ADC3 global Interrupt */
FSMC_IRQn = 48, /*!< FSMC global Interrupt */
SDIO_IRQn = 49, /*!< SDIO global Interrupt */
TIM5_IRQn = 50, /*!< TIM5 global Interrupt */
SPI3_IRQn = 51, /*!< SPI3 global Interrupt */
UART4_IRQn = 52, /*!< UART4 global Interrupt */
UART5_IRQn = 53, /*!< UART5 global Interrupt */
TIM6_IRQn = 54, /*!< TIM6 global Interrupt */
TIM7_IRQn = 55, /*!< TIM7 global Interrupt */
DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */
DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */
DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */
DMA2_Channel4_5_IRQn = 59, /*!< DMA2 Channel 4 and Channel 5 global Interrupt */
IRQn_Type;
IRQn为中断号(中断请求号),通过中断号,可以知道是哪个中断发生了,也代表着其在中断向量表的位置。
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1 & ADC2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
DCD TIM8_BRK_IRQHandler ; TIM8 Break
DCD TIM8_UP_IRQHandler ; TIM8 Update
DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation
DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare
DCD ADC3_IRQHandler ; ADC3
DCD FSMC_IRQHandler ; FSMC
DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5
DCD TIM6_IRQHandler ; TIM6
DCD TIM7_IRQHandler ; TIM7
DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1
DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2
DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3
DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
__Vectors_End
/**
\\brief Set Interrupt Priority
\\details Sets the priority of a device specific interrupt or a processor exception.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\\param [in] IRQn Interrupt number.
\\param [in] priority Priority to set.
\\note The priority cannot be set for every processor exception.
*/
__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
if ((int32_t)(IRQn) >= 0)
NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
else
SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
IP寄存器设置外部中断优先级,SHP设置内核中断优先级。
typedef struct
__IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24U];
__IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24U];
__IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56U];
__IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644U];
__OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
NVIC_Type;
F103IP寄存器定义了240个,只用到60个,其余保留。
/**
* @brief Enables a device specific interrupt in the NVIC interrupt controller.
* @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
* function should be called before.
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
* @retval None
*/
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
/* Check the parameters */
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
/* Enable interrupt */
NVIC_EnableIRQ(IRQn);
使能中断
/**
\\brief Enable Interrupt
\\details Enables a device specific interrupt in the NVIC interrupt controller.
\\param [in] IRQn Device specific interrupt number.
\\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
if ((int32_t)(IRQn) >= 0)
NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
hal_cortex.c文件其实就是对core._cm3.h文件里的内容进行了再次封装。
EXTI
External(Extend)interrupt/event Controller,外部(扩展)中断事件控制器。
包括20个产生事件/中断请求的边沿检测器,即总共:20条EXTI线。
中断和事件的区别
- 中断:要进入VNIC,有相应的中断服务函数,需要CPU处理。
- 事件:不进入NVIC,仅用于内部硬件自动控制,如:TIMA,DMA,ADC
每条EXTI都可以单独配置:选择类型(中断或者事件)、触发方式(上升沿、下降沿或者双边沿触发)、支持软件触发、开启/屏蔽、有挂起状态。
①,边沿检测
②,软件触发
③,中断屏蔽/清除
④,事件屏蔽
EXTI和IO的映射关系
AFIO简介
Alternate Function IO,即复用功能IO,主要用于重映射和外部中断映射配置。
AFIO_EXTICR1的 EXTI0[3:0]位控制‘Px0映射到EXTI0
Px1映射到EXTI1
…
Px14映射到EXTI14
Px15映射到EXTI15
如何使用中断
STM32 EXTI配置步骤(GPIO外部中断)
- 使能GPIO
- 设置GPIO输入模式——上/下拉/浮空输入
- 使能AFIO时钟
- 设置EXTI和IO对应关系
- 设置EXTI屏蔽,上/下沿,IMR,RTSR,FTSR
- 设置NVIC:设置优先级分组,设置优先级、使能中断
- 设计中断服务函数:清中断标志
EXTI的HAL库设置步骤
- 使能GPIO时钟:__HAL_RCC_GPIOx_CLK_ENABLE
- GPIO/AFIO/EXTI:使用HAL_GPIO_Init,一步到位
- 设置中断分组,使用HAL_NVIC_SetPrioorityGrouping,一个工程只需要设置一次,在HAL_init()中设置
- 设置中断优先级,使用HAL_NVIC_SetPriority
- 使能中断:HAL_NVIC_EnbaleIRQ
- 设计中断服务函数:EXTIx_IRQHandler,中断服务函数,清中断标志位。
STM32仅有:EXTI0~4、EXTI9_5、EXTI15_10,7个外部中断服务函数。
通过外部中断控制一个灯亮灭
KEY0:输入为上拉输入,下降沿触发
通过KEY0控制LED0亮灭
Duanxx的STM32学习: STM32的存储映射
以上是关于STM32学习的主要内容,如果未能解决你的问题,请参考以下文章