原创 ARM-CorTexM3-STM32-时钟-SysTick定时器

2011-8-1 11:16 2423 10 10 分类: MCU/ 嵌入式

STM32 系统时钟 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 为一个 24 位递减计数器,SysTick 设定初值并使能后,每经过 1 个系统时钟周期,计数值就减 1。计数到 0 时,SysTick 计数器自动重装初值并继续计数,同时内部的 COUNTFLAG 标志会置位,触发中断 (如果中断使能情况下)

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

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

() 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计数器

7、调用SysTick_GetFlagStatus()            --检查SysTick的状态

() SystemTick 工程实战

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

    /* Configure the system clocks */
    RCC_Configuration();
    SysTick_Configuration();

第一步: 配置 RCC 寄存器 和 SysTick 寄存器

RCC_Configuration: 配置 RCC 寄存器
void 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 */
        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, 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() != 0x08)
        {
        }
    }
    /* Enable GPIOA and AFIO clocks */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
                         RCC_APB2Periph_AFIO, ENABLE);
}

SysTick_Configuration: 配置 SysTick
void SysTick_Configuration(void)
{
    /* Select AHB clock(HCLK) as SysTick clock source */
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);


    /* Set SysTick Priority 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 延时函数

Delay: 系统延时函数, 使用系统时钟操作.

void Delay(u32 nTime)
{
    /* Enable the SysTick Counter */
    SysTick_CounterCmd(SysTick_Counter_Enable);
    TimingDelay = nTime;
    while(TimingDelay != 0);
    /* Disable the SysTick Counter */
    SysTick_CounterCmd(SysTick_Counter_Disable);
    /* Clear the SysTick Counter */
    SysTick_CounterCmd(SysTick_Counter_Clear);
}

第四步: 主函数中调用 Delay

Mini-STM32 开发板上有两个 LED , 分别是 PA0, PA1. 我们做个流水灯程序, 让他们循环点亮.
    while(1)
    {  
        GPIO_SetBits(GPIOA,GPIO_Pin_0);
        Delay(100);
        GPIO_ResetBits(GPIOA,GPIO_Pin_0);
        Delay(100);
        GPIO_SetBits(GPIOA,GPIO_Pin_1);
        Delay(100);
        GPIO_ResetBits(GPIOA,GPIO_Pin_1);
        Delay(100);
    }

下面为深圳英蓓特公司的STM32开发板的的关于<Systick.c>文件说明,仅供参考,谢谢!

///////////////////////////////////////////////////////////////////////////////////////

////////////**********************Systick库函数**************************//////////////

/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name          : stm32f10x_systick.c
* Author             : MCD Application Team
* Version            : V2.0.1
* Date               : 06/13/2008
* Description        : This file provides all the SysTick firmware functions.
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_systick.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* ---------------------- SysTick registers bit mask -------------------- */
/* CTRL TICKINT Mask */
#define CTRL_TICKINT_Set      ((u32)0x00000002)
#define CTRL_TICKINT_Reset    ((u32)0xFFFFFFFD)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : SysTick_CLKSourceConfig
* Description    : Configures the SysTick clock source.
* Input          : - SysTick_CLKSource: specifies the SysTick clock source.
*                    This parameter can be one of the following values:
*                       - SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8
*                         selected as SysTick clock source.
*                       - SysTick_CLKSource_HCLK: AHB clock selected as
*                         SysTick clock source.
* Output         : None
* Return         : None

说明:设置Systick的时钟源: 1Systick时钟源由 < AHB   >提供(即系统时钟SYSCLK

                           2Systick时钟源由 < AHB/8 >提供
*******************************************************************************/
void SysTick_CLKSourceConfig(u32 SysTick_CLKSource)  {
  /* Check the parameters */
  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;
  }
}

/*******************************************************************************
* Function Name  : SysTick_SetReload
* Description    : Sets SysTick Reload value.
* Input          : - Reload: SysTick Reload new value.
*                    This parameter must be a number between 1 and 0xFFFFFF.
* Output         : None
* Return         : None

说明:SysTick 定时器设定装载的计数值,范围:0 - 16777215 0xFFFFFF
*******************************************************************************/
void SysTick_SetReload(u32 Reload)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_RELOAD(Reload));

  SysTick->LOAD = Reload;
}

/*******************************************************************************
* Function Name  : SysTick_CounterCmd
* Description    : Enables or disables the SysTick counter.
* Input          : - SysTick_Counter: new state of the SysTick counter.
*                    This parameter can be one of the following values:
*                       - SysTick_Counter_Disable: Disable counter
*                       - SysTick_Counter_Enable: Enable counter
*                       - SysTick_Counter_Clear: Clear counter value to 0
* Output         : None
* Return         : None

说明:Systick 定时器的开启(Enable)

      Systick 定时器的停止(SysTick_counter_Disable)

      Systick 定时器的清楚计数到 0(SysTick_counter_clear)
*******************************************************************************/
void SysTick_CounterCmd(u32 SysTick_Counter)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_COUNTER(SysTick_Counter));

  if (SysTick_Counter == SysTick_Counter_Enable)
  {
    SysTick->CTRL |= SysTick_Counter_Enable;
  }
  else if (SysTick_Counter == SysTick_Counter_Disable)
  {
    SysTick->CTRL &= SysTick_Counter_Disable;
  }
  else /* SysTick_Counter == SysTick_Counter_Clear */
  {
    SysTick->VAL = SysTick_Counter_Clear;
  }   
}

/*******************************************************************************
* Function Name  : SysTick_ITConfig
* Description    : Enables or disables the SysTick Interrupt.
* Input          : - NewState: new state of the SysTick Interrupt.
*                    This parameter can be: ENABLE or DISABLE.
* Output         : None
* Return         : None

说明:Systick 定时器的中断的使能(ENABLE

      Systick 定时器的中断的禁止(DISABLE
*******************************************************************************/
void SysTick_ITConfig(FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    SysTick->CTRL |= CTRL_TICKINT_Set;
  }
  else
  {
    SysTick->CTRL &= CTRL_TICKINT_Reset;
  }
}

/*******************************************************************************
* Function Name  : SysTick_GetCounter
* Description    : Gets SysTick counter value.
* Input          : None
* Output         : None
* Return         : SysTick current value

说明:读取  < Systick 定时器的的计数值 >
*******************************************************************************/
u32 SysTick_GetCounter(void)
{
  return(SysTick->VAL);
}

/*******************************************************************************
* Function Name  : SysTick_GetFlagStatus
* Description    : Checks whether the specified SysTick flag is set or not.
* Input          : - SysTick_FLAG: specifies the flag to check.
*                    This parameter can be one of the following values:
*                       - SysTick_FLAG_COUNT
*                       - SysTick_FLAG_SKEW
*                       - SysTick_FLAG_NOREF
* Output         : None
* Return         : None

说明:检查指定的SysTick 标志位设置与否

       SysTick_FLAG_COUNT:自从上一次被读取,计数器计数至0
       SysTick_FLAG_SKEW
:由于时钟频率,校准值不精确等于10ms
       SysTick_FLAG_NOREF
:参考时钟未提供
 
*******************************************************************************/
FlagStatus SysTick_GetFlagStatus(u8 SysTick_FLAG)
{
  u32 statusreg = 0, tmp = 0 ;
  FlagStatus bitstatus = RESET;

  /* Check the parameters */
  assert_param(IS_SYSTICK_FLAG(SysTick_FLAG));

  /* Get the SysTick register index */
  tmp = SysTick_FLAG >> 3;

  if (tmp == 2) /* The flag to check is in CTRL register */
  {
    statusreg = SysTick->CTRL;
  }
  else          /* The flag to check is in CALIB register */
  {
    statusreg = SysTick->CALIB;
  }

  if ((statusreg & ((u32)1 << SysTick_FLAG)) != (u32)RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  return bitstatus;
}

/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

////////////************************结束*************************//////////////

////////////************************中断函数*********************//////////////

*******************************************************************************

* Function Name  : SysTickHandler

* Description    : This function handles SysTick Handler.

* Input          : None

* Output         : None

* Return         : None

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

void SysTickHandler(void)

{

/* Decrement the TimingDelay variable */

  Decrement_TimingDelay();

}

////////////************************结束*************************//////////////

 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
10
关闭 站长推荐上一条 /3 下一条