OpenEdv-开源电子网

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

转摘-------------关于STM32的systick定时器的详细说明

[复制链接]

10

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2012-3-14
在线时间
0 小时
发表于 2012-3-24 16:39:53 | 显示全部楼层 |阅读模式
 

ARM学习《九》——关于STM32的systick定时器的详细说明

标签: ARM systick 定时器 详细说明 学习 2010-05-13 23:58

我不得不说意法半导体确实有点风骚!甚至有点变态。我对ST文档 STM32F10XXX参考手册的编辑水平真是不敢恭维。手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑。比如前面我说过的关于NVIC嵌套向量中断控制器的介绍,这部分我认为是非常重要的,但当你看完他这部分介绍,你根本不会设置中断服务程序,他有哪些寄存器都不知道,更别说去设置了,NVIC的详细介绍是在Cotex-M3中有详细的介绍,不多说。今天我们说的是systick定时器。

systick定时器和我上面说的情况一样,在手册中根本没有介绍。我费了九牛二虎之力才在一个犄角格拉里找到systick定时器的英文版的说明。在Cotex-M3有介绍,为什么要找STM32的介绍,是因为功能设置上还有点区别。首先看一下systick定时器的作用,下面是Cotex-M3里的一段话:fficeffice" />

SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。

Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLKCM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。(知道我为什么找ST关于systick的说明了吧)

下面介绍STM32中的systickSystick 部分内容属于NVIC控制部分,一共有4个寄存器,名称和地址分别是:

STK_CSR, 0xE000E010 -- 控制寄存器
STK_LOAD, 0xE000E014 --
重载寄存器
STK_VAL, 0xE000E018 --
当前值寄存器
STK_CALRB, 0xE000E01C --
校准值寄存器

首先看STK_CSR控制寄存器:寄存器内有4个位t具有意义

0位:ENABLESystick 使能位 0:关闭Systick功能;1:开启Systick功能)
1位:TICKINTSystick 中断使能位 0:关闭Systick中断;1:开启Systick中断)
2位:CLKSOURCESystick时钟源选择 0:使用HCLK/8 作为Systick时钟;1:使用HCLK作为Systick时钟)
3位:COUNTFLAGSystick计数比较标志,
如果在上次读取本寄存器后,SysTick 已经数到了0,则该位为1。如果读取该位,该位将自动清零

STK_LOAD 重载寄存器:

Systick是一个递减的定时器,当定时器递减至0时,重载寄存器中的值就会被重装载,继续开始递减。STK_LOAD 重载寄存器是个24位的寄存器最大计数0xFFFFFF

STK_VAL当前值寄存器:

也是个24位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在SysTick 控制及状态寄存器中的COUNTFLAG 标志。

STK_CALRB 校准值寄存器:

这个寄存器好像目前的水平我还用不到,大体意思明白点,把英文说明放这吧:

31 NOREF 1=没有外部参考时钟(STCLK 不可用)0=外部参考时钟可用

30 SKEW1=校准值不是准确的1ms 0=校准值是准确的1ms

[23:0] Calibration value

Indicates the calibration value when the SysTick counter runs on HCLK max/8 as external clock. The value is product dependent, please refer to the Product Reference Manual, SysTick Calibration Value section. When HCLK is programmed at the maximum frequency, the SysTick period is 1ms. If calibration information is not known, calculate the calibration value required from the frequency of the processor clock or external clock.

SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。

下面我们就应用SysTick定时器来裸奔,把它作为一个定时器来用,还是老一套,在寄存器头文件中添加定义寄存器:

//*****************************************************************

//* SystemTick-Register

//*******************************************************************

#define SYSTICK_TENMS (*((volatile unsigned long *)0xE000E01C))

#define SYSTICK_CURRENT (*((volatile unsigned long *)0xE000E018))

#define SYSTICK_RELOAD (*((volatile unsigned long *)0xE000E014))

#define SYSTICK_CSR (*((volatile unsigned long *)0xE000E010))

配置systick寄存器:

void SysTick_Configuration(void)

{

SYSTICK_CURRENT=0; //当前值寄存器

SYSTICK_RELOAD=20000; //重装载寄存器,系统时钟20M中断一次1mS

SYSTICK_CSR|=0x06;// HCLK作为Systick时钟,Systick中断使能位

}

中断处理:

void SysTick_Handler(void) //中断函数

{

extern unsigned long TimingDelay; // 延时时间,注意定义为全局变量

SYSTICK_CURRENT=0;

if (TimingDelay != 0x00)

TimingDelay--;

}

利用systick的延时函数:

unsigned long TimingDelay; // 延时时间,注意定义为全局变量

void Delay(unsigned long nTime) //延时函数

{

SYSTICK_CSR|=0x07; // 使能SysTick计数器

TimingDelay = nTime; // 读取延时时间

while(TimingDelay != 0); // 判断延时是否结束

SYSTICK_CSR|=0x06;// 关闭SysTick计数器

}

int main()

{

SystemInit0(); //系统(时钟)初始化

stm32_GpioSetup (); //GPIO初始化

SysTick_Configuration(); //配置systick定时器

while(1)

{

GPIO_PORTB_ODR|=(1<<5);

Delay(1000); //1S

GPIO_PORTB_ODR&=~(1<<5);

Delay(1000); //1S

}

}

完成!Delay(1000);实现了1S的精确延时,利用Delay(unsigned long nTime);配合systick定时器可以实现任意时间的精确延时,当然通过定时器TIMx也是可以这样做的,我只是用它来说明systick定时器的用法。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

10

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2012-3-14
在线时间
0 小时
 楼主| 发表于 2012-3-24 16:42:37 | 显示全部楼层
本人也在找systick的资料,发现文档上面居然没有,在网上找到了这个,分享给大家
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2012-3-24 17:28:42 | 显示全部楼层
图片一个都看不到...
楼主处理下.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

20

主题

562

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
670
金钱
670
注册时间
2012-2-28
在线时间
0 小时
发表于 2012-3-26 14:07:13 | 显示全部楼层
发个链接吧…………
努力,前进。
回复 支持 反对

使用道具 举报

10

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2012-3-14
在线时间
0 小时
 楼主| 发表于 2012-3-26 15:39:50 | 显示全部楼层
http://www.360doc.com/content/12/0324/16/9330952_197289687.shtml
这是链接
回复 支持 反对

使用道具 举报

10

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2012-3-14
在线时间
0 小时
 楼主| 发表于 2012-3-26 16:03:51 | 显示全部楼层
我看了一下这个的程序,发现了一个疑问,我没有去测试代码,提出来供大家参考:
void Delay(unsigned long nTime) //延时函数

{

SYSTICK_CSR|=0x07; // 使能SysTick计数器

TimingDelay = nTime; // 读取延时时间

while(TimingDelay != 0); // 判断延时是否结束

SYSTICK_CSR|=0x06;// 关闭SysTick计数器

}

这个函数中,最后一句SYSTICK_CSR|=0x06;// 关闭SysTick计数器
是不是有问题?我觉得再systick打开以后,这条语句是没办法将它关掉的。
是不是应该换做SYSTICK_CSR&=0x06;
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2012-3-26 16:56:34 | 显示全部楼层
是不是之类的问题,自己试试就知道了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-25 07:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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