1、NVIC配置说明及例子代码汉化注释STM32中Cortex-M3寄存器说明-NVIC寄存器组、系统控制SCB寄存器组、嘀嗒定时. 在STM32中用到了Cortex-M3定义的三组寄存器,有关这三组寄存器的说明不在STM32的技术手册中,需要参考ARM公司发布的Cortex-M3 Technical Reference Manual (r2p0)。在STM32的固件库中定义了三个结构体与这三个寄存器组相对应,这三个结构体与ARM手册中寄存器的对应关系如下:一、NVIC寄存器组STM32的固件库中有如下定义:typedef structvu32 ISER2;u32 RESERVED030;vu32
2、 ICER2;u32 RSERVED130;vu32 ISPR2;u32 RESERVED230;vu32 ICPR2;u32 RESERVED330;vu32 IABR2;u32 RESERVED462;vu32 IPR11; NVIC_TypeDef;它们对应ARM手册中的名称为ISER = Interrupt Set-Enable RegistersICER = Interrupt Clear-Enable RegistersISPR = Interrupt Set-Pending RegisterICPR = Interrupt Clear-Pending RegisterIABR =
3、 Active Bit RegisterIPR = Interrupt Priority Registers每个寄存器有240位,以Interrupt Set-Enable Registers说明,ISER0对应中断源031,ISER1对应中断源3263,STM32只有60个中断源,所以没有ISER2:7。参考STM32技术参考手册中的中断向量表,中断源的位置为:位置0 - WWDG = Window Watchdog interrupt位置1 - PVD = PVD through EXTI Line detection interrupt位置2 - TAMPER = Tamper inte
4、rrupt.位置58 - DMA2_Channel3 = DMA2 Channel3 global interrupt位置59 - DMA2_Channel4_5 = DMA2 Channel4 and DMA2 Channel5 global interrupts二、系统控制寄存器组STM32的固件库中有如下定义:typedef structvuc32 CPUID;vu32 ICSR;vu32 VTOR;vu32 AIRCR;vu32 SCR;vu32 CCR;vu32 SHPR3;vu32 SHCSR;vu32 CFSR;vu32 HFSR;vu32 DFSR;vu32 MMFAR;vu3
5、2 BFAR;vu32 AFSR; SCB_TypeDef; /* System Control Block Structure */它们对应ARM手册中的名称为CPUID = CPUID Base RegisterICSR = Interrupt Control State RegisterVTOR = Vector Table Offset RegisterAIRCR = Application Interrupt/Reset Control RegisterSCR = System Control RegisterCCR = Configuration Control RegisterS
6、HPR = System Handlers Priority RegisterSHCSR = System Handler Control and State RegisterCFSR = Configurable Fault Status RegistersHFSR = Hard Fault Status RegisterDFSR = Debug Fault Status RegisterMMFAR = Mem Manage Address RegisterBFAR = Bus Fault Address RegisterAFSR = Auxiliary Fault Status Regis
7、ter三、系统时钟寄存器组STM32的固件库中有如下定义:typedef structvu32 CTRL;vu32 LOAD;vu32 VAL;vuc32 CALIB; SysTick_TypeDef;它们对应ARM手册中的名称为CTRL = SysTick Control and Status RegisterLOAD = SysTick Reload Value RegisterVAL = SysTick Current Value RegisterCALIB = SysTick Calibration Value Register-SYSTICK我不得不说意法半导体确实有点风骚!甚至有点
8、变态。我对ST文档 STM32F10XXX参考手册的编辑水平真是不敢恭维。手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑。比如前面我说过的关于NVIC嵌套向量中断控制器的介绍,这部分我认为是非常重要的,但当你看完他这部分介绍,你根本不会设置中断服务程序,他有哪些寄存器都不知道,更别说去设置了,NVIC的详细介绍是在Cotex-M3中有详细的介绍,不多说。今天我们说的是systick定时器。systick定时器和我上面说的情况一样,在手册中根本没有介绍。我费了九牛二虎之力才在一个犄角格拉里找到systick定时器的英文版的说明。在Cotex-M3有介
9、绍,为什么要找STM32的介绍,是因为功能设置上还有点区别。首先看一下systick定时器的作用,下面是Cotex-M3里的一段话:SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。Cort
10、exM3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。(知道我为什么找ST关于systick的说明了吧)。下面介绍STM32中的systick,Systick 部分内容属于NVIC控制部分,一共有4个寄存器,名称和地址分别是:STK_CSR, 0xE000E010-控制寄
11、存器STK_LOAD, 0xE000E014-重载寄存器STK_VAL, 0xE000E018-当前值寄存器STK_CALRB, 0xE000E01C- 校准值寄存器首先看STK_CSR控制寄存器:寄存器内有4个位t具有意义 第0位:ENABLE,Systick 使能位(0:关闭Systick功能;1:开启Systick功能)第1位:TICKINT,Systick 中断使能位 (0:关闭Systick中断;1:开启Systick中断)第2位:CLKSOURCE,Systick时钟源选择(0:使用HCLK/8 作为Systick时钟;1:使用HCLK作为Systick时钟)第3位:COUNTFL
12、AG,Systick计数比较标志,如果在上次读取本寄存器后,SysTick 已经数到了0,则该位为1。如果读取该位,该位将自动清零STK_LOAD 重载寄存器:Systick是一个递减的定时器,当定时器递减至0时,重载寄存器中的值就会被重装载,继续开始递减。STK_LOAD 重载寄存器是个24位的寄存器最大计数0xFFFFFF。STK_VAL当前值寄存器:也是个24位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在SysTick 控制及状态寄存器中的COUNTFLAG 标志。STK_CALRB 校准值寄存器:这个寄存器好像目前的水平我还用不到,大体意思明白点,把英文说明放这吧
13、:位31 NOREF :1=没有外部参考时钟(STCLK 不可用)0=外部参考时钟可用位30 SKEW:1=校准值不是准确的1ms 0=校准值是准确的1ms位23:0 :Calibration valueIndicates the calibration value when the SysTick counter runs on HCLK max/8 as external clock. The value is product dependent, please refer to the Product Reference Manual, SysTick Calibration Value
14、 section. When HCLK is programmed at the maximum frequency, the SysTick period is 1ms. If calibration information is not known, calculate the calibration value required from the frequency of the processor clock or external clock.SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。要注意的是,当处理器在调试期间被喊停(halt
15、)时,则SysTick定时器亦将暂停运作。下面我们就应用SysTick定时器来裸奔,把它作为一个定时器来用,还是老一套,在寄存器头文件中添加定义寄存器:/*/* SystemTick-Register /*#define SYSTICK_TENMS (*(volatile unsigned long *)0xE000E01C)#define SYSTICK_CURRENT (*(volatile unsigned long *)0xE000E018)#define SYSTICK_RELOAD (*(volatile unsigned long *)0xE000E014)#define SYS
16、TICK_CSR (*(volatile unsigned long *)0xE000E010)配置systick寄存器:void SysTick_Configuration(void) SYSTICK_CURRENT=0; /当前值寄存器 SYSTICK_RELOAD=20000; /重装载寄存器,系统时钟20M中断一次1mS SYSTICK_CSR|=0x06;/ HCLK作为Systick时钟,Systick中断使能位中断处理:void SysTick_Handler(void) /中断函数extern unsigned long TimingDelay; / 延时时间,注意定义为全局变
17、量SYSTICK_CURRENT=0;if (TimingDelay != 0x00)TimingDelay-;利用systick的延时函数:unsigned long TimingDelay; / 延时时间,注意定义为全局变量void Delay(unsigned long nTime) /延时函数SYSTICK_CSR|=0x07; / 使能SysTick计数器TimingDelay = nTime; / 读取延时时间while(TimingDelay != 0); / 判断延时是否结束SYSTICK_CSR|=0x06;/ 关闭SysTick计数器int main() SystemIni
18、t0(); /系统(时钟)初始化stm32_GpioSetup (); /GPIO初始化 SysTick_Configuration(); /配置systick定时器while(1) GPIO_PORTB_ODR|=(15);Delay(1000); /1SGPIO_PORTB_ODR&=(15);Delay(1000); /1S 完成!Delay(1000);实现了1S的精确延时,利用Delay(unsigned long nTime);配合systick定时器可以实现任意时间的精确延时,当然通过定时器TIMx也是可以这样做的,我只是用它来说明systick定时器的用法-STM32 入门教程
19、 系统时钟 SysTick(一) 背景介绍在传统的嵌入式系统软件按中通常实现 Delay(N) 函数的方法为:for(i = 0; i = x; i +); x - 对应于 对应于 N 毫秒的循环值对于STM32系 列微处理器来说,执行一条指令只有几十个 ns,进行 for 循环时,要实现 N 毫秒的 x 值非常大,而且由于系统频率的宽广,很难计算出延时 N 毫秒的精确值。针对 STM32 微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用 Delay(N)。(二) STM32 SysTick 介绍Cortex-M3 的内核中包含一个 SysTick 时钟。SysTick 为一
20、个 24 位递减计数器,SysTick 设定初值并使能后,每经过 1 个系统时钟周期,计数值就减 1。计数到 0 时,SysTick 计数器自动重装初值并继续计数,同时内部的 COUNTFLAG 标志会置位,触发中断 (如果中断使能情况下)。在 STM32 的应用中,使用 Cortex-M3 内核的 SysTick 作为定时时钟,设定每一毫秒产生一次中断,在中断处理函数里对 N 减一,在Delay(N) 函数中循环检测 N 是否为 0,不为 0 则进行循环等待;若为 0 则关闭 SysTick 时钟,退出函数。注: 全局变量 TimingDelay , 必须定义为 volatile 类型 ,
21、延迟时间将不随系统时钟频率改变。(三) ST SysTick 库文件使用ST的函数库使用systick的方法1、调用SysTick_CounterCmd() - 失能SysTick计数器2、调用SysTick_ITConfig () - 失能SysTick中断3、调用SysTick_CLKSourceConfig() - 设置SysTick时钟源。4、调用SysTick_SetReload() - 设置SysTick重装载值。5、调用SysTick_ITConfig () - 使能SysTick中断6、调用SysTick_CounterCmd() - 开启SysTick计数器(四) Syste
22、mTick 工程实战外部晶振为 8 MHz,9 倍频,系统时钟为 72MHz,SysTick 的最高频率为9MHz(最大为HCLK / 8),在这个条件下,把 SysTick 效验值设置成9000,将 SysTick 时钟设置为 9 MHz, 就能够产生 1ms 的时间基值,即 SysTick 产生 1ms 的中断。 /* Configure the system clocks */ RCC_Configuration(); SysTick_Configuration();第一步: 配置 RCC 寄存器 和 SysTick 寄存器RCC_Configuration: 配置 RCC 寄存器voi
23、d RCC_Configuration(void) /* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus = SUCCESS) /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK *
24、/ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* PLLCLK = 8MHz * 9 = 72 MHz */ RCC_PLLConfig(RCC_PLLSource_HSE_Div1,
25、 RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) = RESET) /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x0
26、8) /* Enable GPIOA and AFIO clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);SysTick_Configuration: 配置 SysTickvoid SysTick_Configuration(void) /* Select AHB clock(HCLK) as SysTick clock source */ SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); /* Set SysTick Prio
27、rity to 3 */ NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 3, 0); /* SysTick interrupt each 1ms with HCLK equal to 72MHz */ SysTick_SetReload(72000); /* Enable the SysTick Interrupt */ SysTick_ITConfig(ENABLE);第二步: 配置 SysTick 中断函数这里我们定义了一个 TestSig 全局变量, 用于我们使用 Keil 软件自带的逻辑分析仪来分析.volatile vu32 TimingDelay = 0;vu8 TestSig = 0;void SysTickHandler(void) TimingDelay-; if(TimingDelay % 2) TestSig = 1; else TestSig = 0; 第三步: 编写 Delay 延时函数
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1