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).以上设置都可以根据实际情况进行。

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

bash 复制代码
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     
}  

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的初始化及其影响因子的确定。下面将对延时函数做具体的分析说明。

bash 复制代码
//延时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;                   //时间超过/等于要延迟的时间,则退出.
                }  
        };                                                                              
}  

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

bash 复制代码
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));                              //普通方式延时
}

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

相关推荐
Whappy0012 分钟前
51单片机-AD(模拟信号转数字信号)-实验()
单片机·嵌入式硬件·51单片机
redcocal10 小时前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘
辰哥单片机设计13 小时前
门磁模块详解(防盗感应开关 STM32)
stm32·单片机·嵌入式硬件·传感器
夜间去看海13 小时前
基于51单片机的自动清洗系统(自动洗衣机)
嵌入式硬件·51单片机·proteus·洗衣机
yrx02030714 小时前
stm32 IIC总线busy解决方法
stm32·单片机·嵌入式硬件
YHPsophie15 小时前
ATGM331C-5T杭州中科微BDS/GNSS全星座定位授时模块应用领域
经验分享·笔记·单片机·信息与通信·交通物流
Archie_IT16 小时前
【STM32系统】基于STM32设计的SD卡数据读取与上位机显示系统(SDIO接口驱动、雷龙SD卡)——文末资料下载
arm开发·stm32·单片机·嵌入式硬件
辰哥单片机设计16 小时前
1×4矩阵键盘详解(STM32)
stm32·单片机·嵌入式硬件·矩阵·传感器
wmkswd16 小时前
CAN总线-STM32上CAN外设
stm32·单片机·嵌入式硬件