系统时钟

一、系统定时器

SysTick叫做系统滴答时钟、系统定时器属于Cortex-M4内核中的一个外设24bit向下递减的计数器

二、系统定时器的中断使用方法

1.代码的初始化

//初始化系统定时器,1S内核触发1000次中断,说白了定时1ms
    SysTick_Config(SystemCoreClock/1000);

2. 中断服务函数的编写

void SysTick_Handler(void)
{
    static uint32_t cnt=0;

    cnt++;
    
    //到达500ms的定时
    if(cnt >= 500)
    {
        cnt=0;
        
        PFout(9)^=1;
    
    }
}
#include <stdio.h>
#include "stm32f4xx.h"
#include "sys.h"

GPIO_InitTypeDef   GPIO_InitStructure;

int main(void)
{

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

    /* 配置PF9引脚为输出模式 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                    //第9根引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                //设置输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                //推挽模式,增加驱动电流
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;            //设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;            //不需要上拉电阻
    GPIO_Init(GPIOF, &GPIO_InitStructure);

    //初始化系统定时器,1S内核触发1000次中断,说白了定时1ms
    //SysTick_Config(SystemCoreClock/1000);// 168000000
    
    //初始化系统定时器,1S内核触发10次中断,说白了定时100ms,现象失败
    SysTick_Config(SystemCoreClock/10);    
    
    //初始化系统定时器,1S内核触发11次中断,说白了定时90.90ms,能够成功
    SysTick_Config(SystemCoreClock/11);    
    
    PFout(9)=1;
    
    while(1)
    {


    }

}


void SysTick_Handler(void)
{
    static uint32_t cnt=0;
    
    cnt++;
    
    //到达500ms的定时
    if(cnt >= 5)
    {
        cnt=0;
        
        PFout(9)^=1;
    
    }
}

3.  定时时间的计算

SysTick_Config(SystemCoreClock/频率);

让系统定时器触发1秒中断是否可以?如果不可以,最大的定时时间又是什么?

不能触发1秒中断

在额定频率情况下,最大定时时间 = 2^24 /168000000 ≈ 99.86ms

超频的频率(216MHz)下,最大定时时间 = 2^24 /216000000≈77.67ms

测试结果:

         //初始化系统定时器,1S内核触发1000次中断,说白了定时1ms,能够成功
         //SysTick_Config(SystemCoreClock/1000);
         
         //初始化系统定时器,1S内核触发10次中断,说白了定时100ms,现象失败 最大只能99.86ms
         SysTick_Config(SystemCoreClock/10);     
         
         //初始化系统定时器,1S内核触发11次中断,说白了定时90.90ms,能够成功
         SysTick_Config(SystemCoreClock/11);     

 

三、系统定时器的用途

两个方面:

没有操作系统:只用于延时 

有操作系统(ucos2 ucos3 freertos....):为操作系统提供精准的定时中断(1ms~50ms)

四、使用系统定时器用于延时的用途

If you want to use the SysTick timer in polling mode, you can use the count flag in the SysTick Control and

Status Register (SysTick->CTRL) to determine when the timer reaches zero.

For example, you can create a timed delay by setting the SysTick timer to a certain value and waiting until it reaches zero:

 

SysTick->CTRL = 0; // Disable SysTick
SysTick->LOAD = 0xFF; // Count from 255 to 0 (256 cycles)
SysTick->VAL = 0; // Clear current value as well as count flag
SysTick->CTRL = 5; // Enable SysTick timer with processor clock
while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
SysTick->CTRL = 0; // Disable SysTick

1.  配置系统定时器的时钟源

 SysTick_Config初始化定时器会触发中断,不需要中断时,用SysTick_CLKSourceConfig来配置

/**
  * @brief  Configures the SysTick clock source.
  * @param  SysTick_CLKSource: specifies the SysTick clock source.
  *   This parameter can be one of the following values:
  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
  * @retval None
  */
void SysTick_CLKSourceConfig(uint32_t 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;
  }
}

2,系统定时器寄存器

1.  当SysTick使用168MHz系统时钟频率时,代码编写如下:

void delay_us(uint32_t nus)
{
 
    SysTick->CTRL = 0;                      // Disable SysTick
    SysTick->LOAD = (SystemCoreClock/1000000)*nus; // 计数值
    SysTick->VAL = 0;                       // Clear current value as well as count flag
    SysTick->CTRL = 5;                      // Enable SysTick timer with processor clock
    while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
    SysTick->CTRL = 0;                      // Disable SysTick
}
 
void delay_ms(uint32_t nms)
{
    SysTick->CTRL = 0;                      // Disable SysTick
    SysTick->LOAD = (SystemCoreClock/1000)*nms; // 计数值
    SysTick->VAL = 0;                       // Clear current value as well as count flag
    SysTick->CTRL = 5;                      // Enable SysTick timer with processor clock
    while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
    SysTick->CTRL = 0;                      // Disable SysTick
}
 
最大的延时为99.86ms

2.  当SysTick使用168MHz系统时钟频率并进行8分频时,代码编写如下:

 

void delay_us(uint32_t nus)
{
    SysTick->CTRL = 0;                      // Disable SysTick
    SysTick->LOAD = (SystemCoreClock/8/1000000)*nus; // 计数值
    SysTick->VAL = 0;                       // Clear current value as well as count flag
    SysTick->CTRL = 1;                   // Enable SysTick timer with processor clock
    while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
    SysTick->CTRL = 0;                      // Disable SysTick
}
 
 
void delay_ms(uint32_t nms)
{
    SysTick->CTRL = 0;                      // Disable SysTick
    SysTick->LOAD = (SystemCoreClock/8/1000)*nms; // 计数值
    SysTick->VAL = 0;                       // Clear current value as well as count flag
    SysTick->CTRL = 1;                   // Enable SysTick timer with processor clock
    while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
    SysTick->CTRL = 0;                      // Disable SysTick
}
 
思考,当前最大的延时时间是多少?如何优化代码,支持秒级别或更长时间的延时?
 
最大的延时时间 = 2^24 / 21000000 ≈ 798.91ms
 
 
void delay_ms(uint32_t nms)
{
    uint32_t m,n;
    
    m = nms/500;
    
    n = nms %500;
    
    //m个500ms的延时
    while(m--)
    {
        SysTick->CTRL = 0;                      // Disable SysTick
        SysTick->LOAD = (SystemCoreClock/8/1000)*500; // 计数值
        SysTick->VAL = 0;                       // Clear current value as well as count flag
        SysTick->CTRL = 1;                      // Enable SysTick timer with processor clock,当使用21MHz的时候,1;当使用168MHz的时候,5;
        while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
        SysTick->CTRL = 0;                      // Disable SysTick  
    }
 
    //不足500ms的延时
    if(n)
    {
        SysTick->CTRL = 0;                      // Disable SysTick
        SysTick->LOAD = (SystemCoreClock/8/1000)*n; // 计数值
        SysTick->VAL = 0;                       // Clear current value as well as count flag
        SysTick->CTRL = 1;                      // Enable SysTick timer with processor clock,当使用21MHz的时候,1;当使用168MHz的时候,5;
        while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
        SysTick->CTRL = 0;                      // Disable SysTick      
    
    }
}

 

#include <stdio.h>
#include "stm32f4xx.h"
#include "sys.h"

GPIO_InitTypeDef   GPIO_InitStructure;


void delay_us(uint32_t nus)
{
    SysTick->CTRL = 0;                         // Disable SysTick
    SysTick->LOAD = (SystemCoreClock/8/1000000)*nus; // 计数值
    SysTick->VAL = 0;                         // Clear current value as well as count flag
    SysTick->CTRL = 1;                         // Enable SysTick timer with processor clock,当使用21MHz的时候,1;当使用168MHz的时候,5;
    while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
    SysTick->CTRL = 0;                         // Disable SysTick
}


void delay_ms(uint32_t nms)
{
    uint32_t m,n;
    
    m = nms/500;
    
    n = nms %500;
    
    //m个500ms的延时
    while(m--)
    {
        SysTick->CTRL = 0;                         // Disable SysTick
        SysTick->LOAD = (SystemCoreClock/8/1000)*500; // 计数值
        SysTick->VAL = 0;                         // Clear current value as well as count flag
        SysTick->CTRL = 1;                         // Enable SysTick timer with processor clock,当使用21MHz的时候,1;当使用168MHz的时候,5;
        while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
        SysTick->CTRL = 0;                         // Disable SysTick    
    }

    //不足500ms的延时
    if(n)
    {
        SysTick->CTRL = 0;                         // Disable SysTick
        SysTick->LOAD = (SystemCoreClock/8/1000)*n; // 计数值
        SysTick->VAL = 0;                         // Clear current value as well as count flag
        SysTick->CTRL = 1;                         // Enable SysTick timer with processor clock,当使用21MHz的时候,1;当使用168MHz的时候,5;
        while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
        SysTick->CTRL = 0;                         // Disable SysTick        
    
    }
}



int main(void)
{
    //配置系统定时器时钟源,当前是使用168MHz
    //SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
    
    //配置系统定时器时钟源,当前是使用168MHz/8=21MHz
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);    

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

    /* 配置PF9引脚为输出模式 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                    //第9根引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                //设置输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                //推挽模式,增加驱动电流
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;            //设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;            //不需要上拉电阻
    GPIO_Init(GPIOF, &GPIO_InitStructure);

    
    while(1)
    {
#if 0        
        delay_ms(90);delay_ms(90);delay_ms(90);delay_ms(90);delay_ms(90);delay_ms(90);
        
        PFout(9)=0;
        
        delay_ms(90);delay_ms(90);delay_ms(90);delay_ms(90);delay_ms(90);delay_ms(90);
        
        PFout(9)=1;        
#else
        delay_ms(1000);
        
        PFout(9)=0;        
        
        delay_ms(1000);
        
        PFout(9)=1;            
#endif
    }

}

 

原文地址:https://www.cnblogs.com/xiangtingshen/p/10961014.html