OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 16365|回复: 12

STM32使用SysTick延时--Alientek源码

[复制链接]

98

主题

408

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1280
金钱
1280
注册时间
2010-12-14
在线时间
0 小时
发表于 2010-12-18 02:05:03 | 显示全部楼层 |阅读模式

2.7.1 delay文件夹

 

delay文件夹内包含了delay.cdelay.h两个文件,这两个文件用来实现系统的延时功能,其中包含3个函数:

void delay_init(u8 SYSCLK);

void delay_ms(u16 nms);

void delay_us(u32 Nus);

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

 

1delay_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;

}

SysTickMDK定义了的一个结构体(在stm32f10x_map.里面),里面包含CTRLLOADVALCALIB4个寄存器,

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的时钟源自HCLK8分频,假设我们外部晶振为8M,然后倍频到72M,那么SysTick的时钟即为9Mhz

fac_us,为us延时的基数,也就是延时1usSysTick->LOAD所应设置的值。fac_msms延时的基数,也就是延时1msSysTick->LOAD所应设置的值。fac_us8位整形数据,fac_ms16位整形数据。正因为如此,系统时钟如果不是8的倍数,则会导致延时函数不准确,这也是我们推荐外部时钟选择8M的原因。这点大家要特别留意。

 

2delay_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的操作。

 

3delay_ms函数

该函数用来延时指定的ms,其参数nms为要延时的微秒数。具体函数如下:

//延时nms

//注意nms的范围

//SysTick->LOAD24位寄存器,所以,最大延时为:

//nms<=0xffffff*8*1000/SYSCLK

//SYSCLK单位为Hznms单位为ms

//72M条件下,nms<=1864

void delay_ms(u16 nms)

{                                        

     u32 temp;                        

     SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD24bit)

     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单位为Hznms的单位为ms。如果时钟为72M,那么nms的最大值为1864ms。超过这个值就会导致延时不准确。

delay.rar

1.22 KB, 下载次数: 686

希望openedv能给大家提供一个友好的技术交流平台!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

10

主题

65

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
204
金钱
204
注册时间
2012-8-16
在线时间
13 小时
发表于 2012-11-12 21:08:01 | 显示全部楼层
为什么循环结束的条件是"temp&0x01&&!(temp&(1<<16))",而不只是"!(temp&(1<<16))"?定时器不是已经开始了吗,还为什么还要判断它?
暂不做硬件,投身机器学习和数据挖掘。欢迎交流!
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
23
金钱
23
注册时间
2012-10-26
在线时间
0 小时
发表于 2012-11-13 14:12:56 | 显示全部楼层
回复【楼主位】张洋:
---------------------------------
其参数nms为要延时的微秒数
     根据单位应该是“毫秒数”吧? 虽然也可以理解为微秒数。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-11-13 16:48:57 | 显示全部楼层
回复【3楼】whp0712:
---------------------------------
是的
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

6

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2012-12-15
在线时间
0 小时
发表于 2012-12-22 15:07:02 | 显示全部楼层
//初始化延迟函数
//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;
}     
//延时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;       //清空计数器        
}   
回复 支持 反对

使用道具 举报

2

主题

6

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2012-12-15
在线时间
0 小时
发表于 2012-12-22 15:09:56 | 显示全部楼层
求指导!为什么在delay_init()函数里SysTick->CTRL&=0xfffffffb;已经配置好了SysTick,那在delay_ms()函数里为什么用SysTick->CTRL=0x01 ;语句,这不会影响到前面初始化的配置吗?
还有while(temp&0x01&&!(temp&(1<<16)));//等待时间到达    
能简化为while(!(temp&(1<<16)));吗?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-12-22 19:34:39 | 显示全部楼层
回复【6楼】ace_young:
---------------------------------
可以
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2013-11-3
在线时间
0 小时
发表于 2013-12-6 09:26:48 | 显示全部楼层
nms<=0xffffff*8*1000/SYSCLK  这个公式是怎么得来的呢,还是有相关资料?
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-6-30
在线时间
0 小时
发表于 2014-7-6 22:10:51 | 显示全部楼层
帮顶及求解!!!
nms<=0xffffff*8*1000/SYSCLK  这个公式是怎么得来的呢,还是有相关资料?===>8088608*8*1000/72000000=898.7ms  为何是1864ms??
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-7-6 23:59:38 | 显示全部楼层
回复【9楼】STM32起步者:
---------------------------------
你再好好捋捋
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
26
金钱
26
注册时间
2014-8-3
在线时间
0 小时
发表于 2014-8-3 10:01:44 | 显示全部楼层
你好,这里的这个8位整数SYSCLK我没看懂,如果它是系统时钟,单位为赫兹,8为怎么够呢??
回复 支持 反对

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
26
金钱
26
注册时间
2014-8-3
在线时间
0 小时
发表于 2014-8-3 10:02:56 | 显示全部楼层
哪位大神能给我解释一下SYSCLK这个数据吗?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-8-3 23:59:09 | 显示全部楼层
回复【12楼】尘封:
---------------------------------
就是个结构体
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-4 23:23

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表