打印
[应用相关]

STM32 系统滴答定时器(Systick) 彻底研究解读

[复制链接]
784|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
STM32 系统滴答定时器(Systick)  彻底研究解读
SysTick 起那些 TIM 定时器可以说简单多啦~~~~~哥的心情也好了不少,
嘎嘎!!
ARM  Cortex-M3 内核的处理器内部包含了一个 SysTick 定时器,它是一个
24 位的倒计数定时器,注意,是倒计数!当计到 0 时它就会从 LOAD 寄存器中
自动重装载定时初值。只要不把 CTRL 寄存器中的 ENABLE 为清 0,它就永不
停息!遗憾的是,Sy sTick 定时器在《STM32 参考手册》里一个屁都没放,只有
在《ARM  Cortex-M3 技术参考手册》和《ARM  Cortex-M3 权威指南》才找到相
关寄存器的介绍。

使用特权

评论回复
沙发
实际测量不符|  楼主 | 2021-4-26 21:54 | 只看该作者
一、SysTick 的时钟来源
我先来看看 STM32 的时钟树
The RCC feeds the Cortex Sy stemTimer (SysTick) external clock with  the AHB
clock(HCLK) divided by  8.The SysTick can work either with  this clock or with the
Cortex clock(HCLK),  configurable in the Sy sTick Control and Status Register.
上面这段话的意思是,SysTick的时钟来源可以是HCLK的8分频或就是HCLK,
具体是哪种可通过配置“控制和状态寄存器(CTRL)”来选择。

使用特权

评论回复
板凳
实际测量不符|  楼主 | 2021-4-26 21:56 | 只看该作者
二、SysTick的寄存器简介
SysTick的寄存器一共有4个。
控制和状态寄存器CTRL(复位值0x00000000)
位段  名称  类型  描述
16  COUNTFLAG  只读  计数到0时置1;读取该位将清0
2  CLKSOURCE  可读可写  时钟来源    0=HCLK/8;1=HCLK
1  TICKINT  可读可写  1=计数到0时产生Sy sTick异常请求
0  ENABLE  可读可写  使能位,即定时器的开关,1有效

使用特权

评论回复
地板
实际测量不符|  楼主 | 2021-4-26 21:59 | 只看该作者
重装值寄存器LOAD(复位值不可预测)
位段  名称  类型  描述
23:0   RELOAD  可读可写  当计数到0时将被重装载的值
当前值寄存器VAL(复位值不可预测)
位段  名称  类型  描述
23:0  CURRENT  可读可写
读取时返回当前倒计数的值;向该寄存器
写入任意值都可以将其清除变为0。清0
该寄存器还会导致CTRL寄存器的
COUNTFLAG  位清零。
另外还有一个校准值寄存器CALIB,暂时用不到,先不刁它!

使用特权

评论回复
5
实际测量不符|  楼主 | 2021-4-26 22:00 | 只看该作者
三、SysTick的库函数
1、寄存器定义在哪里?答:在core_cm3.h中!
ty pedef struct
{
__IO uint32_t CTRL;
__IO uint32_t LOAD;
__IO uint32_t V AL;
__I    uint32_t CALIB;
} SysTick_Ty pe;

#define SysTick    ((SysTick_Ty pe *) SysTick_BASE)

使用特权

评论回复
6
实际测量不符|  楼主 | 2021-4-26 22:01 | 只看该作者
2、函数在哪里?
在V3.3的函数库中关于SysTick的函数只有两个。一个是在misc.C文件中的
SysTick_CLKSourceConfig函数,它是一个时钟源配置函数;另一个是在
core_cm3.h文件中的SysTick_Config函数,它的输入参数只有一个,传给了重装
值寄存器LOAD,另外还将VAL寄存器清0了,此外还将CTRL寄存器中的[2:0]
三位都设为了1,分别是使用HCLK时钟,允许异常请求,开启计数器。

使用特权

评论回复
7
实际测量不符|  楼主 | 2021-4-26 22:02 | 只看该作者
在 misc.C 文件最后有下面一个函数
/**
*@功能:  配置 SysTick 时钟源
*@输入参数:  SysTick_CLKSource:  指定 SysTick 时钟源.
*  该参数可以是以下其中一个值:
* @ SysTick_CLKSource_HCLK_Div8:  AHB 时钟 8 分频作为 Sy sTick 时钟源
* @ SysTick_CLKSource_HCLK: AHB 时钟作为 SysTick 时钟源.
*/
void SysTick_CLKSourceConfig(uint32_t Sy sTick_CLKSource)
{
/*  参数检查  */
assert_param(IS_SYSTICK_CLK_SOURCE(Sy sTi ck_CLKSource));
if(SysTick_CLKSource ==  SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTi ck_CLKSource_HCLK;
}

else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
}
}

使用特权

评论回复
8
实际测量不符|  楼主 | 2021-4-26 22:04 | 只看该作者
3、编写一个精确延时函数!
鉴于SysTick的寄存器比较少,库函数也没写出啥玩意。所以完全有信心用寄存
器的方法写出一个SysTick精确延时函数。偷学了网上的一点程序,写出了如下
的函数,比网上的还精简了几行,哈哈!
/*  微秒级精确延时函数  */
void Delay_us(uint32_t n)  ////////延时多少微秒,n 就输入多少!
{
SysTick->LOAD=72*n;          //装载计数值,因为时钟 72M,72 次在 1μs
SysTick->CTRL=0x00000005;//时钟来源设为为 HCLK(72M),打开定时器
while(! (SysTick->CTRL&0x00010000)); //等待计数到 0
SysTick->CTRL=0x00000004;//关闭定时器
}

使用特权

评论回复
9
实际测量不符|  楼主 | 2021-4-26 22:05 | 只看该作者
编写一个点亮LED的函数测试一下。
int main(void)

{
GPIO_Configuration();
while(1)
{
GPIO_SetBits(GPIOD, GPIO_Pin_3);      //输出高电平
Delay_us(10);                                    //精确延时 10μs
GPIO_ResetBits(GPIOD, GPIO_Pin_3);  //输出低电平
Delay_us(10);                                    //精确延时 10μs
}
}
经示波器测试,发现确实很准,嘎嘎~~~△X=10.5μs,那0.5μs的误差来自哪里
呢?因为要调用GPIO和Delay _us函数,包括Dealy _us函数中的几条设置语句, 所
以说还是相当准的!

使用特权

评论回复
10
coshi| | 2021-5-11 20:42 | 只看该作者
这个定时器很关键

使用特权

评论回复
11
zljiu| | 2021-5-11 20:42 | 只看该作者
介绍的非常的全面

使用特权

评论回复
12
wiba| | 2021-5-11 20:43 | 只看该作者
这个定时器都涉及到什么操作呢

使用特权

评论回复
13
tfqi| | 2021-5-11 20:43 | 只看该作者
它只有这一种时钟来源吗

使用特权

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

本版积分规则

43

主题

589

帖子

1

粉丝