【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);
	}
}
相关推荐
达不溜的日记5 小时前
CAN总线网络传输层CanTp详解
网络·stm32·嵌入式硬件·网络协议·网络安全·信息与通信·信号处理
计算机安禾6 小时前
【数据结构与算法】第44篇:堆(Heap)的实现
c语言·开发语言·数据结构·c++·算法·排序算法·图论
森利威尔电子-6 小时前
森利威尔SL6129兼容 AL8805 / AL8806,输入电压 5.5V - 30V,最大输出电流 1.2A
单片机·嵌入式硬件·集成电路·芯片·电源芯片
FreakStudio6 小时前
嘉立创开源:应该是全网MicroPython教程最多的开发板
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy
qq_441685756 小时前
CC26xx开发 第一节 前期准备
嵌入式硬件
史蒂芬_丁6 小时前
TI F28P65 使用 ePWM 模块模拟 SPI 时钟的详细方法
单片机·嵌入式硬件·fpga开发
LinuxRos7 小时前
I2C子系统与驱动开发:从协议到实战
linux·人工智能·驱动开发·嵌入式硬件·物联网
jolimark7 小时前
C语言标准与编译器,新手该看哪些?
c语言·开发工具·环境搭建·编译器·新手指南
冷凝雨8 小时前
复旦微FM33 MCU 底层开发指南——UART
stm32·单片机·串口·uart·fm33lc0·复旦微电子