【STM32HAL库学习】定时器功能、时钟以及各种模式理解

一、文章目的

记录自己从学习了定时器理论->代码实现使用定时->查询数据手册,加深了对定时器的理解以及该过程遇到了的一些不清楚的知识。

  • 上图为参考手册里通用定时器框图,关于定时器各种情况的工作都在上面了,在理论学习和实际应用后再来看这张图会觉得豁然开朗。

  • 定时器基本的单元为16位自动装载寄存器ARR,16位预分频器PSC,计数器CNT,另外有4个独立通道,在我看来只有两种大功能:

    -- 输入捕获 (如测输入信号频率、占空比、编码器)

    -- 输出比较 (如输出PWM波控制电机、舵机)
    根据这两种功能可以将定时器配置为不同模式,比如输出pwm的PWM模式、读取编码器的Encoder模式。

二、定时器时钟来源选择(极为重要)

内部时钟(CK_INT)

内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器

外部时钟模式1:外部输入脚(TIx) ,4个独立通道的输入

外部时钟模式2:外部触发输入(ETR) ,模式1和模式2看上去非常相似

清楚定时器的时钟来源,后续才能理解定时器的各种模式

三、 理解最基本的定时

在时钟的驱动下,计数器CNT递增+1(默认向上计数),当到达自动重装载寄存器ARR中的目标值时,溢出清零,产生中断,循环这个过程。

HAL库实现基本定时

  • 1、打开并设置基本定时器
    *

    1. 选择为内部时钟,即内部时钟模式
      1. 设置以下参数:定时器的时钟频率 fc=f /(PSC+1)/(ARR+1),f为单片机时钟来源。
      预分频器Prescaler    PSC
    
      自动重装寄存器CouterPeriod   ARR
    
      输入滤波器的频率分频InternalClockDivision(一般不需要)
    
  • 2、打开中断
  • 3、main函数中初始化TIM2
c 复制代码
HAL_TIM_Base_Start_IT(&htim2);

4、驱动函数中找回调函数然后在main.c中重写

c 复制代码
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim); //原型
//重写
uint16_t hhRetCount=0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	if(htim==&htim2){
		hhRetCount+=1;
	}
}

四 、输出比较

此项功能是用来控制一个输出波形,或者指示一段给定的的时间已经到时。

定时器的每个输出通道能够独立的产生一路PWM信号(由ARR寄存器确定频率、由CCR寄存器确定占空比的信号。)

HAL库实现生成PWM(驱动舵机、电机、呼吸灯)

  • 1、设置TIM2定时器相关参数

    • 生成1000HZ,占空比为20的PWM波形

    HAL库实现编码器读取

  • 2、main函数中启动生成PWM

c 复制代码
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,Speed); //设置CCR值控制占空比

五 、输入捕获

输入捕获模式下,当通道输入引脚出现指定电平跳变时(类似于中断),当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数。

可配置为PWMI模式(不清楚没关系),同时测量频率和占空比;也可配合主从触发模式`(下文中从模式的复位模式),实现硬件全自动测量(触发输入实现定时器的自动清零)。

对于同一个定时器,输入捕获和输出比较只能同时用一个。
输入捕获:将CNT的值写到CCR
输出比较:根据CNTCCR的比较后输出

输入捕获测频率、测占空比

从模式-复位模式下,上升沿触发,因此上升沿来临时,计数器CNT的值存进了CCR1中然后自动清零;下降沿来临时,CNT的值存进了CCR2中,并未清零。然后可以计算频率(用CCR1)和占空比(用CCR1和CCR2)。

HAL库实现输入测频率、占空比

  • 1、TIM2生成PWM待测信号、启动
  • 2、设置TIM3定时器相关参数
    • 通道1用于测频率
      1. 设置TI1FP1ResetMode,即清空计数
      1. 使用内部时钟
      1. 通道1设置为输入捕获模式
      1. 设置预分频器为72
      1. 自动重装寄存器为65535
      1. 输入捕获上升沿
    • 通道2用于测占空比
      1. 打开通道2为交叉模式、设置下降沿触发

通道1

通道2

  • 3、打开TIM3的全局中断、main中开启TIM3
c 复制代码
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);

3、找到输入捕获回调函数并重写

c 复制代码
uint32_t capture;
int32_t freq;
uint32_t DutyResult;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == TIM3) {
		if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
		// 上升沿触发的中断
			capture =HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)+1;
			uint32_t aa=HAL_RCC_GetPCLK1Freq();
			uint32_t bb=(htim->Instance->PSC+1);
			uint32_t cc=HAL_RCC_GetPCLK1Freq()/(htim->Instance->PSC+1);
			freq=1000000/capture;
		} else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
			// 下降沿触发的中断
			uint32_t capture2 =HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)+1;
			DutyResult=capture2 *100 / capture;
		}
	}
}

可动态修改TIM2的频率和占空比

c 复制代码
__HAL_TIM_SET_PRESCALER(&htim2,72-1);//10000HZ
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 83);//83%

HAL库实现读取旋转编码器

每个高级定时器和通用定时器都拥有一个编码器接口,借用输入捕获IC的通道1和通道2。

当定时器设置为编码器接口时,定时器的计数器就不会由内外部时钟控制,而是由两个正交编码器信

号控制。另外,还可以根据选择的计数方式(TI1、TI2计数还是都计数)以及信号上下沿、电平高低的判断确定方向。

利用CUBMX配置编码器模式非常简单:

  • 1、设置相关参数
    *
    1. 打开编码器模式(使用CH1、CH2两个通道)
      1. 设置定时器的相关参数。由于是检测速度,所以这里就不分频,尽可能让定时器快点。计数器 设置最大,防止输入信号频率太高溢出。
      1. 设置计数模式,TI1计数和TI2计数
      1. 设置信号不反向
  • 2、main函数中打开定时器编码器模式
c 复制代码
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
  • 3、显示计数值
    计数器CNT返回的是一个无符号的 uint32_t 数,因此如果希望反转能够显示负数,还需要将CNT值转换为有符号的 int16_t 数。
c 复制代码
//得到计数值
int16_t CNT=__HAL_TIM_GET_COUNTER(&htim3);
  • 4、计算速度
    如果还希望计算编码器速度,那就秒钟读取一次定时器的计数值(编码器的脉冲)并清空,得到的数字就是当前的速度,单位是Plus/S
c 复制代码
int16_t hhGetEncoderSpeedCountAndReset(){
	int16_t Speed;
	Speed=__HAL_TIM_GET_COUNTER(&htim3);
	__HAL_TIM_SET_COUNTER(&htim3,0);
	return Speed;
}

六、主从模式

根据定时器的时钟来源(或者说是否受到从模式控制器的控制),可以将定时器的工作状态分为主模式和从模式

首先,触发信号分两大类:触发输入信号TRGI,简单地讲就是从外部引入到本定时器的信号;另一类就是触发输出信号,即TRGO信号,它是定时器输出给其它定时器或外设的触发信号。

从数目上有讲一般可以多达8个,大致分为三类:

第一类来自定时器自身输入通道1或通道2的输入信号 ,经过极性选择和滤波以后生成的触发信号,连接到从模式控制器,进而控制计数器的工作。 (TI1FP1 、 TI2FP2、TI1F_ED

第二类来自于外部触发脚 ETR脚经过极性选择、分频、滤波以后的信号,经过触发输入选择器,连接到从模式控制器 (ETRF

第三类来自其它定时器的触发输出信号 TRGO,通过内部线路连接到本定时器的触发输入控制器而连接到从模式控制器。(ITR0、ITR1、ITR2、ITR3)

这3类信号有个共同特点:都要经过触发输入选择器而连接到从模式控制器,从而使得计数器的工作受到从模式控制器的控制或影响,基于这一点,定时器工作在从模式。而主模式:定时器内部信号映射到TRGO引脚用于触发别的外设。

七、定时器的4种从模式

  • 复位模式
  • 门控模式
  • 触发模式
  • 外部时钟模式2+触发模式
    在我看来从模式其实就是在正常使用定时器外再添加一个控制功能,根据实际的需要再配置即可。

复位模式

在发生一个触发输入事件时,计数器和它的预分频器能够重新被初始化;同时,如果TIMx_CR1寄存器的URS位为低,还会产生一个更新事件UEV;然后所有的预装载寄存器(TIMx_ARR,TIMx_CCRx)都会被更新。

例如TI1输入端的上升沿导致向上计数器被清零:计数器开始依据内部时钟计数,然后正常运转直到TI1出现一个上升沿;此时,计数器被清零然后从0重新开始计数。同时,触发标志(TIMx_SR寄存器中的TIF位)被设置,根据TIMx_DIER寄存器中TIE(中断使能)位和TDE(DMA使能)位的设置,产生一个中断请求或一个DMA请求。

门控模式

按照选中的输入端电平使能计数器。
例如下图,计数器只在TI1 输入电平为低时计数+1

触发模式

按照输入端上选中的事件使能计数器。
例如下图,计数器在TI2输入的上升沿开始向上计数

外部时钟模式2+触发模式

外部时钟模式2可以与另一种从模式(外部时钟模式1和编码器模式除外)一起使用。

外部时钟模式2,ETR信号被用作外部时钟的输入,在复位模式、门控模式或触发模式时可以选择另一个输入作为触发输入。

例如下图,TI1 输入上升沿使能计数器,然后在ETR信号每次的上升沿计数

八、其他

遇到查询数据手册即可

相关推荐
啦啦右一1 分钟前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习
远翔调光芯片^1382879887218 分钟前
远翔升压恒流芯片FP7209X与FP7209M什么区别?做以下应用市场摄影补光灯、便携灯、智能家居(调光)市场、太阳能、车灯、洗墙灯、舞台灯必看!
科技·单片机·智能家居·能源
霍格沃兹测试开发学社测试人社区29 分钟前
软件测试学习笔记丨Flask操作数据库-数据库和表的管理
软件测试·笔记·测试开发·学习·flask
今天我又学废了1 小时前
Scala学习记录,List
学习
王俊山IT1 小时前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
极客小张1 小时前
基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路
stm32·单片机·嵌入式硬件·mqtt·sqlite·毕业设计·智能充电桩
Mephisto.java2 小时前
【大数据学习 | kafka高级部分】kafka中的选举机制
大数据·学习·kafka
南宫生2 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
武子康3 小时前
大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和
大数据·人工智能·学习·算法·机器学习·数据挖掘
使者大牙4 小时前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型