STM32中断设置相关寄存器的分析

1.中断设置使能和清除寄存器器的分析

地址 名称 描述
0xE000 E100 SETENA 设置使能中断0到31,写1将位置1,写0无作用
0xE000 E180 CLRENA 写1将位置0,禁能中断,写0无作用
__ASM void SET_CLEAR_IRQ(void)
            {
                    LDR         R0, =0xE000E100
                    MOVS        R1, #0x4
                    STR         R1, [R0]

                    LDR         R0, =0xE000E180
                    MOVS    R1, #0x4
                    STR         R1, [R0]
        }

初始状态是这样的`
这里写图片描述

这里第一个STR R1,[R0]是设置使能外部中断2的。执行后:
这里写图片描述

第二个STR R1,[R0]是设置除能外部中断2的。执行后:
这里写图片描述

可以看到SETENA,CLRENA寄存器所对应的地址的内容是相同的,都是中断寄存器的内容,表示哪个中断是开启的。
只是写1后有不同的行为,SETENA写1,置位对应的位,CLRENA写1,清除对应的位。

使用两个寄存器,一个用来设置,一个用来清除,这样的操作的优势在于使能或者除能中断只需要一个写操作就可以完成。

如果使用一个简单的读/写寄存器来完成操作,则使能或者除能中断需要读-修改-写的过程。
如果在读写过程中,发生了中断,而中断中改变了该寄存器的值,那么中断返回后,继续写操作,那么ISR对寄存器的修改有可能会被覆盖。

使用C语言:

*((volatile unsigned long *)(0xE000E100))=0x04;//使能中断2
*((volatile unsigned long *)(0xE000E180))=0x04;//除能中断2

CMSIS提供了以下函数来使能或者除能中断:

void NVIC_EnableIRQ(IRQn_Type_IRQn);
void NVIC_DisableIRQ(IRQn_Type_IRQn);

2.中断挂起和清除挂起

当一个终端发生了,却又无法立即处理(比如处理器正在处理更高优先级的中断),这个中断请求就会被挂起。挂起状态保存在一个寄存器中。如果中断变为当前优先级最高的中断,中断得到处理,那么硬件就会清除中断请求,也可以手动清除。
地址 名称 描述
0xE000E200 SETPEND 设置中断0到31的挂起状态,写1将置1,写0无作用
0xE000E280 CLRPEND 清除中断0到31的挂起状态,写1置位,写0无作用

汇编代码和C语言访问参考上面的中断使能,除能,将地址替换一下就行了。

CMSIS提供了以下函数来访问中断挂起状态寄存器:

void NVIC_SetPendingIRQ(IRQn_Type_IRQn);//设置一个中断的挂起状态
void NVIC_ClearPendingIRQ(IRQn_Type_IRQn);//清除
void NVIC_GetPendingIRQ(IRQn_Type_IRQn);//返回true表示中断挂起状态为1

3.中断优先级

Cortex-M0(+)每一个外部中断都是有一个对应的优先级寄存器(设置内部异常优先级的寄存器和这个不同),每个优先级设置占用1个字节,但是只使用最高的2个位。Cortex-M3使用的是1个字节中的高4位,分为两组,响应优先级和子优先级。Cortex-M0(+)是没有子优先级设置的。为什么使用高位做优先级,主要是为了不同处理器间移植,不会导致中断优先级发生顺序的颠倒。
Cortex-M0中的NVIC寄存器只支持字传输,这样每次修改寄存器都会同时涉及4个中断优先级寄存器。
对于CM0,应该避免中断使能之后改变优先级设定。改变的结果在ARMv6-M体系结构上是不可预知的。而CM3支持中断优先级的动态切换,且支持中断优先级设置寄存器的字节或者半字传输。

设置中断#2的优先级为0xC0(采用高2位,优先级为3),使用C语言:
(访问可能会被随时且不被当前程序所知道的改变的内容,需要使用volatile)

unsigned int temp;
temp=*((volatile unsigned int *)(0xE000E400));
temp=temp&(0xFF00FFFF)|(0xC0<<16);
*((volatile unsigned int*)(0xE000E400))=temp;

CMSIS中的设置函数:

void NVIC_SetPriority(IRQn_Type_IRQn,uint32_t priority);//设置中断或异常的优先级
void NVIC_GetPriority(IRQn_Type_IRQn);//返回中断或异常的优先级

4.异常屏蔽寄存器(PRIMASK)

在对时间敏感的应用,需要在一段较短的时间内禁止所有中断。CM0通过一个PRIMASK寄存器来屏蔽除了NMI和硬件错误异常的其他所有中断和系统异常。
PRIMASK只有一位可用。当为1时,禁止中断和异常,为0时使能。
设置方法:

    MOVS  R0 , #1
    MSR     PRIMASK, R0

或者

CPSIE i;//清除PRIMASK
CPSID i;//设置PRIMASK

CMSIS中

void _enable_irq(void);
void _disable_irq(void);

这两个函数会被编译为CPS指令。
注意时间敏感的程序完成后,需要清除PRIMASK。中断返回并不会清除PRIMASK。

你可能感兴趣的:(STM32中断设置相关寄存器的分析)