13. Advanced-control timers (TIM1 and TIM8)
1. 基本介绍
有三个基础的寄存器:
- 计数寄存器(TIMx_CNT,Counter register)
- 预分频寄存器(TIMx_PSC,Prescaler register)
- 自动重载寄存器(TIMx_ARR,Auto-reload register)
- 重复计数寄存器(TIMx_RCR,Repetition counter register),当前频率下你需要比CNT更大的计数值时,可以使用。
计数器运行在TIMx_PSC预分频后的CK_CNT,前提是TIMx_CR1 寄存器里的CEN(Counter enable)位是1。只要CEN是1,计数器就开始计数。
如果TIMx_CR1 寄存器里的ARPE(Auto-reload Enable)位是1的话,在每次更新事件(UEV,update event)发生的时候TIMx_ARR寄存器的数值就会装载到计数器内;否则的话,只装载1次。
1.1 TIMx_PSC,Prescaler register
预分频,即预分频的比率:就是将原来的(n+1)个CK_PSC信号视为1个时钟信号。所以实际上,计数器的时钟信号频率CK_CNT = fCK_PSC / (PSC[15:0] + 1)。
你可以在任意时刻修改TIMx_PSC,但是只有在UEV事件发生时,新的预分频比率才会被使用:
这里可以看出与预分频相关的有3个寄存器:
- PSC,用于写入新的分频比率
- buffer,当前预分频计数器的上限,一般来自PSC,主要看什么时刻更新。
- counter,当前预分频计数器的值
1.2 TIMx_ARR,Auto-reload register
自动重载寄存器,和它相关的主要是要不要缓存TIMx_ARR。
当TIM1_CR1寄存器里的ARPE(Auto-reload preload enable)位是0时, TIMx_ARR不会被缓冲,所以会被立即更新:
修改TIMx_ARR <=> 立即修改自动重载的预加载寄存器 -> 立即更新自动重载的影子寄存器
当TIM1_CR1寄存器里的ARPE(Auto-reload preload enable)位是1时, TIMx_ARR会被缓冲,所以不会被立即更新:
修改TIMx_ARR <=> 立即修改自动重载的预加载寄存器 -> 在UEV事件时更新自动重载的影子寄存器
1.3 TIMx_RCR,Repetition counter register
重复计数寄存器,这里会影响UEV的触发条件:通常情况下在计数器overflow或者underflow时就会触发UEV;但是如果使用了TIMx_RCR那么需要当计数重载的次数达到(1+TIMx_RCR)后才会触发UEV。
事实上当计数重复计数器的值为0时就会触发UEV,当UEV触发后,重复计数器就会重新加载TIMx_RCR的值。
在上下计数的模式下,当TIMx_RCR的值是奇数时,UEV是在overflow还是underflow产生不仅取决于TIMx_RCR的值,还取决于计数器是从什么时间开始。比如,当TIMx_RCR=3时,UEV就会在每第4个overflow或underflow时触发。
1.4 计数模式
1.4.1 向上计数,Upcounting mode
此模式下,计数器从0加到TIMx_ARR,然后触发一个overflow事件并从0开始重新计数。
UEV事件的触发与否:
- 如果使用了TIMx_RCR,当计数器重复了(TIMx_RCR+1)遍时会触发UEV事件,否则在每次的overflow会触发UEV事件。
- 设置TIM1_EGR寄存器里的UG(Update generation)位会触发UEV事件
- 如果TIMx_CR1 寄存器里的UDIS( Update disable)位是1时,不会触发UEV事件。
- 如果TIMx_CR1 寄存器里的URS(Update request source)位是1时,虽然UEV事件会发生,但是不会触发中断:不会置位对应的UIF标志位
当UEV事件发生时,会造成:
- 更新TIMx_SR寄存器的状态标志位UIF(Update interrupt flag),前提是TIMx_CR1 寄存器里的URS(Update request source)位是0
- 重新初始化TIMx_CNT:如果DIR=1(向下计数)就从TIMx_ARR寄存器重载;否则(DIR= 0,即向上计数;或者中心对齐模式)计数器清零。
- 更新预分频buffer为TIMx_PSC,预分频计数器清零。
- 更新自动重载计数器的shadow为TIMx_ARR
- 更新重复计数器的值为TIMx_RCR
1.4.2 向下计数,Downcounting mode
此模式下,计数器从TIMx_ARR减到0,然后触发一个underflow事件并从TIMx_ARR开始重新计数。
其他同向上计数。
1.4.3 居中对齐模式,Center-aligned mode (up/down counting)
此模式下,计数器从0加到(TIMx_ARR - 1)后触发一个overflow事件,接着从(TIMx_ARR )减到1后触发一个underflow事件,如此往复。
此模式下,TIMx_CR1 寄存器里的DIR(Direction)不受软件控制,由硬件控制。
使用条件:
- TIMx_CR1 寄存器里的CMS(Center-aligned mode selection)位不能是0
- 通道配置成输出后(CCxS=00 in TIMx_CCMRx register),OC中断标志位会被置位,当:
- CMS=01:Center-aligned mode 1,只有当计数器向下计数时。
- CMS=10:Center-aligned mode 2,只有当计数器向上计数时。
- CMS=11:Center-aligned mode 3,当计数器向上或向下计数时。
2. 时钟选择
计数器的时钟来源:
- 内部时钟(CK_INT)
- 外部时钟模式1:外部管脚输入
- 外部时钟模式2:外部触发输入 ETR
- 内部触发输入:ITRx,可以用1个计数器作为另一个计数器的预分频计数器。
2.1 Internal clock source (CK_INT)
只要slave模式禁用(SMS=000,TIMx_SMCR),TIMx_CR1寄存器里的CEN、DIR位和TIMx_EGR寄存器里的UG就是实际的控制位,并且只能由软件修改(除了UG,它会自动清零)。
2.2 External clock source mode 1
slave模式(SMS=0111,TIMx_SMCR),计数器可以在选择管脚的每一个上升及下降沿计数:
如果需要计数器在TI2的上升沿计数,配置如下:
- 配置CC2通道作为输入并映射到TI2:修改CC2S(Capture/Compare 2 Selection)=01, TIMx_CCMR1
- 配置输入捕获的滤波器时间,不需要滤波的话:修改IC2F(Input capture 2 filter)=0000,TIMx_CCMR1
- 选择上升沿极性:修改CC2P(Capture/Compare 2 output polarity)=0 和 CC2NP(Capture/Compare 1 complementary output polarity)=0,TIMx_CCER
- 配置计数器在外部时钟源模式1下:修改SMS(Slave mode selection)=111,TIMx_SMCR
- 选择TI2作为时钟源:修改TS(Trigger selection)=110,TIMx_SMCR
- 使能计数器:修改CEN=1,TIMx_CR1
说明:
- 此用途中,捕获的预分频不需要设置,因为没有用到。
- 当检测到TI2的上升沿时,计数器+1,并置位TIF
- TI2的上升沿与实际计数器时钟的上升沿之间的延迟,取决于TI2输入的再同步电路。
2.3 External clock source mode 2
此模式,可通过置位TIMx_SMCR寄存器的ECE(External clock enable)来选择。
关于ECE:
- 置位ECE,和在External clock source mode 1下将TRGI连到ETRF(SMS=111 and TS=00111)有相同的效果。
- 在复位、门级、触发的slave模式下可以同时使用External clock source mode 2,但是TRGI不能连到ETRF(TS!=00111)
- 在External clock source mode 1和External clock source mode 2同时使用时,外部时钟源是ETRF。
如果需要配置一个向上计数器来数ETRF每隔2个上升沿的次数:
- 不需要滤波的话, 配置ETF(External trigger filter)=0,TIMx_SMCR
- 配置预分频 ETPS(External trigger prescaler)=01,TIMx_SMCR
- 选择ETRF的上升沿:ETP(External trigger polarity)=0,TIMx_SMCR
- 选择外部时钟源模式2:ECE(External clock enable)=1,TIMx_SMCR
- 启动计数器: CEN=1,TIMx_CR1
3. Capture/compare channels
每一个捕获比较(看到CC,就是这个了)都是建立在:
- 捕获比较寄存器,包括一个影子寄存器
- 输入阶段:数字滤波、多路复用、预分频
- 输出阶段:比较器和输出控制
捕获比较模块由预加载寄存器和影子寄存器组成,读和写都是访问的预加载寄存器。
- 在捕获模式下,捕获实际上是在影子寄存器完成的,它会复制到预加载寄存器。
- 在比较模式下,预加载寄存器的内容会被复制到与计数器比较的影子寄存器。
3.1 输入捕获模式
在输入捕获模式,CC寄存器(TIMx_CCRx)用于当一个事务通过相应的ICx信号检测到时锁存计数器的值。
当捕获发生时,对应的在TIMx_SR寄存器CCxIF(Capture/Compare x interrupt flag)标志位会被置位,并且中断或者DMA请求将会发生,如果使能的话。
如果捕获发生在CCxIF已经被置位的情况下,那么CCxOF( Capture/Compare x overcapture flag)会被置位。
CCxIF标志位可以通过向此位写0清除,或者读取存储在TIMx_CCRx寄存器的捕获数据。
CCxOF标志物可以通过向此位写0清除。
假如需要配置,当TI1输入上升沿时捕获计数器的数值到TIMx_CCR1:
- 配置通道用途:TIMx_CCR1必须连接到TI1,所以配置CC1S(Capture/Compare 1 Selection)=01,TIMx_CCMR1。如果CC1S不为0,说明通道配置成输入,那么TIMx_CCR1就会变成只读。
- 配置输入滤波:假设当TI1信号反转时大概至少需要5个clk的时间稳定,我们可以将连续采样值设为8(2^3),所以配置IC1F=3,TIMx_CCMR1。
- 配置TI1信号的触发沿:设成上升沿的话,配置CC1P=0,CC1NP=0, TIMx_CCER (capture/compare enable register)。
- 配置输入信号的预分频:这里不需要, IC1PS=0,TIMx_CCMR1
- 使能计数器: 配置CC1E =1,TIMx_CCER。
- 如果需要的话,可以开启相应的中断:配置CC1IE=1,TIMx_DIER;或者DMA中断请求:CC1DE =1,TIMx_DIER。
当输入捕获发生时:
- TIMx_CCR1寄存会获取计数器的值
- 中断标志位CC1IF置1;如果至少连续2次捕获发生并且CC1IF标志位一直未被清除时,会置位CC1OF
- CC1IE控制中断是否发生;CC1DE控制DMA请求是否触发。
注意:
- 为了处理捕获溢出的情况,建议在捕获溢出前先读取TIMx_CCRx,这是为了避免捕获溢出发生在读取标志位之后且在读数据之前。
13. Advanced-control timers (TIM1 and TIM8)的更多相关文章
- 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介
目录 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境 PY32F0系列上市其实相 ...
- STM32F4 Timer simplified block diagram
Timers TIM1 and TIM8 use 16-bit counters and are the most complex timers of all timers included in t ...
- 高级定时器TIM1&TIM8
高级定时器 初识stm32高级定时器: (1)高级控制定时器(TIM1 和 TIM8)和通用定时器在基本 ...
- 13 Stream Processing Patterns for building Streaming and Realtime Applications
原文:https://iwringer.wordpress.com/2015/08/03/patterns-for-streaming-realtime-analytics/ Introduction ...
- [C++] Copy Control (part 1)
Copy, Assign, and Destroy When we define a class, we specify what happens when objects of the class ...
- [翻译]MySQL 文档: Control Flow Functions(控制流函数)
本文翻译自13.4 Control Flow Functions Table 13.6 Flow Control Operators 名称 描述 CASE Case 运算符 IF() if/else ...
- STM32 TIM1高级定时器RCR重复计数器的理解
STM32 TIM1高级定时器RCR重复计数器的理解 TIMx_RCR重复计数器寄存器,重复计数器只支持高级定时器TIM1和TIM8,下面看标准外设库的TIM结构体的封装: typedef struc ...
- STM32 TIM1高级定时器配置快速入门
layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 重点内容 时基单元 计 ...
- STM32通用定时器(转载)
STM32的定时器功能很强大,学习起来也很费劲儿. 其实手册讲的还是挺全面的,只是无奈TIMER的功能太复杂,所以显得手册很难懂,我就是通过这样看手册:while(!SUCCESS){看手册-}才搞明 ...
- 嵌入式单片机STM32应用技术(课本)
目录SAIU R20 1 6 第1页第1 章. 初识STM32..................................................................... ...
随机推荐
- 3D捕鱼大富翁源码分析
今天接受了一个捕鱼的源码,技术栈采用: 客户端:Unity 服务端:Java 数据库:mysql 缓存:redis 先来几张成品图 编辑编辑 编辑编辑 编辑 在代码中看到有腾讯推广渠道, ...
- 你要的AI Agent工具都在这里
只有让LLM(大模型)学会使用工具,才能做出一系列实用的AI Agent,才能发挥出LLM真正的实力.本篇,我们让AI Agent使用更多的工具,比如:外部搜索.分析CSV.文生图.执行代码等. 1. ...
- 如何查看docker容器的volume挂载情况
准备在docker容器当中编写个日常维护的脚本,但容器里连yum和vim命令都没有,所以就想到通过容器映射在本机的volume里编写脚本这样在容器中不就可以直接用了吗,那么在这之前你首先得知道dock ...
- vue-router 路由模式有几种?
实际上存在三种模式: Hash: 使用URL的hash值来作为路由.支持所有浏览器. History: 以来HTML5 History API 和服务器配置.参考官网中HTML5 His ...
- PHP易混淆函数的区别及用法汇总(函数和方法的区别)
1.echo和print的区别PHP中echo和print的功能基本相同(输出),但是两者之间还是有细微差别的.echo输出后没有返回值,但print有返回值,当其执行失败时返回flase.因此可以作 ...
- [oeasy]python0145_版本控制_git_备份还原
git版本控制 回忆上次内容 上次我们了解了 try 的完全体 try 尝试运行 except 发现异常时运行的代码块 else 没有发现异常时运行的代码块 finally 无论是否发现异 ...
- oeasy教您玩转python - 007 - # 字符本质
字符本质 回忆上次内容 hello world 不是从来就有的 来自于unix和c 虽然我们今天有各种先进的学习手段 最早的高级语言学习是从最早的那张打字机用纸的手写代码起源的 所以输出用的是 p ...
- 3分钟带你搞定Spring Boot中Schedule
一.背景介绍 在实际的业务开发过程中,我们经常会需要定时任务来帮助我们完成一些工作,例如每天早上 6 点生成销售报表.每晚 23 点清理脏数据等等. 如果你当前使用的是 SpringBoot 来开发项 ...
- c#写一个WINFORM的多线程操作
以下是一个简单的示例,展示了如何在C# WinForms中创建一个按钮的异步事件,并使用Label控件来显示事件执行的时长. 首先,确保你已经在你的项目中添加了一个Button和一个Label控件.假 ...
- 《Programming from the Ground Up》阅读笔记:p88-p94
<Programming from the Ground Up>学习第5天,p88-p94总结,总计7页. 一.技术总结 1.touppercase.s #PURPOSE: This pr ...