• 系统时钟


    一、系统定时器

    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
        }
    
    }

     

  • 相关阅读:
    ie6下absolute:fixed问题,完美兼容
    ajax传输 基础一
    获取ip的ip138.com
    css 常用代码解析
    QQ客服出现“企业QQ在线咨询无权限在当前场景使用!” 问题
    用js实现QQ自定义在线图片
    getElement的几中属性介绍
    Ecshop 单选按钮组功能 颜色多选
    IE6完美解决fix问题
    PHP站内搜索、多关键字、加亮显示
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/10961014.html
Copyright © 2020-2023  润新知