stm32高级TIM的常用功能

介绍 STM32 高级定时器的刹车死区、互补输出、输入捕获 的基本资料。

1. 刹车死区(Brake Dead Time)

高级定时器(如 TIM1TIM8 )支持 刹车死区(Brake Dead Time) 功能,通常用于电机控制和其他需要安全保护的应用。广泛用于车载测试以及工控检测.

  • 死区时间:死区时间是控制信号之间的延迟时间,用于避免两个互补输出信号同时切换而导致的短路。
  • 用途:在电机驱动系统中,死区时间可以防止两个互补信号(如正反向驱动信号)发生冲突,从而保护硬件。

2. 互补输出(Complementary Output)

高级定时器支持 互补输出 ,这是用于控制例如 H 桥电路电机驱动 的功能。互补输出提供两路反向的 PWM 信号,通常用于驱动逆变器或其他电力设备。

  • 工作原理 :两个输出信号(如 PWM1PWM2 )是互补的,当 PWM1 为高时,PWM2 为低,反之亦然。
  • 优点:互补输出可以有效驱动电机或逆变器系统,同时避免短路或损坏电路。

3. 输入捕获(Input Capture)

输入捕获用于 测量输入信号的时间特性 ,如频率、脉冲宽度等。它通常用于 PWM 信号的测量外部事件的计时

配置流程

  • 工作原理 :当输入信号(如外部触发引脚)发生变化时,定时器会捕获 计数器值 ,从而记录信号的时间。

    STM32 TIM 输入捕获原理

    输入捕获(Input Capture) 是 STM32 定时器的一个重要功能,用于测量外部信号的时间特性。它允许你捕获输入信号的 边沿 (上升沿或下降沿),并记录定时器的 计数值 。输入捕获常用于测量 脉冲宽度频率时间间隔

    基本原理

    输入捕获利用定时器的计数器来捕获外部信号发生变化的时间。捕获信号的触发通常发生在 输入引脚(如 TIMx_CH1、TIMx_CH2)电平变化(如从低电平到高电平,或从高电平到低电平)。

  • 计数器和输入信号

    • 当外部输入信号发生边沿变化时,定时器会记录下当前计数器的值。
    • 你可以通过获取两次捕获事件的计数器值来计算外部信号的时间特性,比如 脉冲宽度频率
  • 输入信号的类型

    • 上升沿触发:当输入信号从低电平变为高电平时,触发输入捕获。
    • 下降沿触发:当输入信号从高电平变为低电平时,触发输入捕获。
    • 双边沿触发:捕获信号的上升沿和下降沿,通常用于测量周期。
  • 定时器的工作模式

    • 在捕获模式下,定时器的计数器值将在外部信号的变化时存储到捕获寄存器中。
    • 可以通过读取捕获寄存器的值,得到信号的捕获时间。
  • 应用场景

    • 频率测量:通过捕获连续的两个上升沿(或下降沿),可以计算信号的周期,从而得到频率。
    • 脉冲宽度测量:通过计算捕获的两个信号的时间差,得到脉冲的宽度。
    • 时间间隔测量:计算两个信号之间的时间差,应用于事件计时或延迟分析。
  • 启用定时器和输入捕获功能

    • 配置定时器的 计数器预分频器计数模式
    • 配置 输入引脚 ,如 GPIO 模式设置为输入浮动。
    • 配置定时器的输入捕获通道,如 TIM1_CH1TIM2_CH2 等。
  • 配置输入捕获参数

    • 设置捕获的 触发边沿(上升沿、下降沿或双边沿)。
    • 设置捕获 分频器滤波器,以便根据需求过滤信号。
  • 读取捕获数据

    • 当信号发生变化时,定时器会将捕获的计数器值存储到捕获寄存器。
    • 可以通过 获取捕获寄存器值,来计算时间间隔或脉冲宽度。
  • 中断和回调函数

    • 可以使能 捕获中断,当捕获事件发生时触发中断,进入回调函数处理捕获的计数器值。
    • 通过 TIM
  • 应用场景

    • 频率测量:通过捕获输入信号的周期,可以计算信号的频率。
    • 脉冲宽度测量:通过测量高电平和低电平的持续时间,计算脉冲宽度。

代码示例

以下是一个使用 STM32 TIM1 高级定时器的示例,展示如何配置刹车死区和互补输出,并实现输入捕获功能。

1. TIM1 互补输出与死区时间配置
复制代码
#include "stm32f10x.h"

void TIM1_PWM_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

    // 启用 TIM1 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

    // 配置 PWM 引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置定时器基础设置
    TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;  // 设置预分频
    TIM_TimeBaseStructure.TIM_Period = 1000 - 1;  // 设置周期
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    // 配置 PWM 输出
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);

    // 配置刹车死区时间
    TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
    TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
    TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
    TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
    TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
    TIM_BDTRInitStructure.TIM_LockLevel = TIM_LockLevel_OFF;
    TIM_BDTRInitStructure.TIM_DeadTime = 10;  // 设置死区时间
    TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

    // 启动定时器
    TIM_Cmd(TIM1, ENABLE);
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
2. 输入捕获配置
复制代码
void TIM1_InputCapture_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;

    // 启用 TIM1 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

    // 配置输入引脚(例如 PA8)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置定时器输入捕获
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  // 上升沿捕获
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  // 不分频
    TIM_ICInitStructure.TIM_ICFilter = 0x00;
    TIM_ICInit(TIM1, &TIM_ICInitStructure);

    // 启动定时器
    TIM_Cmd(TIM1, ENABLE);
    TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);  // 启用中断
}

总结

  • 刹车死区:用于保护电机驱动系统,防止互补输出信号同时高电平导致短路。
  • 互补输出:主要用于驱动 H 桥电路或电机控制系统,输出互补的 PWM 信号。
  • 输入捕获:用于测量输入信号的时间特性,如频率、脉冲宽度等。

项目:

1利用pwm输出互补波形,同时配置刹车死区功能,在TIM1_KBKIN引脚接低电平时,示波器显示pwm输出互补波形,在TIM1_BKIN引脚接高电平时抑制pwm输出,示波器不输出波形

操作:

1配置pwm原波形输出引脚GPIO以及pwm互补波形输出引脚以及刹车死区引脚(采用推挽输出)

2配置TIM基本结构体

3配置pwm互补输出以及原输出通道,初始化,调用预装载值使能输出函数

4配置刹车死区结构体并初始化

5使能TIM定时器

复制代码
#include "stm32f10x.h"                  // Device header
#include "pwmplus.h"
 TIM_ICUserValue   TIM_CaptureSturt;
void pwmplus_GPIO_Config()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef   pwmplus_GPIO_Initsturt;

	//TIM1的输出通道CH1的   PA8
	pwmplus_GPIO_Initsturt.GPIO_Mode = GPIO_Mode_AF_PP;
	pwmplus_GPIO_Initsturt.GPIO_Pin =GPIO_Pin_8;
	pwmplus_GPIO_Initsturt.GPIO_Speed=GPIO_Speed_50MHz; 
	GPIO_Init(GPIOA, &pwmplus_GPIO_Initsturt);
	
	//输出互补通道TIM1-CH1N   PB13
	
	pwmplus_GPIO_Initsturt.GPIO_Mode = GPIO_Mode_AF_PP;
	pwmplus_GPIO_Initsturt.GPIO_Pin =GPIO_Pin_13;
	pwmplus_GPIO_Initsturt.GPIO_Speed=GPIO_Speed_50MHz; 
	GPIO_Init(GPIOB, &pwmplus_GPIO_Initsturt);
	
	//配置刹车通道 TIM1-BKIN   PB12
	pwmplus_GPIO_Initsturt.GPIO_Mode = GPIO_Mode_AF_PP;
	pwmplus_GPIO_Initsturt.GPIO_Pin =GPIO_Pin_12;
	pwmplus_GPIO_Initsturt.GPIO_Speed=GPIO_Speed_50MHz; 
	GPIO_Init(GPIOB, &pwmplus_GPIO_Initsturt);
	
	 GPIO_ResetBits(GPIOB,GPIO_Pin_12);
	
}

void pwmplus_Config()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	//配置TIM1的基本结构体
	TIM_TimeBaseInitTypeDef  TIM1_Initsturt;
	TIM1_Initsturt.TIM_ClockDivision =TIM_CKD_DIV1;
	TIM1_Initsturt.TIM_CounterMode =TIM_CounterMode_Up;
	TIM1_Initsturt.TIM_Period =7;
	TIM1_Initsturt.TIM_Prescaler =8;
	TIM1_Initsturt.TIM_RepetitionCounter =0;
	TIM_TimeBaseInit(TIM1, &TIM1_Initsturt);
	
	
	//输出比较通道TIM1-CH1及其互补
     TIM_OCInitTypeDef   pwmplus_OCInitsturt;
	   pwmplus_OCInitsturt.TIM_OCMode =TIM_OCMode_PWM1 ;
	 pwmplus_OCInitsturt.TIM_OutputState = TIM_OutputState_Enable;
	 pwmplus_OCInitsturt.TIM_OutputNState = TIM_OutputNState_Enable;
	pwmplus_OCInitsturt.TIM_Pulse =4;
	pwmplus_OCInitsturt.TIM_OCIdleState = TIM_OCIdleState_Set   ;
	pwmplus_OCInitsturt.TIM_OCNIdleState =  TIM_OCNIdleState_Reset ;  
	pwmplus_OCInitsturt.TIM_OCNPolarity = TIM_OCNPolarity_High ;
	pwmplus_OCInitsturt.TIM_OCPolarity = TIM_OCPolarity_High ;
	TIM_OC1Init(TIM1,&pwmplus_OCInitsturt);
   TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //预装载值输出使能
	
	//初始化刹车和死区的结构体
	TIM_BDTRInitTypeDef  pwm_BTR_Initsturt;
	pwm_BTR_Initsturt.TIM_AutomaticOutput =TIM_AutomaticOutput_Enable ;
	pwm_BTR_Initsturt.TIM_Break =TIM_Break_Enable ; //当BINK引脚检测到高电平时,输出信号被禁止,好像刹车一样
	pwm_BTR_Initsturt.TIM_BreakPolarity =TIM_BreakPolarity_High;
	pwm_BTR_Initsturt.TIM_DeadTime =11;  //死区时间设置为152ns
	pwm_BTR_Initsturt.TIM_LOCKLevel =TIM_LOCKLevel_1 ;
	pwm_BTR_Initsturt.TIM_OSSIState =TIM_OSSIState_Enable ;
	pwm_BTR_Initsturt.TIM_OSSRState = TIM_OSSRState_Enable  ;
	TIM_BDTRConfig(TIM1, &	pwm_BTR_Initsturt);
	
	//使能计数器
	TIM_Cmd(TIM1,ENABLE);
	//主输出使能,用于高级定时器
	TIM_CtrlPWMOutputs(TIM1,ENABLE);
	
}

项目二: 配置输入捕获按键按下产生的脉冲信号,并将信号转换成高电平持续的时间通过串口显示在上位机上

操作:

1 //配置输入捕获脉冲频率引脚 PA0

2配置TIM基本结构体

3输入捕获结构体初始化

4启动更新时间函数中断(更新中断,以及捕获第一次上升沿中断)

5编写中断服务函数(检测第一次捕获的上升沿的计数值,同时转换成下降沿进行捕获)

6在主函数里面计算捕获值换算成时间

复制代码
//配置输入捕获脉冲频率引脚  PA0
void General_TIM_Mode_GPIO()
{
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
	GPIO_InitTypeDef  GPIO_TIM_Initsturt;
	 GPIO_TIM_Initsturt.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
	 GPIO_TIM_Initsturt.GPIO_Pin =GPIO_Pin_0 ;
   GPIO_Init(GPIOB, &GPIO_TIM_Initsturt);
	
	
}

void General_TIM_Config()//TIM5
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
	TIM_TimeBaseInitTypeDef    TIM_InitConfig;
	  TIM_InitConfig.TIM_ClockDivision =TIM_CKD_DIV1;
	  TIM_InitConfig.TIM_CounterMode =TIM_CounterMode_Up ;
	  TIM_InitConfig.TIM_Period =0xFFFF;
	  TIM_InitConfig.TIM_Prescaler = 72-1;
	  TIM_InitConfig.TIM_RepetitionCounter =0;
	 TIM_TimeBaseInit( TIM5, &TIM_InitConfig);
	
	//输入捕获结构体初始化
	
	TIM_ICInitTypeDef  TIM_IcInitsturt;
	TIM_IcInitsturt.TIM_Channel = TIM_Channel_1;//选择通道1
	TIM_IcInitsturt.TIM_ICFilter =0;
	TIM_IcInitsturt.TIM_ICPolarity =TIM_ICPolarity_Rising;//采用上升沿的方式
	TIM_IcInitsturt.TIM_ICPrescaler =TIM_ICPSC_DIV1 ;
	TIM_IcInitsturt.TIM_ICSelection =TIM_ICSelection_DirectTI;//选择直连的方式
	TIM_ICInit( TIM5, &	TIM_IcInitsturt);
	
	TIM_ClearFlag(TIM5,TIM_FLAG_Update|TIM_FLAG_CC1);//清楚更新和捕获中断标志位
	
	TIM_ITConfig(TIM5, TIM_IT_Update|TIM_IT_CC1, ENABLE );
	TIM_Cmd( TIM5, ENABLE );
	
	
	//配置TIM5输入捕获中断NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_InitTypeDef  nvic_Initsturt;
	nvic_Initsturt.NVIC_IRQChannel = TIM5_IRQn;
	nvic_Initsturt.NVIC_IRQChannelCmd =ENABLE  ;
	nvic_Initsturt.NVIC_IRQChannelPreemptionPriority =0;
	nvic_Initsturt.NVIC_IRQChannelSubPriority =0;
	NVIC_Init(&nvic_Initsturt);
	

}

void   TIM5_IRQHandler ()
{
	if(TIM_GetITStatus(TIM5,  TIM_IT_Update)==SET)
	{
//当捕获信号的周期大于定时器的最长定长时,就会溢出产生更新中断,这时需要把最长定时时间周期加到捕获信号的时间里面去
		TIM_CaptureSturt.Capture_Period ++;
		TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
		
	}
	//上升捕获中断
	if(TIM_GetITStatus(TIM5, TIM_IT_CC1 )==SET)
	{
		//第一次捕获
		if(TIM_CaptureSturt.Capture_StartFlag ==0)
		{
			//计数清零
			TIM_SetCounter( TIM5,0);
			//自动重装寄存器更新标志请0
			TIM_CaptureSturt .Capture_Period =0;
			//存放捕获比较寄存器的变量清0
			TIM_CaptureSturt .Capture_CorValue =0;
			//当第一次捕获到上升沿时就把捕获边沿配置为下降沿
			 TIM_OC1PolarityConfig(TIM5,TIM_OCPolarity_Low);
			//标志位置为1
			TIM_CaptureSturt .Capture_StartFlag =1;
			
		}
		//下降沿捕获
		else{
			//第二次捕获
			//获取捕获比较器的值,这个值就是捕获到的高电平时间的值
		TIM_CaptureSturt .Capture_CorValue =TIM_GetCapture1(TIM5);
			
			//当第二次捕获到下降沿后,就把捕获边沿配置为上升沿,开启新的一轮捕获
			TIM_OC1PolarityConfig(TIM5,TIM_OCPolarity_High);
			
			//开始捕获标志清0
			TIM_CaptureSturt .Capture_StartFlag =0;
			//捕获完成标志置1
			TIM_CaptureSturt .Capture_FinishFlag =1;
			
		}
				TIM_ClearITPendingBit(TIM5,TIM_IT_CC1 );
	}
	
	
}

 uint32_t time;
	uint32_t TIM_pscCLK  =72000000/9;
	   usart_Config();
		 usart_GPIO_Config();
	  General_TIM_Config( );
	General_TIM_Mode_GPIO( );
	printf("\r\n野火 STM32 输入捕获实验\r\n");
	printf ("\r\n按下K1,测试K1的按下时间\r\n");
//	
	 while(1)
	 {
		
			if(TIM_CaptureSturt .Capture_FinishFlag ==1)
			{
				//计算高电平时间的计数值
				  time=  TIM_CaptureSturt .Capture_Period *(7+1)+(TIM_CaptureSturt .Capture_CorValue +1);
				
			//打印高电平脉宽时间
			printf ("\r\n测得高电平时间:%d.%d  s\r\n",time/TIM_pscCLK,time%TIM_pscCLK);
			TIM_CaptureSturt .Capture_FinishFlag =0;
			}
	 }
}
相关推荐
森焱森1 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白1 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D2 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术5 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt5 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘6 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang6 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n8 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件
Despacito0o11 小时前
ESP32-s3摄像头驱动开发实战:从零搭建实时图像显示系统
人工智能·驱动开发·嵌入式硬件·音视频·嵌入式实时数据库
门思科技11 小时前
设计可靠 LoRaWAN 设备时需要考虑的关键能力
运维·服务器·网络·嵌入式硬件·物联网