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类同)
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属于后者。

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2013-05-04 18:38  vendanner  阅读(684)  评论(0编辑  收藏  举报