STM32的SYSTICK详解.docx

上传人:b****5 文档编号:11834550 上传时间:2023-04-05 格式:DOCX 页数:12 大小:143.27KB
下载 相关 举报
STM32的SYSTICK详解.docx_第1页
第1页 / 共12页
STM32的SYSTICK详解.docx_第2页
第2页 / 共12页
STM32的SYSTICK详解.docx_第3页
第3页 / 共12页
STM32的SYSTICK详解.docx_第4页
第4页 / 共12页
STM32的SYSTICK详解.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

STM32的SYSTICK详解.docx

《STM32的SYSTICK详解.docx》由会员分享,可在线阅读,更多相关《STM32的SYSTICK详解.docx(12页珍藏版)》请在冰豆网上搜索。

STM32的SYSTICK详解.docx

STM32的SYSTICK详解

摘自网络

什么是SYSTICK:

这是一个24位的系统节拍定时器systemticktimer,SysTick,具有自动重载和溢出中断功能,所有基于Cortex_M3处理器的微控制器都可以由这个定时器获得一定的时间间隔。

作用:

在单任务引用程序中,因为其架构就决定了它执行任务的串行性,这就引出一个问题:

当某个任务出现问题时,就会牵连到后续的任务,进而导致整个系统崩溃。

要解决这个问题,可以使用实时操作系统(RTOS).

因为RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。

这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。

这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。

微控制器的定时器资源一般比较丰富,比如STM32存在8个定时器,为啥还要再提供一个SYSTICK?

原因就是所有基于ARMCortex_M3内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。

而使用RTOS的第一项工作往往就是将其移植到开发人员的硬件平台上,由于SYSTICK的存在无疑降低了移植的难度。

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

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

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

时钟的选择:

用户可以在位于Cortex_M3处理器系统控制单元中的系统节拍定时器控制和状态寄存器(SysTickcontrolandstatusregister,SCSR)选择systick时钟源。

如将SCSR中的CLKSOURCE位置位,SysTick会在CPU频率下运行;而将CLKSOUCE位清除则SysTick会以CPU主频的1/8频率运行。

3.5版本的库函数与以往的有所区别

不存在stm32f10x_systick.c文件,故原来的一些函数也不存在,比如SysTick_SetReload(u32reload);SysTick_ITConfig(FunctionalStateNewState);等

在3.5版本的库函数中与systick相关的函数只有两个

第一个,SysTick_Config(uint32_tticks),在core_cm3.h头文件中进行定义的。

第二个,voidSysTick_CLKSourceConfig(uint32_tSysTick_CLKSource),在misc.c文件中定义的。

SysTick_Config(uint32_tticks),在core_cm3.h

主要的作用:

1、初始化systick

2、打开systick

3、打开systick的中断并设置优先级

4、返回一个0代表成功或1代表失败

注意:

Uint32_tticks  即为重装值,

这个函数默认使用的时钟源是AHB,即不分频。

要想分频,调用voidSysTick_CLKSourceConfig(uint32_tSysTick_CLKSource),

但是要注意函数调用的次序,先SysTick_Config(uint32_tticks),

后SysTick_CLKSourceConfig(uint32_tSysTick_CLKSource)

函数说明:

/**

*@brief  InitializeandstarttheSysTickcounteranditsinterrupt.

*

*@param  ticks  numberofticksbetweentwointerrupts

*@return  1=failed,0=successful

*

*Initialisethesystemticktimeranditsinterruptandstartthe

*systemticktimer/counterinfreerunningmodetogenerate

*periodicalinterrupts.

*/

static__INLINEuint32_tSysTick_Config(uint32_tticks)

{

  if(ticks>SysTick_LOAD_RELOAD_Msk)  return

(1);        

  /*Reloadvalueimpossible*/重装载值必须小于0XFFFFFF,为什么,这是一个24位的递减计数器。

  SysTick->LOAD  =(ticks&SysTick_LOAD_RELOAD_Msk)-1;

    /*setreloadregister*/设置重装载值,SysTick_LOAD_RELOAD_Msk定义见后面

  NVIC_SetPriority(SysTick_IRQn,(1<<__NVIC_PRIO_BITS)-1);

/*setPriorityforCortex-M0SystemInterrupts*/

  SysTick->VAL  =0;

  /*LoadtheSysTickCounterValue*/

  SysTick->CTRL  =SysTick_CTRL_CLKSOURCE_Msk|

            SysTick_CTRL_TICKINT_Msk  |

            SysTick_CTRL_ENABLE_Msk;            

/*EnableSysTickIRQandSysTickTimer*/

  return(0);

  /*Functionsuccessful*/

}

#endif

与systick相关的寄存器定义

/**@addtogroupCMSIS_CM3_SysTickCMSISCM3SysTick

  memorymappedstructureforSysTick

  @{

*/

typedefstruct

{

  __IOuint32_tCTRL;/*!

0x00  SysTickControlandStatusRegister*/

  __IOuint32_tLOAD;/*!

0x04  SysTickReloadValueRegister    */

  __IOuint32_tVAL;/*!

0x08  SysTickCurrentValueRegister    */

  __I  uint32_tCALIB;/*!

0x0C  SysTickCalibrationRegister      */

}SysTick_Type;

与systick寄存器相关的寄存器及位的定义

/*SysTickControl/StatusRegisterDefinitions*/控制/状态寄存器

#define  SysTick_CTRL_COUNTFLAG_Pos  16    /*!

COUNTFLAGPosition*/

#defineSysTick_CTRL_COUNTFLAG_Msk      (1ul<

/*!

COUNTFLAGMask*/溢出标志位

#defineSysTick_CTRL_CLKSOURCE_Pos  2    /*!

CLKSOURCEPosition*/

#defineSysTick_CTRL_CLKSOURCE_Msk      (1ul<

/*!

CLKSOURCEMask*/时钟源选择位,0=外部时钟;1=内核时钟

#defineSysTick_CTRL_TICKINT_Pos    1      /*!

TICKINTPosition*/

#defineSysTick_CTRL_TICKINT_Msk        (1ul<

/*!

TICKINTMask*/异常请求位

#defineSysTick_CTRL_ENABLE_Pos        0    /*!

ENABLEPosition*/

#defineSysTick_CTRL_ENABLE_Msk        (1ul<

/*!

ENABLEMask*/使能位

/*SysTickReloadRegisterDefinitions*/

#defineSysTick_LOAD_RELOAD_Pos        0  /*!

RELOADPosition*/

#defineSysTick_LOAD_RELOAD_Msk        (0xFFFFFFul<

/*!

RELOADMask*/

/*SysTickCurrentRegisterDefinitions*/

#defineSysTick_VAL_CURRENT_Pos        0    /*!

CURRENTPosition*/

#defineSysTick_VAL_CURRENT_Msk        (0xFFFFFFul<

/*!

CURRENTMask*/

/*SysTickCalibrationRegisterDefinitions*/

#defineSysTick_CALIB_NOREF_Pos        31    /*!

NOREFPosition*/

#defineSysTick_CALIB_NOREF_Msk        (1ul<

/*!

NOREFMask*/

#defineSysTick_CALIB_SKEW_Pos        30    /*!

SKEWPosition*/

#defineSysTick_CALIB_SKEW_Msk        (1ul<

/*!

SKEWMask*/

#defineSysTick_CALIB_TENMS_Pos        0    /*!

TENMSPosition*/

#defineSysTick_CALIB_TENMS_Msk        (0xFFFFFFul<

TENMSMask*/

/*@}*//*endofgroupCMSIS_CM3_SysTick*/

与systick相关的寄存器的说明

voidSysTick_CLKSourceConfig(uint32_tSysTick_CLKSource)

作用:

选择systick的时钟源,AHB时钟或AHB的8分频

默认使用的是AHB时钟,即72MHz

函数说明:

/**

  *@brief  ConfigurestheSysTickclocksource.

  *@param  SysTick_CLKSource:

specifiestheSysTickclocksource.

  *  Thisparametercanbeoneofthefollowingvalues:

  *    @argSysTick_CLKSource_HCLK_Div8:

AHBclockdividedby8selectedasSysTickclocksource.

  *    @argSysTick_CLKSource_HCLK:

AHBclockselectedasSysTickclocksource.

  *@retvalNone

  */

voidSysTick_CLKSourceConfig(uint32_tSysTick_CLKSource)

{

  /*Checktheparameters*/

  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));

  if(SysTick_CLKSource==SysTick_CLKSource_HCLK)

  {

  SysTick->CTRL|=SysTick_CLKSource_HCLK;

  }

  else

  {

  SysTick->CTRL&=SysTick_CLKSource_HCLK_Div8;

  }

}

Systick时钟源的定义:

/**@defgroupSysTick_clock_source

  *@{

  */

#defineSysTick_CLKSource_HCLK_Div8  ((uint32_t)0xFFFFFFFB)//将控制状态寄存器的第二位置0,即用外部时钟源

#defineSysTick_CLKSource_HCLK      ((uint32_t)0x00000004)//将控制状态寄存器的第二位置1,即用内核时钟

#defineIS_SYSTICK_CLK_SOURCE(SOURCE)(((SOURCE)==SysTick_CLKSource_HCLK)||\

                          ((SOURCE)==SysTick_CLKSource_HCLK_Div8))

Systick定时时间的设定:

重装载值=systick时钟频率(Hz)X想要的定时时间(S)

如:

时钟频率为:

AHB的8分频;AHB=72MHz那么systick的时钟频率为72/8MHz=9MHz;要定时1秒,则

重装载值=9000000X1=9000000;

定时10毫秒

重状态值=9000000X0.01=90000

Systick的中断处理函数,

在startup_stm32f10x_hd.s启动文件中有定义。

DCD    SysTick_Handler        ;SysTickHandler

根据需要直接编写中断处理函数即可:

VoidSysTick_Handler(void)

{;}

注意:

如果在工程中,加入了stm32f10x_it.c,而又在主函数中编写中断函数,则会报错。

因为在stm32f10x_it.c文件中,也有这个中断函数的声明,只是内容是空的。

/**

  *@brief  ThisfunctionhandlesSysTickHandler.

  *@param  None

  *@retvalNone

  */

voidSysTick_Handler(void)

{

}

中断优先级的修改

在调用SysTick_Config(uint32_tticks)之后,调用voidNVIC_SetPriority(IRQn_TypeIRQn,uint32_tpriority)。

这个函数在core_cm3.h头文件中。

具体内容如下:

/**

*@brief  Setthepriorityforaninterrupt

*

*@param  IRQn    Thenumberoftheinterruptforsetpriority

*@param  priority  Theprioritytoset

*

*Setthepriorityforthespecifiedinterrupt.Theinterrupt

*numbercanbepositivetospecifyanexternal(devicespecific)

*interrupt,ornegativetospecifyaninternal(core)interrupt.

*

*Note:

Theprioritycannotbesetforeverycoreinterrupt.

*/

static__INLINEvoidNVIC_SetPriority(IRQn_TypeIRQn,uint32_tpriority)

{

  if(IRQn<0){

  SCB->SHP[((uint32_t)(IRQn)&0xF)-4]=((priority<<(8-__NVIC_PRIO_BITS))&0xff);}/*setPriorityforCortex-M3SystemInterrupts*/

  else{

  NVIC->IP[(uint32_t)(IRQn)]=((priority<<(8-__NVIC_PRIO_BITS))&0xff);  }      /*setPriorityfordevicespecificInterrupts  */

}

下面以一个实例来说明:

利用systick来实现以1秒的时间间隔,闪亮一个LED指示灯,指示灯接在GPIOA.8,低电平点亮。

#include"stm32f10x.h"

//函数声明

voidGPIO_Configuration(void);//设置GPIOA.8端口

u32t;//定义一个全局变量

intmain(void)

{

//SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

    SysTick_Config(9000000);

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

    GPIO_Configuration();

    while

(1);    

}

//GPIOA.8设置函数

voidGPIO_Configuration(void)

{

GPIO_InitTypeDef  GPIO_InitStruct;//定义一个端口初始化结构体

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开GPIOA口时钟

    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//设置为推挽输出

    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//设置输出频率50M

    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;//指定第8脚

    GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIOA.8    

    GPIO_SetBits(GPIOA,  GPIO_Pin_8);//置高GPIOA.8,关闭LED

}

//systick中断函数

voidSysTick_Handler(void)

{

t++;

    if(t>=1)

    {

          if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)==1)

          {GPIO_ResetBits(GPIOA,GPIO_Pin_8);}    

    }

    if(t>=2)

    {

          if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)==0)

              {GPIO_SetBits(GPIOA,GPIO_Pin_8);}

              t=0;

    }

}

模拟后的结果

1、8分频后结果

2、直接调用SysTick_Config(9000000);即不分频的结果,间隔为1/8=0.125s

总结:

1、要使用systick定时器,只需调用SysTick_Config(uint32_tticks)函数即可,

  自动完成了,重装载值的装载,时钟源选择,计数寄存器复位,中断优先级的设置(最低),开中断,开始计数的工作。

2、要修改时钟源调用SysTick_CLKSourceConfig(uint32_tSysTick_CLKSource)。

3、要修改中断优先级调用

    voidNVIC_SetPriority(IRQn_TypeIRQn,uint32_tpriority)

应用说明:

1、因systick是一个24位的定时器,故重装值最大值为2的24次方=16777215,

  要注意不要超出这个值。

2、systick是cortex_m3的标配,不是外设。

故不需要在RCC寄存器组打开他的时钟。

3、每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。

4、采用使用库函数的方法,只能采用中断的方法响应定时器计时时间到,如要采用查询的方法,那只能采用设置systick的寄存器的方法,具体操作以后再做分析。

  

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

当前位置:首页 > 求职职场 > 简历

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

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