misc
STM32F10x MISC 标准库函数参考文档
数据类型定义
NVIC_InitTypeDef - NVIC初始化结构体
typedef struct
{
uint8_t NVIC_IRQChannel; /* 指定要使能或失能的IRQ通道 */
uint8_t NVIC_IRQChannelPreemptionPriority; /* 指定IRQ通道的抢占优先级 */
uint8_t NVIC_IRQChannelSubPriority; /* 指定IRQ通道的子优先级 */
FunctionalState NVIC_IRQChannelCmd; /* 指定IRQ通道的使能状态 */
} NVIC_InitTypeDef;成员说明:
NVIC_IRQChannel:指定要配置的IRQ通道号,可以是IRQn_Type类型的任意值(完整的IRQ通道列表请参考stm32f10x.h文件)NVIC_IRQChannelPreemptionPriority:指定IRQ通道的抢占优先级,取值范围0-15,具体取值范围取决于优先级分组配置NVIC_IRQChannelSubPriority:指定IRQ通道的子优先级,取值范围0-15,具体取值范围取决于优先级分组配置NVIC_IRQChannelCmd:指定IRQ通道的使能状态,可设置为ENABLE或DISABLE
常量定义
向量表基地址定义
#define NVIC_VectTab_RAM ((uint32_t)0x20000000) /* RAM中的向量表基地址 */
#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) /* FLASH中的向量表基地址 */系统低功耗模式定义
#define NVIC_LP_SEVONPEND ((uint8_t)0x10) /* 挂起事件唤醒 */
#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) /* 深度睡眠模式 */
#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) /* 退出时睡眠 */抢占优先级分组定义
#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /* 0位抢占优先级,4位子优先级 */
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /* 1位抢占优先级,3位子优先级 */
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /* 2位抢占优先级,2位子优先级 */
#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /* 3位抢占优先级,1位子优先级 */
#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /* 4位抢占优先级,0位子优先级 */SysTick时钟源定义
#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) /* HCLK/8作为SysTick时钟源 */
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) /* HCLK作为SysTick时钟源 */优先级分组表
根据NVIC_PriorityGroupConfig函数配置的优先级分组,抢占优先级和子优先级的允许值如下:
| 优先级分组 | 抢占优先级范围 | 子优先级范围 | 说明 |
|---|---|---|---|
| NVIC_PriorityGroup_0 | 0 | 0-15 | 0位抢占优先级,4位子优先级 |
| NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1位抢占优先级,3位子优先级 |
| NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2位抢占优先级,2位子优先级 |
| NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3位抢占优先级,1位子优先级 |
| NVIC_PriorityGroup_4 | 0-15 | 0 | 4位抢占优先级,0位子优先级 |
标准库函数详解
1. NVIC_PriorityGroupConfig
/**
* @brief 划分 NVIC 抢占/子优先级位数,决定中断嵌套与同级排序规则,系统初始化时全局配置一次
* @param NVIC_PriorityGroup: 指定优先级分组,可以是以下值之一:
* - NVIC_PriorityGroup_0: 0位抢占优先级,4位子优先级
* - NVIC_PriorityGroup_1: 1位抢占优先级,3位子优先级
* - NVIC_PriorityGroup_2: 2位抢占优先级,2位子优先级
* - NVIC_PriorityGroup_3: 3位抢占优先级,1位子优先级
* - NVIC_PriorityGroup_4: 4位抢占优先级,0位子优先级
* @retval 无
* @example
* NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);功能说明:
- 全工程通常只调用一次,更改分组会使已配优先级含义变化
- Group_2 等分抢占与子优先级,适合多数裸机/RTOS 混合场景
- 分组决定
NVIC_Init中两字段的合法取值范围
2. NVIC_Init
/**
* @brief 为指定 IRQ 通道设置抢占/子优先级并使能中断,是外设中断可用的关键一步
* @param NVIC_InitStruct: 指向NVIC_InitTypeDef结构体的指针,包含NVIC的配置信息
* @retval 无
* @example
* NVIC_InitTypeDef NVIC_InitStructure;
* NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
* NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
* NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
* NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
* NVIC_Init(&NVIC_InitStructure);
*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);功能说明:
- 须在外设
xxx_ITConfig与全局__enable_irq之前或之后按项目习惯配置 - 抢占数值越小优先级越高,可打断低抢占优先级 ISR
- 同一通道重复 Init 会覆盖旧优先级配置
3. NVIC_SetVectorTable
/**
* @brief 重定位中断向量表基址,用于 Bootloader 跳转、IAP 或在 RAM 中调试向量表
* @param NVIC_VectTab: 指定向量表是在RAM还是FLASH中,可以是以下值之一:
* - NVIC_VectTab_RAM: 向量表位于RAM中
* - NVIC_VectTab_FLASH: 向量表位于FLASH中
* @param Offset: 向量表基地址的偏移量,必须是200的倍数
* @retval 无
* @example
* NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
*/
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);功能说明:
- 偏移须为 512 字节(0x200)对齐,否则行为未定义
- App 从非 0x08000000 启动时须与链接脚本起始地址一致
- RAM 向量表适合调试时快速修补单条 ISR 入口
4. NVIC_SystemLPConfig
/**
* @brief 配置 Cortex-M 低功耗相关行为,如中断返回后自动睡眠或深度睡眠配合 STOP 模式
* @param LowPowerMode: 指定要配置的低功耗模式,可以是以下值之一:
* - NVIC_LP_SEVONPEND: 挂起事件唤醒
* - NVIC_LP_SLEEPDEEP: 深度睡眠模式
* - NVIC_LP_SLEEPONEXIT: 退出时睡眠
* @param NewState: 指定低功耗模式的新状态,可以是ENABLE或DISABLE
* @retval 无
* @example
* NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE);
*/
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);功能说明:
SLEEPONEXIT适合 ISR 处理完即睡,主循环用 WFI 唤醒SLEEPDEEP与 PWR 模块 STOP/STANDBY 配合使用- 各 LowPowerMode 可独立 ENABLE/DISABLE
5. SysTick_CLKSourceConfig
/**
* @brief 选择 SysTick 计数时钟为 HCLK 或 HCLK/8,影响 tick 周期与延时/RTOS 时基计算
* @param SysTick_CLKSource: 指定SysTick时钟源,可以是以下值之一:
* - SysTick_CLKSource_HCLK_Div8: HCLK/8作为SysTick时钟源
* - SysTick_CLKSource_HCLK: HCLK作为SysTick时钟源
* @retval 无
* @example
* SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);功能说明:
- 须在
SysTick_Config或写 LOAD 寄存器前配置 - HCLK 精度更高;Div8 在 72MHz 下便于整除得到 1ms
- 更改时钟源后须重算重装载值
使用示例
NVIC中断配置示例
#include "misc.h"
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 设置NVIC优先级分组为Group2: 2位抢占优先级,2位子优先级 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART1中断 */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 配置定时器2中断 */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}SysTick配置示例
void SysTick_Configuration(void)
{
/* 配置SysTick时钟源为HCLK/8 */
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
/* 配置SysTick为1ms中断一次,假设HCLK为72MHz */
SysTick_Config(9000); /* 72MHz/8/9000 = 1000Hz = 1ms */
}低功耗模式配置示例
void LowPower_Configuration(void)
{
/* 使能退出时睡眠功能 */
NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE);
/* 配置深度睡眠模式 */
NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP, ENABLE);
}注意事项
-
优先级分组配置:NVIC_PriorityGroupConfig函数在整个应用程序中应该只调用一次,建议在系统初始化阶段配置,之后不要再更改。
-
优先级值范围:抢占优先级和子优先级的有效范围取决于优先级分组的配置,超出范围的值将被忽略。
-
向量表重定位:使用NVIC_SetVectorTable时,偏移量必须是512字节(0x200)的倍数,否则可能导致系统不稳定。
-
SysTick时钟源:选择不同的SysTick时钟源会影响定时精度,需要根据实际的HCLK频率来计算合适的重装载值。
-
低功耗模式:配置低功耗模式时要注意系统的唤醒条件,确保系统能够正常从低功耗模式中唤醒。
-
中断优先级:抢占优先级高的中断可以打断抢占优先级低的中断,而子优先级只在抢占优先级相同时起作用,用于决定同时挂起的中断的执行顺序。
总结
MISC模块是STM32F10x标准库中的重要组成部分,提供了NVIC中断控制器和SysTick系统定时器的配置功能。通过合理配置中断优先级分组和各个中断的优先级,可以实现复杂的中断管理策略。SysTick定时器为系统提供了精确的时基,是实时操作系统和延时功能的基础。掌握MISC模块的使用对于开发高性能、低功耗的嵌入式应用至关重要。