STM32基础定时器详解
目录
01、定时器介绍
02、时钟源
03、时基单元
04、计数模式
4.1、向上计数模式
4.2、向下计数模式
4.3、中央对齐(向上/向下计数模式)
05、基础定时代码
定时器最基本的功能就是定时处理事情。比如定时发送USART数据、定时采集AD数据、定时检测IO口电位、还可以通过IO口输出波形等。可以实现非常丰富的功能。定时器是一个很强大的外设,不同行业使用的方式不同,知识面很广。
01、定时器介绍
首先我们可以在STM32F207数据手册找到定制器的资源,从下图可以看到STM32F207一共10个通用定时器,2个高级定时器,2个基本定时器。
不同定时器的区别
在STM32F207的用户参考手册中可以看到定时器的基本框图,下图是定时器1&8的看图。
由上图看出,不同寄存器具有不同的参数,位数的区别,计数模式的区别,DMA请求的区别,通道得的区别,互补输出的区别和其他。在具体项目中选择哪个定时器,需要看具体的应用场景。下文主要讲解定时器的基础定时功能,选择定时器3。其他定时器原理是相同的,理解定时器3的定时功能,其他定时器也就能理解了。对于STM32系列的单片机,外设基本都是一致的,并且其他家的MCU也是类似的,国内的有兆易创新、新唐科技、上海灵动微电子等等。
02、时钟源
定时器基本定时功能框图。
①CK_PSC是定时器时钟TIMxCLK,经APB1预分频器后分频提供。
②定时器时钟经过PSC 预分频器之后,即CK_CNT,用来驱动计数器计数。
③计数器CNT 是一个16 位的计数器,向上,向下,向上/下计数模式,最大计数值为65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
④自动重装载寄存器ARR 是一个16位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
定时器说白了就是个计数器,就像我们用心跳粗略估算时间一样,心脏跳动粗略可以认为是1s,那么我们计时60次心跳就过了60秒。其中CK_CNT时钟就类似心跳,CNT计数器就类似心跳次数。举一个极端简单的例子,我们要实现60秒定时,CK_CNT是1s,我们设置CNT计数器向上计数开启中断,因为只有溢出时,也就是计数到65535时才会有中断,那么我们设置CNT计数器为65535-60=65475,开始及时,那么60秒后就会产生中断。我们设置自动重装载寄存器ARR也为65475,当CNT计数器溢出时,自动重装载寄存器ARR就会自动装载到CNT计数器中,就能实现自动循环定时60秒。
经过上面分析,精确定时的关键在于CK_CNT的频率,而CK_CNT是由定时器时钟分频而来的。那么我们就要知道timer3的定时器时钟。我们就要看时钟系统部分,具体看文章《STM32F207时钟系统解析》,这篇文章主要讲解了系统的120M时钟如何从外部的25M的晶振得到的。其中说到APB外设时钟的问题。
定时器在APB定时器时钟下,具体在APB1还是在APB2时钟下我们可以从STM32F207数据手册上看到,图片名字STM32F20xblock diagram。
从上文我们看timer3是在APB1下的。
那么我们来分析APB1的频率
从上图看出,APB1定时器的从系统120M时钟(系统时钟可配置的,我们使用默认的120M时钟)经过AHB分频,APB分频得到的。
在这里说上图红框中的“错误”,萌新可能不太理解。首先手册中少了个右括号。修改后应该为:
if(APBx presc == 1)X1
elseX2
也就是说
APB分频系数如果是1,频率不变,APB输出的频率就是APB下面时钟的频率。
APB分频系数不是1,频率X2,APB输出的频率乘以2是APB下面时钟的频率。
下面我们分析APB1时钟,从system_stm32f2xx.c中的SetSysClock函数中如下
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK / 2*/
RCC->CFGR |=RCC_CFGR_PPRE2_DIV2;/* PCLK1 = HCLK / 4*/
RCC->CFGR|= RCC_CFGR_PPRE1_DIV4;
可以看到AHB分频系数是1,APB1分频系数是4。
timer3的时钟为120M/1/4*2= 60MHZ。
这里有个疑问,ST提供的system_stm32f2xx.c注释为什么是HCLK,PCLK2,PCLK1,却没有上文提到的APB,AHB字眼,具体看下我之前写过的文章《STM32F207时钟系统解析》。
其实我们出了分析代码,system_stm32f2xx.c文件头也是有注释的,方便查看。
当然,这要求我们的外部晶振是25M的,且system_stm32f2xx.c是没有被修改过的,如果大家需要修改这个文件单片机超频运行,建议把文件头的注释修改,养成一个良好的习惯。
03、时基单元
可编程高级定时器控制模块主要是一个带有相关自动重载16位计数器。这个计数器可以向上计数,向下计数或者交替递增和递减计数。计数器时钟可以通过一个分频器分频。
计数器的自动重载寄存器和预分频寄存器可以通过软件读写。即使当计数器正在运行也可以读写。
时基单元包括
计数器寄存器 (TIMx_CNT)
预分频器寄存器 (TIMx_PSC)
自动重载寄存器 (TIMx_ARR)
重复计数器寄存器 (TIMx_RCR)
自动重载寄存器是预装载的。从自动重载寄存器写入或读取会访问预装载寄存器。预装载寄存器的内容既可以直接传送到影子寄存器,也可以在每次发生更新事件(UEV)时传送到影子寄存器,这取决于TIMx_CR1 寄存器中的自动重载预装载使能位(ARPE)。当计数器达到上溢值(或者在递减计数时达到下溢值)并且TIMx_CR1 寄存器中的UDIS 位为0时,将发送更新事件。该更新事件也可由软件产生。
计数器由预分频器输出CK_CNT 提供时钟,仅当TIMx_CR1 寄存器中的计数器启动位(CEN)置1 时,才会启动计数器。
预分频器说明
预分频器可对计数器时钟频率进行分频,分频系数介于1 和65536 之间。该预分频器基于TIMx_PSC寄存器中的16 位寄存器所控制的16位计数器。由于该控制寄存器具有缓冲功能,因此可对预分频器进行实时更改。而新的预分频比将在下一更新事件发生时被采用。
下图以一些示例说明在预分频比实时变化时计数器的行为。
预分频器分频由1 变为2 时的计数器时序图
预分频器分频由1 变为4 时的计数器时序图
04、计数模式
4.1、向上计数模式
在向上计数模式中,计数器从0增加到自动重载值(TIMx_ARR寄存器的值),然后从0重新开始并产生一个计数器溢出事件。
如果使用重复计数器,则当递增计数的重复次数达到重复计数器寄存器中编程的次数加一次(TIMx_RCR+1)后,将生成更新事件(UEV)。否则,将在每次计数器上溢时产生更新事件。
将TIMx_EGR寄存器的UG位置1通过软件或使用从模式控制器时,也将产生更新事件。
通过软件将TIMx_CR1寄存器中的UDIS位置1可禁止UEV事件。这可避免向预装载寄存器写入新值时更新影子寄存器。在UDIS位写入0之前不会产生任何更新事件。不过,计数器和预分频器计数器都会重新从0开始计数(而预分频比保持不变)。此外,如果TIMx_CR1寄存器中的URS位(更新请求选择)已置1,则将UG位置1会生成更新事件UEV,但不会将UIF标志置1(因此,不会发送任何中断或DMA请求)。这样一来,如果在发生捕获事件时将计数器清零,将不会同时产生更新中断和捕获中断。
发生更新事件时,将更新所有寄存器且将更新标志(TIMx_SR寄存器中的UIF位)置1取决于URS位)
重复计数器中将重新装载TIMx_RCR寄存器的内容
自动重载影子寄存器将以预装载值 (TIMx_ARR) 进行更新
预分频器的缓冲区中将重新装载预装载值(TIMx_PSC寄存器的内容)
计数器时序图,1 分频内部时钟
计数器时序图,2 分频内部时钟
从上面两图看出,中断标志是需要软件清除的
计数器时序图,ARPE=0 时更新事件(TIMx_ARR 未预装载)
从上面两图看出,向上计数,还没有到达0x36,就把自动重载寄存器修改为0x36,就会在计数到0x36时产生动作。
计数器时序图,ARPE=1 时更新事件(TIMx_ARR 预装载)
从上面两图看出,向上计数,还没有到达0x36,就把自动重载预装载寄存器修改为0x36,就不会在计数到0x36时产生动作,会在这个时将自动重载预装载寄存器值赋给自动重载影子寄存器。
4.2、向下计数模式
在向下计数模式中,计数器从自动重载值(TIMx_ARR寄存器的值)向下计数到0,然后从自动重载值(重新开始并产生一个计数器溢出事件。
如果使用重复计数器,则当递减计数的重复次数达到重复计数器寄存器中编程的次数加一次(TIMx_RCR+1)后,将生成更新事件(UEV)。否则,将在每次计数器下溢时产生更新事件。
将TIMx_EGR 寄存器的UG 位置1(通过软件或使用从模式控制器)时,也将产生更新事件。
通过软件将TIMx_CR1 寄存器中的UDIS 位置1 可禁止UEV 更新事件。这可避免向预装载寄存器写入新值时更新影子寄存器。在UDIS 位写入0之前不会产生任何更新事件。不过,计数器会重新从当前自动重载值开始计数,而预分频器计数器则重新从0 开始计数(但预分频比保持不变)。
此外,如果TIMx_CR1 寄存器中的URS 位(更新请求选择)已置1,则将UG 位置1 会生成更新事件UEV,但不会将UIF 标志置1(因此,不会发送任何中断或DMA 请求)。这样一来,如果在发生捕获事件时将计数器清零,将不会同时产生更新中断和捕获中断。
发生更新事件时,将更新所有寄存器且将更新标志(TIMx_SR 寄存器中的UIF 位)置1(取决于 URS 位):
重复计数器中将重新装载 TIMx_RCR 寄存器的内容
预分频器的缓冲区中将重新装载预装载值( TIMx_PSC 寄存器的内容)
自动重载活动寄存器将以预装载值( TIMx_ARR 寄存器的内容)进行更新。注意,自动重载寄存器会在计数器重载之前得到更新,因此,下一个计数周期就是我们所希望的新的周期长度
以下各图以一些示例说明当TIMx_ARR=0x36 时不同时钟频率下计数器的行为
计数器时序图,1 分频内部时钟
计数器时序图,2 分频内部时钟
计数器时序图,未使用重复计数器时更新事件
4.3、中央对齐(向上/向下计数模式)
在中心对齐模式下,计数器从0 开始计数到自动重载值(TIMx_ARR 寄存器的内容)-1,生成计数器上溢事件;然后从自动重载值开始向下计数到1 并生成计数器下溢事件。之后从0开始重新计数。
当TIMx_CR1 寄存器中的CMS位不为“00”时,中心对齐模式有效。将通道配置为输出模式时,其输出比较中断标志将在以下模式下置1,即:计数器递减计数(中心对齐模式1,CMS=“01”)、计数器递增计数(中心对齐模式2,CMS =“10”)以及计数器递增/递减计数(中心对齐模式3,CMS =“11”)。
在此模式下,TIMx_CR1 寄存器的DIR 方向位不可写入值,而是由硬件更新并指示当前计数器方向。
每次发生计数器上溢和下溢时都会生成更新事件,或将TIMx_EGR 寄存器中的UG 位置1(通过软件或使用从模式控制器)也可以生成更新事件。这种情况下,计数器以及预分频器计数器将重新从0 开始计数。
通过软件将TIMx_CR1 寄存器中的UDIS 位置1 可禁止UEV 更新事件。这可避免向预装载寄存器写入新值时更新影子寄存器。在UDIS 位写入0 之前不会产生任何更新事件。不过,计数器仍会根据当前自动重载值进行递增和递减计数。
此外,如果TIMx_CR1 寄存器中的URS 位(更新请求选择)已置1,则将UG 位置1 会生成UEV 更新事件,但不会将UIF 标志置1(因此,不会发送任何中断或DMA 请求)。这样一来,如果在发生捕获事件时将计数器清零,将不会同时产生更新中断和捕获中断。
发生更新事件时,将更新所有寄存器且将更新标志(TIMx_SR 寄存器中的UIF 位)置1(取决于URS 位):
重复计数器中将重新装载 TIMx_RCR 寄存器的内容
预分频器的缓冲区中将重新装载预装载值( TIMx_PSC 寄存器的内容)
自动重载活动寄存器将以预装载值( TIMx_ARR 寄存器的内容)进行更新。注意,如果更新操作是由计数器上溢触发的,则自动重载寄存器在重载计数器之前更新,因此,下一个计数周期就是我们所希望的新的周期长度(计数器被重载新的值)。
以下各图以一些示例说明不同时钟频率下计数器的行为
计数器时序图,1 分频内部时钟,TIMx_ARR = 0x6
计数器时序图,2 分频内部时钟
计数器时序图,ARPE=1 时的更新事件(计数器下溢)
计数器时序图,ARPE=1 时的更新事件(计数器上溢)
05、基础定时代码
10ms中断配置代码
关于设置分频值
TIM3CLK = 2 * PCLK1=2*HCLK / 4= HCLK / 2 = SystemCoreClock /2=60MHZ
所以下图红框内就是TIM3CLK
这里的值是分频系数=TIM3CLK/定时器实际频率,所以定时器频率是10000,也就是说除数就是定时器频率。一个clk是1/10000s。定时时间=1/10000*定时器重载值。根据上面的配置,定时器重载值是100,也就是定时器中断周期是=1/10000*100=0.01s=10ms,也就是100HZ。
如果在定时器翻转LED灯,那么LED灯闪烁频率是50Hz。
上面的的分频值当然可以直接赋值5999,如果想修改为定时器频率为1000,那么还要重新计算。如果按照上面的写法,直接将除数修改为1000即可。
看到这里大家会有疑问,给的重载值明明是99,分频率值也减去1。下面将说明分频值和自动重载周期值都需要减去1的原因。
自动重载值:因为从0开始计算,赋值10,从0开始计数到10是11次。
分频值:在TIMx_PSC寄存器有以下描述。
特别说明
时钟分频因子
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2;
其实仔细看过技术手册后发现这句话与PWM输出实验其实是没关系的,这句话是设置定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分频比例的(与输入捕获相关),0表示滤波器的频率和定时器的频率是一样的。
首先这个colck_division时钟分割系数并不是对定时器的时钟频率进行分割。我们都知道输入捕获模式下有一个数字滤波器,这个数字滤波器可以通过配置寄存器改变他的采样频率,从而将一些频率滤除。
具体细节在输入捕获中详解。
我们也可以根据定时器的计数器的特性,使用查询计数器的方法实现精确延时,具体请看《STM32延时函数的四种方法》。
定时器代码开源地址:
https://github.com/strongercjd/STM32F207VCT6
点击查看本文所在的专辑,STM32F207教程
关注公众号,第一时间收到文章更新。评论区不能及时看到,需要交流可以到公众号沟通
STM32基础定时器详解相关推荐
- STM32的定时器详解(嵌入式学习)
STM32的定时器详解 0. 前言 1. Systick定时器 概念 工作原理 时钟基准 Systick练习 2. HAL_Delay函数分析 3. 定时器 基本概念 定时器分类 定时器组成 计数器 ...
- STM32之定时器详解
STM32F103系列的单片机一共有11个定时器,其中: 2个高级定时器 4个普通定时器 2个基本定时器 2个看门狗定时器 1个系统嘀嗒定时器 出去看门狗定时器和系统滴答定时器的八个定时器列表; 8个 ...
- STM32 定时器详解
STM32 定时器详解 吃了一个猛亏,自己理解花了大半天时间,结果一看代码发现巨简单 算了,把自己理解的放上来吧 目录 STM32 定时器详解 前言 一.定时器种类和区分 二.时钟源 三.计数过程 3 ...
- STM32 CAN通信协议详解—小白入门(二)
文章目录 (一)CAN通信协议简介 (二)CAN物理层 2.1.闭环总线网络2.2.开环总线网络2.3.通信节点2.4.差分信号2.5.CAN协议的差分信号 (三)协议层 3.1.CAN的波特率及位同 ...
- STM32串口通信详解以及通信异常或者卡死常见问题分析
STM32串口通信详解以及通信异常或者卡死常见问题分析 目录 STM32串口通信详解以及通信异常或者卡死常见问题分析 一.常见的异常问题 二.STM32的串口简介 1.串口的通讯方式 ①按数据传输方向 ...
- STM32最小系统详解
STM32最小系统详解 1. 电源电路 2. 晶振电路 3. 复位电路 4. 下载电路(串口下载) 本文章将以普中的STM32F103系列的开发板为载体,任何一款STM32开发板都是在其最小系统基础上 ...
- java基础(十三)-----详解内部类——Java高级开发必须懂的
java基础(十三)-----详解内部类--Java高级开发必须懂的 目录 为什么要使用内部类 内部类基础 静态内部类 成员内部类 成员内部类的对象创建 继承成员内部类 局部内部类 推荐博客 匿名内部 ...
- Nmap扫描教程之基础扫描详解
Nmap扫描教程之基础扫描详解 Nmap扫描基础扫描 当用户对Nmap工具了解后,即可使用该工具实施扫描.通过上一章的介绍,用户可知Nmap工具可以分别对主机.端口.版本.操作系统等实施扫描.但是,在 ...
- R语言基础知识详解及概括
R语言基础知识详解及概括 目录 R语言基础知识详解及概括 R数据可视化示例 R语言进行数据创建
最新文章
- mysql复杂连接查询语句_MySQL查询语句之复杂查询
- 事件驱动模式--Reactor
- 浅析为何使用融合CDN是大趋势?
- 【linux杂谈】查看centOS系统的版本号和内核号
- node-red教程 7dashboard简介与输入型仪表板控件的使用
- Telnet远程访问思科交换机、路由器
- python 使用整数编码字符串的值
- 跳出公式,看清全局,图神经网络(GCN)原理详解
- ad系统安装配置指南(java-jndi-ldap),AD系统安装配置指南(JAVA-JNDI-LDAP-Exchange)
- 用枚举法实现单例设计模型
- idea导出配置和导入配置
- 持久层框架有哪些?区别是什么?Mybatis框架的优点和缺点
- FDS学习笔记(一)FDS中的基本概念
- 平时杂技,串口摄像头+portmon.exe
- NepCTF2021 梦里花开牡丹亭
- mysql中selec sum返回null的解决方法
- Flash Socket 的基本通讯协议流程例子
- S5PV210启动过程分析
- 刘未鹏博客精华整理55条
- 热血航线服务器维护,《航海王热血航线》修复优化了什么 修复优化一览
热门文章
- 东华大学计算机科学与技术考研方向,2017考研:计算机科学与技术专业考研院校推荐之东华大学...
- matlab ascii 异或,GPS数据包的ASCII异或校验和计算方法(VC++)
- webwork在freemarker中使用iterator
- 中移4G模块-ML302-OpenCpu开发-服务器搭建
- python列表注解
- abaqus实例手册_ABAQUS_6.10例子问题手册(目录)
- react 16 对外暴露function_【第 25 期】React 架构的演变 从同步到异步(一)
- java .equal_Java中的equals()
- c语言输入日期返回星期几,C语言程序设计: 输入年月日 然后输出是星期几
- char*,wchar_t*,CString和BSTR之间的转换