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

相关推荐
沐欣工作室_lvyiyi几秒前
基于单片机的智能家居窗帘控制系统设计(论文+源码)
单片机·嵌入式硬件·毕业设计·智能家居·智能窗帘
嵌入式分享16 分钟前
嵌入式分享#41:RK3576改UART波特率【精简版】
linux·嵌入式硬件·ubuntu·嵌入式
典则1 小时前
STM32FreeRtos入门(四)——任务状态和调度
stm32·单片机·嵌入式硬件
充哥单片机设计1 小时前
【STM32项目开源】基于STM32的智能天然气火灾监控
stm32·单片机·嵌入式硬件
充哥单片机设计1 小时前
【STM32项目开源】基于STM32的智能仓库火灾检测系统
stm32·单片机·嵌入式硬件
就叫飞六吧3 小时前
普中stm32大Dap烧录流程
stm32
A9better4 小时前
嵌入式开发学习日志38——stm32之看门狗
stm32·嵌入式硬件·学习
小莞尔4 小时前
【51单片机】【protues仿真】基于51单片机智能路灯控制系统
c语言·stm32·单片机·嵌入式硬件·51单片机
辰哥单片机设计14 小时前
TT直流减速电机(STM32)
stm32
A9better14 小时前
嵌入式开发学习日志36——stm32之USART串口通信前述
stm32·单片机·嵌入式硬件·学习