• STM32F4XX - 系统定时器(SysTick)设置


    SysTick: cortex_m4 核心内置的系统定时器(系统定时器,又名系统嘀嗒定时器). 定时器的设置需要参考cortex_m4的技术文档。
    附上时钟树一张:

    在这里插入图片描述上面图中可以看出时钟HSE经过PLL倍频后得到PLLCLK,SYSCLK可以选择使用HSI、HSE或者PLLCLK作为系统时钟(SYSCLK,设置方式可见系统时钟设置章节)。AHB的时钟通过对SYSCLK分频后得到(一般分频系数设置为1,即使用SYSCLK时钟)。AHB时钟后又经过分频得到APBX的时钟(程序中可设置为2和4等),存储器、DMA以及cortex_m4系统定时器的时钟(可设置为1和8).以上设置都可以根据实际情况进行。

    下面结合实际代码进行说明:

    void delay_init(u8 SYSCLK)
    {
            u32 reload;
            SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); 
            fac_us=SYSCLK;                                                  //不论是否使用OS,fac_us都需要使用
            reload=SYSCLK;                                                  //每秒钟的计数次数 单位为M         
            reload*=1000000/configTICK_RATE_HZ;             //根据configTICK_RATE_HZ设定溢出时间
                                                                                            //reload为24位寄存>器,最大值:16777216,在168M下,约合0.0998s左右  
            fac_ms=1000/configTICK_RATE_HZ;                 //代表OS可以延时的最少单位          
            SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
            SysTick->LOAD=reload;                                   //每1/configTICK_RATE_HZ断一次  
            SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK     
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
    SYSCLK = 168;
    这个是设置HCLK作为系统滴答的时钟,可选择SysTick_CLKSource_HCLK或者SysTick_CLKSource_HCLK_Div8。
    系统时钟章节我们计算了HCLK时钟为168MHz。所以延时1us,需要168个节拍时钟周期,所以设置us影响因子为168。比如需要延时3us,那么需要计数的节拍数为3*168 个。
    fac_us=SYSCLK;

    fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位
    因为我们使用了rtos系统,系统使用的滴答频率是1000Hz,我们延时可以使用系统的延时接口,所以设置ms影响因子为1.

    //不论是否使用OS,fac_us都需要使用
    reload=SYSCLK; //每秒钟的计数次数 单位为M
    reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间
    这个是装载到计数器的计数值。因为1us需要168个节拍,所以这里直接将reload值设定为能够计数到1ms的值,也就是168000.(个人觉得这个值设定多少不重要)

    上面是系统定时器SysTick的初始化及其影响因子的确定。下面将对延时函数做具体的分析说明。

    //延时nus
    //nus:要延时的us数.     
    //nus:0~204522252(最大值即2^32/fac_us@fac_us=168)                                                                          
    void delay_us(u32 nus)
    {               
            u32 ticks;
            u32 told,tnow,tcnt=0;
            u32 reload=SysTick->LOAD;                               //LOAD的值               
            ticks=nus*fac_us;                                               //需要的节拍数 
            told=SysTick->VAL;                                      //刚进入时的计数器值
            while(1)
            {
                    tnow=SysTick->VAL;      
                    if(tnow!=told)
                    {           
                            if(tnow<told)tcnt+=told-tnow;   //这里注意一下SYSTICK是一个递减的计数器就可以了.
                            else tcnt+=reload-tnow+told;        
                            told=tnow;
                            if(tcnt>=ticks)break;                   //时间超过/等于要延迟的时间,则退出.
                    }  
            };                                                                              
    }  
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    上面是us的延时函数,根据影响因子计算出需要的节拍数(ticks=nus*fac_us;),比如需要延时3us,那么需要节拍数3x168个。不断地从计数器中取值,累加并跟需要的节拍数3x168相比较,如果超过节拍数,则表示延时达到并退出。

    void delay_ms(u32 nms)
    {       
            if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
            {               
                    if(nms>=fac_ms)                                         //延时的时间大于OS的最少时间周期 
                    { 
                            vTaskDelay(nms/fac_ms);                 //FreeRTOS延时
                    }
                    nms%=fac_ms;                                            //OS已经无法提供这么小的延时了,采用
    普通方式延时    
            }
            delay_us((u32)(nms*1000));                              //普通方式延时
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ms的延时相对更简单了,先使用实时系统的延时函数vTaskDelay进行ms的延时,然后再使用us的函数接口进行us的延时处理.

  • 相关阅读:
    Node.js在携程的落地和最佳实践
    数据结构之洗牌算法
    Spring Boot
    C语言pow函数简单介绍
    因 Log4j 漏洞,ONUS 被黑客攻击后拒交赎金;OpenHarmony 3.0 实现全设备能力初步覆盖;压缩软件 7-Zip 新版发布 | 开源日报
    【含视频教程】python实现图书管理系统
    面试题-多线程-Java 如何实现多线程之间的通讯和协作
    【MyBatis框架】Mybatis实战之基础篇
    基于 nodejs+vue城市轨道交通线路查询系统mysql
    【Summary】机器人方法汇总
  • 原文地址:https://blog.csdn.net/qq_28219531/article/details/136247792