打印
[STM32F4]

Nucleo F401再探索Systick 系统定时器

[复制链接]
1097|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
LED 实验我们为了让 LED 间隔闪烁的明显,调用了一个自己编写的延时函数
Delay,本章我们将来学习另一种通过 Systick 系统定时器来实现的延时。这种延
时不像 Delay 函数,让 CPU 不停自加,占用 CPU 的资源,而是通过硬件本身的
定时器来完成,涉及到操作系统相关问题我们在这里先不谈,以后逐步深入。
沙发
aizaixiyuanqian|  楼主 | 2018-5-30 13:18 | 只看该作者
1.什么是 Systick 定时器?
SysTick—系统定时器是属于 CM4 内核中的一个外设,内嵌在 NVIC 中。系
统定时器是一个 24bit 的向下递减的计数器,计数器每计数一次的时间为
1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 180M。当重装载数值寄存器的
值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。因为 SysTick
是属于 CM4 内核的外设,所以所有基于 CM4 内核的单片机都具有这个系统定
时器,使得软件在 CM4 单片机中可以很容易的移植。系统定时器一般用于操作
系统,用于产生时基,维持操作系统的心跳。

使用特权

评论回复
板凳
aizaixiyuanqian|  楼主 | 2018-5-30 13:19 | 只看该作者
2.SysTick 寄存器介绍
SysTick—系统定时器有 4 个寄存器,如下表。使用 SysTick 产生定时的时候,
只需要配置前三个寄存器,最后一个校准寄存器不需要配置。

使用特权

评论回复
地板
aizaixiyuanqian|  楼主 | 2018-5-30 13:20 | 只看该作者
图表为systick寄存器描述:


使用特权

评论回复
5
aizaixiyuanqian|  楼主 | 2018-5-30 13:20 | 只看该作者
关于 Sytick 寄存器的每一位相关描述大家可以参考其他类相关书籍,本教程
以应用型为主,重点在实践上。

使用特权

评论回复
6
aizaixiyuanqian|  楼主 | 2018-5-30 13:38 | 只看该作者
3. Systick 定时器有什么用?
本次实验将利用 Systick 定时器产生 1S 的时基,LD2 以 1S 的频率闪烁。同时编
写毫秒级与微秒级延时函数并将其封装,方便以后编写其他驱动使用。

使用特权

评论回复
7
aizaixiyuanqian|  楼主 | 2018-5-30 14:55 | 只看该作者
4. 如何利用 Systick 来实现毫秒与微妙级的延时?
4.1 与 LED 类似,在 APP 文件夹中新建 Systick 文件夹。并新建 Systick.C 与
Systick.H 文件。

使用特权

评论回复
8
aizaixiyuanqian|  楼主 | 2018-5-30 14:56 | 只看该作者
4.2 在 systick.c 中我们需要编写两个函数,参考原子的《STM32F4 开发指南——
库函数版本》

使用特权

评论回复
9
aizaixiyuanqian|  楼主 | 2018-5-30 14:56 | 只看该作者
void delay_init(u8 SYSCLK)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //8 分频
fac_us=SYSCLK/8;
fac_ms=(u16)fac_us*1000;
}

使用特权

评论回复
10
aizaixiyuanqian|  楼主 | 2018-5-30 14:56 | 只看该作者
void delay_ms(u16 nms) //毫秒级延时函数
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD 为 24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}
while((temp&0x01)&&!(temp&(1<<16)));//等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}

使用特权

评论回复
11
aizaixiyuanqian|  楼主 | 2018-5-30 14:57 | 只看该作者
void delay_us(u32 nus) //微秒级延时函数
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));//等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}

使用特权

评论回复
12
aizaixiyuanqian|  楼主 | 2018-5-30 14:57 | 只看该作者
4.3 在 systick.h 中我们需要声明这个函数,方便其他文件函数调用,这里是为
了方便主函数调用。
void delay_init(u8 SYSCLK);
void delay_us(u32 nus);
void delay_ms(u16 nms);

使用特权

评论回复
13
aizaixiyuanqian|  楼主 | 2018-5-30 14:57 | 只看该作者
简单的完成了毫秒与微妙级的延时后下面我们开始利用 systick 延时来间隔点
亮 LD2,主函数中首先是对 LED 的初始化,然后在主循环中让 LD2 亮灭,中间夹
杂延时。
int main()
{
LED_Init(); //LED 初始化
delay_init(168);
while(1)
{
LD2_ON ;
delay_ms(1000); //延时
LD2_OFF ;
delay_ms(1000); //延时
}
}

使用特权

评论回复
14
aizaixiyuanqian|  楼主 | 2018-5-30 17:27 | 只看该作者
6. 通过 ST-Link 烧录后,发现 LD2 的确在闪烁,但不是以 1S 间隔闪烁,误差很
大,这个问题困扰了我好几天,经过查询资料发现STM32F401最大支持频率84M,
哈哈原来我超频了,这是原封不动移植别人代码的下场的后果。

使用特权

评论回复
15
aizaixiyuanqian|  楼主 | 2018-5-30 17:28 | 只看该作者
7.参考 STM32F40 系列的时钟树,我将 PLL_M、PLL_N 、PLL_P 的值修改。根据
系统时钟的计算公式: SYSCLK=晶振频率(8M)*PLL_N/(PLL_M*PLL_P);

使用特权

评论回复
16
aizaixiyuanqian|  楼主 | 2018-5-30 17:40 | 只看该作者
将 PLL_N、PLL_M、PLL_P 暂时修改为 320 、 8、 4 则系统时钟为 80M(主:
需要在 system_stm32f4xx.c 文件中修改)如下图所示。







使用特权

评论回复
17
aizaixiyuanqian|  楼主 | 2018-5-30 17:46 | 只看该作者
7. 需要将 delay_init(168)改为 delay_init(80) 我们的系统时钟发生改变了,需要
重新计算下延时。主函数如下:
int main()
{
LED_Init(); //LED 初始化
delay_init(80);
while(1)
{
LD2_ON ;
delay_ms(1000); //延时
LD2_OFF ;
delay_ms(1000); //延时
}
}

使用特权

评论回复
18
aizaixiyuanqian|  楼主 | 2018-5-30 17:46 | 只看该作者
8. 本次关于时钟的配置和利用 systick 系统定时器编写的毫秒与微妙级延时函数
就先到这里,我们现在也不敢保证毫秒与微秒的正确性,在后面的外设中我们再
一步步验证。

使用特权

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

本版积分规则

62

主题

1353

帖子

6

粉丝