一文带你了解Stm32定时器常用知识

2 篇文章 0 订阅
1 篇文章 0 订阅

Stm32定时器

本文讲解了在Stm32常用的定时器相关知识,并带有部分示例代码。若有错误,欢迎指出

类型编号总线功能
高级定时器TIM1、TIM8APB2拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能
通用定时器TIM2、TIM3、TIM4、TIM5APB1拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能
基本定时器TIM6、TIM7APB1拥有定时中断、主模式触发DAC的功能

一些概念解释

死区生成

通常大功率电机、变频器等,末端都是由大功率管、IGBT等元件组成的H桥或3相桥。每个桥的上半桥和下半桥是绝对不能同时导通的,但高速的PWM驱动信号在达到功率元件的控制端时,往往会由于各种各样的原因产生延迟的效果,造成某个半桥元件在应该关断时没有关断,造成功率元件烧毁。

PWM输出时的Dead Zone(死区)作用是在电平翻转时插入一个时间间隔,避免关闭前一个设备和打开后一个设备时因为开关速度的问题出现同时开启状态而增加负荷的情况(在没有彻底关闭前打开了后一个设备),尤其是电流过大时容易造成短路等损坏设备

刹车输入

STM32的安全措施,TIMx_BRK引脚或者来自CSS(时钟安全系统)控制pwm输出。

定时器的时钟频率

定时器的时钟频率默认都是72MHz。虽然有部分时钟挂接在APB1总线上(APB1总线经过分频只有系统时钟的一半,36MHz),但是从系统时钟树可以得知,挂接APB1的时钟又经过一次倍频,变回了72MHz。

在这里插入图片描述

高级控制定时器框图

在这里插入图片描述

一些介绍

通道

TIMx_CH1,TIMx_CH2,TIMx_CH3,TIMx_CHy就是通道引脚,通道引脚在输入捕获模式下用作输入,在输出比较模式下用作输出,但同时只能用作一种模式。

重要的寄存器

寄存器
自动重装器ARR
预分频器PSC
重复计数器RCR仅高级定时器有
计数器CNT
捕获/比较寄存器CCRxx=1,2,3,4(因为有四个通道)

定时器模式

输出比较

输出比较模式就是用计数器寄存器的值和比较寄存器进行比较,然后按照模式让对应通道引脚输出高/低电平。

输出比较的八种模式
模式TIM_OCMode描述
冻结TimingCNT=CCR时,REF保持为原状态
匹配时置有效电平ActiveCNT=CCR时,REF置有效电平
匹配时置无效电平InactiveCNT=CCR时,REF置无效电平
匹配时电平翻转ToggleCNT=CCR时,REF电平翻转
强制为无效电平ForcedAction_ActiveCNT与CCR无效,REF强制为无效电平
强制为有效电平ForcedAction_InActiveCNT与CCR无效,REF强制为有效电平
PWM模式1PWM1向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平
向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平
PWM模式2PWM2向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平
向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平

输入捕获

输入捕获模式当输入通道有电平跳变的时候,将计数器寄存器的值保存到对应通道的捕获寄存器

注意

高级定时器(TIM1、TIM8等)中,如果要使用输出比较模式输出PWM的话,需要额外配置

  • 使能主输出,配置 TIMx_BDTR 寄存器的 MOE 位
    • MOE: 主输出使能 (Main output enable) 一旦刹车输入有效,该位被硬件异步清’0’。根据AOE位的设置值,该位可以由软件清’0’或被自 动置1。它仅对配置为输出的通道有效。
      • 0:禁止OC和OCN输出或强制为空闲状态
      • 1:如果设置了相应的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),则开启OC和OCN输出。
  • 配置 TIM_OCInitTypeDef.TIM_OCIdleState 成员值
    • TIM_OCInitTypeDef.TIM_OCIdleState:指定空闲状态期间TIM输出比较引脚状态。
    • 本质是配置 TIMx_CR2 寄存器的 OISx(x=通道号)
      • OISx:输出空闲状态x(OCx输出) (Output Idle state x)
        • 0 (TIM_OCIdleState_Reset):当MOE=0时,如果实现了OC1N,则死区后OC1=0
        • 1 (TIM_OCIdleState_Set):当MOE=0时,如果实现了OC1N,则死区后OC1=1
//...配置结构体其他成员
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;

TIM_OC1Init(TIM1, &TIM_OCInitStructure);

TIM_CtrlPWMOutputs(TIM1,ENABLE);

使用实例

基础定时中断功能

void Timer_Init(void)
{
    //使能TIM2的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
    //选择使用内部时钟,可省略,因为默认就是使用内部时钟
	TIM_InternalClockConfig(TIM2);
	
    /* 
    	定时器基础配置
    	计数器溢出频率计算: CK_CNT_OV = CK_PSC / (PSC + 1) / (ARR + 1)
    	下面的配置是 1s 溢出进入中断一次
	*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;			//滤波器工作频率分配系数
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;		//计数器模式:向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;				   //ARR自动重装器
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;				   //PSC预分频器
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;			   //重复计算器,高级定时器才有
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
    //清除一次中断标志位,避免启动定时器后直接进中断
    //原因:在TIM_TimeBaseInit中,当配置完之后会置更新事件标志位,在定时器启动之后就直接进入中断了
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
    
    //配置中断:使能更新中断
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    
	//设置优先级配置分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
    //初始化 TIM2 中断通道
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
    //启动定时器
	TIM_Cmd(TIM2, ENABLE);
}

//TIM2 中断函数
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

外部引脚触发计数器

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
    //配置PA0,因为PA0复用为TIM2_CH1_ETR
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//手册建议配置为浮空输入,但上拉输入也可以
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
    /* 
    配置使用外部时钟模式2,通过ETR引脚输入时钟信号
    TIM_ETRClockMode2Config 函数介绍
    	TIM_TypeDef* TIMx :配置的定时器
		uint16_t TIM_ExtTRGPrescaler:外部触发预分配器,TIM_ExtTRGPSC_OFF 为不分频
		uint16_t TIM_ExtTRGPolarity: 外部触发的极性,TIM_ExtTRGPolarity_NonInverted 高电平或上升沿有效
		uint16_t ExtTRGFilter:外部触发滤波器,0x0F为采样频率fSAMPLING=fDTS/32,N=8
	*/
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
	
    //其他内容和 基础定时中断功能 大差不差
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

输出PWM波

void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
    //使用内部时钟
	TIM_InternalClockConfig(TIM2);
	
    //定时器基础配置,频率是 1K hz
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
    //定时器输出通道1配置
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);	//因为是局部变量,内存数据不确定,因此要给结构体赋初始值
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//输出模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		 //输出极性:有效电平为高电平
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	 //输出使能
	TIM_OCInitStructure.TIM_Pulse = 30;		//CCR,在PWM模式中决定输出的占空比
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
/*
	TIM_OC2Init(TIM2, &TIM_OCInitStructure);	//可以配置通道2输出
	实际上因为四个通道共用一个计数器,因此四个通道输出pwm波的频率一致,但是CCR寄存器不一样可以输出不同占空比的pwm
*/
	
	TIM_Cmd(TIM2, ENABLE);
}

//设置占空比
void PWM_SetCompare(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);		//更改通道1的CCR寄存器
}

输入捕获

void IC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

输入捕获之PWMI(测量PWM的频率与占空比)

void IC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
    //定时器基础配置,72分频,每过1us计数器加一,自动重装载的值要尽可能大。
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
    //配置输入捕获
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;		//通道1
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3, ENABLE);
}

//获取频率
uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

//获取占空比
uint32_t IC_GetDuty(void)
{
	return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F103是意法半导体(STMicroelectronics)推出的一款32位单片机系列,属于Cortex-M3内核。下面是一份简要的说明,帮助你了解STM32F103。 1. 内核架构:STM32F103采用ARM Cortex-M3内核,具有较高的性能和低功耗特性。它运行在最高72MHz频率下。 2. 存储器:STM32F103具有不同的存储器选项,包括闪存(Flash)和随机存取存储器(SRAM)。闪存用于存储程序代码和常量数据,SRAM用于存储变量和堆栈。 3. 外设:STM32F103拥有丰富的外设,包括通用定时器、串行通信接口(USART、SPI、I2C)、模数转换器(ADC)、通用输入输出引脚(GPIO)等。这些外设可用于实现各种应用,如控制、通信和传感器接口。 4. 开发环境:对于STM32F103的开发,你可以使用ST提供的官方开发工具——STM32CubeIDE,它是基于Eclipse的集成开发环境。此外,你还可以使用其他第三方软件,如Keil MDK或IAR Embedded Workbench。 5. 编程语言:你可以使用C/C++编程语言进行STM32F103的开发。ST提供了丰富的库函数和示例代码,方便开发者快速上手。 6. 资源:为了更好地了解STM32F103,你可以参考ST官方的技术文档、数据手册和应用笔记。此外,CSDN等网站上也有很多关于STM32F103的教程和案例供你学习参考。 需要注意的是,上述信息只是对STM32F103的一个简要介绍,如果你希望深入了解它的特性和开发方法,建议你查阅更多资料并进行实际的开发练习。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值