自学内容网 自学内容网

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     
}  

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

上面是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));                              //普通方式延时
}

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


原文地址:https://blog.csdn.net/qq_28219531/article/details/136247792

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!