【stm32_5】Systick嘀嗒定时器、解析时钟源、分析时钟树、应用Systick设计延时

目录

[1. 系统嘀嗒定时器的基本概念](#1. 系统嘀嗒定时器的基本概念)

[2. Systick基本应用](#2. Systick基本应用)

[3. Systick定时器的时钟频率分析](#3. Systick定时器的时钟频率分析)

4.时钟源的概述

[5. 时钟源详解](#5. 时钟源详解)

(1)HSE高速外部时钟

晶振

(2)HSI高速内部时钟

(3)LSE低速外部时钟

(4)LSI低速内部时钟

(5)PLL倍频锁相环

[6.从时钟树框图分析Sys tick](#6.从时钟树框图分析Sys tick)

7.控制方式

程序设计


继上文文末提及到的"延时消抖",本章节就来解析"延时"和"计算时间"。

1. 系统嘀嗒定时器的基本概念

定时器是STM32中常用的外设,一般定时器的基本功能就是定时

在Cortex M3/M4内核中包含一个简单的系统嘀嗒定时器(Systick)它属于CM4内核的一个外设 ,++++内嵌在NVIC中++++,所有基于Cortex-M3/M4内核的MCU中都包含这个Systick定时器,所以在不同的硬件中移植起来非常方便。

2. Systick基本应用

  1. 裸机开发 :编写专门的延时函数,实现微秒、毫秒级别的延时,如作为闹钟或者**++++延时++++**。
  2. 操作系统 :可以为RTOS实时操作系统的任务调度提供时钟节拍,RTOS的架构是并行的。

3. Systick定时器的时钟频率分析

利用Systick定时器进行定时,则必须清楚Systick定时器时钟频率

++++定时器是挂载在总线下,而不同的总线的频率是不同的,而总线的频率是由时钟源提供,而时钟源的提供者又各不相同,所以必须要提前了解时钟源的区别++++。

4.时钟源的概述

一般情况下一款MCU有多种时钟源时钟源用于提供时钟信号****)

|---------------------------------------|---------------|
| 时钟源分为两类 每种时钟源的频率各不相同。 | 内部时钟源 |
| 时钟源分为两类 每种时钟源的频率各不相同。 | 外部时钟源 |

结论: 不清楚时钟源的频率,就无法计算总线的频率(因为总线的频率也是靠时钟源提供),从而无法计算挂载在总线下外设的频率。

++++定时器属于外设,外设在总线身上, 总线的频率由时钟源提供。++++

5. 时钟源详解

|-----|--------|-----------|
| HSE | 高速外部时钟 | 8MHz |
| HSI | 高速内部时钟 | 16MHz |
| LSE | 低速外部时钟 | 32.768KHz |
| LSI | 低速内部时钟 | 32KHz |
| PPL | 倍频锁相环 ||

MCU提供5种时钟源,分别是HSI、HSE、LSI、LSE、PLL,每种时钟源的频率都是不同的。

(1)HSE高速外部时钟

设计晶振电路的注意事项:晶振电路要尽可能靠近芯片。

|-------------------------------------------------------------------------------------------------------------------------|
| Q:为什么晶振电路要尽可能靠近芯片? A :让它容易振荡,容易起振。(振得快) 减小误差。(振得准) 因为石英有压电效应,把电能转换为机械能。机械能开始振荡。如果振得不稳,就有问题。 |

晶振

晶振全称叫做晶体振荡器,一般是++采用石英晶体进行制作++ ,石英品体必须经过高精度的角度切割,才可以用于制作晶振,++采用石英晶体是因为石英具体机电效应++ ,可以把机械能和电能进行转换 ,石英晶体通电之后会开始振荡,并且单位时间内振荡的频率是固定的,比如有8MHZ、12MHZ、25MHZ....并且石英晶休的损耗很小,是高度稳定的。

(2)HSI高速内部时钟

(3)LSE低速外部时钟

(4)LSI低速内部时钟

(5)PLL倍频锁相环

作用:频率放大器,可以通过锁相环回路把一个较低的频率进行倍频,可以放大。

PLL由 HSE 或 HSI 振荡器提供时钟信号。

PLL 使能后配置参数不可更改,所以对 PLL进行配置,然后再使能(选择 HSI 或 HSE 振荡器作为 PLL 时钟源,并配置分频系数 M、N、P 和 Q)。

由于当前STM32F407芯片的PLL是HSE(8MHz)提供时钟信号(用于PLL可以把较低的HSE时钟频率进行放大),则需要用户修改工程中的PLL参数 以及修改工程中的HSE_VALUE和PLL_M。

|------------------------------------|
| 修改system_stm32f4xx.c的PLL_M,从25修改为8 |
| 修改stm32f4xx.h的HSE_VALUE,从25修改为8 |

MCU主频的计算 = ( HSE_VALUE / PLL_M * PLL_N ) / PLL_P

= (8MHz / 8 * 336) / 2

= 168MHz !!!!

6.从时钟树框图分析Systick

当前STM32F407时钟树框图中生成Systick的时钟源是HSE,STM32F407的HSE是8MHz。8MHz的HSE通过PPL倍频到168MHz,并且给到AHB总线,所以AHB总线的频率是168MHz。Systick定时器的++内部时钟(FCLK)的频率是168MHZ++ ,外部时钟++(STCLK)的频率经过8分频是168MHZ/8 = 21MHZ 。++

(1)内部时钟

如果选择使用内部时钟(168MHZ)作为系统嘀嗒定时器的时钟源,则嘀嗒定时器的计数周期:1000000us生成168000000个脉冲,意味着 ++++1us可以生成168个脉冲++++ ,所以++++计数周期等于1/168us。++++

(2)外部时钟

如果选择使用外部时钟(21MHZ)作为系统嘀嗒定时器的时钟源,则嘀嗒定时器的计数周期:1000000us生成21000000个脉冲,意味着 ++++1us可以生成21个脉冲++++ ,所以++++计数周期等于1/21us++++。

内部时钟计数周期等于1/168us,外部时钟计数周期等于1/21us,相较而言,计数一样多的次数,外部时钟可以获得更大的时间。

7.控制方式

#define SysTick ((SysTick_Type *) SysTick_BASE )
typedef struct

{

__IO uint32_t CTRL; /*!<SysTick Control and Status Register */

__IO uint32_t LOAD; /*!<SysTick Reload Value Register */

__IO uint32_t VAL; /*!<SysTick Current Value Register */

__I uint32_t CALIB; /*!<SysTick Calibration Register */

} SysTick_Type;

注意:尽管使用21MHz的外部时钟,最多也只能延时798ms。因为Systick是个24bit的递减计时器,计数 "2的24次方" 下,最多可以延时798ms。

程序设计

需求:使用外部时钟(21MHz)生成 "延时毫秒ms"、"延时微妙"、"延时秒"

cpp 复制代码
void delay_us(uint32_t nus)
{
	SysTick->CTRL = 0; 									// 关闭systick的控制状态寄存器------该寄存器的bit0置0
	SysTick->LOAD = ( 21 * nus - 1); 		// systick的重载寄存器------计数时长 = 计数周期 * 计数次数
	SysTick->VAL = 0; 									// 清空systick的当前数值寄存器
	SysTick->CTRL = 1; 									// 使能systick的控制状态寄存器------该寄存器的bit0置1
	while ((SysTick->CTRL & 0x00010000)==0);// 递减计数到了则控制状态寄存器的bit16为1,计数次数没到则bit16为0.
	SysTick->CTRL = 0; 									//关闭systick的控制状态寄存器
}

void delay_ms(uint32_t nms)
{
	SysTick->CTRL = 0; 									// 关闭systick的控制状态寄存器------该寄存器的bit0置0
	SysTick->LOAD = ( 21*1000*nms - 1); // systick的重载寄存器------计数时长 = 计数周期 * 计数次数
	SysTick->VAL = 0; 									// 清空systick的当前数值寄存器
	SysTick->CTRL = 1; 									// 使能systick的控制状态寄存器------该寄存器的bit0置1
	while ((SysTick->CTRL & 0x00010000)==0);// 递减计数到了则控制状态寄存器的bit16为1,计数次数没到则bit16为0.
	SysTick->CTRL = 0; 									//关闭systick的控制状态寄存器
}

void delay_s(uint32_t ns)
{
	while(ns--)
	{
		delay_ms(500);
		delay_ms(500);
	}
}
相关推荐
iCxhust4 分钟前
一块电路板的自觉
单片机·嵌入式硬件·嵌入式·微机原理
学习者12345678921 分钟前
Bootloader跳转APP代码流程
单片机·嵌入式硬件
努力努力再努力wz31 分钟前
【MySQL进阶系列】拒绝冗余SQL:带你透彻理解视图的底层逻辑
android·c语言·数据结构·数据库·c++·sql·mysql
ACP广源盛1392462567333 分钟前
一芯搞定多屏高清@ACP#GSV1221 DP 1.4 MST 转 HDMI 1.4 高集成转换芯片
网络·人工智能·嵌入式硬件·计算机外设·电脑
iCxhust44 分钟前
在 emu8086 中可以直接编译运行的完整汇编程序,演示数组的定义、遍历、求和、求最大值。
开发语言·前端·javascript·汇编·单片机·嵌入式硬件·算法
Yupureki1 小时前
《Linux网络编程》4.应用层HTTP协议
linux·服务器·c语言·网络·c++·http
LCG元1 小时前
STM32实战:基于STM32F103的SG90舵机控制(PWM精准控制)
stm32·单片机·嵌入式硬件
上弦月-编程1 小时前
C语言链表详解,新手也能看懂! ——从入门到精通的完整教程
java·c语言·c++
孬甭_1 小时前
文件操作详解
c语言
wuminyu11 小时前
专家视角看Java字节码加载与存储指令机制
java·linux·c语言·jvm·c++