stm32片上资源分析
SysTick----系统定时器----常用的寄存器:STK_VAL、STK_LOAD、STK_CTRL
----SysTick定时器被捆绑在NVIC中,用于产生SysTick异常(异常号:15)
-----SysTick是一个24位的定时器,即一次最多可以计数224 个时钟脉冲,这个脉冲计数值被保存到 当前计数值寄存器STK_VAL (SysTick current valueregister) 中,只能向下计数,每接收到一个时钟脉冲STK_VAL的值就向下减1,直至0,当STK_VAL的值被减至0时,由硬件自动把重载寄存器STK_LOAD(SysTick reload valueregister)中保存的数据加载到STK_VAL(相当于51定时器模式2),重新向下计数。当STK_VAL的值被计数至0时,触发异常,就可以在中断服务函数中处理定时事件了。
-----SysTick_Config(uint32 ticks)此函数用来配置SysTick(详见st的库函数)。注:如果不配置SysTick的clk_source和SystemLP的话就不用添加misc这个中断设置文件
NVIC----中断控制器(关于stm32的优先级分组我就不解释了,参考书很多;这里我主要是想结合ARICR这个寄存器分析NVIC的函数)
先给个链接看看吧http://www.ichanging.org/stm32_NVIC.html
----关于ARICR这个寄存器(关于这个寄存器的资料很少),它配置了中断的优先级分组
详细的内容可以参看这个http://d1.ourdev.cn/bbs_upload782111/files_48/ourdev_699297A502KF.pdf
----void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)//定义了中断优先级分组
库函数如下:SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;相关宏定义如下: #define NVIC_PriorityGroup_0 ((uint32_t)0x700)
#define NVIC_PriorityGroup_1 ((uint32_t)0x600)
#define NVIC_PriorityGroup_2 ((uint32_t)0x500)#define NVIC_PriorityGroup_3 ((uint32_t)0x400)#define NVIC_PriorityGroup_4 ((uint32_t)0x300)#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)由上可知NVIC_PriorityGroupConfig函数就是改变了ARICR寄存器的[8-10]位来配置中断优先级分组的到此你也许会有两个问题:1:SCB是什么:SCB是st库定义的一个数据结构(其实就是一段连续的地址空间,查看core_m3.h中scb的定义可知,下面的NVIC类同)2 AIRCR_VECTKEY_MASK定义为 0x05FA0000,请看下图
----void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)//设置外设的中断
库函数如下:tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);tmpsub = tmpsub >> tmppriority;tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;tmppriority = tmppriority << 0x04;//如果你看了上面的pdf的话 就会理解为什么要想左移4位NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;/* Enable the Selected IRQ Channels --------------------------------------*/NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
函数实现的功能:根据NVIC_IRQChannelPreemptionPriority、NVIC_IRQChannelSubPriority和中断优先级分组设置好对应外设的中断响应
这里需要注意的是不能随便设置NVIC_IRQChannelPreemptionPriority和NVIC_IRQChannelSubPriority,否则会出现意想不到的错误。你可以在NVIC_PriorityGroup_4情况下,NVIC_IRQChannelPreemptionPriority不为0,则会出现你不想要的结果(具体原因你可以查看和上面的文档)
----SysTick_Config(由于此函数中也有中断相关的内容,所以没在SysTick分析而放在了这里;SysTick这个有别与其他外设中断)
追踪库函数SysTick_Config,发现与中断有关的函数是
----static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority),然后函数体是:
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);
库函数默认SysTick的中断是最小的(查看__NVIC_PRIO_BITS值为4),注意此时SysTick中断的优先级分组也是按照ARICR来进行的(至于SHP是什么查库函数吧)
最后解释下为什么说SysTick和其他外设中断不一样呢,stm32包含60个可屏蔽中断通道(不包含16个Cortex™-M3的中断线),SysTick属于后者。
版权声明:本文为博主原创文章,未经博主允许不得转载。