找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1963|回复: 1
打印 上一主题 下一主题
收起左侧

STM32 NVIC编程模板

[复制链接]
跳转到指定楼层
楼主
ID:319895 发表于 2019-12-28 14:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
今天和大家聊聊什么是NVIC,NVIC全名也叫做嵌套向量控制器,看名字也就知道了它和中断密不可分。它是ARM公司设计的内核管理设备,因此各个厂商在使用的时候往往都各不相同,但是原理都差不多,我们今天讨论的就是ST公司是在怎么使用的,这里大家最好看看M3/M4权威指南第7章,239页。这里我就不说中断的基本概念了,直接进入主题。为什么要使用中断?CPU的运行有中断和查询,但是查询的时候CPU一直工作,这样一直占用CPU,而中断来的时候,CPU检查到了中断标志,就会立刻知道要有事情去处理。那么它就会去处理紧急的事情。这里就涉及到了优先级的3种情况。

1)抢占优先级:看名字就知道它特别霸道,会从CPU手中去抢占资源,也就是高抢占优先级会干扰低抢占优先级,也就是中断嵌套。
2)响应优先级:高响应优先级有优先处理(同时到来),但是如果高响应优先级后来的话,那么对不起,你也要排队,等这个事情处理完,响应优先级没有中断嵌套。
3)自然优先级:有没有响应优先级,我们在数据手册看到的中断(除了内核设备)都是自然优先级,我们可以通多NVIC来设置优先级级别。

二:中断的来源:1:外设比如定时器,串口等;2:中断请求;3:系统滴答定时器;4:系统异常;5:软件中断。总共要有255个中断来源,15个是系统异常,240个是外部中断。

三:ARM公司设计NVIC:
some of the registers are saved onto the stack automatically                                                这段话表明了在处理中断的时候,外了恢复中断程序,ARM                                                                                                                                                  公司把一些寄存器保存到堆栈中,在返回的时候自动恢复,
when an exception is accepted, and are also automatically restored in an exception
return sequence. This mechanism allows the exception handlers to be written as
normal C functions without any additional software overhead.


Set up the priority level of the required interrupt (this step is optional)
• Enable the interrupt generation control in the peripheral that triggers the interrupt
• Enable the interrupt in the NVIC
这段话告诉我们:当要使用中断的时候,第一步:使用外部中断的使能(就好比开时钟一样);第二步:设置中断的优先级级别;第3步:启用NVIC的中断。

四:优先级级别有优先级级别寄存器来控制,ARM公司一共有8位确定优先级级别;但是ST公司只使用了4位;我们看看ST公司是在怎么确定优先级级别的。
      看下面4个函数就知道了在CM4.h文件的1485页。
1)void NVIC_EnableIRQ(IRQn_Type IRQn)   函数功能:NVIC中断使能,函数参数:IRQn_Type IRQn,中断名:指明了是哪一个中断


2)void NVIC_SetPriority (IRQn_Type IRQn,uint32_t priority) 1568页:函数功能:设定优先级级别,函数参数:IRQn_Type IRQn,中断名:指明了是哪一个中断
uint32_t priority:中断优先级级别。
3)void NVIC_SetPriorityGrouping(uint32_tPriorityGroup)函数功能:设定优先级分组(一个工程内就只能用一次分组,如果多次分组,之前的分组就会无效)函数参数:uint32_tPriorityGroup优先级分组值 ===========(7-组编号)


4)uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
{
  uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);          /* only values 0..7 are used          */    //表示ST公司只用了4位
  uint32_t PreemptPriorityBits;                          //抢占优先级位数
  uint32_t SubPriorityBits;                                  //响应优先级位数
  PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
  SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;

return (
           ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) |
           ((SubPriority     & ((1 << (SubPriorityBits    )) - 1)))
         );






}
NVIC_PRIO_BITS:恒等于4

我们来分析这个函数:函数功能:得到优先级级别;函数参数:uint32_t PriorityGroup;优先级分组值;uint32_t PreemptPriority:抢占优先级

uint32_t SubPriority:响应优先级;
uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);  上面我们说过PriorityGroup=7-组边号,当组边号是0,PriorityGroupTmp=7;带进这一句话

PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;结果PreemptPriorityBits =0;表示抢占优先级位数是0,响应优先级位数是4;返回的值是0和15.然后依次分析1,2 ,3,4。组。得到优先级级别。


下面我们把这4个函数封装成一个函数得到:


void My_NVIC_Init(IRQn_Type IRQn,u32 PG,u32 PP,u32 SP)
{

u32 priority;

NVIC_SetPriorityGrouping(PG);      //设定优先级分组

priority=NVIC_EncodePriority (PG,PP,SP);  //得到优先级级别
  
  NVIC_SetPriority (IRQn, priority);          //设定优先级级别

NVIC_EnableIRQ (IRQn);                          /NVIC中断使能。

}
接下来我会通过外部中断实验来告诉你们如何使用这个NVIC函数。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:170498 发表于 2020-1-15 20:41 | 只看该作者
不错不错,看明白了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表