本文章是本人学习江科大STM32视频记录,目的为了更好的记忆。
1.TIM 简介
1.1 定时器基本功能:
定时器对输入的是中进行计数,并在数值达到设定值时触发中断,可以发现定时器就是计数器,当每次计数输入时准确可靠的基准时钟,再计数时就成为了计时器。
stm32的计数器拥有16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时。(计数器就是用来计数定时的一个寄存器,每来一个时钟,计时器加1;预分配器,可以对计数器进行分频,让计数更加灵活;自动重装寄存器就是计数的目标值,就是我想计多少个时钟申请中断)不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。
1.2 计时器类型
三种定时器由高级到低级向下兼容的·,在操作一个外设时,应该先检查是否有该外设。
从基准时钟,到预分频器,在到计数器,计数器计数自增(这是向上计数,还有向下计数和中央对齐,是通用定时器和高级定时器所拥有),同时不断与自动重装寄存器进行比较,它两值相等,即计时时间到,这时产生一个更新中断和更新事件,CPU响应定时中断。
外部时钟模式的输入可以是ETR引脚、其他定时器、CH1引脚的边沿、CH1引脚和CH2引脚,一般使用ETR引脚,其他是特定功能使用。
2.定时中断
2.1 基本结构
左边是为时基单元选择时钟的部分,可以选择RCC的内部时钟,也可以选ETR引脚的外部时钟模式2,还可以选这触发输入当外部时钟,即外部时钟模式1,对应有ETR外部时钟,ITRx其他定时器,TIx输入捕获通道,最后的编码其独用的编码器模式。
中间是由PSC预分频器,CNT计数器,ARR重装计数器这三个寄存器构成的时基单元,下面是控制寄存器的一些位,可以启动停止、向下向上计数等等。
右边,计时时间到,产生更新中断后的信号去向,,中断信号会在状态寄存器里置一个中断标志位,这个标志位会通过中断输出控制,到NVIC申请中断。
杂项:
选择内部时钟时,预分频值越大计数越慢,到达计数器值时申请中断;
选择外部通道,预分频值越大,需要增加计数值的触发次数越多;
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
2.2 定时器配置
1.RCC开启时钟,打开后定时器的基准时钟和争个外设的工作时钟就会同时打开了
2.选择时基单元的时钟源
TIM_InternalClockConfig //选择内部时钟
TIM_ITRxExternalClockConfig //选择ITRx其他定时器的时钟
TIM_TIxExternalClockConfig //选择TIx捕获通道的时钟
TIM_ETRClockMode1Config //选择ETR通过外部时钟模式1输入的时钟
TIM_ETRClockMode2Config //选择ETR通过外部时钟模式2输入的时钟
(不写,默认内部时钟)
3.配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision //时钟分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode //计数器模式
TIM_TimeBaseInitStructure.TIM_Period = //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter //重复计数器,高级定时器用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
4.配置输出中断控制,允许更新中断输出到NVIC
TIM_ITConfig //使能中断
5.配置NVIC,在NVIC中打开定时中断的通道,并分配一个优先级
6.运行控制,整个模块配置后,我们还需要使能一下计数器,当定时器使能后,计数器就会开始计数了,当计数器更新使能,触发中断
TIM_Cmd //使能定时器
7.写一个定时器的中断函数,这样每隔一段时间执行一次
3.输出比较
3.1 输出比较简介(OC)
输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
每个高级定时器和通用定时器都拥有4个输出比较通道
高级定时器的前3个通道额外拥有死区生成和互补输出的功能
3.2 PWM简介
在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域
PWM参数:
频率 = 1 / TS 占空比 = TON / TS 分辨率 = 占空比变化步距
3.3 输出比较模式
冻结:当你输出PWM波形,想暂停一会输出维持原波形,就可以设置此模式
匹配时置有效(高)电平、匹配时置无效(低)电平、匹配时电平翻转:当你输入一次性的信号可以使用匹配时置有效电平和匹配时置无效电平,当想输出占空比为50%时,可以使用匹配时电平翻转
强制有效电平、强制无效电平:如果你想暂停输出,并且想保持高或低电平,可以使用
PWM模式1、PWM模式2:可以用于输出频率和占空比都可调的PWM模式
3.4 PWM基本结构
左边是上边内容,输出PWM不需要申请中断。配置好时基单元,CNT开始自增运行,下方时输出比较单元,总共有4路,CCR捕获/比较寄存器是自己设置,CCR与变化CNT不断比较,输出PWM波(如图,蓝线是CNT的值,红线是CCR的值,当CNT小于CCR,输出高电平,当CNT大于CCR,输出低电平,从而产生PWM波形,改变CCR的值,能不断改变占空比),最终通过机型选择,输出使能,通向GPIO口。
3.5 参数计算
PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
PWM占空比: Duty = CCR / (ARR + 1)
PWM分辨率: Reso = 1 / (ARR + 1)
ARR的值可以适当调大,占空比可以变更加细腻,可调节的范围也更多。
3.6 输出比较配置
1.RCC开启时钟,把我们要用的TIM外设和GPIO外设时钟打开
2.配置时基单元
3.配置输出比较单元
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure); //结构体初始化,若结构体没有完整赋值(这样可以有效防止出现故障)
TIM_OCInitStructure.TIM_OCMode //输出比较模式
TIM_OCInitStructure.TIM_OCPolarity //输出极性电平取反
TIM_OCInitStructure.TIM_OutputState //输出使能
TIM_OCInitStructure.TIM_Pulse //初始的CCR值
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
4.配置GPIO,把对应的GPIO口,初始化为复用推挽输出的配置(在配置GPIO口上时,要注意引脚定义表)
5.运行控制,启动定时器
同一个定时器不同通道输出PWM的特点
对于同一个定时器的不同通道输出的PWM,由于公用一个技术器,所以它们的频率必须一样,它们的占空比有各自的CCR决定,所以占空比可以各自控制,还用就是它们的相位,由于计数器更新,所有PWM跳变,所以它们相位是同步的。
引脚重映射
GPIO_PINRemapConfig //引脚重映射配置
引脚重映射表
4.输入捕获
4.1 输入捕获简介
输入捕获模式下,当通道输入引脚出现指定电平跳变时,当CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
每个高级定时器和通用定时器都拥有4个输入捕获通道
可配置为PWMI模式,同时测量频率和占空比
可配合主从触发模式,实现硬件全自动测量
注意:对于同一定时器,不能同时使用输入捕获和输出比较
4.2 频率测量
对于STM32而言,只能测量数字信号,如果你需要一个正弦波,需要搭建一个信号预处理电路,如果测量的信号电平非常高,那还要考虑一下隔离的问题。
测频法时在单位时间测量上升沿的次数,适合高频信号,测量结果更新的慢一些数值相对稳定(测频法测量的是在闸门时间内的多个周期,所以它自带一个均值滤波,如果在闸门时间内波形频率有变化 ,那得到的其实是这一段时间的平均频率),测周法时是测一个周期的时间然后渠道书得到频率,适合低频信号,测量结果更新的快数值跳变也快(只测一个周期,结果较快,但容易受噪声干扰)。(无论测频法还是测周法都有一定误差,所以要进行多次测量)
测频法,用定时器,顶1S的定时中断,在中断犁每隔1s取一下计次值,同时清零,为下一次做准备,这样得到的数字直接为频率。
4.3 主从触发模式
4.4 输入捕获基本结构
右上角是时基单元,配置好后,启动定时器,CNT就会在预分频之后的这个时钟驱动下,不断自增,CNT就是测周法用来计数计时的东西,经过预分配后这个位置的时钟频率,就是驱动CNT的标准频率fc。输入捕获的通道1的GPIO口,输入一个方波信号,经过滤波器与边沿检测选择TIFP1为上升沿触发,之后输入选择直连的通道,分频器选择不分频,当TIFP出现上升沿之后,CNT的当前计数值转运到CCR1里,同时触发源选择,选中TIFP为触发信号,从模式选择复位操作,这样TIFP1的上升沿,也会通过上面这一路,触发CNT清零。(注意事项:首先CNT的值是有上限的,最大为65535,如果信号频率太低,CNT计数值可能会溢出;另外这个从模式的触发源选择,只能选择通道1和通道2,通道3和通道4就只能开启捕获中断,在中断手动清零)
4.5 输入捕获配置
1.RCC开启时钟,把GPIO和TIM的时钟打开
2.GPIO初始化,把GPIO配置成输入模式(一般选择上拉或者浮空输入)
3.配置时基单元,让CNT计数器在内部时钟的驱动下自增运行
4.配置输入捕获单元
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel //选择配置定时器通道
TIM_ICInitStructure.TIM_ICFilter //输入滤波器参数,可以过滤信号抖动
TIM_ICInitStructure.TIM_ICPolarity //选择极性
TIM_ICInitStructure.TIM_ICPrescaler //捕获预分频
TIM_ICInitStructure.TIM_ICSelection //输入信号交叉
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure); //配置输入捕获通道,此函数同时会把另一个通道配置为相反的配置,实现PWMI模式
5.选择从模式的触发源
TIM_SelectInputTrigger //触发源选择
TIM_SelectSlaveMode //从模式选择
6.选择触发之后执行的操作
7.开启定时器
假如给的标准频率为1MHz,计数器最大只能记到65535,所以所测量的最低频率为1M/65535,大概为15Hz,在降低一些最低频率的限制可以把预分频在加大点,这样标准频率更低,所支持测量的最低频率也更低,这是测量频率的下限。最大频率看你对误差的要求,正负1误差可以认为是1/计数值,如果误差为千分之1,频率上线就是1M/1000=1kHz,如果想提高上限就把psc降低,频率更高就用测频法。
5.编码器接口
5.1 编码器接口简介
编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度
每个高级定时器和通用定时器都拥有1个编码器接口
两个输入引脚借用了输入捕获的通道1和通道2
5.2 正交编码器
正交信号的好处,正交信号的精度更高,因为A、B相都可以计次,相当于计次频率提高一倍。其次正交信号可以抗噪声,因为正交信号,两个信号必须交替跳变的,所以可以设计一个抗噪声电路,如果一个信号不变,另一个信号连续跳变,也就是产生噪声,那时计次值是不会变化的。
5.2 编码器接口基本结构
输入捕获的前两个通道,通过GPIO口接入编码器的A、B相,然后通过滤波器和边沿检测极性选择,产生TI1FP1和TI2FP2,通向编码器接口,编码器接口通过预分频器控制CNT计数器的时钟,同时,编码器接口还根据编码器的旋转方向,控制CNT的计数方向,编码器正转CNT自增,编码器反转CNT自减,另外ARR也是有效的,一般会设置ARR为65535最大量程,利用补码特性很容易得到负数。
5.3 编码器接口配置
1.RCC开启时钟,开启GPIO和定时器的时钟
2.配置GPIO
(上拉和下拉如何选择,我们一般可以看接到这个引脚的外部模块输出的默认电平,和外部模块保持默认状态一致,防止默认电平打架;如果不确定外部模块输出的默认状态,或者外部信号的输出功率非常小,这是就尽量选择浮空输入,浮空输入没有上拉或者下拉电阻影响信号,但缺点就是引脚悬空时,没默认的电平,输入就会受噪声干扰,来回不断跳变)
3.配置时基单元
4.配置输入捕获单元
5.配置编码器接口模式
TIM_EncoderInterfaceConfig //配置编码器模式以及两个输入通道是否反相,此函数必须在输入捕获初始化之后进行,否则输入捕获的配置会覆盖此函数的部分配置
6.启动定时器
部分TIM函数:
TIM_ETRConfig //单独配置ETR引脚的预分频器、极性、滤波器参数
TIM_PrescalerConfig //用来单独写预分频值
TIM_CounterModeConfig // 用来改变计数器的计数模式 TIM_ARRPreloadConfig //自动重装器预装功能配置 TIM_SetCounter //给计数器写入一个值
TIM_SetAutoreload //给自动重装器写入一个值 TIM_GetCounter //获取当前计数器的值
TIM_GetPrescaler //获取当前预分频器的值
TIM_GetFlagStatus //获取指定标志位
TIM_ClearFlag //清楚指定标志位
TIM_GetITStatus //获取中断标志位
TIM_ClearITPendingBit //清除中断标志位
TIM_SetCompare //用来单独更改CCR寄存器的值
TIM_PrescalerConfig //用来单独修改PSC预分频器的值
如果有错误的地方或者需要改进的地方,可以在评论区留言。