STM32定时器

一、STM32定时/计数器概述

        定时器可以对输入的脉冲进行计数,并在计数值达到设定值时触发中断,同时也可以进行计时
        时基单元:16位预分频器PSC、16位计数器CNT、16位自动重装载寄存器ARR,在72MHz计数时钟下可以实现最大59.65s的定时

1.1 定时器类型

主要功能高级定时器通用定时器基本定时器
更新中断和DMA(直接存储器访问)
计数方向向下、向上、双向向下、向上、双向向上
内外时钟源选择
其他定时器触发或级联
输入捕获、输出比较
单脉冲输出方式
正交编码器输入
霍尔传感器输入
输出比较信号死区生产
制动信号输入
        STM32芯片最多包含8个定时/计数器,其中 STM32F103C8T6定时器资源:TIM1、 TIM2 TIM3 TIM4
         基本定时器 :集成了1个16位自动加载递增计数器、1个16位预分频器、1个16位自动重装载寄存器。可以作为定时器提供时间基准,特别的, 为DAC提供时钟,在芯片内部直接连接到DAC并通过触发输出直接驱动DAC
         通用定时器 :集成了1个16位自动加载递增/递减计数器、1个16位预分频器、1个16位自动重装载寄存器 和4个独立通道。每个通道都可以用于输入捕获(测量输入信号的脉冲长度)、输出比较(PWM输出)和单脉冲输出
        高级定时器 :集成了1个16位自动加载递增/递减计数器、1个16位预分频器、1个16位自动重装载寄存器和4个独立通道。通道的功能与通用定时器相同。高级定时器可以看作分配到6个通道的三相PWM发生器,它具有 带死区插入的PWM输出 ,还可以作为通用定时器使用
         上述三类定时器均可使用内部时钟源8MHz,均可以产生中断和DMA(直接寄存器访问)请求。除了基本定时器只有向上计数方式,其他两类均有向上、向下和双向3种计数方式
        此外,STM2还具有 2个看门狗定时器和1个 系统滴答定时器(24位递减计数器)

1.2 计数模式

(1)向上计数模式:
        计数器从0计数到自动加载值(TIMx_ARR),然后从0开始并产生一个上溢事件。每次计数溢出时,可产生一个更新事件,所有寄存器都被更新同时置更新标志位
(2)向下计数模式:
        计数器从自动加载值(TIMx_ARR)向下计数到0,然后从ARR开始并产生一个 下溢事件。每次计数溢出时,可产生一个更新事件,所有寄存器都被更新同时置更新标志位
(3)中央对齐模式:
        在中央对齐模式,计数器从0 开始计数到 自动加载的值(TIMx_ARR寄存器)  − 1 ,产生一个计数器上溢事件,然后向下计数到1 并且产生一个计数器下溢事件;然后再从 0 开始重新计数。

1.3 时钟源

1.3.1 内部时钟(CK_INT)

        当使用 内部时钟时,计数器对内部脉冲时钟进行计数,属于 定时功能

1.3.2 外部时钟模式1(外部输入引脚TIx)

        计数器对输入通道的 TI1F_ED(上升沿、下降沿均有效)或这 TI1FP1、TI2FP2的每个上升沿下降沿进行计数,属于 计数功能

1.3.3 外部时钟模式2(外部触发输入ETR,External Trigger Input)

        计数器对外部触发引脚 (TIMx_ETR)进行计数,属于 计数功能

1.3.4 内部触发输入(ITR,Internal Trigger Input)

        使用一个定时器作为另一个定时器的预分频器

二、STM32定时器的结构(以通用定时器为例)

        
        通用定时器主要包括1个外部触发引脚(TIMx_ETR,External Trigger Input),4个输入/输出通道(TIMx_CHx),1个内部时钟,1个触发控制器,一个时钟单元(预分频器PSC、自动重装载寄存器ARR和计数器CNT)

(1)定时/计数中断

        预分频器对时钟信号进行分频,之后CNT计数器可以对分频后的时钟信号进行计数,当达到自动重装载寄存器ARR的值(向上计数)后,产生一个更新事件
实际分频系数=预分频器的值+1
计数频率:CK_CNT = CK_PSC / (PSC + 1)
溢出频率:CNT_OV = CK_PSC / (PSC + 1) / ARR
        值得注意的是, 预分频器PSC、自动重装载寄存器ARR和4个捕获/比较寄存器都有一个在物理上与其对应的寄存器,称为 影子寄存器(阴影部分)。
预装载寄存器可以用程序读写,但影子寄存器无法被读写,在实际中 真正起作用的是影子寄存器。根据TIMx_CR1寄存器中自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容被立即或每次产生更新事件时传入影子寄存器

(2)输出比较(Output Compare,OC)

        输出比较可以通过 比较CNT与CCR (捕获/比较) 寄存器值的关系,来对 输出电平进行置1、置0或翻转  的操作,用于输出一定频率和占空比的PWM 波形
①PWM频率与定时器的溢出频率相同
Freq = 时钟源频率 / 预分频系数 / 自动给重装载寄存器的值
(时钟源频率 / 预分频系数 = 计数的频率;计数的频率 / 目标值 = 溢出频率
②占空比:Duty = CCR/(ARR + 1)
③分辨率:占空比的变化步距 
        输出比较:CNT寄存器与CCR寄存器进行比较,当达到某个条件后,按照输出模式进行输出 OC1REF(reference,输出参考信号),可以输出至主模式控制器,还可以通过输出极性配置进行输出
输出比较模式:

(3)输入捕获模式(Input Capture

频率测量:
①测频法:在既定的时间T内,测量上升沿或下降沿的次数N,每来一个边沿信号则认为是一个周期( 适用高频信号
Freq = N / T
②测周法:在两个相同且相邻的边沿信号内以标准频率f进行计次N( 适用低频信号
Freq = f / N
③中界频率:由于上述两种频率都会产生±1的误差,当N的值越大,其误差的影响就越小。当N相同时,则可得到中界频率(小于此频率,选用测周法比较合适;大于此频率,选用测频法比较合适)

※主从触发模式

主模式: 可以将定时器中的内部信号,输出至TRGO引脚,用于触发其他外设
从模式: 接收其他外设或自身的一些信号,用于控制自身定时器的运行
触发源:选择从模式的触发信号源
输入捕获的结构框图:
输入捕获测量波形频率的基本思想:
        频率:当遇到输入波形的上升沿时,将 CNT中的值锁存到CCR1中,并 利用从模式实现CNT自动清0,当遇到下一个上升沿时,依然进行锁存,清零。此时已为一个波形的周期。CCR中存放一个完整周期的计数值。因此:标准频率 / (CCR+1)即为输入波形频率(由于CNT是从0开始计数,所以各个CCR的值都需要加1)
PWMI的结构框图:
测量PWM波形的频率和占空比的基本思想:
        占空比:当遇到输入波形的上升沿时,将CNT中的值锁存到CCR1中,并利用从模式实现CNT自动清0,当遇到下降沿时,通过通道2,将CNT中的值锁存到CCR2中.当遇到下一个上升沿时,依然进行锁存,清零。此时已为一个波形的周期。CCR2中存放高电平时,计数的个数;CCR1存放一个周期内,计数的个数。当然,整个计数的频率都是相同的,因此:CCR2/CCR1即为占空比,由于CCR1<CCR2,若想使其显示百分比的形式,需要给CCR2✖100,即可(由于CNT是从0开始计数,所以CCR的值都需要加1)
        频率:在一个完整的周期内,在标准频率下,CNT计数值锁存在CCR1中。因此:
标准频率 / (CCR1 + 1)即为波形频率(由于CNT是从0开始计数,所以各个CCR的值都需要加1)

(4)编码器接口(Encoder Interface)

正交信号:一个信号相对于另一路信号超前或滞后90°
                当电机转的越快,其输出的方波频率就越高。简而言之, 方波频率代表了速度
优点:①精度高,A、B相均可以计次,频率相当于提高了一倍
           ② 抗噪声,正交信号是交替跳变的,当一个信号因噪声干扰跳变,另一个信号不                      变, 使得计次值不会增加
工作流程:
        编码器的正交信号,分别通过通道1和通道2输入,之后通过编码器接口,控制计数器的计数时钟和计数方向
        在输入通道中会遇到极性选择,而 编码器的上升沿和下降沿均有效(CNT均计次)。此时, 极性选择表示高低电平的选择上升沿:高、低电平均不反转;下降沿:高、低电平均反转
        编码器接口模式基本上相当于使用了一个 带有方向选择的外部时钟(接管定时器) 。这意味着计数器只在0 到 TIMx_ARR寄存器的自动装载值之间连续计数 ( 根据方向,或是 0 ARR 计数,或是 ARR 0 计数)
(5)单脉冲模式
        计数器响应一个激励,并在一个程序可控的延时之后,产生一个脉宽可程序控制的脉冲。
        计数器 可以通过软件启动,也可以通过从模式触发 计数器启动后,在下一个更新事件来临之前的时间段内实现固定个数的脉冲输出。当下一个更新事件来临时计数器停止计数。输出的脉冲个数可以一个或几个。如果是 通用计数器就是1个,如果是 高级定时器脉冲个数与RCR数值和计数模式有关。

三、定时器相关库函数

3.1 时基单元初始化:TIM_TimeBaseInit()

所谓时钟分频因子,就是数字滤波器的采样频率与定时器时钟之间的关系

3.2 输出比较初始化:TIM_OCInit()

高电平:极性不反转,低电平:极性反转

3.3 输入捕获初始化:TIM_ICInit()

3.4 定时器使能:TIM_Cmd()

3.5 定时器中断配置函数:TIM_ITConfig()

3.6 选择触发源TIM_SelectInputTrigger()

3.7 选择从模式TIM_SlectSlaveMode()

3.8 编码器接口配置:TIM_EncoderInterfaceConfig()

四、定时器配置流程

4.1 定时器中断配置

(1)开启定时器时钟
(2)选择定时器的时钟源
	TIM_InternalClockConfig(TIM2);  //使用内部时钟
(3)配置时钟单元,完成初始化(清除标志位)
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  //滤波器的采样频率是由内部时钟信号提供的,可以分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;   //向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 10000-1;   //自动重装载寄存器的值
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7200-1;  //预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;  //重复次数寄存器的值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);    //TIM_TimeBaseInit()会产生一个更新
(4)配置定时器中断控制
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  //中断配置:更新中断
(5)配置NVIC优先级分组
(6)配置NVIC,完成初始化
(7)使能定时器

4.2 定时器输出比较配置

(1)开启定时器时钟,GPIO(使用对应通道的引脚)
如果选择重映射的方式,先要使能AFIO时钟,并进行重映射配置
如果重映射的方式,还需要将调式的功能关闭
(2)进行GPIO配置,完成初始化(配置为复用推挽输出)
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
(3)选择定时器的时钟源
	TIM_InternalClockConfig(TIM2);  //使用内部时钟
(4)配置时钟单元,完成初始化
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  //滤波器的采样频率是由内部时钟信号提供的,可以分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;   //向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 100-1;   //自动重装载寄存器的值
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1;  //预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;  //重复次数寄存器的值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
(5)配置输出比较单元,完成初始化
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_OCStructInit(&TIM_OCInitStruct);
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;   //PWM1模式
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;   //极性不反转
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse = 0;  //CCR
	TIM_OC1Init(TIM2,&TIM_OCInitStruct);
(6)使能定时器

4.3 定时器输入捕获比较配置

(1)开启定时器时钟,GPIO(使用对应通道的引脚)
如果选择重映射的方式,先要使能AFIO时钟,并进行重映射配置
如果重映射的方式,还需要将调式的功能关闭
(2)进行GPIO配置,完成初始化(配置为浮空输入)
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
(3)选择定时器的时钟源
	TIM_InternalClockConfig(TIM3);  //使用内部时钟
(4)配置时钟单元,完成初始化
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  //滤波器的采样频率是由定时器提供的
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;   //向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 65535-1;   //自动重装载寄存器的值
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1;  //预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;  //重复次数寄存器的值,高级定时的功能
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
(5)配置输入捕获单元,完成初始化
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;  //通道1
	TIM_ICInitStruct.TIM_ICFilter = 0xF;   //数字滤波器
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;  //上升沿
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;   //分频系数为1
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;  //直接通道
	TIM_ICInit(TIM3,&TIM_ICInitStruct);
(6)选择从模式的触发源,并选择从模式
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);  //选择TIM通道1的TI1FP信号作为触发源
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);  //选择从模式:复位,自动实现CNT清零
(6)使能定时器

4.4 定时器编码器接口配置

(1)开启定时器时钟,GPIO(使用对应通道的引脚)
如果选择重映射的方式,先要使能AFIO时钟,并进行重映射配置
如果重映射的方式,还需要将调式的功能关闭
(2)进行GPIO配置,完成初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  //上拉输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
(3)配置时钟单元,完成初始化
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  //滤波器的采样频率是由内部时钟信号提供的,可以分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;   //计数方式也被编码器托管
	TIM_TimeBaseInitStruct.TIM_Period = 65535-1;   //自动重装载寄存器的值
	TIM_TimeBaseInitStruct.TIM_Prescaler = 1-1;  //预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;  //重复次数寄存器的值
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
(4)配置输出比较单元,完成初始化
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM_ICStructInit(&TIM_ICInitStruct);   //结构体成员默认值
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1 | TIM_Channel_2;
	TIM_ICInitStruct.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3,&TIM_ICInitStruct);
(5)配置编码器接口
	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);  //上升沿:高低电平不反转
(6)使能定时器
  • 31
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32定时器STM32微控制器中的一个非常重要的模块,它可以用来生成精确的时钟信号,并且可以实现很多不同的功能。 STM32定时器主要分为两种类型:基本定时器和通用定时器。基本定时器只有一个计数器,而通用定时器则有多个计数器,并且支持更多的功能。具体可以根据实际需要选择使用哪种类型的定时器。 在STM32中使用定时器可以通过以下步骤完成: 1. 配置定时器的时钟源和分频系数; 2. 设置定时器计数器的初始值和自动重载值; 3. 开启定时器中断(可选); 4. 启动定时器。 例如,以下是使用STM32的基本定时器TIM6进行定时中断的代码: ```c #include "stm32f10x.h" void TIM6_IRQHandler(void) { // 定时器中断处理函数 } int main(void) { // 使能TIM6的时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // 配置TIM6的时钟源为内部时钟,分频系数为72 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStruct); // 开启TIM6的更新中断 TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); // 启动TIM6 TIM_Cmd(TIM6, ENABLE); while (1) { // 程序主循环 } } ``` 在上面的代码中,我们使用了STM32的库函数来配置和控制定时器,首先通过RCC_APB1PeriphClockCmd函数使能了TIM6的时钟,然后使用了TIM_TimeBaseInit函数来配置了定时器的时钟源、分频系数、计数器自动重载值等参数,然后开启了定时器的更新中断,并且最后启动了定时器。在定时器中断处理函数中可以编写需要定时执行的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值