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 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寄存器
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的时钟源: 1、Systick时钟源由< AHB >提供(即系统时钟SYSCLK)
2、Systick时钟源由< 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();
}
////////////************************结束*************************//////////////