历史上的今天
今天是:2024年10月16日(星期三)
2018年10月16日 | stm32之滴答定时器(4):滴答定时器的优先级设置
2018-10-16 来源:eefocus
上次讲的只剩滴答定时器的优先级设置函数NVIC_SetPriority没有讲,这个函数具体如下
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } * set Priority for Cortex-M3 System Interrupts */
else {
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } * set Priority for device specific Interrupts */
}
它是设置中断标号以及优先级的函数,由于滴答定时器是系统内部中断因此优先级是通过SCB中的SHP寄存器设置的。
这里的SCB无论是STM32技术手册还是CORTEX技术手册都没有具体的说明,在英文的cortex编程手册中介绍,这个是系统控制块system control block。
库函数中,SCB的基地址为0xE000ED00,其结构体如下(注释符还是跟原来同理。。怕被注释)
typedef struct
{
__I uint32_t CPUID; *!< Offset: 0x00 CPU ID Base Register */
__IO uint32_t ICSR; *!< Offset: 0x04 Interrupt Control State Register */
__IO uint32_t VTOR; *!< Offset: 0x08 Vector Table Offset Register */
__IO uint32_t AIRCR; *!< Offset: 0x0C Application Interrupt / Reset Control Register */
__IO uint32_t SCR; *!< Offset: 0x10 System Control Register */
__IO uint32_t CCR; *!< Offset: 0x14 Configuration Control Register */
__IO uint8_t SHP[12]; *!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */
__IO uint32_t SHCSR; *!< Offset: 0x24 System Handler Control and State Register */
__IO uint32_t CFSR; *!< Offset: 0x28 Configurable Fault Status Register */
__IO uint32_t HFSR; *!< Offset: 0x2C Hard Fault Status Register */
__IO uint32_t DFSR; *!< Offset: 0x30 Debug Fault Status Register */
__IO uint32_t MMFAR; *!< Offset: 0x34 Mem Manage Address Register */
__IO uint32_t BFAR; *!< Offset: 0x38 Bus Fault Address Register */
__IO uint32_t AFSR; *!< Offset: 0x3C Auxiliary Fault Status Register */
__I uint32_t PFR[2]; *!< Offset: 0x40 Processor Feature Register */
__I uint32_t DFR; *!< Offset: 0x48 Debug Feature Register */
__I uint32_t ADR; *!< Offset: 0x4C Auxiliary Feature Register */
__I uint32_t MMFR[4]; *!< Offset: 0x50 Memory Model Feature Register */
__I uint32_t ISAR[5]; *!< Offset: 0x60 ISA Feature Register */
} SCB_Type;
其结构体与技术手册中的寄存器完全对应,可以看到 __IO uint8_t SHP[12] ,其是系统异常优先级寄存器,关于这个为什么8位寄存器,12个8位,同样需要参考cm3编程手册。

其地址虽然是连续的,但是实际寄存器内部分布比较特殊


下面回到程序
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff)
查滴答定时器的中断标号为-1,这里涉及了uint32_t(32位无符号整形)强制转换一个负数,由于stm32必须通过硬件才能进入调试状态,因此使用visual C/C++编个程序验证一下.
#include
typedef unsigned __int32 uint32_t;
void main()
{
//typedef unsigned __int32 uint32_t;
int aa=-1;
uint32_t bb = 888;
bb=(uint32_t)aa;
printf("bb is %x", bb);
}
最后得出的结果是0xFFFFFFFF,这里的原因在于机器存储负数的机制,最高位为符号位,负数为其补码,补码为反码加一,因此-1表示就是10000001,反码11111110,补码1111111,32位表示就是0xFFFFFFFF。
回到程序中其实就是0xF-4,也就是SHP[11],也就是寄存器组的最后一个。
#define __NVIC_PRIO_BITS 4 *!< STM32 uses 4 Bits for the Priority Levels */
代入得出优先级是15,也就是系统中断的最低优先级。
滴答定时器就全部介绍完毕啦,实际滴答定时器用起来只要会算计数值就可以了,为什么这么详细呢,因为我自己认为这是学stm32的一个方法,学会了这种思路,以后学习stm32不论是内核还是外设,都能触类旁通,明白学习库函数到寄存器到数据手册的流程
史海拾趣
|
在淘宝上买了一块这样的TFT,用ARM2148去驱动,不知道为什么屏幕显示背景色的时候只能显示一半,就卡死了,什么都出不来了。 程序代码见下: #include \"config.h\" #define uint unsigned int #define uchar unsigned char #define  ...… 查看全部问答> |
|
我看到很多说明书的输出电容的要求都是若干uF或更大,这里指的更大是说可以无限制大吗(至少100倍吧)? 如果是,那么说明更大的电容是不影响稳定性的,可是我算了下,比如TI的tps720xx,如果使用他规定的最小的1uF电容,那么在最重载情况下,负载 ...… 查看全部问答> |
|
c语言函数不能被初始化和赋值,不知道是什么原因,单步调试显示没有赋值,函数变量用静态static修饰可以初始化赋值,但是不能再赋值。 我在ARM2103芯片上编程的,ram大小只有8k字节,是不是函数嵌套层数多了,ram不够了?编译的时候ram显示用了7k.… 查看全部问答> |
|
Windows Mobile程序移植到WinCE手机上的工作量? Windows Mobile程序移植到WinCE手机上的工作量? 我有一个Windows Mobile程序,包括跟pc端进行tcp、ip通讯,调用一些系统接口,比如发送键盘消息,获取窗口句柄等,现在想要把这个程序移植到WinCE 6.0手机上,我想请教一些,会有多大的工作量? ...… 查看全部问答> |
|
cc2430有个写好的样例程序,里面AES的主函数里面包含如下两个函数: aes_main() { aes(); 仅仅是AES加密,把明文分成16bit,设置加密模式等等,没有设涉及到任何DMA的设置问题 aesdma(); AES加载密钥、加密时的DM ...… 查看全部问答> |
|
中断法收数据,波特率38400就正常,再往高去,就收不全了。测试程序,PC发送17个字节,STM32只能收到14个字节,以前在别的芯片上都是这么处理的,到stm32上行不通了、… 查看全部问答> |




