STM32F030 Nucleo-做个准确的延时SysTick

发布者:平静心境最新更新时间:2018-07-17 来源: eefocus关键字:STM32F030  延时  SysTick 手机看文章 扫描二维码
随时随地手机看文章

写过单片机程序的人都知道,软件延时是不准确的,当然,当在我们可接受的情况下,很多地方还是用软件延时的!但是在情况允许的条件下,我们还是希望延时越准确越好,这样可以保证我们Demo的一些精度或者时候准确性。

在所以的ST32位MCU中,基本上都存在这么一个定时器,很多人都叫它“滴答定时器”,也就是SysTick,在我移植过的好几个实时操作系统中,这个滴答定时器都用来作为操作系统调度的定时器了。其实这个定时器的使用非常简单,但是基本上很多人又觉得它是神秘的!为毛呢??打开MCU的DadaSheet,参考手册,都很少提到SysTick,并且提到的地方也就是一句话带过,库手册也就是说明一下操作它的接口!然后!然后!然后就没有然后了。

那么我们怎么样使用它呢??有可能我们根本就不了解这个定时器,就算它再简单,没资料,呵呵!玩起来也是很费劲的啊!这个疑问先放起来!看看下一个疑问??

文章的开头不是“做个准确的延时”么??那么它和SysTick有毛关系呢??(可能多远单片机程序员来说,延时就是:delay_ms(x)这种),其实我就想用SysTick来给我做延时,因为MCU的运行时钟在配置好之后,就基本上是稳定的了!稳定的时钟数山羊,那就可以计算出每数一次山羊所用的时间,更可以算出在一定时间内能数多少只山羊了(还记得小时候的数山羊游戏吗?)。所以就是利用这么个思想来干这种事。

当然,问题又来了,STM32有那么多个通用定时器和特殊定时器,干嘛非得用SysTick啊??我个人给的答案就是:(1)只要你开心,想怎么样都好。(2)对于通用定时器和特殊定时器而言,他们除了定时功能之外,还有其他的很多特殊复用功能,比如说PWM的输出等等,非得这么干的话你这是在浪费资源(当然,你若开心,便是晴天),然而,SysTick据我本人所知,它就是ARM核用来数山羊的,就这么个定时计时功能,不用它用谁??

回到最上面的问题,我们怎么使用SysTick定时器呢??

首先,第一件事就是找到它再时钟树的位置(还是时钟树,可以想想它的地位有多重要了)。如下图:

上图还是时钟树(Clock Tree)从上图我们可以得到这么几个信息:

(1)SysTick就是内核系统定时器(不管它,咱还是叫滴答定时器)

(2)SysTick的时钟源来自HCLK

(3)SysTick的时钟为HCLK的8分频,即Fsystick = HCLK/8

(4)蓝色框表示系统时钟咱在前面的帖子已经配置好了!哈哈!

好!第一件事干完了,也得到了相应的信息,那么咱们干第二件事:

还记得在准备资料的时候,特别提示,一点要将MCU的编程手册下载下来吗???在这里就用到它了!

就是上图这个东西,名字叫STM32F0xxx Cortex-M0 programming manual ---->STM32F0xxx 系列Corte-M0编程手册。

打开这个手册,我们可以看到很多的东西,我简单介绍一下吧!

浏览整个目录,分为5章,如下:

第一章从技术角度来说,可能不是那么重要,但是对于不了解ST说明文档的布局的童鞋而言,我个人认为还是必须浏览第一章的,因为他介绍了,本文档的格式和关键词使用还有必要的说明格式等,再就是简单的介绍了文章的布局,和所包含的内容,这对于阅读文档,找到想要的资料是最快速的方法。

第二章基本上就是对Cortex-M0内核的简单介绍了,比如模式,堆栈,内核寄存器,数据类型,内存,低功耗模式等等的介绍了。

第三章看到这些想都不用想,就知道这是Cortex-M0内核的汇编指令,操作指令了。


第四章,哈哈哈哈哈哈!看到标题没??Core peripherals 我想英语水平再差的人都知道这是Cortex-M0的核心外设了,那就是说这是ARM架构Cortex-M0核有的东西,并不只有ST的才有。OK!SysTick就是核心外设之一啦!这就是为毛找它的原因了啊!哈哈!!等等,还有第五章,得装完B再说。

下去!看看!就可以看到!第五章就是记录着修订历史的,如下图:


从这个图我们可以得知,第一次出这个文档的时间,而且从未修改过!哈哈 !不管了!谈谈感受些。

首先,我觉得这个手册是写给程序员看的!它不是真正的Cortex-M0手册,因为从手册的内容来看,它再教我们怎么使用,怎么写程序配置,而不是解释Cortex-M0内核(当然,从名字就知道了!哈哈!)。这一点很重要,所以它是非常重要的手册,比库函数手册重要N倍。

OK!废话了一大堆!先把滴答定时器用起来吧!

第一件事,找到库中相应的操作函数接口,所以我在keil中全工程搜索了一下,结果如下:

从上图可以看出了,只看到了两个与SysTick相关的函数(我用红框标出了),分别是:void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)函数和__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)函数,(在Linux中__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)这种类型的函数叫内联函数,不知道这是不是这样叫),其中,void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)函数的作用,是是选择SysTick的时钟和初始化SysTick(从注释和函数名就可以看出来了)。__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)函数就是“The function initializes the System Timer and its interrupt, and starts the System Tick Timer.

Counter is in free running mode to generate periodic interrupts.”初始化SysTick和中断,开启定时器。

从注释上来分析,要让SysTick跑起来使用这两函数的确足够了,但是想想哪里不对劲啊??咱的目的是做个延时程序,希望能够精确的延时,并且咱随时指定延时多久,这怎么还玩起中断来了,不对,不对,这不靠谱(我说的不靠谱是和我们的目的不靠谱,并非这个库不靠谱,哈哈!),唉!没办法,只能对ST的攻城狮说,你不给咱写好,咋就自己玩了!哈哈!那砸门就自己玩!

那么怎么玩呢???这就是为毛在开篇的时候一大堆废话谈《Cortex-M0编程手册》的原因了,咱自己玩,得靠它啊!OK!继续--0------>

看到上图,我想再不明白的人也要明白了!这就清清楚楚的介绍了SysTick的使用了哈!(翻译就算了,水平太菜了,不恶心人了)。

继续晒图:

哈哈哈!看到了没??SysTick的寄存器被我看到了!既然看到了寄存器,那要搞它就不难了。哈哈!继续再往下!再往下!再往下!

嘎嘎!你看到的没错,你没眼花,这里清清楚楚的说明了SySTick的第一个寄存器STK_CSR的功能和使用了。东西比较少,我就解释一下:

Bit 0 ----- 0位,SysTick的开关,置1使能

Bit 1-----1位,SysTick的异常开关,其实就是中断开关,置1,当SysTick计时到0时,产生中断

注意:SysTick数山羊的方式和咱小时候玩的不太一样,人家要倒着数,到0说明完成一次数山羊

Bit 2-----2位,SysTick的时钟资源选择,置0,使用外部参考时钟;置1,使用处理器的时钟

Bit 16---16位,定时器数山羊数到0的时候,返回1

这个寄存器就这么愉快的搞定了!!!哈哈哈哈!继续装B!

看到这个,就知道了,STK_RVR寄存器就是SysTick的装载寄存器了,用来装山羊的个数的嘛,哈哈!但是注意哦,因为SysTick是24位的定时器(前面文档有介绍),所以别越界了哦!越界就像是用个吃饭的碗来装一桶水,肯定装不完啦!肯定会溢出啦!不懂啥事溢出的话,就想想水从碗里溢出来的现象哈哈!只是在这里是数据溢出而言!

所以这个寄存器没啥好解释的了(没解释也废话了半天。。。汪汪)!

看看下一个:

看标题就知道了,SysTick的当前计数值寄存器,想知道此时计数到哪里了,读它就好了!

下一个!

SysTick的校准定时器!!!!咱不校准,想校准的童鞋自己看看!多么简单的东西!

到这里,我们得到的信息是:

(1)我们需要操作的寄存器:STK_CSR、STK_RVR和STK_CVR

(2)寄存器的地址:如下图

现在要干的第一件事是,我们应该怎样才能操作寄存器:

方法1:直接操作

在头文件里直接定义这三个寄存器的物理地址(特别注意:寄存器是32位的),相应操作寄存器的某一位只需要操作TK_CSR、STK_RVR和STK_CVR的相应的某一位即可。就是这么简单!

方法2:使用库的定义

在core_m0.h文件中,有如下定义:

从注释来看,它说这就是SysTick的寄存器结构体!OK!怎么证明呢??

再往下:

有这么几个信息:

(1)基地址为 SCS_BASE (0xE000E000UL) ,即基地址就是0xE000E000了

(2)SysTick的基地址为:(SCS_BASE + 0x0010UL),即为:0xE000E010 咦是不是和STK_CSR寄存器地址一样了呢??对的,就是一样的,再往下

(3)宏#define SysTick ((SysTick_Type *) SysTick_BASE ),首先SysTick的基地址SysTick_BASE被强制转换为结构体SysTick_Type类型的指针(也就是以这个地址为起点sizeof(SysTick_Type)大小的空间成为这个结构体类型),然后定义成宏SysTick,所以宏SysTick就成为了SysTick_Type的指针。再往下分析:

(4)分析得下图:

SysTick的地址就是0xE000E010了,而根据结构体的贴心,第一个成员的地址和结构体的地址值是相等的,所以就有了上图(要是不懂的话,建议好好的去补补C语言,把基本功打扎实了,没点功力肿么能玩转物理地址呢??),所以,结构体的成员和SysTick的寄存器就对应上了。哈哈!其实ST的库里面的寄存器的结构都是这么干的,定义寄存器的方法都是一样的!

当然,喜欢玩寄存器的童鞋,我建议就应该用以上的方法1的方法,这才是玩寄存器啊,!直接使用ST定义好的结构,多没意思!!哈哈!!

好的!完事具备!只欠程序了!如下:

首先,先定义两个本文件全局变量(记住这两个全局变量只适用在本文件),分别是:fac_ms和fac_us,啥意思呢??它俩就是分别用来记录1ms和1us时间内SysTick能计的数。

变量定义玩了,就是初始化SysTick了!其实初始化SysTick就是一句话SysTick->CTRL = 0xfffffffb;,就是操作TK_CSR寄存器。至于为毛是这个值,那就自己看手册了!

但是,其实适用库函数接口也是可以的:就是这个:

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),这个函数的注释是选择SysTick的时钟,其实就是初始化了,但是必须注意:参数必须是:SysTick_CLKSource_HCLK_Div8即HCLK的8分频,证据就是前面的时钟树。但是将到这里咱不放看看这个函数的原型,

从函数中,也可以看出也是操作TK_CSR寄存器,因为参数必须是SysTick_CLKSource_HCLK_Div8,所以我们可以看看SysTick_CLKSource_HCLK_Div8的定义值如何:

看到没:SysTick_CLKSource_HCLK_Div8的值也是0xFFFFFFFB

OK!初始化解决了!那么,这个初始化函数还有一个参数,干啥的呢??其实就是系统时钟啦!比如,咱的系统时钟已经配置成48MHz,那么调用的时候,直接SysTick_Init(48);即可,其实这个参数就是用来计算fac_ms和fac_us的值的,公式如下:

SysTick的时钟:Fsystick = HCLK/8

SysTick计数一次的时间:Tsystick = 1/Fsystick

有了以上两个公式(对于哪来的公式,别问我,问手册去),那么计算fac_ms和fac_us的值就不难了!哈哈!OK!初始化结束。

咱们来个毫秒延时:

上面函数的意思就是:延时nms,比如需要延时100毫秒,就调用:delay_ms(100);即可。

那么实现是怎么样的呢??

其实在编程手册里面就教了我们怎么使用:

哈哈!人家明明白白的告诉了咱怎么使用,并且列出了1,2,3,那咱就不能客气了!哈哈!

1.将计数值装载到装载寄存器

2.清空计数器

3.计数开始

4.等等计数到达

5.关闭计数器

6.清空计数器

过程就如上6步了。

注意一点啊:SysTick->CTRL = 0x01;开启计时器时是对寄存器直接赋值,而不是操作某一位啊!所以这样的话,是不会产生中断的!因为中断被关了啊!

OK!毫秒延时就这样!!

下面就是微秒延时了!哈哈!

毫秒延时都讲的这么清楚了,微秒延时就不说了,都是一个妈生的!过程没啥说的!

来看看咱怎么调用吧!

调用就如上图了!记住哦,先配置好系统时钟哦!要是顺序搞反了,搞不出来就该打屁屁了哦!哈哈哈!

纵观IT界,一个简单的东西内说个20页可能也就是我这种逗逼了!哈哈!不过呢!我只是想解决一些初学者迷茫或者吐血的问题!高手的问题咱不敢解决!


关键字:STM32F030  延时  SysTick 引用地址:STM32F030 Nucleo-做个准确的延时SysTick

上一篇:STM32F407学习记录2:SysTick嘀嗒定时器学习
下一篇:Cortex-M4 Systick滴答定时器

推荐阅读最新更新时间:2024-03-16 16:09

C51延时函数delay的编写
例如,要写一个延迟10ms的delay函数:(12M晶振) void delay_10ms() { unsigned char i,j,k; for(i=5;i 0;i--) { for(j=4;j 0;j--) { for(k=248;j 0;j--); } } } 原理:3层for循环,循环次数是 NUM = 4X5X248 = 4960次,由每次循环都有条件判断(如 i 0)和自减语句(如 i--),因此每次循环又耗费两个机器周期 所以,总耗费的机器周期为 SUM = NUM x 2 = 9920个 又因为 12M 晶振频率,
[单片机]
浅谈STM32F10X芯片SysTick系统时钟定时器
如题,正文如下: 1、介绍 实现Cortex-M3系统定时器SysTick的配置,需要具备以下知识:Cortex-M3系统定时器默认频率是HCLK的8分频(如下图所示),因此需要会RCC时钟的配置;然后配置SysTick系统定时器;编写SysTick中断处理函数。 系统时钟及系统定时器时钟(详见手册) 2、寄存器描述 l SysTick控制及状态寄存器STK_CTRL l SysTick重装载数值寄存器STK_LOAD l SysTick当前数值寄存器STK_VAL l SysTick校准数值寄存器STK_CALIB 与SysTick相关的固件库函数有以下几个: l
[单片机]
Atmega168 延时函数晶振频率的设置方法
本文介绍,在Atmel Studio环境中,更改延时函数(宏)的晶振频率的方法。 在Atmel Studio中,可以使用_delay_us(x)宏和_delay_ms(x)进行精准延时,但是在使用这2个宏之前必须设置当前的晶振频率,本日志介绍其设置方法。 1、在项目上点击右键,选择属性 2、在属性栏中,选择工具链,然后选择“Symbols”,然后将F_CPU宏,更改为相应的晶振频率即可。
[单片机]
Atmega168 <font color='red'>延时</font>函数晶振频率的设置方法
C语言延时子程序准确设置
在给单片机写程序的时候往往需要一个微秒或者毫秒的延时子程序,但是C语言不同于汇编,很难根据语句确定准确的延时时间,经过各种查资料得到一种简单实用的方法:通过keil下断点调试确定时间。 就是编写一个延时子程序,然后在延时程序处和while(1)设置断点,运行程序,在调试模式下就可以获得该延时子程序的准确延时时间。 1,编写如下源程序: #include void delay_ms(unsigned int ms) { unsigned int i; unsigned char j; for(i=0;i { for(j=0;j 200;j++); for(j=0;j 102
[单片机]
C语言<font color='red'>延时</font>子程序准确设置
MSP430 实现精准延时
对于大多数单片机我们在进行操作时都需要一定的延时 对于51系列常使用_NOP_( );指令进行1us延时或者更简单粗暴一些直接使用for循环for(i=0;i 1000;i++)做一MS的延时 大多数的单片机执行+1运算时间为1US,但是这种延时并不准确 下面实现精准延时 IAR 软件430的编译器里面我们可以利用它内部的延时子程序来实现我们想要的高精度软件延时,方法如下: (1):将以下这段代码复制到你的.C源文件中。 #define CPU_F ((double)8000000) #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #def
[单片机]
单片机精确延时几种方式
目前在单片机中有不少延时的方法: 1、使用循环函数延时: void delay1ms(void) //误差 0us,延时1ms { unsigned char a,b; for(b=199;b 0;b--) for(a=1;a 0;a--); } 可以用单片机精灵来获取更多延时,下载地址https://pan.baidu.com/s/1qYQeoig 这种延时方式虽然说可以比较精确的延时,但是他会一直占用cpu,延时期间cpu只能选择等待,无法执行其他事情,降低了cpu的使用效率。 2、使用定时器中断延时(C语言版) void IinitTimer() { TMOD = 0x01;
[单片机]
STM32F030单片机的翻转引脚介绍
1. 第一个工程 翻转引脚 上一篇文章我们详细介绍了 STM32F030 从复位时取得复位向量,系统初始化,然后跳转到 main( ) 函数的过程。下面我们结合一个最简单的例子,对 Cube 库的使用做一个简单的介绍。我们用 Keil 打开下面这个工程:STM32Cube_FW_F0_V1.11.0ProjectsSTM32F030R8-NucleoExamplesGPIOGPIO_IOToggleMDK-ARMProject.uvprojx 编译下载运行此代码,会看到一个 LED灯(连至MCU的 PA5引脚)不停地闪烁。为了完成这个简单的功能,我们看到这个工程里包含了不少文件: 如果是初次用这种库的方式做开发,乍一看还真
[单片机]
<font color='red'>STM32F030</font>单片机的翻转引脚介绍
可编程宽频带精密延时器设计
1. 系统设计方案 在水下探测时,常常利用激光发生器以一定的频率发出激光探测信号,到达探测目标后反射。反射回的信号中的一部分被反射光采集器采集,将信号转换后传入从 PC机,通过远程传输传入主PC机做数据及图像处理。在基准信号和发射光采集器开始工作之间需要有精确的延时系统,以便用于测量物体距离等重要参数。 精密延时系统由源信号发生器发出毫秒级的脉冲信号,经信号调节电路并经选通后输入粗调延时装置,再由细调延时装置进行微调延时,延时的时间可由单片机通过键盘控制或者通过上位机(PC机)串行通信实现,系统控制可达到精度为1ns。本系统设计框图如图1所示。 图1 系统设计框图 2.系统硬件电路设计 本系统主要电路由单片
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved