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的延时处理.

相关推荐
LateBloomer77731 分钟前
FreeRTOS——信号量
笔记·stm32·学习·freertos
wenchm1 小时前
细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的另一种方法
stm32·单片机·嵌入式硬件
编码追梦人2 小时前
如何实现单片机的安全启动和安全固件更新
单片机
电子工程师UP学堂2 小时前
电子应用设计方案-16:智能闹钟系统方案设计
单片机·嵌入式硬件
飞凌嵌入式3 小时前
飞凌嵌入式T113-i开发板RISC-V核的实时应用方案
人工智能·嵌入式硬件·嵌入式·risc-v·飞凌嵌入式
blessing。。4 小时前
I2C学习
linux·单片机·嵌入式硬件·嵌入式
嵌新程5 小时前
day03(单片机高级)RTOS
stm32·单片机·嵌入式硬件·freertos·rtos·u575
Lin2012306 小时前
STM32 Keil5 attribute 关键字的用法
stm32·单片机·嵌入式硬件
电工小王(全国可飞)6 小时前
STM32 RAM在Memory Map中被分为3个区域
stm32·单片机·嵌入式硬件
maxiumII6 小时前
Diving into the STM32 HAL-----DAC笔记
笔记·stm32·嵌入式硬件