打印
[应用相关]

STM32使用SysTick延时--Alientek源码

[复制链接]
972|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
原贴链接:http://www.openedv.com/forum.php?mod=viewthread&tid=93


2.7.1 delay文件夹

delay文件夹内包含了delay.c和delay.h两个文件,这两个文件用来实现系统的延时功能,其中包含3个函数:
void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 Nus);
下面分别介绍这三个函数,在介绍之前,我们先了解一下编程思想:CM3内核的处理器,内部包含了一个SysTick定时器,SysTick是一个24位的倒计数定时器,当计到0时,将从RELOAD寄存器中自动重装载定时初值。只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。SysTick在STM32的参考手册里面介绍的很简单,其详细介绍,请参阅《Cortex-M3权威指南》第133页。我们就是利用STM32的内部SysTick来实现延时的,这样不占用中断,也不占用系统定时器。

1)delay_init函数
该函数用来初始化2个重要参数:fac_us以及fac_ms;同时吧SysTick的时钟源选择外部时钟。具体代码如下:
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
     SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
     fac_us=SYSCLK/8;                       
     fac_ms=(u16)fac_us*1000;
}
SysTick是MDK定义了的一个结构体(在stm32f10x_map.里面),里面包含CTRL、LOAD、VAL、CALIB等4个寄存器,
SysTick->CTRL的各位定义如下图所示:


                              图2.7.1.1 SysTick->CTRL寄存器各位定义
SysTick-> LOAD的定义如下图所示:


                              图2.7.1.2 SysTick->LOAD寄存器各位定义
SysTick-> VAL的定义如下图所示:


                              图2.7.1.3 SysTick->VAL寄存器各位定义
SysTick-> CALIB不常用,在这里我们也用不到,故不介绍了。
SysTick->CTRL&=0xfffffffb;这一句把SysTick的时钟选择外部时钟,这里需要注意的是SysTick的时钟源自HCLK的8分频,假设我们外部晶振为8M,然后倍频到72M,那么SysTick的时钟即为9Mhz。
fac_us,为us延时的基数,也就是延时1us,SysTick->LOAD所应设置的值。fac_ms为ms延时的基数,也就是延时1ms,SysTick->LOAD所应设置的值。fac_us为8位整形数据,fac_ms为16位整形数据。正因为如此,系统时钟如果不是8的倍数,则会导致延时函数不准确,这也是我们推荐外部时钟选择8M的原因。这点大家要特别留意。

2)delay_us函数
该函数用来延时指定的us,其参数nus为要延时的微秒数。具体函数如下:
//延时us                                                                                          
void delay_us(u32 nus)
{              
     u32 temp;                       
     SysTick->LOAD=nus*fac_us; //时间加载                          
     SysTick->VAL=0x00;        //清空计数器
     SysTick->CTRL=0x01 ;      //开始倒数     
     do
     {
                 temp=SysTick->CTRL;
     }
     while(temp&0x01&&!(temp&(1<<16)));//等待时间到达  
     SysTick->CTRL=0x00;       //关闭计数器
     SysTick->VAL =0X00;       //清空计数器
}
有了上面对SysTick寄存器的描述,这段代码不难理解。其实就是先把要延时的us数换算成SysTick的时钟数,然后写入LOAD寄存器。然后清空当前寄存器VAL的内容,再开启倒数功能。等到倒数结束,即延时了nus。最后关闭SysTick,清空VAL的值。实现一次延时nus的操作。

3)delay_ms函数
该函数用来延时指定的ms,其参数nms为要延时的微秒数。具体函数如下:
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{                                       
     u32 temp;                        
     SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
     SysTick->VAL =0x00;           //清空计数器
     SysTick->CTRL=0x01 ;          //开始倒数
     do
     {
                 temp=SysTick->CTRL;
     }
     while(temp&0x01&&!(temp&(1<<16)));//等待时间到达  
     SysTick->CTRL=0x00;       //关闭计数器
     SysTick->VAL =0X00;       //清空计数器                 
}
此部分代码和7.2节的delay_us大致一样,但是要注意因为LOAD仅仅是一个24bit的寄存器,延时的ms数不能太长。否则超出了LOAD的范围,高位会被舍去,导致延时不准。最大延迟ms数可以通过公式:nms<=0xffffff*8*1000/SYSCLK计算。SYSCLK单位为Hz,nms的单位为ms。如果时钟为72M,那么nms的最大值为1864ms。超过这个值就会导致延时不准确。

附件:
delay.rar (1.22 KB)

使用特权

评论回复
沙发
零三翟邢止胃| | 2019-3-29 09:17 | 只看该作者
感谢分享啊! 真是不错啊!好帖子啊!帮你顶住啊!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

80

帖子

0

粉丝