NVIC配置说明及例子代码汉化注释.docx

上传人:b****6 文档编号:7694531 上传时间:2023-01-25 格式:DOCX 页数:35 大小:70.03KB
下载 相关 举报
NVIC配置说明及例子代码汉化注释.docx_第1页
第1页 / 共35页
NVIC配置说明及例子代码汉化注释.docx_第2页
第2页 / 共35页
NVIC配置说明及例子代码汉化注释.docx_第3页
第3页 / 共35页
NVIC配置说明及例子代码汉化注释.docx_第4页
第4页 / 共35页
NVIC配置说明及例子代码汉化注释.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

NVIC配置说明及例子代码汉化注释.docx

《NVIC配置说明及例子代码汉化注释.docx》由会员分享,可在线阅读,更多相关《NVIC配置说明及例子代码汉化注释.docx(35页珍藏版)》请在冰豆网上搜索。

NVIC配置说明及例子代码汉化注释.docx

NVIC配置说明及例子代码汉化注释

STM32中Cortex-M3寄存器说明-NVIC寄存器组、系统控制SCB寄存器组、嘀嗒定时...

在STM32中用到了Cortex-M3定义的三组寄存器,有关这三组寄存器的说明不在STM32的技术手册中,需要参考ARM公司发布的Cortex-M3TechnicalReferenceManual(r2p0)。

在STM32的固件库中定义了三个结构体与这三个寄存器组相对应,这三个结构体与ARM手册中寄存器的对应关系如下:

一、NVIC寄存器组

STM32的固件库中有如下定义:

typedefstruct

{

vu32ISER[2];

u32RESERVED0[30];

vu32ICER[2];

u32RSERVED1[30];

vu32ISPR[2];

u32RESERVED2[30];

vu32ICPR[2];

u32RESERVED3[30];

vu32IABR[2];

u32RESERVED4[62];

vu32IPR[11];

}NVIC_TypeDef;

它们对应ARM手册中的名称为

ISER=InterruptSet-EnableRegisters

ICER=InterruptClear-EnableRegisters

ISPR=InterruptSet-PendingRegister

ICPR=InterruptClear-PendingRegister

IABR=ActiveBitRegister

IPR=InterruptPriorityRegisters

每个寄存器有240位,以InterruptSet-EnableRegisters说明,ISER[0]对应中断源0~31,ISER[1]对应中断源32~63,STM32只有60个中断源,所以没有ISER[2:

7]。

参考STM32技术参考手册中的中断向量表,中断源的位置为:

位置0-WWDG=WindowWatchdoginterrupt

位置1-PVD=PVDthroughEXTILinedetectioninterrupt

位置2-TAMPER=Tamperinterrupt

......

位置58-DMA2_Channel3=DMA2Channel3globalinterrupt

位置59-DMA2_Channel4_5=DMA2Channel4andDMA2Channel5globalinterrupts

二、系统控制寄存器组

STM32的固件库中有如下定义:

typedefstruct

{

vuc32CPUID;

vu32ICSR;

vu32VTOR;

vu32AIRCR;

vu32SCR;

vu32CCR;

vu32SHPR[3];

vu32SHCSR;

vu32CFSR;

vu32HFSR;

vu32DFSR;

vu32MMFAR;

vu32BFAR;

vu32AFSR;

}SCB_TypeDef;/*SystemControlBlockStructure*/

它们对应ARM手册中的名称为

CPUID=CPUIDBaseRegister

ICSR=InterruptControlStateRegister

VTOR=VectorTableOffsetRegister

AIRCR=ApplicationInterrupt/ResetControlRegister

SCR=SystemControlRegister

CCR=ConfigurationControlRegister

SHPR=SystemHandlersPriorityRegister

SHCSR=SystemHandlerControlandStateRegister

CFSR=ConfigurableFaultStatusRegisters

HFSR=HardFaultStatusRegister

DFSR=DebugFaultStatusRegister

MMFAR=MemManageAddressRegister

BFAR=BusFaultAddressRegister

AFSR=AuxiliaryFaultStatusRegister

三、系统时钟寄存器组

STM32的固件库中有如下定义:

typedefstruct

{

vu32CTRL;

vu32LOAD;

vu32VAL;

vuc32CALIB;

}SysTick_TypeDef;

它们对应ARM手册中的名称为

CTRL=SysTickControlandStatusRegister

LOAD=SysTickReloadValueRegister

VAL=SysTickCurrentValueRegister

CALIB=SysTickCalibrationValueRegister

----------------------------------------------------------------------------------------------------------------------

SYSTICK

我不得不说意法半导体确实有点风骚!

甚至有点变态。

我对ST文档STM32F10XXX参考手册的编辑水平真是不敢恭维。

手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑。

比如前面我说过的关于NVIC嵌套向量中断控制器的介绍,这部分我认为是非常重要的,但当你看完他这部分介绍,你根本不会设置中断服务程序,他有哪些寄存器都不知道,更别说去设置了,NVIC的详细介绍是在Cotex-M3中有详细的介绍,不多说。

今天我们说的是systick定时器。

systick定时器和我上面说的情况一样,在手册中根本没有介绍。

我费了九牛二虎之力才在一个犄角格拉里找到systick定时器的英文版的说明。

在Cotex-M3有介绍,为什么要找STM32的介绍,是因为功能设置上还有点区别。

首先看一下systick定时器的作用,下面是Cotex-M3里的一段话:

SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:

15)。

在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。

例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。

因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。

Cortex‐M3处理器内部包含了一个简单的定时器。

因为所有的CM3芯片都带有这个定时器,软件在不同CM3器件间的移植工作得以化简。

该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟),或者是外部时钟(CM3处理器上的STCLK信号)。

不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。

(知道我为什么找ST关于systick的说明了吧)。

下面介绍STM32中的systick,Systick部分内容属于NVIC控制部分,一共有4个寄存器,名称和地址分别是:

STK_CSR,      0xE000E010  --  控制寄存器

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位:

COUNTFLAG,Systick计数比较标志,如果在上次读取本寄存器后,SysTick已经数到了0,则该位为1。

如果读取该位,该位将自动清零

STK_LOAD 重载寄存器:

Systick是一个递减的定时器,当定时器递减至0时,重载寄存器中的值就会被重装载,继续开始递减。

STK_LOAD 重载寄存器是个24位的寄存器最大计数0xFFFFFF。

 

STK_VAL当前值寄存器:

也是个24位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在SysTick控制及状态寄存器中的COUNTFLAG标志。

STK_CALRB 校准值寄存器:

这个寄存器好像目前的水平我还用不到,大体意思明白点,把英文说明放这吧:

位31NOREF:

1=没有外部参考时钟(STCLK不可用)0=外部参考时钟可用

位30SKEW:

1=校准值不是准确的1ms0=校准值是准确的1ms

位[23:

0]:

Calibrationvalue

IndicatesthecalibrationvaluewhentheSysTickcounterrunsonHCLKmax/8asexternalclock.Thevalueisproductdependent,pleaserefertotheProductReferenceManual,SysTickCalibrationValuesection.WhenHCLKisprogrammedatthemaximumfrequency,theSysTickperiodis1ms.Ifcalibrationinformationisnotknown,calculatethecalibrationvaluerequiredfromthefrequencyoftheprocessorclockorexternalclock.

SysTick定时器除了能服务于操作系统之外,还能用于其它目的:

如作为一个闹铃,用于测量时间等。

要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。

下面我们就应用SysTick定时器来裸奔,把它作为一个定时器来用,还是老一套,在寄存器头文件中添加定义寄存器:

//*****************************************************************

//*                              SystemTick-Register                                 

//*******************************************************************

#defineSYSTICK_TENMS   (*((volatileunsignedlong*)0xE000E01C))

#defineSYSTICK_CURRENT (*((volatileunsignedlong*)0xE000E018))

#defineSYSTICK_RELOAD  (*((volatileunsignedlong*)0xE000E014))

#defineSYSTICK_CSR     (*((volatileunsignedlong*)0xE000E010))

 

配置systick寄存器:

voidSysTick_Configuration(void)

{

  SYSTICK_CURRENT=0;//当前值寄存器

  SYSTICK_RELOAD=20000;//重装载寄存器,系统时钟20M中断一次1mS

  SYSTICK_CSR|=0x06;//HCLK作为Systick时钟,Systick中断使能位

 }

中断处理:

voidSysTick_Handler(void)//中断函数

{

externunsignedlongTimingDelay;//延时时间,注意定义为全局变量

 

SYSTICK_CURRENT=0;

if(TimingDelay!

=0x00)

TimingDelay--;

}

利用systick的延时函数:

 

unsignedlongTimingDelay; //延时时间,注意定义为全局变量

voidDelay(unsignedlongnTime) //延时函数

{

SYSTICK_CSR|=0x07;  //使能SysTick计数器

TimingDelay=nTime;//读取延时时间

while(TimingDelay!

=0);//判断延时是否结束

SYSTICK_CSR|=0x06;//关闭SysTick计数器

}

 

intmain()

 {

 SystemInit0();   //系统(时钟)初始化

 stm32_GpioSetup();//GPIO初始化

 SysTick_Configuration();//配置systick定时器

 while

(1)

 {

 GPIO_PORTB_ODR|=(1<<5);

Delay(1000);//1S

 GPIO_PORTB_ODR&=~(1<<5);

 Delay(1000);//1S                                                                             

 }

}

完成!

Delay(1000);实现了1S的精确延时,利用Delay(unsignedlongnTime);配合systick定时器可以实现任意时间的精确延时,当然通过定时器TIMx也是可以这样做的,我只是用它来说明systick定时器的用法

----------------------------------------------------------------------------------------------------------------------

STM32入门教程系统时钟SysTick

(一)背景介绍

在传统的嵌入式系统软件按中通常实现Delay(N)函数的方法为:

for(i=0;i<=x;i++);

        x---对应于对应于N毫秒的循环值

对于STM32系列微处理器来说,执行一条指令只有几十个ns,进行for循环时,要实现N毫秒的x值非常大,而且由于系统频率的宽广,很难计算出延时N毫秒的精确值。

针对STM32微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用Delay(N)。

(二)STM32SysTick介绍

Cortex-M3的内核中包含一个SysTick时钟。

SysTick为一个24位递减计数器,SysTick设定初值并使能后,每经过1个系统时钟周期,计数值就减1。

计数到0时,SysTick计数器自动重装初值并继续计数,同时内部的COUNTFLAG标志会置位,触发中断(如果中断使能情况下)。

在STM32的应用中,使用Cortex-M3内核的SysTick作为定时时钟,设定每一毫秒产生一次中断,在中断处理函数里对N减一,在Delay(N)函数中循环检测N是否为0,不为0则进行循环等待;若为0则关闭SysTick时钟,退出函数。

注:

全局变量TimingDelay,必须定义为volatile类型,延迟时间将不随系统时钟频率改变。

(三)STSysTick库文件

使用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计数器

(四)SystemTick工程实战

外部晶振为8MHz,9倍频,系统时钟为72MHz,SysTick的最高频率为9MHz(最大为HCLK/8),在这个条件下,把SysTick效验值设置成9000,将SysTick时钟设置为9MHz,就能够产生1ms的时间基值,即SysTick产生1ms的中断。

   /*Configurethesystemclocks*/

   RCC_Configuration();

   SysTick_Configuration();

第一步:

配置RCC寄存器和SysTick寄存器

RCC_Configuration:

配置RCC寄存器

voidRCC_Configuration(void)

{

   /*RCCsystemreset(fordebugpurpose)*/

   RCC_DeInit();

   

   /*EnableHSE*/

   RCC_HSEConfig(RCC_HSE_ON);

   

   /*WaittillHSEisready*/

   HSEStartUpStatus=RCC_WaitForHSEStartUp();

   

   if(HSEStartUpStatus==SUCCESS)

   {

       /*HCLK=SYSCLK*/

       RCC_HCLKConfig(RCC_SYSCLK_Div1);

       

       /*PCLK2=HCLK*/

       RCC_PCLK2Config(RCC_HCLK_Div1);

       

       /*PCLK1=HCLK/2*/

       RCC_PCLK1Config(RCC_HCLK_Div2);

       

       /*Flash2waitstate*/

       FLASH_SetLatency(FLASH_Latency_2);

       /*EnablePrefetchBuffer*/

       FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

       

       /*PLLCLK=8MHz*9=72MHz*/

       RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);

       

       /*EnablePLL*/

       RCC_PLLCmd(ENABLE);

       

       /*WaittillPLLisready*/

       while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)

       {

       }

       

       /*SelectPLLassystemclocksource*/

       RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

       

       /*WaittillPLLisusedassystemclocksource*/

       while(RCC_GetSYSCLKSource()!

=0x08)

       {

       }

   }

   

   /*EnableGPIOAandAFIOclocks*/

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|

                        RCC_APB2Periph_AFIO,ENABLE);

}

SysTick_Configuration:

配置SysTick

voidSysTick_Configuration(void)

{

   /*SelectAHBclock(HCLK)asSysTickclocksource*/

   SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);

   

   /*SetSysTickPriorityto3*/

   NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick,3,0);

   

   /*SysTickinterrupteach1mswithHCLKequalto72MHz*/

   SysTick_SetReload(72000);

   

   /*EnabletheSysTickInterrupt*/

   SysTick_ITConfig(ENABLE);

}

第二步:

配置SysTick中断函数

这里我们定义了一个TestSig全局变量,用于我们使用Keil软件自带的逻辑分析仪来分析.

volatilevu32TimingDelay=0;

vu8TestSig=0;

voidSysTickHandler(void)

{

   TimingDelay--;

   if(TimingDelay%2)

   {

       TestSig=1;

   }

   else

   {

       TestSig=0;

   }

}

第三步:

编写Delay延时函数

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1