STM32-定时器的基本定时/计数功能实现配置教程(寄存器版)
本章概述思维导图:
STM32-定时器
STM32定时器是一种功能强大的外设模块,通过时基单元(包含预分频器、计数器和自动重载寄存器)实现精准定时和计数功能,广泛应用于PWM控制、信号测量、定时任务调度等场景。
STM32F103系列提供8个定时器:
2个基本定时器:TIM6、TIM7;
4个通用定时器:TIM2、TIM3、TIM4、TIM5;
2个高级定时器:TIM1、TIM8;
STM32定时器工作原理:(1)时钟源、(2)时基单元、(3)计数模式;
(1)时钟源:
内部时钟(CK_INT):由APB总线时钟经倍频后得到,是定时器的主要时钟源。
外部时钟:通过外部输入脚(TIx)或外部触发输入(ETR)提供时钟信号。
内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器。
(2)时基单元:
计数器寄存器(TIMx_CNT):核心计数单元,存储当前的计数值。
预分频器(TIMx_PSC):对输入时钟进行分频,分频系数为1~65536。
自动重装载寄存器(TIMx_ARR):决定计数周期,当计数器达到该值时产生更新事件。
(3)计数模式:
向上计数模式:从0计数到ARR值,然后重新从0开始计数。
向下计数模式:从ARR值向下计数到0,然后重新从ARR开始计数。
中央对齐模式:先向上计数到ARR值,再向下计数到0,常用于PWM输出中实现更精确的脉冲宽度控制。
基本定时器介绍
基本定时器TIM6和TIM7个包含一个16位自动装载计数器,由各自的可编程预分频器驱动。
它们可以作为通用定时器提供时间基准,特别地可以为数模转换器(DAC)提供时钟。实际上它们在芯片内部直接连接到DAC并通过触发输出直接驱动DAC。
这两个定时器是相互独立得,不共享任何资源
TIM6和TIM7基本定时器的主要功能:
1. 16位自动重装载累加计数器
2. 16位可编程(可实时修改)预分频器,用于对输入的时钟系数为1~65536之间的任意数值分频
3. 触发DAC的同步电路
4. 在更新事件(计数器溢出)时产生中断/DMA请求
通用定时器介绍
TIM2、TIM3、TIM4、TIM5通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。
它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较PWM)。
使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒见调整。
每个定时器都是完全独立的,没有互相共享任何资源。它们可以一起同步操作。
TIM2、TIM3、TIM4、TIM5通用定时器的功能包括(拥有基本定时器所有功能):
1.16位向上、向下、向上/向下自动装载计数器。
2. 16位可编程(可实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值.
3. 4个独立通道:(1)输入捕获;(2)输出比较;(3)PWM生成;(4)单脉冲模式输出
4.多种时钟源。
5.支持针对定位的增量(正交)编码器和霍尔传感器电路。
高级定时器介绍
高级控制定时器(TIM1和TIM8)由一个16位的自动装载计数器组成,它由一个可编程的预分频器驱动。
它适合多种用途,包含测量输入信号的脉冲宽度(输入捕获),或者产生输出波形(输出比较、PWM、嵌入死区时间的互补PWM等)。
使用定时器预分频器和RCC时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒到几个毫秒的调节。
高级控制定时器(TIM1和TIM8)和通用定时器(TIMX)是完全独立的,它们不共享任何资源。它们可以同步操作。
TIM1和TIM8高级定时器的功能包括(拥有通用定时器所有功能):
1.死区时间可编程的互补输出
2. 断路输入信号(刹车输入信号)
3.重复计数器
总结:
STM32的定时器分为基本定时器(TIM6和TIM7)、通用定时器(TIM2、TIM3、TIM4、TIM5)、高级定时器(TIM1和TIM8),功能逐级递增;
基本定时器:仅提供基础定时中断功能,适用于简单的定时任务。
通用定时器:支持输入捕获、输出比较及编码器接口,适用于测量输入信号的脉冲长度或产生输出波形。
高级定时器:支持PWM生成、死区控制、刹车保护等复杂功能,适用于电机控制等场景。
实现定时器计数功能配置
配置计数器功能要用到的相关寄存器
计数器:TIM_CNT
分频器:TIM_PSC(要查看时钟树,知道默认时钟工作频率是多少。查看当前配置定时器需要多少时钟工作频率进行设置)
重装载值寄存器:TIM_ARR
控制寄存器:TIM_CR1 ;TIM_CR2;
状态寄存器:TIM_SR
中断寄存器:TIM_DIER
配置定时器2实现计数功能配置步骤:
1.开时钟
2.开启复位时钟然后关闭
3.配置计数器寄存器清0操作
4.配置预分频寄存器->计数器的时钟频率CK_CNT等于fck_psc/(PSC[ 1 5 : 0 ] +1 );最大填写不能超过65535;内部减一(psc-1)可以填写65536
5.配置自动重装载寄存器
6.配置CR1控制寄存器ARPE:自动重装载预装载允许位
7.配置CR1控制寄存器CEN:使能计数器
8.配置中断使能寄存器(TIMx_DIER)UIE:允许更新中断
9.调用中断优先级函数
代码示例:
#include "TIM.h"
#include "SYS.h"
/*配置通用定时器2实现计数功能形参:PSC->预分频系数arr->重装载值(计数周期)
*/
void TIM2_Init(u16 psc,u16 arr)
{
// 1.开时钟RCC->APB1ENR|=1<<0;//开启TIM2时钟
// 2.开启复位时钟然后关闭RCC->APB1RSTR|=1<<0;//开启TIM2复位RCC->APB1RSTR&=~(1<<0);//关闭复位
// 3.配置计数器寄存器清0操作TIM2->CNT=0;
// 4.配置预分频寄存器->计数器的时钟频率CK_CNT等于fck_psc/(PSC[ 1 5 : 0 ] +1 );最大填写不能超过65535;内部减一(psc-1)可以填写65536TIM2->PSC=(psc-1);
// 5.配置自动重装载寄存器TIM2->ARR=arr;
// 6.配置CR1控制寄存器ARPE:自动重装载预装载允许位TIM2->CR1|=1<<7;
// 7.配置CR1控制寄存器CEN:使能计数器TIM2->CR1|=1<<0;
// 8.配置中断使能寄存器(TIMx_DIER)UIE:允许更新中断TIM2->DIER|=1<<0;
// 9.调用中断优先级函数STM32_SetNVICPriority(TIM2_IRQn,1,1);
}
形参写入讲解:
例如:TIM2_Init( 72, 1000);
此时定时器的工作频率为72MHZ;
72MHZ/72=1MHZ,芯片TIMXCLK时钟/分频系数PSC=1MHZ;
转换时间为:1/1MHZ=1us;1us*周期时间=1us*1000=1ms;
算出定时时间为1ms;
例如:TIM2_Init( 65536, 65536);定时器最长定时时间
此时定时器2的工作频率为72MHZ;
72MHZ/65536=72000KHZ/65536=1.0987328125KHZ;
芯片TIMXCLK时钟/分频系数PSC=1.0987328125KHZ;
转换时间为:1/1.0987328125KHZ=0.9102222222222ms;
判断定时器定时时间操作
判断定时器状态寄存器中UIF位更新中断标记(当产生更新事件时该位由硬件置’1’。它由软件清’0’。):注意这是在主函数中判断,要注释实现定时器计数功能配置里步骤8和步骤9。
代码示例:
#include "LED.h"
#include "USART1.h"
#include "stdio.h"
#include "TIM.h"
int main()
{LED_Init();//LED灯初始化函数USART1_Init(115200);//USART1串口1初始化函数TIM2_Init(7200,50000);//定时器2设置定时时间为5000毫秒=5秒u8 flag=0;while(1){if(TIM2->SR&1<<0){printf("定时器2计数时间到,循环定时时间为5秒\n");LED1(!flag);TIM2->SR&=~(1<<0);}}
}
代码运行结果:
配置定时器2中断服务函数
配置步骤:
1.在stm32f10x_md.s文件夹中找定时器2中断服务函数
2.在中断服务函数中判断定时器状态寄存器中UIF位更新中断标记
代码示例:
/*定时器2中断服务函数
*/
void TIM2_IRQHandler(void)
{if(TIM2->SR&1<<0){printf("定时器2计数时间到,循环定时时间为5秒\n");TIM2->SR&=~(1<<0);}
}
主函数代码示例:
#include "LED.h"
#include "USART1.h"
#include "stdio.h"
#include "TIM.h"
int main()
{LED_Init();//LED灯初始化函数USART1_Init(115200);//USART1串口1初始化函数TIM2_Init(7200,50000);//定时器2设置定时时间为5000毫秒=5秒while(1){}
}
代码运行结果: