您的位置 首页 编程

STM32的嵌套中止体系NVIC和RCC具体收拾

STM32的嵌套中断系统NVIC和RCC详细整理用的是stm32f103的最新35的库。一、综述:1、STM32(Cortex-M3)中的优先级概念STM32(Cortex-M3)

STM32的嵌套中止体系NVIC和RCC具体收拾 用的是stm32f103的最新3.5的库。

一、总述:
1、STM32 (Cortex-M3)中的优先级概念
STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和呼应优先级,也把呼应优先级称作“亚优先级”或“副优先级”,每个中止源都需求被指定这两种优先级。
1. 何为占先式优先级(pre-emption priority)
高占先式优先级的中止事情会打断当时的主程序/中止程序运转—抢断式优先呼应,俗称中止嵌套。
2. 何为副优先级(subpriority)
在占先式优先级相同的情况下,高副优先级的中止优先被呼应;
在占先式优先级相同的情况下,假如有低副优先级中止正在履行,高副优先级的中止要等候已被呼应的低副优先级中止履行完毕后才干得到呼应—非抢断式呼应(不能嵌套)。
3. 判别中止是否会被呼应的依据
首先是占先式优先级,其次是副优先级;
占先式优先级决议是否会有中止嵌套;
Reset、NMI、Hard Fault 优先级为负(高于一般中止优先级)且不可调整。
4. 优先级抵触的处理
具有高抢占式优先级的中止能够在具有低抢占式优先级的中止处理进程中被呼应,即中止的嵌套,或许说高抢占式优先级的中止能够嵌套低抢占式优先级的中止。
当两个中止源的抢占式优先级相一起,这两个中止将没有嵌套联系,当一个中止到来后,假如正在处理另一个中止,这个后到来的中止就要比及前一个中止处理完之后才干被处理。假如这两个中止一起抵达,则中止操控器依据他们的呼应优先级凹凸来决议先处理哪一个;假如他们的抢占式优先级和呼应优先级都持平,则依据他们在中止表中的排位次序决议先处理哪一个。
5.Cortex-M3中对中止优先级的界说
已然每个中止源都需求被指定这两种优先级,就需求有相应的寄存器位记载每个中止的优先级;在Cortex-M3中界说了8个比特位用于设置中止源的优先级,这8个比特位能够有8种分配方法,如下:
一切8位用于指定呼应优先级
最高1位用于指定抢占式优先级,最低7位用于指定呼应优先级
最高2位用于指定抢占式优先级,最低6位用于指定呼应优先级
最高3位用于指定抢占式优先级,最低5位用于指定呼应优先级
最高4位用于指定抢占式优先级,最低4位用于指定呼应优先级
最高5位用于指定抢占式优先级,最低3位用于指定呼应优先级
最高6位用于指定抢占式优先级,最低2位用于指定呼应优先级
最高7位用于指定抢占式优先级,最低1位用于指定呼应优先级
这便是优先级分组的概念。
6.stm32中对中止优先级的界说
Cortex-M3答应具有较少中止源时运用较少的寄存器位指定中止源的优先级,因而STM32把指定中止优先级的寄存器位削减到4位,这4个寄存器位的分组方法如下:
第0组:一切4位用于指定呼应优先级
第1组:最高1位用于指定抢占式优先级,最低3位用于指定呼应优先级
第2组:最高2位用于指定抢占式优先级,最低2位用于指定呼应优先级
第3组:最高3位用于指定抢占式优先级,最低1位用于指定呼应优先级
第4组:一切4位用于指定抢占式优先级
file:///C:/DOCUME~1/LU/LOCALS~1/Temp/msohtml1/03/clip_image001.jpg
AIRC(Application Interrupt and Reset Register)寄存器中有用于指定优先级的 4bits。这4个bits用于分配preemption优先级和sub优先级,在STM32的固件库中界说如下:
#define NVIC_PriorityGroup_0((u32)0x700)
#define NVIC_PriorityGroup_1((u32)0x600)
#define NVIC_PriorityGroup_2((u32)0x500)
#define NVIC_PriorityGroup_3((u32)0x400)
#define NVIC_PriorityGroup_4((u32)0x300)
能够经过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()挑选运用哪种优先级分组方法,这个函数的参数有下列5种:
NVIC_PriorityGroup_0=> 挑选第0组
NVIC_PriorityGroup_1 => 挑选第1组
NVIC_PriorityGroup_2 => 挑选第2组
NVIC_PriorityGroup_3 => 挑选第3组
NVIC_PriorityGroup_4 => 挑选第4组
接下来便是指定中止源的优先级,下面以一个简略的比如阐明怎么指定中止源的抢占式优先级和呼应优先级:
// 挑选运用优先级分组第1组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//界说NVIC的结构体变量
NVIC_InitTypeDef NVIC_InitStructure;
//使能EXTI0中止
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定抢占式优先等级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定呼应优先等级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能EXTI9_5中止
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //指定抢占式优先等级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;// 指定呼应优先等级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
——————————————————————————-
要留意的几点是:
1. 假如指定的抢占式优先等级或呼应优先等级超出了选定的优先级分组所限制的规模,将或许得到意想不到的成果;
2. 抢占式优先等级相同的中止源之间没有嵌套联系;
3. 假如某个中止源被指定为某个抢占式优先等级,又没有其它中止源处于同一个抢占式优先等级,则能够为这个中止源指定恣意有用的呼应优先等级。
2、开关总中止
在STM32/Cortex-M3中是经过改动CPU的当时优先级来答应或制止中止。
PRIMASK位:只答应NMI和hardfault反常,其他中止/反常都被屏蔽(当时CPU优先级=0)。
FAULTMASK位:只答应NMI,其他一切中止/反常都被屏蔽(当时CPU优先级=-1)。
在STM32固件库中(stm32f10x_nvic.c和stm32f10x_nvic.h) 界说了四个函数操作PRIMASK位和FAULTMASK位,改动CPU的当时优先级,然后到达操控一切中止的意图。
下面两个函数等效于封闭总中止:
voidNVIC_SETPRIMASK(void);
voidNVIC_SETFAULTMASK(void);
下面两个函数等效于敞开总中止:
voidNVIC_RESETPRIMASK(void);
voidNVIC_RESETFAULTMASK(void);
上面两组函数要成对运用,但不能穿插运用。
例如:
榜首种方法:
NVIC_SETPRIMASK();//封闭总中止 ,只答应NMI和hard fault反常
NVIC_RESETPRIMASK();//敞开总中止
第二种方法:
NVIC_SETFAULTMASK();//封闭总中止 ,只答应NMI
NVIC_RESETFAULTMASK();//敞开总中止
常常运用:
NVIC_SETPRIMASK();//Disable Interrupts
NVIC_RESETPRIMASK();  // Enable Interrupts
能够用:
#define CLI()  __set_PRIMASK(1)  //封闭总中止
#define SEI()  __set_PRIMASK(0)  //翻开总中止
来完成开关总中止的功用。
二、寄存器介绍:

1、在core_cm3.h中界说了:

…………………………
…………………………
…………………………

五、实例详解
void NVIC_config()//装备中止
{
NVIC_InitTypeDef NVIC_InitStructure;
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//挑选中止分组1
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//挑选串口1中止
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;//抢占式中止优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 3;//呼应式中止优先级设置为3
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;//使能中止
NVIC_Init(&NVIC_InitStructure);
}

STM32的时钟体系
本文档由“~风中的叶~”收拾;QQ:654705188
一、总述:
1、时钟源
在 STM32 中,一共有 5 个时钟源,分别是 HSI 、 HSE 、 LSI 、 LSE 、 PLL 。
①HSI 是高速内部时钟, RC 振动器,频率为 8MHz ;
②HSE 是高速外部时钟,可接石英 / 陶瓷谐振器,或许接外部时钟源,频率规模是 4MHz –16MHz ;
③LSI 是低速内部时钟, RC 振动器,频率为 40KHz ;
④LSE 是低速外部时钟,接频率为 32.768KHz的石英晶体;
⑤PLL 为锁相环倍频输出,严厉的来说并不算一个独立的时钟源, PLL 的输入能够接 HSI/2 、 HSE 或许 HSE/2 。PLL倍频可挑选为 2– 16 倍,可是其输出频率最大不得超越 72MHz 。
其间, 40kHz 的 LSI 供独立看门狗 IWDG 运用,别的它还能够被挑选为实时时钟 RTC 的时钟源。别的,实时时钟 RTC 的时钟源还能够挑选 LSE ,或许是 HSE 的 128 分频。
STM32 中有一个全速功用的 USB 模块,其串行接口引擎需求一个频率为 48MHz 的时钟源。该时钟源只能从 PLL 端获取,能够挑选为 1.5 分频或许 1分频,也便是,当需运用到 USB 模块时, PLL 有必要使能,而且时钟装备为 48MHz 或 72MHz 。
别的 STM32 还能够挑选一个时钟信号输出到 MCO 脚 (PA.8) 上,能够挑选为 PLL 输出的 2分频、 HSI 、 HSE 或许体系时钟。
体系时钟 SYSCLK ,它是供给 STM32 中绝大部分部件作业的时钟源。体系时钟能够挑选为 PLL 输出、 HSI 、 HSE 。系体系时钟最大频率为 72MHz ,它经过 AHB 分频器分频后送给各个模块运用, AHB 分频器能够挑选 1 、 2 、 4 、 8 、 16 、 64 、 128 、 256 、 512 分频,AHB分频器输出的时钟送给 5大模块运用:
①送给 AHB 总线、内核、内存和 DMA 运用的 HCLK 时钟;
②经过 8分频后送给 Cortex 的体系定时器时钟STCLK;
③直接送给 Cortex 的闲暇运转时钟 FCLK ;
④送给 APB1 分频器。 APB1 分频器能够挑选 1 、 2 、 4 、 8 、 16 分频,其输出一路供 APB1 外设运用( PCLK1 ,最大频率 36MHz ),另一路送给定时器 (Timer)2 、3 、4 倍频器运用。该倍频器依据PCLK1的分频值主动挑选 1或许 2倍频,时钟输出供定时器 2、 3、 4运用。
⑤送给 APB2 分频器。 APB2 分频器能够挑选 1 、 2 、 4 、 8 、 16 分频,其输出一路供 APB2 外设运用( PCLK2 ,最大频率 72MHz ),别的一路送给定时器 (Timer)1 倍频运用。该倍频器依据PCLK2的分频值主动挑选1 或2 倍频,时钟输出供定时器 1运用。别的 APB2 分频器还有一路输出供 ADC 分频器运用,分频后送给 ADC 模块运用。 ADC 分频器可挑选为 2 、 4 、 6 、 8 分频。
需求留意的是定时器的倍频器,当 APB 的分频为 1 时,它的倍频值为 1 ,不然它的倍频值就为 2 。
file:///C:/DOCUME~1/LU/LOCALS~1/Temp/msohtml1/01/clip_image002.jpg
2、APB1和APB2衔接的模块
①衔接在 APB1( 低速外设 )上的设备有:电源接口、备份接口、 CAN 、 USB 、 I2C1 、 I2C2 、 UART2 、 UART3 、 SPI2 、窗口看门狗、 Timer2 、 Timer3 、 Timer4 。留意USB模块尽管需求一个独自的48MHz的时钟信号,可是它应该不是供USB模块作业的时钟,而仅仅供给给串行接口引擎(SIE)运用的时钟。USB模块的作业时钟应该是由APB1供给的。
②衔接在 APB2 (高速外设)上的设备有: UART1 、 SPI1 、 Timer1 、 ADC1 、 ADC2 、 GPIOx(PA~PE) 、第二功用IO 口。

file:///C:/DOCUME~1/LU/LOCALS~1/Temp/msohtml1/01/clip_image004.jpg
二、寄存器介绍:
typedefstruct
{
__IO uint32_t CR;
__IO uint32_t CFGR;
__IO uint32_t CIR;
__IO uint32_t APB2RSTR;
__IO uint32_t APB1RSTR;
__IO uint32_t AHBENR;
__IO uint32_t APB2ENR;
__IO uint32_t APB1ENR;
__IO uint32_t BDCR;
__IO uint32_t CSR;
#ifdefSTM32F10X_CL
__IO uint32_t AHBRSTR;
__IO uint32_t CFGR2;
#endif
#if defined(STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined(STM32F10X_HD_VL)
uint32_t RESERVED0;
__IO uint32_t CFGR2;
#endif
}RCC_TypeDef;
1、时钟操控寄存器(RCC_CR):(复位值为0x0000 xx83,内部低速时钟使能和安排妥当,内部时钟校准)
主要功用:内外部高速时钟的使能和安排妥当标志(含内部高速时钟校准调整),外部高速时钟旁路,时钟安全体系CSS使能,PLL使能和PLL安排妥当标志。
2、时钟装备寄存器(RCC_CFGR):(复位值为0x0000 0000)
主要功用:体系时钟源切换及状况,AHB、APB1、APB2、ADC、USB预分频,PLL输入时钟源挑选及HSE输入PLL分频挑选,PLL倍频系数,MCO(PA8)引脚微操控器时钟输出。
3、时钟中止寄存器 (RCC_CIR):(复位值: 0x0000 0000)
主要功用:LSI、LSE、HIS、HSE、PLL安排妥当中止标志,HSE时钟失效导致时钟安全体系中止标志,LSI、LSE、HIS、HSE、PLL安排妥当中止使能,铲除LSI、LSE、HIS、HSE、PLL安排妥当中止,铲除时钟安全体系中止。
4、APB2外设复位寄存器 (RCC_APB2RSTR):(复位值: 0x0000 0000)
主要功用:AFIO、IOPA、IOPB、IOPC、IOPD、IOPE、IOPF、IOPG、ADC1、ADC2、TIM1、SPI1、TIM8、USART1、ADC3复位。
5、APB1外设复位寄存器 (RCC_APB1RSTR) :(复位值: 0x0000 0000)
主要功用:TIM2、TIM3、TIM4、TIM5、TIM6、TIM7、WWDG、SPI2、SPI3、USART2、USART3、USART4、USART5、I2C1、I2C2、USB、CAN、BKP、PWR、DAC复位。
6、AHB外设时钟使能寄存器 (RCC_AHBENR) :(复位值: 0x0000 0014睡觉形式时SRAM、闪存接口电路时钟敞开)
主要功用:DMA1、DMA2、SRAM、FLITF、CRC、FSMC、SDIO时钟使能。
7、APB2外设时钟使能寄存器(RCC_APB2ENR) :(复位值: 0x0000 0000)
主要功用:AFIO、IOPA、IOPB、IOPC、IOPD、IOPE、IOPF、IOPG、ADC1、ADC2、TIM1、SPI1、TIM8、USART1、ADC3时钟使能。
8、APB1外设时钟使能寄存器(RCC_APB1ENR) :(复位值: 0x0000 0000)
主要功用:TIM2、TIM3、TIM4、TIM5、TIM6、TIM7、WWDG、SPI2、SPI3、USART2、USART3、USART4、USART5、I2C1、I2C2、USB、CAN、BKP、PWR、DAC时钟使能。
9、备份域操控寄存器 (RCC_BDCR) :(复位值: 0x0000 0000)
主要功用:外部低速振动器使能和安排妥当标志及旁路、RTC时钟源挑选和时钟使能、备份域软件复位。
10、操控/状况寄存器 (RCC_CSR) :(复位值: 0x0C00 0000 NRST引脚复位标志、上电/掉电复位标志)
主要功用:内部低速振动器安排妥当、铲除复位标志、NRST引脚复位标志、上电/掉电复位标志、软件复位标志、独立看门狗复位标志、窗口看门狗复位标志、低功耗复位标志。
三、初始化设置
选用8MHz 外部HSE 时钟,在 MDK 编译平台中,程序的时钟设置参数流程如下:
将 RCC 寄存器从头设置为默认值:RCC_DeInit();
翻开外部高速时钟晶振 HSE :RCC_HSEConfig(RCC_HSE_ON);
等候外部高速时钟晶振作业:HSEStartUpStatus= RCC_WaitForHSEStartUp();
设置 AHB 时钟 (HCLK):RCC_HCLKConfig(RCC_SYSCLK_Div1);

设置APB 2时钟(APB2):RCC_PCLK2Config(RCC_HCLK_Div1);
设置APB1时钟(APB1):RCC_PCLK1Config(RCC_HCLK_Div2);

设置 PLL :RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
翻开 PLL :RCC_PLLCmd(ENABLE);
等候 PLL 作业:while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET);
设置体系时钟:RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
判别 PLL 是否是体系时钟:while(RCC_GetSYSCLKSource()!= 0x08);

1、运用库函数进行时钟体系初始化装备
voidRCC_config()//假如外部晶振为8M,PLLCLK=SYSCLK=72M,HCLK=72M,//P2CLK=72M,P1CLK=36M,ADCCLK=36M,USBCLK=48M,TIMCLK=72M
{
ErrorStatus HSEStartUpStatus;//界说过错状况变量
RCC_DeInit();//将RCC寄存器从头设置为默认值
RCC_HSEConfig(RCC_HSE_ON);//翻开外部高速时钟晶振
HSEStartUpStatus =RCC_WaitForHSEStartUp();//等候外部高速时钟晶振作业
if(HSEStartUpStatus == SUCCESS)
{
RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置AHB不分频,HCLK=SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1);//设置APB2不分频,P2CLK=HCLK
RCC_PCLK1Config(RCC_HCLK_Div2);//设置APB1为2分频,P1CLK=HCLK/2
FLASH_SetLatency(FLASH_Latency_2);//设置FLASH代码延时
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能预取指缓存
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);//设置PLL时钟源,

//外部时钟不分频,为HSE的9倍频8MHz * 9 =72MHz

RCC_PLLCmd(ENABLE);//使能PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET);//等候PLL准备安排妥当
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置PLL为体系时钟源
while(RCC_GetSYSCLKSource() != 0x08);//判别PLL是否是体系时钟
}

}

2、运用寄存器进行RCC时钟初始化装备
voidRCC_init(u8 PLL)//输入PLL的倍频值2—16倍频
//HCLK=PLLCLK=SYSCLK=P2CLK=P1CLK*2=ADCCLK*2=TIMCLK=USBCLK*2/3
{
unsigned char temp=0;
//RCC_DeInit();//将RCC寄存器从头设置为默认值
RCC->CR|=0x00010000;//外部高速时钟使能HSEON
while(!(RCC->CR>>17));//等候外部时钟安排妥当
RCC->CFGR=0X00000400;//APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL-=2;//抵消2个单位
RCC->CFGR|=PLL<<18;//设置PLL倍频值 2~16
RCC->CFGR|=1<<16;//PLL时钟源挑选
FLASH->ACR|=0x32;//FLASH 2个延时周期
RCC->CR|=0x01000000;//PLLON
while(!(RCC->CR>>25));//等候PLL确定
RCC->CFGR|=0x00000002;//PLL作为体系时钟
while(temp!=0x02)//等候PLL作为体系时钟设置成功
{
temp=RCC->CFGR>>2;
temp&=0x03;
}
}
四、相关库函数解析
1、库中所涉及到的结构体
typedef struct
{
uint32_t SYSCLK_Frequency;
uint32_t HCLK_Frequency;
uint32_t PCLK1_Frequency;
uint32_t PCLK2_Frequency;
uint32_t ADCCLK_Frequency;
}RCC_ClocksTypeDef;
2、库函数解析
void RCC_DeInit(void);//将外设RCC寄存器设为缺省值;(除RCC_BDCR和RCC_CSR)
voidRCC_HSEConfig(uint32_t RCC_HSE);//设置外部高速晶振(HSE);
//输入:RCC_HSE_OFF,RCC_HSE_ON,RCC_HSE_Bypass(HSE旁路)
ErrorStatusRCC_WaitForHSEStartUp(void);//等候HSE起振;
//返回值:SUCCESS,HSE晶振安稳且安排妥当;ERROR,HSE晶振未安排妥当
voidRCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue);//调整内部高速晶振(HSI)校准值
//输入:校准补偿值(该参数取值有必要在0到0x1F之间)
voidRCC_HSICmd(FunctionalState NewState);//使能或许失能内部高速晶振(HSI)
//输入:ENABLE或许DISABLE(假如HSI被用于体系时钟,或许FLASH编写操作进行中,那么它不能被停振)
void RCC_PLLConfig(uint32_tRCC_PLLSource, uint32_t RCC_PLLMul);//设置PLL时钟源及倍频系数
//输入:RCC_PLLSource_HSI_Div2,RCC_PLLSource_HSE_Div1,RCC_PLLSource_HSE_Div2
//输入:RCC_PLLMul_2到RCC_PLLMul_16
voidRCC_PLLCmd(FunctionalState NewState);// 使能或许失能PLL
//输入:ENABLE或许DISABLE
#if defined(STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) ||defined (STM32F10X_CL)
void RCC_PREDIV1Config(uint32_tRCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div);//
#endif
#ifdefSTM32F10X_CL
void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div);//
void RCC_PLL2Config(uint32_t RCC_PLL2Mul);//
void RCC_PLL2Cmd(FunctionalState NewState);//
void RCC_PLL3Config(uint32_t RCC_PLL3Mul);//
void RCC_PLL3Cmd(FunctionalState NewState);//
#endif

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/biancheng/258391.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部