STM32产生位时可调的PWM信号,定时器单脉冲模式,主从定时器功能使用


前言

STM32单片机每个通用定时器可以独立产生4路PWM信号,每个通道的PWM信号频率由预分频器PSC和重装载寄存器ARR决定,脉宽由预分频器PSC和比较/捕获寄存器CCRx决定,但对于一些特殊使用场景,如可控硅控制,步进电机控制,或基带信号PPM调制等,需要对PWM输出信号的位时(类似于正弦信号的相位)进行调节,普通PWM输出模式无法满足这种需求,本文所述主从定时器结合定时器单脉冲模式实现输出频率、脉宽、位时均可自由调节的PWM信号。且相对于传统PWM输出方式来说,可以最大限度的提高脉宽调节精度,72M主频下可实现13.89ns的调节精度。而缺点正是多耗费一个定时器。


一、实现思路

输出
触发
输出
主定时器
TRGO信号
从定时器
单脉冲

思路清晰,但实现起来需要掌握几个基础知识。

  • 什么是主从定时器
  • 什么是TRGO信号
  • 定时器单脉冲模式

二、基础知识

1.什么是主从定时器

图1.主/从定时器原理
在这里插入图片描述

所有TIMx定时器在内部相连,用于定时器同步或链接。当一个定时器处于主模式时,它可以对另一个处于从模式的定时器的计数器进行复位、启动、停止或提供时钟等操作。根据参考手册,分别描述了这几种从模式的功能。紧跟思路,本文需要用主定时器启动从定时器,故从模式选择触发模式,利用主定时器产生触发信号,启动从定时器。而这个触发信号正是TRGO信号。在这里插入图片描述

2.什么是TRGO信号

请添加图片描述
根据定时器框图,定时器的触发控制器可输出TRGO信号,用于为其他定时器、ADC/DAC提供触发信号。本文中,对于主定时器,能够输出TRGO信号,但从定时器如何利用这个信号呢,这时就需要参考以下定时器内部接线图了:
在这里插入图片描述
在这里插入图片描述
例:根据以上两个表,若将TIM2作为主定时器,TIM4作为从定时器,可以看到TIM2的TOGO信号连接TIM4的ITR1线上。

3.定时器单脉冲模式

在这里插入图片描述
根据手册的描述,单脉冲模式就是一种特殊的比较输出模式,可以与PWM模式进行对比,PWM模式输出连续的脉冲,而单脉冲模式是让PWM模式输出一个脉冲后立即停止定时器,实现单脉冲输出,同时定时器停止后电平回到无效电平。所以,要研究如何产生单脉冲,必须先了解PWM模式的配置。
在这里插入图片描述
根据这一段描述,先配置PWM模式为向上计数,然后只需要关注两个参数的配置,PWM模式1/2和有效电平。
对于四种组合:

  • PWM模式1 高电平有效
  • PWM模式1 低电平有效
  • PWM模式2 高电平有效
  • PWM模式2 低电平有效

需要产生单脉冲,就要配置输出如下图OC1的波形。可知有效电平为高电平,无效电平为低电平。然后再考虑选用PWM模式1还是PWM模式2。
在这里插入图片描述
PWM模式1- 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平
PWM模式2- 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平
由图可知,t_delay时间段内单脉冲为低电平,同时低电平为无效电平,由此应该选择PWM模式2。

三、配置代码

有了以上基础知识,便可轻松编写出实现代码,采用TIM2做主定时器,TIM4做从定时器,同时TIM4通道4作为单脉冲输出口。

1.主定时器配置

void TIM2_Init(u16 arr,u16 psc)
{
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	/* 开启时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM2时钟
	
	TIM_TimeBaseInitStructure.TIM_Period=arr;   //自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	//产生触发信号
	TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);//开启定时器2主从模式
	TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//选择TIM2输出TRGO信号
	
	TIM_Cmd(TIM2,ENABLE); //使能定时器	
}

2.从定时器配置

void TIM4_CH4_OPM_Init(u16 arr,u16 psc,u16 ccr)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 开启时钟 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/* 配置GPIO的模式和IO口 */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	TIM_TimeBaseInitStructure.TIM_Period=arr;   //自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);	
	
	TIM_OCInitStructure.TIM_Pulse=ccr;
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;//配置输出PWM模式2
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//有效电平为高电平
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OC4Init(TIM4,&TIM_OCInitStructure); //输出比较通道4初始化
	
	TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable); //使能TIM4在CCR4的预装载寄存器
	TIM_ARRPreloadConfig(TIM4,ENABLE);//使能预装载寄存器
	
	TIM_SelectOnePulseMode(TIM4,TIM_OPMode_Single);//开启单脉冲模式
	
	TIM_SelectSlaveMode(TIM4,TIM_SlaveMode_Trigger);//设置从模式寄存器 
	TIM_SelectInputTrigger(TIM4, TIM_TS_ITR1);//TIM2主连接TIM4,TIM_TS_ITR1
}

3.函数使用

  • 输出PWM频率的计算:输出频率由主定时器决定,即由分频系数PSC和重装置值ARR对72M时钟进行分频,于是频率 f = 72000000 / (PSC+1) / (ARR+1)
  • 从定时器计数周期为分频后频率的倒数,即 T = (PSC+1) / 72000000
  • 脉宽由从定时器PWM后一段高电平时间决定,即 t_pluse = (ARR+1 - CCR) * T
  • 位时由从定时器PWM前一段低电平时间决定,即 t_delay = CCR * T

以下以产生50Hz,2ms脉宽,10ms位时的PWM信号为例:

TIM4_CH4_OPM_Init(12000-1,72-1,10000);	//从定时器:T = 72/72000000 * 1000000 = 1us
										//t_delay = 10000 * T = 10ms
										//t_pluse = (12000 - 10000) * T = 2ms
TIM2_Init(7200-1,200-1);				//主定时器:72000000/7200/200 = 50Hz

总结

知识在于积累,以上记录学习过程,难免出现理解不到位的地方,这就需要仔细阅读参考手册了。

  • 22
    点赞
  • 153
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简单|纯粹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值