OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 12558|回复: 39

进来讨论一下,NVIC寄存器组中的中断挂起SETPEND与消除CLRPEND,与外部中断挂起寄存器EXTI_PR有何关系?

[复制链接]

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
发表于 2018-7-27 09:09:55 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 warship 于 2018-7-27 19:32 编辑

如题,讨论一下

最佳答案

查看完整内容[请看2#楼]

没有人对此感兴趣,我自己研究理解了一下, 贴出来供参考。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-27 09:09:56 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 10:42 编辑

没有人对此感兴趣,我自己研究理解了一下,
贴出来供参考。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-28 10:35:50 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 11:11 编辑

先说结论,STM32的中断控制是分级管理的,CM3内核中的NVIC是顶层,对每个通道都设有1BIT的中断挂起位,
但每个通道可能不止一个中断源,比如EXTI5_9_IRQn,对NVIC而言,只算一个通道,但实际包含有5个中断源,
因此,下层就必须实现对这多个中断源的独立监控,这就是EXTI->PR中的挂起位了。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-28 10:36:15 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 14:51 编辑

STM32的中断系统可以理解为分两级管理,
顶层当然是CM3内核强大的NVIC,下层就是形形色色的片上外设了,
对于NVIC来说,它最大可以管理256个不同的中断通道,
这256个中断,内核自留了16个,剩下的通称为外部中断(注意与EXTI不要混淆,EXTI是外部中断中的一小部分,全称为外部线中断),外部中断可以多达240个(具体的芯片只实现了约60多个)。
这240个中断通道,在CM3的内核中,每一个中断都标配如下的控制:


1、中断优先级寄存器IP:8位(一般芯片只具体实现了高4位可表达16个优先级)


2、中断使能SETENA:1位,写1使能,写0无效
3、中断禁能CLRENA:1位,写1禁能,写0无效。 以上二者是联动的,实际只相当于1位,要使能就置SETENA位,要禁能就置CLRENA


4、中断挂起SETPEND:1位,写1挂起,写0无效,中断请求收到但暂不能服务时,置1,进入中断服务后由硬件清除
5、中断解挂CLRPEND:1位,写1解挂,写0无效。以上二者是联动的,实际只相当于1位,要挂起就置SETPEND位,要解挂就置CLRPEND


6、中断活动状态ACTIVE:1位,用于指示该中断是否处于活动状态,只读,从进入中断服务程序开始由硬件置位,直到中断服务返回由硬件清除。

以上几个内核寄存器(位)中,用户编程经常用到是主要是前3项,我们需要用到某个中断的时候,首先就是设置优先级,ENABLE中断,库函数所执行的就是对这前3项的设置,使用寄存器编程的同学也经常会直接操作;
后3项,用户编程基本用不到,包括使用寄存器编程的同学,甚至都感觉不到它们的存在,没有特殊需求的都任由硬件自由操作了。

NVIC是如何访问这些众多的寄存器或控制位的呢?  靠的就是中断通道号。
NVIC唯一认识的ID,也就是中断通道号,说白了就是0-239的号码牌IRQn,
NVIC就根据此号码去找相应的控制位(或寄存器),达到管理这240个中断通道的目的。
根据这个号码也可以从向量表中找到对应的中断服务程序入口(地址偏移量=0x0000 0040+IRQn*4)


我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-28 10:36:36 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 12:06 编辑

其实虽说NVIC强大,但也可以说傻得可以,它其实根本不知道中断的具体来头,只须照章办事。
来了IRQ后,根据IRQn编号值去查相应的控制位(或寄存器),严格走下述流程:
1、首先是看该IRQ是否使能,只有使能位为1,才能受理申请,如果是禁能状态,则直接无视;
2、然后查看优先级寄存器IP[IRQn],该IRQ的优先级;
3、再通过查看ACTIVE可知,目前处于活动状态的所有中断;
4、如果有正在活动状态的中断(即正在服务中),则进行中断优先级比较。如果活动的中断优先级高,则先挂起这个IRQ。
    反复此步,直到没有更高优先级的中断需要服务;
5、轮到这个IRQ享受服务(由编号查向量表进入对应的中断服务程序,服务开始后置位它对应的中断活动状态位),解挂。


第5步里,就是NVIC对挂起和解挂的操作,这算是CM3内核的硬件自动完成的。
但它也允许软件来手动干预,手动挂起相当于来一次软件IRQ申请,手动解挂相当于软件撤消IRQ申请。

我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-28 10:37:06 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 12:09 编辑

至于形形色色的片上外设的中断控制,则属于NVIC的下级机构了,

必须注意的是,这些下级机构,按上面的描述,一个IRQ号算一个下级机构的话,最大可达240个。
如果一个IRQ号只有一个中断源的话,就简单了,下级机构根本无须额外的控制功能,
直接由NVIC代管,用NVIC的中断使能、中断挂起位可以了。
但是实际上,多数情况下,每个IRQ的中断源,往往不止一个。
这样,就必须在外设中增加控制功能了。
不同的外设设置的控制功能可能略有不同,
名称可能也有差异,但万变不离其宗,基本都是有如下控制:
中断屏蔽(或使能)
中断挂起(或标志)
前者进行控制,后者显示状态。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-28 10:37:19 | 显示全部楼层
本帖最后由 warship 于 2018-7-30 08:58 编辑

比如EXTI5_9_IRQn对于NVIC来说,只是一个中断,编号为23
但实际却包括了5个中断源,这一点NVIC根本是不知情的。EXTI5_9_IRQn是我们编的一个符号,实际就是一个常数,值为23(本文称为编号)
这5个中断源就具体由下级机构来管理了,每个都必须要有:
中断屏蔽位:是否受理该中断请求(在EXTI->IMR中)
中断挂起位:是否发生了该中断请求(在EXTI->PR中)
只要这5个中任一个或多个触发了中断条件(上升沿/下降沿等),相应的中断挂起就会被硬件置位,如果对应的一个或多个中断屏蔽是开放的,都会产生向NVIC发出EXTI5_9_IRQn号中断请求
至于这个EXTI5_9_IRQn是谁发的,是EXTI5、EXTI6、EXTI7、EXTI8还是EXTI9申请了中断? NVIC是无从知道的,它也管不了那么多。
软件如果需要的话,可以通过调阅监控记录来了解细节,而这个监控记录就是在外设中实现的中断挂起位。
在STM32的外部线中断EXTI系统中,共有19条外部中断线,每一条都有相应的中断挂起位,即EXTI->PR的BIT18:0,满足中断条件后,由硬件置位,并一直保持(随便等待调阅监控),直到由软件手动清除。
注:19条是目前常用芯片具体实现的数目,有些互联型的是20条,EXTI各用一个字来设置中断屏蔽位和中断挂起位,理论上最大可扩展能力为可以表达32条外部中断线
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-28 10:37:34 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 11:59 编辑

STM32的外部线中断共19条,而对于NVIC来说,实际上只有10个通道,具体如下:


内核值(IRQn)       助记符                             备注
6                           EXTI0_IRQn                     PX0(即PA0-PG0口线)
7                           EXTI1_IRQn                     PX1口线
8                           EXTI2_IRQn                     PX2口线
9                           EXTI3_IRQn                     PX3口线
10                         EXTI4_IRQn                     PX4口线
23                         EXTI5_9_IRQn                  PX5-PX9口线
40                         EXTI15_10_IRQn               PX10-PX15口线
1                           PVD_IRQn                        电压监测
41                         RTC_IRQn                        RTC闹钟
42                         USB_IRQn                        USB唤醒


我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-28 10:46:28 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 14:54 编辑

为进一步加深理解,我们从中断控制的角度来看一下串口1
虽然说只是一个串口,从中断控制的角度来看,也算是NVIC一个比较典型的下级机构,
对于NVIC来说,串口1只分配到了一个中断通道USART1_IRQn,编号值为37
但USART1的中断源是非常多的,
常用的有:
  RXNE接收缓冲区非空中断
  TC发送完成中断
  TXE发送缓冲区空中断
其它的还有IDLE中断、CTS中断、错误中断等等,总计不下十种。
但这些,NVIC都是一概不管的,对NVIC只能算一个中断!!!。

具体各类小中断的细分都是由串口1的外设来实现,具体实现套路是:
每一种小中断必有相应的屏蔽位(有时候称为中断允许位xxIE, 一般在控制寄存器CR中),
另外必有相应的标志位(名称如RXNE、TC、TXE等,一般在状态寄存器中),相当于挂起位,在满足触发条件时由硬件置位,并一直保持(随便等待调阅监控)
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2018-7-28 13:14:35 | 显示全部楼层
可以  很强大
猪猪熊呢?
回复

使用道具 举报

0

主题

8

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2018-7-15
在线时间
5 小时
发表于 2018-7-28 14:45:49 | 显示全部楼层
感谢楼主
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-7-29 23:36:12 | 显示全部楼层
楼主对STM32中断的理解,已经超神了。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-7-29 23:40:12 | 显示全部楼层
warship 发表于 2018-7-28 10:35
先说结论,STM32的中断控制是分级管理的,CM3内核中的NVIC是顶层,对每个通道都设有1BIT的中断挂起位,
但 ...

虽然内核只有一个通道,但是外设可以对这个通道的响应有具体的标志位。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-7-29 23:43:51 | 显示全部楼层
warship 发表于 2018-7-28 10:36
STM32的中断系统可以理解为分两级管理,
顶层当然是CM3内核强大的NVIC,下层就是形形色色的片上外设了,
...

地址偏移量=0x0000 0040+IRQn*4  这个公式的出处能否告诉下,如果IRQn为负数呢?
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-30 09:02:25 | 显示全部楼层
本帖最后由 warship 于 2018-8-1 17:39 编辑
hougeqvjing 发表于 2018-7-29 23:40
虽然内核只有一个通道,但是外设可以对这个通道的响应有具体的标志位。

对,准确地说是:虽然内核通常只用一个中断通道对应一个外设,但是外设在使用这个通道的时候可以设多个具体的标志位,这些标志位不是给内核看的,而是给软件看的。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-30 09:09:59 | 显示全部楼层
本帖最后由 warship 于 2018-7-30 09:12 编辑
hougeqvjing 发表于 2018-7-29 23:43
地址偏移量=0x0000 0040+IRQn*4  这个公式的出处能否告诉下,如果IRQn为负数呢?

没有出处,是我自己的理解。
负数也适用,这个0040就是为负数留出的空间,内核保留16个异常,每向量4个字节,正好是0x0040。
硬件的设计一定要简洁便于实现,
不像软件那样可以灵活处理各个分支,
硬件一般尽量使用逻辑电路实现:IRQn左移4位与0x0000 0040相加就可得到偏移量,
向量表的基址在SCB->VTOR(这样可以实现向量表的重定位,而不用存放在固定的Flash中)中,再与它相加就得到绝对地址了
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-7-30 23:25:45 | 显示全部楼层
warship 发表于 2018-7-28 10:36
STM32的中断系统可以理解为分两级管理,
顶层当然是CM3内核强大的NVIC,下层就是形形色色的片上外设了,
...

中断号为负数怎么理解呢?比如systick的编号为15,中断号为-1。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-7-30 23:26:46 | 显示全部楼层
warship 发表于 2018-7-28 10:36
STM32的中断系统可以理解为分两级管理,
顶层当然是CM3内核强大的NVIC,下层就是形形色色的片上外设了,
...

就是小于0的中断号,不归NIVC管?
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-31 08:41:02 | 显示全部楼层
hougeqvjing 发表于 2018-7-30 23:25
中断号为负数怎么理解呢?比如systick的编号为15,中断号为-1。

这种东西纯属ARM的规定,外部中断从0开始编正数,内核中断编号就只能负数了。systick属于内部中断,它是绑定在nvic中的,但离用户最近,所以得了个-1
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-7-31 08:44:21 | 显示全部楼层
hougeqvjing 发表于 2018-7-30 23:26
就是小于0的中断号,不归NIVC管?

当然也要归nvic管了,只不过小于0的中断比较重要,影响全局,由nvic亲自管理,相当于中央直属单位
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-7-31 23:05:50 | 显示全部楼层
warship 发表于 2018-7-31 08:41
这种东西纯属ARM的规定,外部中断从0开始编正数,内核中断编号就只能负数了。systick属于内部中断,它是 ...

NVIC里面不能设置SYSTICK的优先级,也不能开启systick的优先级,为什么说是systick绑定在NVIC中呢?中断异常向量中,位置可以理解为在向量表中的偏移地址,但是优先级有个默认值的意思么?另外NVIC里面是只能设置中断号为0以上的优先级吧?我们设置NVIC的初始化函数,就传递了中断号,抢占优先级,响应优先级,优先级分组。其他可以设置优先级分组的异常,实在SCB中设置的吧?
1111111.png
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-1 16:57:50 | 显示全部楼层
本帖最后由 warship 于 2018-8-1 18:05 编辑
hougeqvjing 发表于 2018-7-31 23:05
NVIC里面不能设置SYSTICK的优先级,也不能开启systick的优先级,为什么说是systick绑定在NVIC中呢?中断 ...

1、NVIC功能强大,将“异常”的概念发挥到了极致,可以说,搞懂了NVIC,就基本掌握了CM3内核的90%以上,因此,它的寄存器数量庞大,你翻看一下权威指南的附录D,就是NVIC寄存器小结,列出了它的所有寄存器,而SYSTICK的区区几个寄存器严格来说也属于NVIC的寄存器,NVIC管理着全天下所有异常的优先级,当然也包括SYSTICK的优先级,系统内核的异常的优先级存放在NVIC的SCB->SHP[12]中(与外部中断IP[240]类似),因为有三个系统异常的优先级是固定的,加上一个保留位置无须设优先级,所以只须16-3-1=12个字节,下标从0到11,SYSTICK为最后一个,即NVIC的SCB->SHP[11]中就存放着SYSTICK的中断优先级(我上次曾让你查看过这个寄存器,系统复位时它的值为0,实际对应最高优先级),你可以通过指令:SCB->SHP[11]=0xF0;  就可以让它的优先级为最低。另有中断控制及状态寄存器ICSR、系统Handler控制及状态寄存器SHCSR可以控制和监视系统级的异常,SYSTICK当然逃不出如来的手心了。另外,我认为不能单纯通过字面如NVIC->IP[240] 及 SCB->AIRCR中的寄存器字冠来说SCB不属于NVIC的寄存器,事实上只有与外部中断相关的一组寄存器(主要是240个中断的中断优先级、使能/除能、挂起/解挂、活动状态等寄存器)冠以NVIC以外,大量NVIC的寄存器族都另起了其它的名称,如SCB、VTOR、SYSTICK等等,具体查看权威指南的附录D。因为NVIC的寄存器种类庞大,地址跨度很大,用单一的结构体来访问比较令人头大,且不如分开成多个意义更明确。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-1 17:06:50 | 显示全部楼层
本帖最后由 warship 于 2018-8-1 17:37 编辑
hougeqvjing 发表于 2018-7-31 23:05
NVIC里面不能设置SYSTICK的优先级,也不能开启systick的优先级,为什么说是systick绑定在NVIC中呢?中断 ...

2、你说的表中的优先级那一栏,我没有看到进一步的说明,可以理解为优先级排序,越排在前面优先级越高,前3个为负数并且值为固定,这是权威指南中有说明的,至于后面的从0开始到好几十(理论上可以至多排到240),没有太多实际意义,不是默认优先级,因为实际的芯片优先级没有那么多,我的理解是:当两个中断优先级设置完全相同时,这个排序决定了谁将会优先得到响应(表中数值小者优先)。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-1 17:35:32 | 显示全部楼层
hougeqvjing 发表于 2018-7-31 23:05
NVIC里面不能设置SYSTICK的优先级,也不能开启systick的优先级,为什么说是systick绑定在NVIC中呢?中断 ...

3、NVIC的寄存器管理着包括系统异常(小于0)和外部中断(0-240)的所有中断的优先级。有如下三处与优先级设置相关的寄存器:
一是应用程序中断及复位控制寄存器(AIRCR)的10:8这三位,用于定义全系统的优先级分组,它定义了如何去解读每一个中断优先级设定值的具体含义(即哪几位代表抢占级,哪几位代表响应级?)
二是系统异常(中断号小于0的)的中断优先级。就是第1点已经回答的SCB的SHP[12],共12个8BIT的数组,其中SHP[11]里存放着SYSTICK的优先级;
三是所有外部中断(中断号大于等于0的)的优先级,存放在IP[240]中,共240个8BIT的数组,可以通过各个中断号作为数组下标来访问。例如:如果想设置EXTI0_IRQn的优先级为最高,使用指令: NVIC->IP[6]=0x00;  就可以了(EXTI0_IRQn中断号为6)。
注意:以上二和三项的表示方法是统一的,每一个中断都可以最大用8BIT定义中断优先级,但我们常用的具体芯片只实现了4BIT,即只有高四位有效。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-8-2 15:43:32 | 显示全部楼层
warship 发表于 2018-8-1 17:35
3、NVIC的寄存器管理着包括系统异常(小于0)和外部中断(0-240)的所有中断的优先级。有如下三处与优先 ...

好点,嗯嗯。我看了下优先级分组的函数如下:
static void MY_NVIC_PriorityGroupConfig(u32 PriorityGroup)
{
    uint32_t reg_value;
        uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);
        reg_value  =  SCB->AIRCR;
        reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk);
        reg_value  =  (reg_value                       |
                      (0x5FA << SCB_AIRCR_VECTKEY_Pos) |
                      (PriorityGroupTmp << 8));
        SCB->AIRCR = reg_value;
}
优先级分组展开为:0x700,0x600,,,,,我怎么感觉该函数应该为下面这样呢?
不知理解得对不对?
static void MY_NVIC_PriorityGroupConfig(u32 PriorityGroup)
{
  uint32_t reg_value;
        uint32_t PriorityGroupTmp = PriorityGroup;
        reg_value  =  SCB->AIRCR;
        reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk);
        reg_value  =  (reg_value                       |
                      (0x5FA << SCB_AIRCR_VECTKEY_Pos) |
                      (PriorityGroupTmp));
        SCB->AIRCR = reg_value;
}
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-2 16:08:00 | 显示全部楼层
hougeqvjing 发表于 2018-8-2 15:43
好点,嗯嗯。我看了下优先级分组的函数如下:
static void MY_NVIC_PriorityGroupConfig(u32 PriorityGr ...

粗看了一下,你的意思是不需要左移8吗?

优先级分组的三位是从第8bit开始的,当然要左移8才能设
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-8-2 16:31:41 | 显示全部楼层
warship 发表于 2018-8-2 16:08
粗看了一下,你的意思是不需要左移8吗?

优先级分组的三位是从第8bit开始的,当然要左移8才能设

我的意思是,比如我选择group0,那么因为#define group0  0x700。所以我觉得uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);应该改为:uint32_t PriorityGroupTmp = PriorityGroup;         reg_value  =  (reg_value                       |
                      (0x5FA << SCB_AIRCR_VECTKEY_Pos) |
                      (PriorityGroupTmp << 8));
应该改为: reg_value  =  (reg_value                       |
                      (0x5FA << SCB_AIRCR_VECTKEY_Pos) |
                      (PriorityGroupTmp));
不知理解得对不对。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-2 18:31:25 | 显示全部楼层
hougeqvjing 发表于 2018-8-2 16:31
我的意思是,比如我选择group0,那么因为#define group0  0x700。所以我觉得uint32_t PriorityGroupTmp = ...

按照你的理解有点道理,
但是没有#define group0  0x700这个定义,
并且你调用函数给参数的时候也不是给的是0x700或者group0
而是直接使用MY_NVIC_PriorityGroupConfig(2);   //给的是组号数值,
所以用& 0x07只取三个有效位,然后再左移8位。

假如你的程序中,有#define group0  0x700
而调用的语句是MY_NVIC_PriorityGroupConfig(group0);
函数体就应该像您说的那么写了。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-2 18:34:23 | 显示全部楼层
本帖最后由 warship 于 2018-8-2 18:35 编辑
hougeqvjing 发表于 2018-8-2 16:31
我的意思是,比如我选择group0,那么因为#define group0  0x700。所以我觉得uint32_t PriorityGroupTmp = ...

我所使用的函数体是这样的(供参考):
//设置NVIC优先级组,一般程序只设一次组,优先组确定后,要根据组的要求,为系统的每一个中断确定其在组中的地位
//输入参数NVIC_Group:  NVIC分组 0~4 总共5组                    
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)         
{
        u32 temp,temp1;         
        temp1=(~NVIC_Group)&0x07;//取后三位 运算结果是0-111 1-110 2-101 3-100 4-011  
        temp1<<=8;                 //运算结果为0x700/600/500/400/300其中的位10:8就是设置值
        
        temp=SCB->AIRCR;  //读取先前的优先级分组设置
        temp&=0X0000F8FF; //清空先前分组F8FF=11111000 11111111,正好清除BIT10:8
        temp|=0X05FA0000; //写入钥匙,规定的套路
        temp|=temp1;           
        SCB->AIRCR=temp;  //设置分组                                                         
}
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-8-2 21:03:27 | 显示全部楼层
warship 发表于 2018-8-2 18:34
我所使用的函数体是这样的(供参考):
//设置NVIC优先级组,一般程序只设一次组,优先组确定后,要根据 ...

嗯呢,我的程序中有宏定义,不是传递的0,1,2,3,4.这样理解 就通了。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-2 22:09:24 | 显示全部楼层
hougeqvjing 发表于 2018-8-2 21:03
嗯呢,我的程序中有宏定义,不是传递的0,1,2,3,4.这样理解 就通了。

可是你的原始函数实现(你25楼的前者)却是和我用的这种是一致的。
而你传递的参数却是0x700这样的参数,
怎么会出现这种不配套的问题呢? 正常工作过吗?
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

2

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2018-1-15
在线时间
13 小时
发表于 2018-8-3 08:50:34 | 显示全部楼层
warship 发表于 2018-8-2 22:09
可是你的原始函数实现(你25楼的前者)却是和我用的这种是一致的。
而你传递的参数却是0x700这样的参数 ...

的确,可能 是 强迫症吧,我传递这种数值理解起来容易些。
回复

使用道具 举报

31

主题

1953

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4462
金钱
4462
注册时间
2018-5-11
在线时间
932 小时
 楼主| 发表于 2018-8-3 12:58:42 | 显示全部楼层
hougeqvjing 发表于 2018-8-3 08:50
的确,可能 是 强迫症吧,我传递这种数值理解起来容易些。

如果使用了宏定义并修改函数体,传递group0这样的参数还是更直观,可读性强一些。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

0

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
184
金钱
184
注册时间
2018-6-17
在线时间
57 小时
发表于 2019-1-22 09:29:20 | 显示全部楼层
Mark
回复

使用道具 举报

1

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
227
金钱
227
注册时间
2010-12-14
在线时间
65 小时
发表于 2019-3-17 11:34:22 | 显示全部楼层
楼主真是厉害!!
回复

使用道具 举报

5

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
193
金钱
193
注册时间
2019-7-23
在线时间
22 小时
发表于 2019-12-25 13:43:21 | 显示全部楼层
请问一下楼主,我用的定时器计时中断,但用什么标志位去看他被其他的操作打断呢,是用USART_IT_IDLE吗
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2020-4-23
在线时间
2 小时
发表于 2020-5-11 11:00:22 | 显示全部楼层
描述得很准确,点赞
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2020-4-23
在线时间
2 小时
发表于 2020-5-11 11:38:33 | 显示全部楼层
warship 发表于 2018-7-28 10:35
先说结论,STM32的中断控制是分级管理的,CM3内核中的NVIC是顶层,对每个通道都设有1BIT的中断挂起位,
但 ...

“因此,下层就必须实现对这多个中断源的独立监控,这就是EXTI->PR中的挂起位了。”
这句话,不对。
EXTI->PR,代表这个通道是否存在有效中断触发。 具体是哪个中断源,通过这个通道,仅仅通过这个位,是确认不了的。
配合SYSCFG_EXTICR寄存器,就才可以。
回复

使用道具 举报

18

主题

99

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
465
金钱
465
注册时间
2016-1-20
在线时间
89 小时
发表于 2020-5-26 15:39:06 | 显示全部楼层
楼主,请问外部中断情况下,配置好中断线以及nvic。但是在EXTI->IMR中屏蔽该中断,此时如果有配置的相应的外部中断源来临,在EXTI->PR中相应的位置会不会被置位?如果处于置位状态,此时再关闭掉对中断的屏蔽,会不会直接触发中断?
回复

使用道具 举报

7

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
121
金钱
121
注册时间
2019-11-24
在线时间
46 小时
发表于 2022-5-15 07:20:55 | 显示全部楼层
typedef struct
{
  __IO uint32_t ISER[8];                      /*!< Offset: 0x000  Interrupt Set Enable Register           */
       uint32_t RESERVED0[24];                /********偏移量:0x000中断设置启用寄存器**********/                  
  __IO uint32_t ICER[8];                      /*!< Offset: 0x080  Interrupt Clear Enable Register         */
       uint32_t RSERVED1[24];                 /********偏移量:0x080中断清除启用寄存器**********/                  
  __IO uint32_t ISPR[8];                      /*!< Offset: 0x100  Interrupt Set Pending Register          */
       uint32_t RESERVED2[24];                /********偏移量:0x100中断设置挂起寄存器**********/                  
  __IO uint32_t ICPR[8];                      /*!< Offset: 0x180  Interrupt Clear Pending Register        */
       uint32_t RESERVED3[24];                /********偏移量:0x180中断清除挂起寄存器**********/                  
  __IO uint32_t IABR[8];                      /*!< Offset: 0x200  Interrupt Active bit Register           */
       uint32_t RESERVED4[56];                /********偏移量:0x200中断活动位寄存器**********/                  
  __IO uint8_t  IP[240];                      /*!< Offset: 0x300  Interrupt Priority Register (8Bit wide) */
       uint32_t RESERVED5[644];               /********偏移量:0x300中断优先级寄存器(8位宽)**********/                  
  __O  uint32_t STIR;                         /*!< Offset: 0xE00  Software Trigger Interrupt Register     */
}  NVIC_Type;                                 /********偏移量:0xE00软件触发中断寄存器**********/            
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 05:53

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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