文章目录
时钟与时钟树
频率:如72Mhz即为每秒72M个脉冲
-
时钟的源头
晶振 -
时钟树的分支
分频器:分频器是一种将输入时钟信号的频率降低到其整数倍的电路。
倍频器:倍频器则是将输入时钟信号的频率提高到其整数倍的电路。
参考CSDN文章_时钟系统
他们可以通过改变频率实现不同频率的分支。
stm32时钟树
《STM32F103C8T6从入门到精通》SystemInit函数详细讲解
St公司的配置程序:江科大
- 8Mhz HSI做系统时钟
- 再打开HSE取8Mhz 再通过图中黄色路线到锁相环(PLL)倍频9倍,待锁相环输出稳定后,(红色区域)切换锁相环输出为系统时钟 但是,如果外部晶振HSE出现问题,就不会切换,而是继续使用系统内部时钟HSI.
- 在参考手册中的RCC的CR寄存器中的HSION位的部分 找到了对上面过程的说明
- APB1二分频为36mhz APB2不分频,为72mhz
- PCLK2通常指的是APB2 (Advanced Peripheral Bus 2) 的时钟频率。它的频率通常是由更高频率的AHB (Advanced High-performance Bus) 时钟通过一个分频器来调整得到的。
- 参考以下代码(位于systemInit函数中调用的SetSysClockTo72函数中)
可以手动把系统时钟72mhz改成其他的吗?
可以通过更改这里的宏来实现。
具体代码梳理
ST公司给的外围设备配置文件 的 默认配置说明
《STM32F103C8T6从入门到精通》SystemInit函数详细讲解 该函数配置了系统时钟等
在system_stm32f10x.c文件中提到
- HSI 作为默认时钟源
HSI (High Speed Internal):内部高速时钟,频率为 8 MHz。每次设备复位后,HSI 自动作为系统时钟源。
SystemInit() 函数:在启动文件 startup_stm32f10x_xx.s 中定义的函数,用于配置系统时钟。该函数在跳转到主程序前被调用。 - 时钟源故障处理
如果用户选择的系统时钟源未能成功启动(例如,外部时钟源未正常工作),SystemInit() 函数将不做任何处理,系统将继续使用 HSI 作为时钟源。
用户可以在 SetSysClock() 函数中添加代码来处理这种情况,例如重新配置时钟源或进行错误处理。 - HSE 晶振配置
HSE (High Speed External):外部高速时钟,通常由外部晶振提供。
默认情况下,HSE 晶振的频率设置为 8 MHz 或 25 MHz,具体取决于所使用的 STM32F10x 产品。
HSE_VALUE 定义在 stm32f10x.h 文件中,用于指定 HSE 的频率。
如果使用 HSE 作为系统时钟源(直接或通过 PLL),并且使用了不同的晶振频率,需要调整 HSE_VALUE 以匹配实际使用的晶振频率。
定时器
cortex-M3 内核里有一个systick定时器(江科大的Delay函数就是用systick实现的)
而下面要提到的是核外外设,高级、通用、普通定时器
什么是定时器
定时器就是计数器
定时器就是计数器
定时器就是计数器
动画演示_B站
PS: 预分频器和计数器的长度都是16bit ,216 = 65536
-
预分频器(Prescaler)·:预分频器的值规定在0 ~ n-1(n是输入时钟频率的数值)
它像是计数器的一个助手,规定每隔几个脉冲向计数器报告一次,让计数器加1- 当预分频的值为零时,每一个脉冲计数器加一次;设定值为1时,每隔两个脉冲,计数器加1。
- 预分频器的作用:可以增加定时器的定时上限:
- 当预分频器设置为0时,一个脉冲就记一次,因为计数器最多定65536下,对应65536 * (1/72M) ≈ 0.00091秒。
- 而当预分频器设置为65535时,每72M个脉冲记一次,因为计数器还是最多定65536下,对应时间为,65536 * 65536 * (1/72M) ≈ 59.65 秒 (计数器的值 乘 预分频器处理的记一次对应的脉冲数 再乘 一个脉冲对应的时间)
- 可见,预分配器正是通过自己额外处理时钟脉冲数来提高总时间的
-
计数器(Counter):
- 基本定时器只有向上计数模式。(从零开始加)
- 通用定时器与高级定时器有向上计数、向下计数(从设定值开始减)、中央计数模式。
-
自动重装载寄存器(Auto Reload Register):在计数器到达该寄存器设定值时清零计数器,并同时(如果配置了)
可触发中断。
定时器的类型
类型 | 编号 | 总线 | 功能 |
---|---|---|---|
高级定时器 | TIM1、TIM8 | APB2 | 拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能 |
通用定时器 | TIM2、TIM3、TIM4、TIM5 | APB1 | 拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能 |
基本定时器 | TIM6、TIM7 | APB1 | 拥有定时中断、主模式触发DAC的功能 如何理解主模式触发 |
STM32C8T6 只有TIM1,TIM2,TIM3,TIM4
影子寄存器 | 预装载寄存器(Preload Register)
在学习TIM定时器时了解到。影子寄存器的主要功能缓冲后台存储数据或配置设置,这样在执行某些关键操作时,可以避免由于直接修改主寄存器而导致的问题。
- 作用(用时序图作示例)
- 可看出当 预分频控制寄存器更改数值后,对应在定时器时钟的输出没有随之改变(预分频缓冲器在缓冲)
而是等上一个定时器时钟记满(到下一个计数周期,触发更新事件),才起更改作用。 - 省流版:让值的变化与更新事件同步发生
- 可看出当 预分频控制寄存器更改数值后,对应在定时器时钟的输出没有随之改变(预分频缓冲器在缓冲)
- 在框图中的阴影标识 江科大
相关工程问题
一上电就进了定时中断?可能为了是避免影子寄存器的缓冲带来的副作用
在配置时基单元时,库函数为了让预分频器立刻起作用(因为有缓冲,要等事件才会更新数据),手动配置了一个事件,同时触发了定时中断
通用定时器 相关框图
用作文章查阅参考
- 绿色部分(IC input compare)的细节图
TIM_ICInit、TIX、ICX、TIXFPX是什么- TIx :如用的是定时器2,TI1和TI2对应是 TIM2->CH1 和TIM2->CH2对应的引脚,信号就是外部信号,是直接与管脚相连的信号,即通道x对应的引脚,图中还有一个问题就是TI1是可以是第一通道的外部信号进行触发,也可以设置为,第一通道,第二通道,第三通道异或进行触发。外部信号送往滤波器和边沿检测器。
- TIxFPx :经过滤波器和带极性选择的边缘检测器过后的产生的信号,叫触发有效信号,与管脚直连的信号可以被设置为高、低边沿触发
至于TI1FP1和TI2FP2信号在上身沿计数还是下降沿计数受两点影响:
1,极性(是否反向)
2,边缘检测(上升沿还是下降沿) - ICx:映射信号
IC1 IC2 IC3 IC4:通道有效信号,在他的前面是TIxFP和TRC信号,可以看出,TI1FP与TI2FP可以互相对应IC1和IC2,TI3FP和TI4FP可以互相对应IC3和IC4,这样的不同通道的交叉连接,就可以使一个TIxFP信号对应两个ICx也就是对应两个通道。这样做的目的是,可以通过两个通道去检测一个引脚上的信号,实现PWM输入时,可以由1个来计算周期,另一个来计算占空比。ICx信号被送入预分频器。 (PWMI模式用到)
如下图可实现同时检测同一个引脚的两种特性
- TI1FP2就是CH2(下面这一路)的交叉信号,TI1FP2是CH1的直连信号
- 红色部分 (OC Output Compare)
主从触发模式 (省去了中断,避免占用软件资源)
配置的库函数
1.TIM_SelectOutputTrigger(选择主模式输出触发源)
2.TIM_SelectInputTrigger (从模式选择输入)
3.TIM_SelectSlaveMode (从模式选择输出触发模式)
对于主从触发模式,st的数据手册手册介绍比较少,可参照定时器的信号触发与主从模式
- 主模式: 选择信号用于触发别的外设 (控制别人)
在手册的CCR1j寄存器部分有解释
- 从模式:接收其他外设或者自身外设的信号 用于控制自身定时器的运行。(被控制)
具体用法可查阅手册 定时器->定时器同步的章节
主模式输出TRGO
至另一个从模式的ITRx
跳转结构图,以完成定时器级联功能。
但是从模式的触发源不一定是上一个定时器的TRGO,也可以是其他信号。所以当我们选择一个定时器为从模式,不一定要有主模式的定时器的配置,只是单单希望利用一下从模式的功能比如复位、门控和触发功能也是未尝不可的
定时中断
一. 配置时钟源 (注意一点:这里的内部外部时钟的概念【脉冲】与时钟树的内部外部时钟源【震荡源输出到AHB总线】不同)
- 如果第二步打算配置为rcc的话,就初始化对应定时器的rcc时钟 (选择系统时钟rcc作为输入,起定时作用)
- 若第二步选择外部时钟,则配置为ETR (选择外部脉冲作为输入,如对射红外传感器,遮挡一次一个脉冲)(注意GPIO是指定的)
二. 选择输入时基单元的时钟(上图中黄色部分)
- 以下是相关库函数 详细讲解
配置外部时钟模式1,模式2可参考的文章:
要有外部时钟模式2的原因:- 在从模式控制器被占用时,还可以通过该模式直接引入ETR外部信号,对外部信号进行计数 视频解析
- 方便快捷
这个文章直观的解释了:定时器时钟模式1、2与主从模式
b站大佬动画讲解
三. 配置时基单元
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
- 参数1:对应定时器
- 参数2:结构体里有五个参数
-
TIM_Period
TIM_Period 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。 -
TIM_Prescaler
TIM_Prescaler 设置了用来作为 TIMx 时钟频率除数的预分频值。 -
TIM_CounterMode
配置计数方式(向上计数、向下计数、中央对齐计数) -
TIM_ClockDivision (用于输入滤波)
按一定频率对信号进行采样,来判断信号是否稳定(而这个采样频率来自于系统内部时钟,这里的参数就是对内部时钟再进行分频) b站讲解
主要用于输入检测、死区时间设定等 STM32 时钟分割TIM_ClockDivision配置及使用详细说明 -
TIM_RepetitionCounter (高级定时器才有的功能,配置通用定时器时给0)
重复计数器
-
四. 配置输出控制
- TIM_ITConfig用这个函数
- 其中有一个参数比较关键:TIM_IT (毕竟TIM外设有很多不同的中断)
-
更新中断(Update Interrupt) 是基于定时器自身的计数完成事件。
捕获/比较中断(Capture/Compare Interrupts) 是基于定时器计数器与特定通道的CCR值之间的关系。
触发中断(Trigger Interrupt) 是基于外部触发信号的到达。
五. 配置NVIC(配置中断优先级)
六. 运行控制(相当与一个总开关)开启定时器
OC(Output Compare)输出比较
- 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
- 每个高级定时器和通用定时器都拥有4个输出比较通道
- 高级定时器的前3个通道额外拥有死区生成和互补输出的功能(多用于驱动三相无刷电机)
OC_Mode 输出模式控制
模式 | 描述 |
---|---|
冻结 | CNT=CCR时,REF保持为原状态 |
匹配时置有效电平(理解为高电平) | CNT=CCR时,REF置有效电平 |
匹配时置无效电平(理解为低电平) | CNT=CCR时,REF置无效电平 |
匹配时电平翻转 | CNT=CCR时,REF电平翻转 |
强制为无效电平 | CNT与CCR无效,REF强制为无效电平 |
强制为有效电平 | CNT与CCR无效,REF强制为有效电平 |
PWM模式1 | 向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平 向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平 |
PWM模式2 | 向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平 向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平 |
PWM (Pulse Width Modulation)脉冲宽度调制
在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域
PWM参数:
- 频率 = 1 / TS
频率越高越平稳 - 占空比 = TON / TS
等效输出比 - 分辨率 = 占空比变化步距
占空比变化的精细程度
- PWM输出流程
-
按照定时中断配置的前两步配置好时钟(通常选择内部脉冲RCC)输入
-
接着配置时基单元
-
初始化输出比较单元
- 其中要注意配置输出模式(TIM_Mode)及输出极性时 有几点要注意
- 输出模式 (这里要选择pwm1 或 pwm2 )
在手册中对 捕获/比较 模式寄存器(TIMx_CCMR1)的描述中
下面的有效电平(active)取决于输出极性的配置
2.输出极性
在手册对捕获/比较使能寄存器的描述中
定义了有效电平(active)对应的电平状态
- 输出模式 (这里要选择pwm1 或 pwm2 )
- 其中要注意配置输出模式(TIM_Mode)及输出极性时 有几点要注意
-
需要注意的一点是:初始化GPIO时,要配置为复用推挽输出模式(将输出的控制权从输出寄存器转到定时器
-
最后配置计数器使能(总开关)
- 对于输出比较单元的配置函数参数,有一个结构体,在配置通用定时器时很多都用不到,所以我们可以用给的结构体初始化函数先给结构体初始化一下。
- PWM参数计算
- 一个变化周期 对应 计数器的计数周期
- 频率等于一个变化周期的倒数
- 占空比 Duty = CCR / (ARR + 1) 高电平计数值 比 总计数值
- 分辨率 Reso = 1 / (ARR + 1)
IC (Input Compare) 输入捕获
- 输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
- 每个高级定时器和通用定时器都拥有4个输入捕获通道
- 可配置为PWMI模式,同时测量频率和占空比
- 可配合主从触发模式,实现硬件全自动测量
点击跳转文内的 输入捕获结构框图讲解
频率测量
- 测频法:在闸门时间T内,对上升沿计次,得到N,则频率
𝑓𝑥=𝑁 / 𝑇 (即为测1s内的脉冲数) (适合高频信号) - 测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率
𝑓𝑥=𝑓𝑐 / 𝑁 (即为测一个周期的时间再取到倒数)(适合低频信号)
中界频率:测频法与测周法误差相等的频率点
(可用于判断用那种方法测量)
𝑓𝑚=√(𝑓𝑐 / 𝑇)
- (大于fm选测频法)当标准信号频率远低于被测信号频率时,Tc1窗口内的被测信号脉冲很多(N1很大),测频法得到的结果就越准确。 //要两个定时器实现,一个计时,一个记录脉冲
- (小于fm选测周法)当被测信号频率远低于标准信号频率时,Tx2窗口内的被测信号脉冲很多(N2很大),测周法得到的结果就很准确。 //只要一个定时器,输入捕获脉冲就开始计数,下一个边沿到达,读取时间。
用STM32定时器测量信号频率——测频法和测周法
输入捕获模式 与 PWM输入模式
PWM输入模式是输入捕获模式的一个特例(具体不同请翻阅手册 定时器->PWM输入模式的章节)
- 按照定时中断配置的前两步配置好时钟(通常选择内部脉冲RCC)输入
- 接着配置时基单元
- 初始化输入捕获单元
- 边沿检测 里可选择 上升、下降或是双边沿触发
- 分频器的作用像是一个缓冲区:不分频就是每一个触发信号有效一次,二分频就是每两个触发信号有效一次。(在测PWM频率时应选不分频)
- TIM_ICSelection:选择直连通道或是交叉(间接)通道或是TRC。 (看不明白请参考结构图)
如果要配置PWMI(PWM INPUT),即同时检测占空比、频率时。如果正常配置需要配置两次输入捕获单元,但是有一个库函数简化了过程 PWMI_Config函数 函数介绍 只支持ch1、ch2
- 配置从模式 (点击跳转主从模式讲解)
-
TIM_SelectInputTrigger (从模式选择输入)选择触发源
表78的黄色部分可看出:TIM3可以通过TIM1(在TS = 000时),TIM2(在TS = 001时),TIM5(在TS = 010时)以及TIM4(在TS = 011时)进行触发。 -
TIM_SelectSlaveMode (从模式选择输出触发模式) //如果要检测PWM频率 就选reset
-
- 使能计数器
编码器模式
配置步骤:
- 首先初始化对应gpio(不要忘了rcc时钟,gpio和定时器的都要)
- 初始化时基单元 (可不预分频、预装载直接拉满)
//可注意到:编码器模式不用配置时钟输入,因为编码器充当了信号输入 - 配置输入捕获单元(由结构图可知,只需配置 输入滤波与输入极性)
- 配置编码器输入
- 使能计数器
即使stm32硬件上不支持编码器模式,我们还可以通过exti中断处理其中一项信号,在上升/下降沿触发 读取另一项的电平
总结与反思
其实想输出比较、输入捕获、编码器模式这些都是硬件在支持,以减轻软件资源的压力。若是以后接触到的没有这些模式,也无妨,可以通过外部中断其实都可以实现,就是软件上麻烦一些。
对于中断有几点我容易忽略
1.stm32任何中断最后都要通过NVIC,所以不要忘记配置。
2.中断函数内不要放延时函数
3.中断函数最后记得清除标志位(而且保证清除对应的中断),否则将会出现抽象的问题,难以排查。
对于定时器的配置:
1.无论什么用定时器的哪个模式,最后一定不要忘记 给实际单元使能! TIM_Cmd(TIM3, ENABLE);
2.若用到gpio或是时钟输入 千万千万记得开启rcc时钟 (事故多发地)